diff --git a/CHANGELOG.md b/CHANGELOG.md index d91796c..cd21eb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,35 +1,9 @@ -## Version 1.2.0 +## Version 1.2.1 ### Добавлено -#### extnet -| Идентификатор
задачи | Описание | -| --- | --- | -| BATF-671 | Data source `decort_extnet_reserved_ip_list` в cloudapi/extnet | -| BATF-672 | Вычисляемое поле `account_id` в блоке `reservations` в data sources `dynamix_extnet` в cloudapi/extnet | - #### kvmvm | Идентификатор
задачи | Описание | | --- | --- | -| BATF-674 | Вычисляемое поле `vnc_password` в resources `dynamix_kvmvm` и data sources `dynamix_kvmvm` в cloudapi/kvmvm | -| BATF-673 | Опциональное поле `auto_start_w_node`в resources `dynamix_kvmvm` в cloudapi/kvmvm | -| BATF-673 | Вычисляемое поле `auto_start_w_node`в data_sources `dynamix_kvmvm, dynamix_kvmvm_list, dynamix_kvmvm_list_deleted` в cloudapi/kvmvm | - -#### vins -| Идентификатор
задачи | Описание | -| --- | --- | -| BATF-676 | Вычисляемое поле `account_id` в блоке `reservations` в resource `dynamix_vins` и data source `dynamix_vins` в cloudapi/vins | -| BATF-675 | Вычисляемое поле `vnc_password` в блоке `vnf_dev` в resources `dynamix_vins` и data sources `dynamix_vins` в cloudapi/vins | - -#### общее -| Идентификатор
задачи | Описание | -| --- | --- | -| BATF-679 | Добавлена поддержка работы с режимом аутентификации `bvs` | - -### Удалено - -#### vins -| Идентификатор
задачи | Описание | -| --- | --- | -| BATF-676 | Вычисляемые поля `client_type, description, domain_name, hostname` в блоке `reservations` в resources `dynamix_vins` и data sources `dynamix_vins` в cloudapi/vins| -| BATF-680 | Опциональное поле `compute_ids` в resource `decort_vins_static_route` в cloudapi/vins | +| BATF-692 | Опциональное поле `preferred_cpu`в resource `dynamix_kvmvm` в cloudapi/kvmvm | +| BATF-692 | Вычисляемое поле `preferred_cpu`в data_sources `dynamix_kvmvm, dynamix_kvmvm_list, dynamix_kvmvm_list_deleted` в cloudapi/kvmvm | diff --git a/Makefile b/Makefile index 99e0ebb..51dcc4d 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ ZIPDIR = ./zip BINARY=${NAME} WORKPATH= ./examples/terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${SECONDNAMESPACE}/${VERSION}/${OS_ARCH} MAINPATH = ./cmd/dynamix/ -VERSION=1.2.0 +VERSION=1.2.1 OS_ARCH=$(shell go env GOHOSTOS)_$(shell go env GOHOSTARCH) FILES = ${BINARY}_${VERSION}_darwin_amd64\ @@ -31,7 +31,7 @@ BINS = $(addprefix bin/, $(FILES)) default: install image: - GOOS=linux GOARCH=amd64 go build -o terraform-provider-dynamix ./cmd/basis/ + GOOS=linux GOARCH=amd64 go build -o terraform-provider-dynamix ./cmd/dynamix/ docker build . -t rudecs/tf:3.2.2 rm terraform-provider-dynamix diff --git a/docs/data-sources/kvmvm.md b/docs/data-sources/kvmvm.md index 9f20431..8a148c6 100644 --- a/docs/data-sources/kvmvm.md +++ b/docs/data-sources/kvmvm.md @@ -76,6 +76,7 @@ description: |- - `os_users` (Attributes List) (see [below for nested schema](#nestedatt--os_users)) - `pci_devices` (List of Number) - `pinned` (Boolean) +- `preferred_cpu` (List of Number) - `ram` (Number) - `reference_id` (String) - `registered` (Boolean) diff --git a/docs/data-sources/kvmvm_list.md b/docs/data-sources/kvmvm_list.md index 4b1994a..d6145b6 100644 --- a/docs/data-sources/kvmvm_list.md +++ b/docs/data-sources/kvmvm_list.md @@ -96,6 +96,7 @@ Read-Only: - `numa_affinity` (String) - `numa_node_id` (Number) - `pinned` (Boolean) +- `preferred_cpu` (List of Number) - `ram` (Number) - `reference_id` (String) - `registered` (Boolean) diff --git a/docs/data-sources/kvmvm_list_deleted.md b/docs/data-sources/kvmvm_list_deleted.md index 3bb8674..8ec9247 100644 --- a/docs/data-sources/kvmvm_list_deleted.md +++ b/docs/data-sources/kvmvm_list_deleted.md @@ -94,6 +94,7 @@ Read-Only: - `numa_affinity` (String) - `numa_node_id` (Number) - `pinned` (Boolean) +- `preferred_cpu` (List of Number) - `ram` (Number) - `reference_id` (String) - `registered` (Boolean) diff --git a/docs/resources/kvmvm.md b/docs/resources/kvmvm.md index ef365ea..417b778 100644 --- a/docs/resources/kvmvm.md +++ b/docs/resources/kvmvm.md @@ -55,6 +55,7 @@ description: |- - `pin_to_stack` (Boolean) - `pool` (String) Pool to use if sepId is set, can be also empty if needed to be chosen by system. - `port_forwarding` (Attributes Set) (see [below for nested schema](#nestedatt--port_forwarding)) +- `preferred_cpu` (List of Number) Recommended isolated CPUs. Field is ignored if compute.cpupin=False or compute.pinned=False - `reset` (Boolean) - `restore` (Boolean) - `rollback` (Attributes) (see [below for nested schema](#nestedatt--rollback)) diff --git a/go.mod b/go.mod index 0440635..98ed7fc 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/sirupsen/logrus v1.9.3 - repository.basistech.ru/BASIS/decort-golang-sdk v1.10.0 + repository.basistech.ru/BASIS/decort-golang-sdk v1.10.1 ) require ( diff --git a/go.sum b/go.sum index ecbd4d7..098a28c 100644 --- a/go.sum +++ b/go.sum @@ -100,5 +100,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -repository.basistech.ru/BASIS/decort-golang-sdk v1.10.0 h1:/Q5MB07rqqv1m1XcAsU3f1ybMRYOgF908+PKEfcHzPs= -repository.basistech.ru/BASIS/decort-golang-sdk v1.10.0/go.mod h1:OaUynHHuSjWMzpfyoL4au6oLcUogqUkPPBKA15pbHWo= +repository.basistech.ru/BASIS/decort-golang-sdk v1.10.1 h1:Z6drv1seHY6nkyEdjGp2LoNKbne1ihrNRs32q93UhcM= +repository.basistech.ru/BASIS/decort-golang-sdk v1.10.1/go.mod h1:OaUynHHuSjWMzpfyoL4au6oLcUogqUkPPBKA15pbHWo= diff --git a/internal/service/cloudapi/kvmvm/flattens/flatten_data_source_compute.go b/internal/service/cloudapi/kvmvm/flattens/flatten_data_source_compute.go index 324527e..f249548 100644 --- a/internal/service/cloudapi/kvmvm/flattens/flatten_data_source_compute.go +++ b/internal/service/cloudapi/kvmvm/flattens/flatten_data_source_compute.go @@ -50,7 +50,9 @@ func DataSourceCompute(ctx context.Context, state *models.RecordComputeModel, c AutoStartWithNode: types.BoolValue(computeRecord.AutoStart), Chipset: types.StringValue(computeRecord.Chipset), BootDiskSize: types.Int64Value(int64(computeRecord.BootDiskSize)), + BootOrder: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &computeRecord.BootOrder), CdImageId: types.Int64Value(int64(computeRecord.CdImageId)), + Clones: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &computeRecord.Clones), CloneReference: types.Int64Value(int64(computeRecord.CloneReference)), ComputeCIID: types.Int64Value(int64(computeRecord.ComputeCIID)), CPU: types.Int64Value(int64(computeRecord.CPU)), @@ -86,11 +88,13 @@ func DataSourceCompute(ctx context.Context, state *models.RecordComputeModel, c NumaNodeId: types.Int64Value(int64(computeRecord.NumaNodeId)), OSUsers: flattenOSUsers(ctx, &computeRecord.OSUsers), Pinned: types.BoolValue(computeRecord.Pinned), + PreferredCPU: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &computeRecord.PreferredCPU), PCIDevices: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, flattenPCI(ctx, pciDevicesList)), RAM: types.Int64Value(int64(computeRecord.RAM)), ReferenceID: types.StringValue(computeRecord.ReferenceID), Registered: types.BoolValue(computeRecord.Registered), ResName: types.StringValue(computeRecord.ResName), + ReservedNodeCpus: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &computeRecord.ReservedNodeCpus), RGID: types.Int64Value(int64(computeRecord.RGID)), RGName: types.StringValue(computeRecord.RGName), SnapSets: flattenSnapSet(ctx, &computeRecord.SnapSets), @@ -105,27 +109,14 @@ func DataSourceCompute(ctx context.Context, state *models.RecordComputeModel, c VirtualImageID: types.Int64Value(int64(computeRecord.VirtualImageID)), VirtualImageName: types.StringValue(computeRecord.VirtualImageName), VNCPassword: types.StringValue(computeRecord.VNCPassword), + VGPUs: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &computeRecord.VGPUs), } - state.BootOrder, diags = types.ListValueFrom(ctx, types.StringType, computeRecord.BootOrder) - if diags != nil { - tflog.Error(ctx, fmt.Sprint("Error FlattenDataSourceCompute", diags)) - } - state.Clones, diags = types.ListValueFrom(ctx, types.Int64Type, computeRecord.Clones) - if diags != nil { - tflog.Error(ctx, fmt.Sprint("Error FlattenDataSourceCompute", diags)) - } + state.Tags, diags = types.MapValueFrom(ctx, types.StringType, computeRecord.Tags) if diags != nil { tflog.Error(ctx, fmt.Sprint("Error FlattenDataSourceCompute", diags)) } - state.ReservedNodeCpus, diags = types.ListValueFrom(ctx, types.Int64Type, computeRecord.ReservedNodeCpus) - if diags != nil { - tflog.Error(ctx, fmt.Sprint("Error FlattenDataSourceCompute", diags)) - } - state.VGPUs, diags = types.ListValueFrom(ctx, types.Int64Type, computeRecord.VGPUs) - if diags != nil { - tflog.Error(ctx, fmt.Sprint("Error FlattenDataSourceCompute", diags)) - } + tflog.Info(ctx, "End FlattenDataSourceCompute") return nil } diff --git a/internal/service/cloudapi/kvmvm/flattens/flatten_data_source_compute_list.go b/internal/service/cloudapi/kvmvm/flattens/flatten_data_source_compute_list.go index 808111b..92cda6e 100644 --- a/internal/service/cloudapi/kvmvm/flattens/flatten_data_source_compute_list.go +++ b/internal/service/cloudapi/kvmvm/flattens/flatten_data_source_compute_list.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-log/tflog" "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/compute" "repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/client" + "repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/flattens" "repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/kvmvm/models" "repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/kvmvm/utilities" ) @@ -74,7 +75,9 @@ func flattenItemsList(ctx context.Context, computes *compute.ListComputes) []mod Architecture: types.StringValue(item.Architecture), AutoStartWithNode: types.BoolValue(item.AutoStart), BootDiskSize: types.Int64Value(int64(item.BootDiskSize)), + BootOrder: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.BootOrder), CdImageId: types.Int64Value(int64(item.CdImageId)), + Clones: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.Clones), CloneReference: types.Int64Value(int64(item.CloneReference)), Chipset: types.StringValue(item.Chipset), ComputeCIID: types.Int64Value(int64(item.ComputeCIID)), @@ -105,10 +108,12 @@ func flattenItemsList(ctx context.Context, computes *compute.ListComputes) []mod NumaAffinity: types.StringValue(item.NumaAffinity), NumaNodeId: types.Int64Value(int64(item.NumaNodeId)), Pinned: types.BoolValue(item.Pinned), + PreferredCPU: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.PreferredCPU), RAM: types.Int64Value(int64(item.RAM)), ReferenceID: types.StringValue(item.ReferenceID), Registered: types.BoolValue(item.Registered), ResName: types.StringValue(item.ResName), + ReservedNodeCpus: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.ReservedNodeCpus), RGID: types.Int64Value(int64(item.RGID)), RGName: types.StringValue(item.RGName), SnapSets: flattenSnapSetInList(ctx, &item.SnapSets), @@ -122,28 +127,13 @@ func flattenItemsList(ctx context.Context, computes *compute.ListComputes) []mod UserManaged: types.BoolValue(item.UserManaged), VINSConnected: types.Int64Value(int64(item.VINSConnected)), VirtualImageID: types.Int64Value(int64(item.VirtualImageID)), + VGPUs: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.VGPUs), } - temp.BootOrder, diags = types.ListValueFrom(ctx, types.StringType, item.BootOrder) - if diags != nil { - tflog.Error(ctx, fmt.Sprint("Error flattenItemsList", diags)) - } - temp.Clones, diags = types.ListValueFrom(ctx, types.Int64Type, item.Clones) - if diags != nil { - tflog.Error(ctx, fmt.Sprint("Error flattenItemsList", diags)) - } temp.Tags, diags = types.MapValueFrom(ctx, types.StringType, item.Tags) if diags != nil { tflog.Error(ctx, fmt.Sprint("Error flattenItemsList", diags)) } - temp.ReservedNodeCpus, diags = types.ListValueFrom(ctx, types.Int64Type, item.ReservedNodeCpus) - if diags != nil { - tflog.Error(ctx, fmt.Sprint("Error flattenItemsList", diags)) - } - temp.VGPUs, diags = types.ListValueFrom(ctx, types.Int64Type, item.VGPUs) - if diags != nil { - tflog.Error(ctx, fmt.Sprint("Error flattenItemsList", diags)) - } res = append(res, temp) } diff --git a/internal/service/cloudapi/kvmvm/flattens/flatten_data_source_compute_list_deleted.go b/internal/service/cloudapi/kvmvm/flattens/flatten_data_source_compute_list_deleted.go index df04c88..258c652 100644 --- a/internal/service/cloudapi/kvmvm/flattens/flatten_data_source_compute_list_deleted.go +++ b/internal/service/cloudapi/kvmvm/flattens/flatten_data_source_compute_list_deleted.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-log/tflog" "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/compute" "repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/client" + "repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/flattens" "repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/kvmvm/models" "repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/kvmvm/utilities" ) @@ -72,7 +73,9 @@ func flattenItemsListDeleted(ctx context.Context, computes *compute.ListComputes Architecture: types.StringValue(item.Architecture), AutoStartWithNode: types.BoolValue(item.AutoStart), BootDiskSize: types.Int64Value(int64(item.BootDiskSize)), + BootOrder: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.BootOrder), CdImageId: types.Int64Value(int64(item.CdImageId)), + Clones: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.Clones), Chipset: types.StringValue(item.Chipset), CloneReference: types.Int64Value(int64(item.CloneReference)), ComputeCIID: types.Int64Value(int64(item.ComputeCIID)), @@ -103,10 +106,12 @@ func flattenItemsListDeleted(ctx context.Context, computes *compute.ListComputes NumaAffinity: types.StringValue(item.NumaAffinity), NumaNodeId: types.Int64Value(int64(item.NumaNodeId)), Pinned: types.BoolValue(item.Pinned), + PreferredCPU: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.PreferredCPU), RAM: types.Int64Value(int64(item.RAM)), ReferenceID: types.StringValue(item.ReferenceID), Registered: types.BoolValue(item.Registered), ResName: types.StringValue(item.ResName), + ReservedNodeCpus: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.ReservedNodeCpus), RGID: types.Int64Value(int64(item.RGID)), RGName: types.StringValue(item.RGName), SnapSets: flattenSnapSetInListDeleted(ctx, &item.SnapSets), @@ -120,28 +125,13 @@ func flattenItemsListDeleted(ctx context.Context, computes *compute.ListComputes UserManaged: types.BoolValue(item.UserManaged), VINSConnected: types.Int64Value(int64(item.VINSConnected)), VirtualImageID: types.Int64Value(int64(item.VirtualImageID)), + VGPUs: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.VGPUs), } - temp.BootOrder, diags = types.ListValueFrom(ctx, types.StringType, item.BootOrder) - if diags != nil { - tflog.Error(ctx, fmt.Sprint("Error flattenItemsListDeleted", diags)) - } - temp.Clones, diags = types.ListValueFrom(ctx, types.Int64Type, item.Clones) - if diags != nil { - tflog.Error(ctx, fmt.Sprint("Error flattenItemsListDeleted", diags)) - } temp.Tags, diags = types.MapValueFrom(ctx, types.StringType, item.Tags) if diags != nil { tflog.Error(ctx, fmt.Sprint("Error flattenItemsListDeleted", diags)) } - temp.ReservedNodeCpus, diags = types.ListValueFrom(ctx, types.Int64Type, item.ReservedNodeCpus) - if diags != nil { - tflog.Error(ctx, fmt.Sprint("Error flattenItemsList", diags)) - } - temp.VGPUs, diags = types.ListValueFrom(ctx, types.Int64Type, item.VGPUs) - if diags != nil { - tflog.Error(ctx, fmt.Sprint("Error flattenItemsListDeleted", diags)) - } res = append(res, temp) } diff --git a/internal/service/cloudapi/kvmvm/flattens/flatten_resource_compute.go b/internal/service/cloudapi/kvmvm/flattens/flatten_resource_compute.go index e44ddaf..e9fd86e 100644 --- a/internal/service/cloudapi/kvmvm/flattens/flatten_resource_compute.go +++ b/internal/service/cloudapi/kvmvm/flattens/flatten_resource_compute.go @@ -121,6 +121,7 @@ func ComputeResource(ctx context.Context, plan *models.ResourceComputeModel, c * NumaNodeId: types.Int64Value(int64(recordItemCompute.NumaNodeId)), OSUsers: flattenResourceOSUsers(ctx, &recordItemCompute.OSUsers), Pinned: types.BoolValue(recordItemCompute.Pinned), + PreferredCPU: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, recordItemCompute.PreferredCPU), ReferenceID: types.StringValue(recordItemCompute.ReferenceID), Registered: types.BoolValue(recordItemCompute.Registered), ResName: types.StringValue(recordItemCompute.ResName), diff --git a/internal/service/cloudapi/kvmvm/models/model_data_source_compute.go b/internal/service/cloudapi/kvmvm/models/model_data_source_compute.go index ba1b599..f22b2a9 100644 --- a/internal/service/cloudapi/kvmvm/models/model_data_source_compute.go +++ b/internal/service/cloudapi/kvmvm/models/model_data_source_compute.go @@ -61,6 +61,7 @@ type RecordComputeModel struct { OSUsers []ItemOSUserModel `tfsdk:"os_users"` PCIDevices types.List `tfsdk:"pci_devices"` Pinned types.Bool `tfsdk:"pinned"` + PreferredCPU types.List `tfsdk:"preferred_cpu"` RAM types.Int64 `tfsdk:"ram"` ReferenceID types.String `tfsdk:"reference_id"` Registered types.Bool `tfsdk:"registered"` diff --git a/internal/service/cloudapi/kvmvm/models/model_data_source_compute_list.go b/internal/service/cloudapi/kvmvm/models/model_data_source_compute_list.go index a64c695..23d26be 100644 --- a/internal/service/cloudapi/kvmvm/models/model_data_source_compute_list.go +++ b/internal/service/cloudapi/kvmvm/models/model_data_source_compute_list.go @@ -73,6 +73,7 @@ type ItemComputeModel struct { NumaAffinity types.String `tfsdk:"numa_affinity"` NumaNodeId types.Int64 `tfsdk:"numa_node_id"` Pinned types.Bool `tfsdk:"pinned"` + PreferredCPU types.List `tfsdk:"preferred_cpu"` RAM types.Int64 `tfsdk:"ram"` ReferenceID types.String `tfsdk:"reference_id"` Registered types.Bool `tfsdk:"registered"` diff --git a/internal/service/cloudapi/kvmvm/models/model_data_source_compute_list_deleted.go b/internal/service/cloudapi/kvmvm/models/model_data_source_compute_list_deleted.go index a21455a..01b90e1 100644 --- a/internal/service/cloudapi/kvmvm/models/model_data_source_compute_list_deleted.go +++ b/internal/service/cloudapi/kvmvm/models/model_data_source_compute_list_deleted.go @@ -71,6 +71,7 @@ type ItemListDeletedComputeModel struct { NumaAffinity types.String `tfsdk:"numa_affinity"` NumaNodeId types.Int64 `tfsdk:"numa_node_id"` Pinned types.Bool `tfsdk:"pinned"` + PreferredCPU types.List `tfsdk:"preferred_cpu"` RAM types.Int64 `tfsdk:"ram"` ReferenceID types.String `tfsdk:"reference_id"` Registered types.Bool `tfsdk:"registered"` diff --git a/internal/service/cloudapi/kvmvm/models/model_resource_compute.go b/internal/service/cloudapi/kvmvm/models/model_resource_compute.go index 5b3d0da..04806ba 100644 --- a/internal/service/cloudapi/kvmvm/models/model_resource_compute.go +++ b/internal/service/cloudapi/kvmvm/models/model_resource_compute.go @@ -38,6 +38,7 @@ type ResourceComputeModel struct { Rollback types.Object `tfsdk:"rollback"` CD types.Object `tfsdk:"cd"` PinToStack types.Bool `tfsdk:"pin_to_stack"` + PreferredCPU types.List `tfsdk:"preferred_cpu"` Description types.String `tfsdk:"description"` CloudInit types.String `tfsdk:"cloud_init"` Enabled types.Bool `tfsdk:"enabled"` diff --git a/internal/service/cloudapi/kvmvm/resource_compute.go b/internal/service/cloudapi/kvmvm/resource_compute.go index 3181d1c..65c7f15 100644 --- a/internal/service/cloudapi/kvmvm/resource_compute.go +++ b/internal/service/cloudapi/kvmvm/resource_compute.go @@ -94,6 +94,11 @@ func (r *resourceCompute) Create(ctx context.Context, req resource.CreateRequest // because additional settings failure is not critical. If errors were added instead of warnings, terraform // framework would mark resource as tainted and delete it, which would be unwanted behaviour. + // pin to stack if needed, warnings added to resp.Diagnostics in case of failure. + if plan.PinToStack.ValueBool() { + resp.Diagnostics.Append(utilities.ComputeResourcePinToStack(ctx, &plan, r.client)...) + } + // enable or disable Compute, warnings added to resp.Diagnostics in case of failure. resp.Diagnostics.Append(utilities.ComputeResourceEnableDisable(ctx, &plan, r.client)...) @@ -146,11 +151,6 @@ func (r *resourceCompute) Create(ctx context.Context, req resource.CreateRequest resp.Diagnostics.Append(utilities.ComputeResourcePCIDevice(ctx, &plan, r.client)...) } - // pin to stack if needed, warnings added to resp.Diagnostics in case of failure. - if plan.PinToStack.ValueBool() { - resp.Diagnostics.Append(utilities.ComputeResourcePinToStack(ctx, &plan, r.client)...) - } - // set auto start_w_node if pin_to_stack == false if !plan.PinToStack.ValueBool() && plan.AutoStartWithNode.ValueBool() { resp.Diagnostics.Append(utilities.ComputeResourceAutoStartWithNode(ctx, &plan, r.client)...) @@ -319,20 +319,20 @@ func (r *resourceCompute) Update(ctx context.Context, req resource.UpdateRequest } } - // Network(s) update if needed - if !plan.Network.Equal(state.Network) && !plan.Network.IsUnknown() { - resp.Diagnostics.Append(utilities.ComputeResourceNetworkUpdate(ctx, &state, &plan, r.client)...) + // PCI device(s) update if needed + if !plan.PCIDevices.Equal(state.PCIDevices) { + resp.Diagnostics.Append(utilities.ComputeResourcePCIDeviceUpdate(ctx, &state, &plan, r.client)...) if resp.Diagnostics.HasError() { - tflog.Error(ctx, "Update resourceCompute: Error update network(s)") + tflog.Error(ctx, "Update resourceCompute: Error update PCI device(s) list") return } } - // PCI device(s) update if needed - if !plan.PCIDevices.Equal(state.PCIDevices) { - resp.Diagnostics.Append(utilities.ComputeResourcePCIDeviceUpdate(ctx, &state, &plan, r.client)...) + // pin to stack if needed + if !plan.PinToStack.Equal(state.PinToStack) { + resp.Diagnostics.Append(utilities.ComputeResourcePinToStackUpdate(ctx, &plan, r.client)...) if resp.Diagnostics.HasError() { - tflog.Error(ctx, "Update resourceCompute: Error update PCI device(s) list") + tflog.Error(ctx, "Update resourceCompute: Error pin/unpin to stack compute") return } } @@ -340,7 +340,7 @@ func (r *resourceCompute) Update(ctx context.Context, req resource.UpdateRequest // Compute parameters update if needed if (!plan.Description.IsUnknown() && !plan.Description.Equal(state.Description)) || !plan.Name.Equal(state.Name) || !plan.NumaAffinity.Equal(state.NumaAffinity) || !plan.CPUPin.Equal(state.CPUPin) || !plan.HPBacked.Equal(state.HPBacked) || (!plan.Chipset.IsUnknown() && !plan.Chipset.Equal(state.Chipset)) || - !plan.AutoStartWithNode.Equal(state.AutoStartWithNode) { + !plan.AutoStartWithNode.Equal(state.AutoStartWithNode) || (!plan.PreferredCPU.IsUnknown() && !plan.PreferredCPU.Equal(state.Description)) { resp.Diagnostics.Append(utilities.ComputeResourceComputeUpdate(ctx, &state, &plan, r.client)...) if resp.Diagnostics.HasError() { tflog.Error(ctx, "Update resourceCompute: Error update compute parameters") @@ -348,6 +348,15 @@ func (r *resourceCompute) Update(ctx context.Context, req resource.UpdateRequest } } + // Network(s) update if needed + if !plan.Network.Equal(state.Network) && !plan.Network.IsUnknown() { + resp.Diagnostics.Append(utilities.ComputeResourceNetworkUpdate(ctx, &state, &plan, r.client)...) + if resp.Diagnostics.HasError() { + tflog.Error(ctx, "Update resourceCompute: Error update network(s)") + return + } + } + // Affinity label update if needed if !plan.AffinityLabel.Equal(state.AffinityLabel) && !plan.AffinityLabel.IsUnknown() { resp.Diagnostics.Append(utilities.ComputeResourceAffinityLabelUpdate(ctx, &plan, r.client)...) @@ -429,15 +438,6 @@ func (r *resourceCompute) Update(ctx context.Context, req resource.UpdateRequest } } - // pin to stack if needed - if !plan.PinToStack.Equal(state.PinToStack) { - resp.Diagnostics.Append(utilities.ComputeResourcePinToStackUpdate(ctx, &plan, r.client)...) - if resp.Diagnostics.HasError() { - tflog.Error(ctx, "Update resourceCompute: Error pin/unpin to stack compute") - return - } - } - // compute pause if need if !plan.Pause.Equal(state.Pause) && !plan.Pause.IsNull() { resp.Diagnostics.Append(utilities.ComputeResourcePauseResumeCompute(ctx, &plan, r.client)...) diff --git a/internal/service/cloudapi/kvmvm/schemas/schema_data_source_compute.go b/internal/service/cloudapi/kvmvm/schemas/schema_data_source_compute.go index de9f97b..234aa27 100644 --- a/internal/service/cloudapi/kvmvm/schemas/schema_data_source_compute.go +++ b/internal/service/cloudapi/kvmvm/schemas/schema_data_source_compute.go @@ -631,6 +631,10 @@ func MakeSchemaDataSourceCompute() map[string]schema.Attribute { "pinned": schema.BoolAttribute{ Computed: true, }, + "preferred_cpu": schema.ListAttribute{ + Computed: true, + ElementType: types.Int64Type, + }, "ram": schema.Int64Attribute{ Computed: true, }, diff --git a/internal/service/cloudapi/kvmvm/schemas/schema_data_source_compute_list.go b/internal/service/cloudapi/kvmvm/schemas/schema_data_source_compute_list.go index 75f970c..d1f7d0b 100644 --- a/internal/service/cloudapi/kvmvm/schemas/schema_data_source_compute_list.go +++ b/internal/service/cloudapi/kvmvm/schemas/schema_data_source_compute_list.go @@ -391,6 +391,10 @@ func MakeSchemaDataSourceComputeList() map[string]schema.Attribute { "pinned": schema.BoolAttribute{ Computed: true, }, + "preferred_cpu": schema.ListAttribute{ + Computed: true, + ElementType: types.Int64Type, + }, "ram": schema.Int64Attribute{ Computed: true, }, diff --git a/internal/service/cloudapi/kvmvm/schemas/schema_data_source_compute_list_deleted.go b/internal/service/cloudapi/kvmvm/schemas/schema_data_source_compute_list_deleted.go index c37d3a8..1f2807c 100644 --- a/internal/service/cloudapi/kvmvm/schemas/schema_data_source_compute_list_deleted.go +++ b/internal/service/cloudapi/kvmvm/schemas/schema_data_source_compute_list_deleted.go @@ -383,6 +383,10 @@ func MakeSchemaDataSourceComputeListDeleted() map[string]schema.Attribute { "pinned": schema.BoolAttribute{ Computed: true, }, + "preferred_cpu": schema.ListAttribute{ + Computed: true, + ElementType: types.Int64Type, + }, "ram": schema.Int64Attribute{ Computed: true, }, diff --git a/internal/service/cloudapi/kvmvm/schemas/schema_resource_compute.go b/internal/service/cloudapi/kvmvm/schemas/schema_resource_compute.go index 3f8fa8a..299d4c2 100644 --- a/internal/service/cloudapi/kvmvm/schemas/schema_resource_compute.go +++ b/internal/service/cloudapi/kvmvm/schemas/schema_resource_compute.go @@ -390,6 +390,12 @@ func MakeSchemaResourceCompute() map[string]schema.Attribute { Default: booldefault.StaticBool(false), Description: "Use Huge Pages to allocate RAM of the virtual machine. The system must be pre-configured by allocating Huge Pages on the physical node.", }, + "preferred_cpu": schema.ListAttribute{ + Optional: true, + Computed: true, + ElementType: types.Int64Type, + Description: "Recommended isolated CPUs. Field is ignored if compute.cpupin=False or compute.pinned=False", + }, "pci_devices": schema.SetAttribute{ Optional: true, ElementType: types.Int64Type, diff --git a/internal/service/cloudapi/kvmvm/utilities/utility_resource_compute_create.go b/internal/service/cloudapi/kvmvm/utilities/utility_resource_compute_create.go index ec16204..06ebcb1 100644 --- a/internal/service/cloudapi/kvmvm/utilities/utility_resource_compute_create.go +++ b/internal/service/cloudapi/kvmvm/utilities/utility_resource_compute_create.go @@ -191,6 +191,15 @@ func CreateResourceCompute(ctx context.Context, plan *models.ResourceComputeMode createReqX86.HPBacked = true } + if !plan.PreferredCPU.IsUnknown() { + preferredCPUList := plan.PreferredCPU.Elements() + preferredCPU := make([]int64, 0, len(preferredCPUList)) + for _, elem := range preferredCPUList { + preferredCPU = append(preferredCPU, elem.(types.Int64).ValueInt64()) + } + createReqX86.PreferredCPU = preferredCPU + } + tflog.Info(ctx, fmt.Sprintf("CreateResourceCompute: creating Compute of type KVM VM x86")) id, err := c.CloudAPI().KVMX86().Create(ctx, createReqX86) if err != nil { diff --git a/internal/service/cloudapi/kvmvm/utilities/utility_resource_compute_update.go b/internal/service/cloudapi/kvmvm/utilities/utility_resource_compute_update.go index 6458186..25b66c0 100644 --- a/internal/service/cloudapi/kvmvm/utilities/utility_resource_compute_update.go +++ b/internal/service/cloudapi/kvmvm/utilities/utility_resource_compute_update.go @@ -47,6 +47,20 @@ func ComputeResourceResize(ctx context.Context, state *models.ResourceComputeMod resizeReq.CPU = uint64(plan.CPU.ValueInt64()) } + if resizeReq.CPU != 0 { + if !plan.PreferredCPU.IsUnknown() { + preferredCPUList := plan.PreferredCPU.Elements() + preferredCPU := make([]int64, 0, len(preferredCPUList)) + for _, elem := range preferredCPUList { + preferredCPU = append(preferredCPU, elem.(types.Int64).ValueInt64()) + } + resizeReq.PreferredCPU = preferredCPU + } + if len(state.PreferredCPU.Elements()) != 0 && len(resizeReq.PreferredCPU) == 0 { + resizeReq.PreferredCPU = []int64{-1} + } + } + if !plan.RAM.Equal(state.RAM) { resizeReq.RAM = uint64(plan.RAM.ValueInt64()) } @@ -288,7 +302,7 @@ func ComputeResourceNetworkUpdate(ctx context.Context, state *models.ResourceCom needStart := false // need stop to attach first network - if len(detachMap) == len(state.Network.Elements()) || (len(state.Network.Elements()) < 1) && len(attachMap) > 0 || hasDPDKnetwork(attachMap) { + if len(detachMap) == len(state.Network.Elements()) || (len(state.Network.Elements()) < 1) && len(attachMap) > 0 { tflog.Info(ctx, "ComputeResourceNetworkUpdate: stop compute", map[string]any{"compute_id": computeId}) _, err = c.CloudAPI().Compute().Stop(ctx, compute.StopRequest{ComputeID: computeId}) if err != nil { @@ -336,6 +350,10 @@ func ComputeResourceNetworkUpdate(ctx context.Context, state *models.ResourceCom } } + if diags.HasError() { + return diags + } + if needStart { diags = ComputeResourceStartStop(ctx, plan, c) } @@ -349,15 +367,6 @@ func ComputeResourceNetworkUpdate(ctx context.Context, state *models.ResourceCom return nil } -func hasDPDKnetwork(networkAttachMap []map[string]attr.Value) bool { - for _, elem := range networkAttachMap { - if elem["net_type"].(types.String).ValueString() == "DPDK" { - return true - } - } - return false -} - func ComputeResourceComputeUpdate(ctx context.Context, state *models.ResourceComputeModel, plan *models.ResourceComputeModel, c *client.Client) diag.Diagnostics { tflog.Info(ctx, "ComputeResourceComputeUpdate: start update compute parameters", map[string]any{"compute_id": plan.ID.ValueString()}) diags := diag.Diagnostics{} @@ -392,11 +401,23 @@ func ComputeResourceComputeUpdate(ctx context.Context, state *models.ResourceCom req.Chipset = plan.Chipset.ValueString() } + if !plan.PreferredCPU.IsUnknown() { + preferredCPUList := plan.PreferredCPU.Elements() + preferredCPU := make([]int64, 0, len(preferredCPUList)) + for _, elem := range preferredCPUList { + preferredCPU = append(preferredCPU, elem.(types.Int64).ValueInt64()) + } + req.PreferredCPU = preferredCPU + } + if len(state.PreferredCPU.Elements()) != 0 && len(req.PreferredCPU) == 0 { + req.PreferredCPU = []int64{-1} + } + // Note bene: numa_affinity, cpu_pin and hp_backed are not allowed to be changed for compute in STARTED tech status. // If STARTED, we need to stop it before update var isStopRequred bool - if !plan.NumaAffinity.Equal(state.NumaAffinity) || !plan.CPUPin.Equal(state.CPUPin) || !plan.HPBacked.Equal(state.HPBacked) || !plan.Chipset.Equal(state.Chipset) { + if !plan.NumaAffinity.Equal(state.NumaAffinity) || !plan.CPUPin.Equal(state.CPUPin) || !plan.HPBacked.Equal(state.HPBacked) || !plan.Chipset.Equal(state.Chipset) || (len(req.PreferredCPU) != 0) { isStopRequred = true tflog.Info(ctx, "ComputeResourceComputeUpdate: stop compute", map[string]any{"compute_id": computeId}) _, err = c.CloudAPI().Compute().Stop(ctx, compute.StopRequest{ComputeID: computeId}) diff --git a/internal/service/cloudbroker/node/flattens/flatten_data_source_cb_node.go b/internal/service/cloudbroker/node/flattens/flatten_data_source_cb_node.go index e242895..3138748 100644 --- a/internal/service/cloudbroker/node/flattens/flatten_data_source_cb_node.go +++ b/internal/service/cloudbroker/node/flattens/flatten_data_source_cb_node.go @@ -2,6 +2,7 @@ package flattens import ( "context" + "fmt" "strconv" "github.com/hashicorp/terraform-plugin-framework/diag" @@ -35,19 +36,25 @@ func NodeDataSource(ctx context.Context, state *models.DataSourceNode, c *client Consumption: flattenConsumpion(ctx, &recordNode.Consumption), CpuInfo: flattenCpuInfo(ctx, &recordNode.CpuInfo), CPUAllocationRatio: types.Int64Value(int64(recordNode.CPUAllocationRatio)), + DPDK: flattenDPDK(ctx, &recordNode.DPDK), GID: types.Int64Value(int64(recordNode.GID)), ID: types.StringValue(strconv.Itoa(int(recordNode.ID))), IPAddr: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &recordNode.IPAddr), - IsolatedCPUs: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &recordNode.IsolatedCpus), + IsolatedCPUs: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &recordNode.IsolatedCpus), Name: types.StringValue(recordNode.Name), NeedReboot: types.BoolValue(recordNode.NeedReboot), + NetworkMode: types.StringValue(recordNode.NetworkMode), NicInfo: flattenNicInfo(ctx, recordNode.NicInfo), NumaTopology: flattenNumaTopology(ctx, &recordNode.NumaTopology), - ReservedCPUs: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &recordNode.ReservedCPUs), + ReservedCPUs: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &recordNode.ReservedCPUs), Roles: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &recordNode.Roles), SriovEnabled: types.BoolValue(recordNode.SriovEnabled), StackId: types.Int64Value(int64(recordNode.StackID)), Status: types.StringValue(recordNode.Status), + ToActive: flattenRole(ctx, &recordNode.ToActive), + ToInstalling: flattenRole(ctx, &recordNode.ToInstalling), + ToMaintenance: flattenRole(ctx, &recordNode.ToMaintenance), + ToRestricted: flattenRole(ctx, &recordNode.ToRestricted), Version: types.StringValue(recordNode.Version), } @@ -125,7 +132,7 @@ func flattenVFList(ctx context.Context, vfMap []interface{}) []models.VFList { for _, item := range vfMap { itemMap := item.(map[string]interface{}) vf := models.VFList{ - FnID: types.Int64Value(itemMap["fnId"].(int64)), + FnID: types.Int64Value(int64(itemMap["fnId"].(float64))), PCISlot: types.StringValue(itemMap["pciSlot"].(string)), } vfList = append(vfList, vf) @@ -167,3 +174,37 @@ func flattenNumaTopologyNodes(ctx context.Context, nodes map[string]node.NodeInf tflog.Info(ctx, "End flattenNumaTopologyNodes") return res } + +func flattenDPDK(ctx context.Context, dpdk *node.DPDK) *models.DPDKModel { + tflog.Info(ctx, "Start flattenDPDK") + hpMemory, diags := types.MapValueFrom(ctx, types.Int64Type, dpdk.HPMemory) + if diags != nil { + tflog.Error(ctx, fmt.Sprint("Error flattenDPDK", diags)) + } + res := models.DPDKModel{ + Bridges: &models.Bridges{ + Backplane1: &models.Backplane1{ + Interfaces: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &dpdk.Bridges.Backplane1.Interfaces), + NumaNode: types.Int64Value(int64(dpdk.Bridges.Backplane1.NumaNode)), + }, + }, + HPMemory: hpMemory, + PMDCPU: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &dpdk.PMDCPU), + } + + tflog.Info(ctx, "End flattenDPDK") + return &res +} + +func flattenRole(ctx context.Context, role *node.Role) *models.Role { + tflog.Info(ctx, "Start flattenRole") + + res := models.Role{ + Actor: types.StringValue(role.Actor), + Reason: types.StringValue(role.Reason), + Time: types.Int64Value(int64(role.Time)), + } + + tflog.Info(ctx, "End flattenRole") + return &res +} diff --git a/internal/service/cloudbroker/node/flattens/flatten_data_source_cb_node_list.go b/internal/service/cloudbroker/node/flattens/flatten_data_source_cb_node_list.go index 3ab65b3..eb7d6f3 100644 --- a/internal/service/cloudbroker/node/flattens/flatten_data_source_cb_node_list.go +++ b/internal/service/cloudbroker/node/flattens/flatten_data_source_cb_node_list.go @@ -57,44 +57,46 @@ func flattenItemsList(ctx context.Context, recordList *node.ListNodes) []models. for _, item := range recordList.Data { temp := models.ItemNodeModel{ - AdditionalPkgs: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.AdditionalPkgs), - CpuInfo: flattenCpuInfo(ctx, &item.CpuInfo), - Description: types.StringValue(item.Description), - GID: types.Int64Value(int64(item.GID)), - GUID: types.StringValue(item.GUID), - HostKey: types.StringValue(item.HostKey), - IPAddr: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.IPAddr), - IsolatedCPUs: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.IsolatedCpus), - LastCheck: types.Int64Value(int64(item.LastCheck)), - MachineGUID: types.StringValue(item.MachineGUID), - MainboardSN: types.StringValue(item.MainboardSN), - Memory: types.Int64Value(int64(item.Memory)), - Milestones: types.Int64Value(int64(item.Milestones)), - Model: types.StringValue(item.Model), - Name: types.StringValue(item.Name), - NeedReboot: types.BoolValue(item.NeedReboot), - NetAddr: flattenNetAddr(ctx, item.NetAddr), - NetworkMode: types.StringValue(item.NetworkMode), - NicInfo: flattenNicInfo(ctx, item.NicInfo), - NodeUUID: types.StringValue(item.NodeUUID), - NodeID: types.Int64Value(int64(item.ID)), - NumaTopology: flattenNumaTopology(ctx, &item.NumaTopology), - PeerBackup: types.Int64Value(int64(item.PeerBackup)), - PeerLog: types.Int64Value(int64(item.PeerLog)), - PeerStats: types.Int64Value(int64(item.PeerStats)), - Pgpus: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.Pgpus), - PublicKeys: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.PublicKeys), - Release: types.StringValue(item.Release), - ReservedCPUs: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.ReservedCPUs), - Roles: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.Roles), - SEPs: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.Seps), - SerialNum: types.StringValue(item.SerialNum), - SriovEnabled: types.BoolValue(item.SriovEnabled), - StackId: types.Int64Value(int64(item.StackID)), - Status: types.StringValue(item.Status), - Tags: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.Tags), - Type: types.StringValue(item.Type), - Version: types.StringValue(item.Version), + AdditionalPkgs: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.AdditionalPkgs), + CpuInfo: flattenCpuInfo(ctx, &item.CpuInfo), + Description: types.StringValue(item.Description), + DPDK: flattenDPDK(ctx, &item.DPDK), + GID: types.Int64Value(int64(item.GID)), + GUID: types.StringValue(item.GUID), + HostKey: types.StringValue(item.HostKey), + IPAddr: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.IPAddr), + IsolatedCPUs: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.IsolatedCpus), + LastCheck: types.Int64Value(int64(item.LastCheck)), + MachineGUID: types.StringValue(item.MachineGUID), + MainboardSN: types.StringValue(item.MainboardSN), + Memory: types.Int64Value(int64(item.Memory)), + Milestones: types.Int64Value(int64(item.Milestones)), + Model: types.StringValue(item.Model), + Name: types.StringValue(item.Name), + NeedReboot: types.BoolValue(item.NeedReboot), + NetAddr: flattenNetAddr(ctx, item.NetAddr), + NetworkMode: types.StringValue(item.NetworkMode), + NicInfo: flattenNicInfo(ctx, item.NicInfo), + NodeUUID: types.StringValue(item.NodeUUID), + NodeID: types.Int64Value(int64(item.ID)), + NumaTopology: flattenNumaTopology(ctx, &item.NumaTopology), + PeerBackup: types.Int64Value(int64(item.PeerBackup)), + PeerLog: types.Int64Value(int64(item.PeerLog)), + PeerStats: types.Int64Value(int64(item.PeerStats)), + Pgpus: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.Pgpus), + PublicKeys: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.PublicKeys), + Release: types.StringValue(item.Release), + ReservedCPUs: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.ReservedCPUs), + Roles: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.Roles), + SEPs: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.Seps), + SerialNum: types.StringValue(item.SerialNum), + SriovEnabled: types.BoolValue(item.SriovEnabled), + StackId: types.Int64Value(int64(item.StackID)), + Status: types.StringValue(item.Status), + Tags: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.Tags), + Type: types.StringValue(item.Type), + UEFIFirmwareFile: types.StringValue(item.UEFIFirmwareFile), + Version: types.StringValue(item.Version), } res = append(res, temp) } diff --git a/internal/service/cloudbroker/node/models/model_data_source_cb_node.go b/internal/service/cloudbroker/node/models/model_data_source_cb_node.go index 6a22598..3cff519 100644 --- a/internal/service/cloudbroker/node/models/model_data_source_cb_node.go +++ b/internal/service/cloudbroker/node/models/model_data_source_cb_node.go @@ -14,12 +14,14 @@ type DataSourceNode struct { Consumption *ConsumptionModel `tfsdk:"consumption"` CpuInfo *CpuInfoModel `tfsdk:"cpu_info"` CPUAllocationRatio types.Int64 `tfsdk:"cpu_allocation_ratio"` + DPDK *DPDKModel `tfsdk:"dpdk"` GID types.Int64 `tfsdk:"gid"` ID types.String `tfsdk:"id"` IPAddr types.List `tfsdk:"ipaddr"` IsolatedCPUs types.List `tfsdk:"isolated_cpus"` Name types.String `tfsdk:"name"` NeedReboot types.Bool `tfsdk:"need_reboot"` + NetworkMode types.String `tfsdk:"network_mode"` NicInfo []NicInfoModel `tfsdk:"nic_info"` NumaTopology *NumaTopologyModel `tfsdk:"numa_topology"` ReservedCPUs types.List `tfsdk:"reserved_cpus"` @@ -27,6 +29,10 @@ type DataSourceNode struct { SriovEnabled types.Bool `tfsdk:"sriov_enabled"` StackId types.Int64 `tfsdk:"stack_id"` Status types.String `tfsdk:"status"` + ToActive *Role `tfsdk:"to_active"` + ToInstalling *Role `tfsdk:"to_installing"` + ToMaintenance *Role `tfsdk:"to_maintenance"` + ToRestricted *Role `tfsdk:"to_restricted"` Version types.String `tfsdk:"version"` } @@ -85,3 +91,24 @@ type NumaTopologyNodesMemory struct { TwoM types.Int64 `tfsdk:"two_m"` Total types.Int64 `tfsdk:"total"` } + +type DPDKModel struct { + Bridges *Bridges `tfsdk:"bridges"` + HPMemory types.Map `tfsdk:"hp_memory"` + PMDCPU types.List `tfsdk:"pmd_cpu"` +} + +type Bridges struct { + Backplane1 *Backplane1 `tfsdk:"backplane1"` +} + +type Backplane1 struct { + Interfaces types.List `tfsdk:"interfaces"` + NumaNode types.Int64 `tfsdk:"numa_node"` +} + +type Role struct { + Actor types.String `tfsdk:"actor"` + Reason types.String `tfsdk:"reason"` + Time types.Int64 `tfsdk:"time"` +} diff --git a/internal/service/cloudbroker/node/models/model_data_source_cb_node_list.go b/internal/service/cloudbroker/node/models/model_data_source_cb_node_list.go index aaa478a..6241d11 100644 --- a/internal/service/cloudbroker/node/models/model_data_source_cb_node_list.go +++ b/internal/service/cloudbroker/node/models/model_data_source_cb_node_list.go @@ -25,44 +25,46 @@ type DataSourceNodeList struct { } type ItemNodeModel struct { - AdditionalPkgs types.List `tfsdk:"additional_pkgs"` - CpuInfo *CpuInfoModel `tfsdk:"cpu_info"` - Description types.String `tfsdk:"description"` - GID types.Int64 `tfsdk:"gid"` - GUID types.String `tfsdk:"guid"` - HostKey types.String `tfsdk:"hostkey"` - IPAddr types.List `tfsdk:"ipaddr"` - IsolatedCPUs types.List `tfsdk:"isolated_cpus"` - LastCheck types.Int64 `tfsdk:"lastcheck"` - MachineGUID types.String `tfsdk:"machine_guid"` - MainboardSN types.String `tfsdk:"mainboard_sn"` - Memory types.Int64 `tfsdk:"memory"` - Milestones types.Int64 `tfsdk:"milestones"` - Model types.String `tfsdk:"model"` - Name types.String `tfsdk:"name"` - NeedReboot types.Bool `tfsdk:"need_reboot"` - NetAddr []NetAddrModel `tfsdk:"net_addr"` - NetworkMode types.String `tfsdk:"network_mode"` - NicInfo []NicInfoModel `tfsdk:"nic_info"` - NodeUUID types.String `tfsdk:"node_uuid"` - NodeID types.Int64 `tfsdk:"node_id"` - NumaTopology *NumaTopologyModel `tfsdk:"numa_topology"` - PeerBackup types.Int64 `tfsdk:"peer_backup"` - PeerLog types.Int64 `tfsdk:"peer_log"` - PeerStats types.Int64 `tfsdk:"peer_stats"` - Pgpus types.List `tfsdk:"pgpus"` - PublicKeys types.List `tfsdk:"public_keys"` - Release types.String `tfsdk:"release"` - ReservedCPUs types.List `tfsdk:"reserved_cpus"` - Roles types.List `tfsdk:"roles"` - SEPs types.List `tfsdk:"seps"` - SerialNum types.String `tfsdk:"serial_num"` - SriovEnabled types.Bool `tfsdk:"sriov_enabled"` - StackId types.Int64 `tfsdk:"stack_id"` - Status types.String `tfsdk:"status"` - Tags types.List `tfsdk:"tags"` - Type types.String `tfsdk:"type"` - Version types.String `tfsdk:"version"` + AdditionalPkgs types.List `tfsdk:"additional_pkgs"` + CpuInfo *CpuInfoModel `tfsdk:"cpu_info"` + Description types.String `tfsdk:"description"` + DPDK *DPDKModel `tfsdk:"dpdk"` + GID types.Int64 `tfsdk:"gid"` + GUID types.String `tfsdk:"guid"` + HostKey types.String `tfsdk:"hostkey"` + IPAddr types.List `tfsdk:"ipaddr"` + IsolatedCPUs types.List `tfsdk:"isolated_cpus"` + LastCheck types.Int64 `tfsdk:"lastcheck"` + MachineGUID types.String `tfsdk:"machine_guid"` + MainboardSN types.String `tfsdk:"mainboard_sn"` + Memory types.Int64 `tfsdk:"memory"` + Milestones types.Int64 `tfsdk:"milestones"` + Model types.String `tfsdk:"model"` + Name types.String `tfsdk:"name"` + NeedReboot types.Bool `tfsdk:"need_reboot"` + NetAddr []NetAddrModel `tfsdk:"net_addr"` + NetworkMode types.String `tfsdk:"network_mode"` + NicInfo []NicInfoModel `tfsdk:"nic_info"` + NodeUUID types.String `tfsdk:"node_uuid"` + NodeID types.Int64 `tfsdk:"node_id"` + NumaTopology *NumaTopologyModel `tfsdk:"numa_topology"` + PeerBackup types.Int64 `tfsdk:"peer_backup"` + PeerLog types.Int64 `tfsdk:"peer_log"` + PeerStats types.Int64 `tfsdk:"peer_stats"` + Pgpus types.List `tfsdk:"pgpus"` + PublicKeys types.List `tfsdk:"public_keys"` + Release types.String `tfsdk:"release"` + ReservedCPUs types.List `tfsdk:"reserved_cpus"` + Roles types.List `tfsdk:"roles"` + SEPs types.List `tfsdk:"seps"` + SerialNum types.String `tfsdk:"serial_num"` + SriovEnabled types.Bool `tfsdk:"sriov_enabled"` + StackId types.Int64 `tfsdk:"stack_id"` + Status types.String `tfsdk:"status"` + Tags types.List `tfsdk:"tags"` + Type types.String `tfsdk:"type"` + UEFIFirmwareFile types.String `tfsdk:"uefi_firmware_file"` + Version types.String `tfsdk:"version"` } type NetAddrModel struct { diff --git a/internal/service/cloudbroker/node/schemas/schema_data_source_cb_node.go b/internal/service/cloudbroker/node/schemas/schema_data_source_cb_node.go index 502b50b..e9513d7 100644 --- a/internal/service/cloudbroker/node/schemas/schema_data_source_cb_node.go +++ b/internal/service/cloudbroker/node/schemas/schema_data_source_cb_node.go @@ -76,6 +76,36 @@ func MakeSchemaDataSourceNode() map[string]schema.Attribute { "cpu_allocation_ratio": schema.Int64Attribute{ Computed: true, }, + "dpdk": schema.SingleNestedAttribute{ + Computed: true, + Attributes: map[string]schema.Attribute{ + "bridges": schema.SingleNestedAttribute{ + Computed: true, + Attributes: map[string]schema.Attribute{ + "backplane1": schema.SingleNestedAttribute{ + Computed: true, + Attributes: map[string]schema.Attribute{ + "interfaces": schema.ListAttribute{ + Computed: true, + ElementType: types.StringType, + }, + "numa_node": schema.Int64Attribute{ + Computed: true, + }, + }, + }, + }, + }, + "hp_memory": schema.MapAttribute{ + Computed: true, + ElementType: types.Int64Type, + }, + "pmd_cpu": schema.ListAttribute{ + Computed: true, + ElementType: types.Int64Type, + }, + }, + }, "gid": schema.Int64Attribute{ Computed: true, }, @@ -88,7 +118,7 @@ func MakeSchemaDataSourceNode() map[string]schema.Attribute { }, "isolated_cpus": schema.ListAttribute{ Computed: true, - ElementType: types.StringType, + ElementType: types.Int64Type, }, "name": schema.StringAttribute{ Computed: true, @@ -96,6 +126,9 @@ func MakeSchemaDataSourceNode() map[string]schema.Attribute { "need_reboot": schema.BoolAttribute{ Computed: true, }, + "network_mode": schema.StringAttribute{ + Computed: true, + }, "nic_info": schema.ListNestedAttribute{ Computed: true, NestedObject: schema.NestedAttributeObject{ @@ -169,7 +202,7 @@ func MakeSchemaDataSourceNode() map[string]schema.Attribute { }, "reserved_cpus": schema.ListAttribute{ Computed: true, - ElementType: types.StringType, + ElementType: types.Int64Type, }, "roles": schema.ListAttribute{ Computed: true, @@ -184,6 +217,62 @@ func MakeSchemaDataSourceNode() map[string]schema.Attribute { "status": schema.StringAttribute{ Computed: true, }, + "to_active": schema.SingleNestedAttribute{ + Computed: true, + Attributes: map[string]schema.Attribute{ + "actor": schema.StringAttribute{ + Computed: true, + }, + "reason": schema.StringAttribute{ + Computed: true, + }, + "time": schema.Int64Attribute{ + Computed: true, + }, + }, + }, + "to_installing": schema.SingleNestedAttribute{ + Computed: true, + Attributes: map[string]schema.Attribute{ + "actor": schema.StringAttribute{ + Computed: true, + }, + "reason": schema.StringAttribute{ + Computed: true, + }, + "time": schema.Int64Attribute{ + Computed: true, + }, + }, + }, + "to_maintenance": schema.SingleNestedAttribute{ + Computed: true, + Attributes: map[string]schema.Attribute{ + "actor": schema.StringAttribute{ + Computed: true, + }, + "reason": schema.StringAttribute{ + Computed: true, + }, + "time": schema.Int64Attribute{ + Computed: true, + }, + }, + }, + "to_restricted": schema.SingleNestedAttribute{ + Computed: true, + Attributes: map[string]schema.Attribute{ + "actor": schema.StringAttribute{ + Computed: true, + }, + "reason": schema.StringAttribute{ + Computed: true, + }, + "time": schema.Int64Attribute{ + Computed: true, + }, + }, + }, "version": schema.StringAttribute{ Computed: true, }, diff --git a/internal/service/cloudbroker/node/schemas/schema_data_source_cb_node_list.go b/internal/service/cloudbroker/node/schemas/schema_data_source_cb_node_list.go index 4ce2489..59c8d85 100644 --- a/internal/service/cloudbroker/node/schemas/schema_data_source_cb_node_list.go +++ b/internal/service/cloudbroker/node/schemas/schema_data_source_cb_node_list.go @@ -75,6 +75,36 @@ func MakeSchemaDataSourceNodeList() map[string]schema.Attribute { "description": schema.StringAttribute{ Computed: true, }, + "dpdk": schema.SingleNestedAttribute{ + Computed: true, + Attributes: map[string]schema.Attribute{ + "bridges": schema.SingleNestedAttribute{ + Computed: true, + Attributes: map[string]schema.Attribute{ + "backplane1": schema.SingleNestedAttribute{ + Computed: true, + Attributes: map[string]schema.Attribute{ + "interfaces": schema.ListAttribute{ + Computed: true, + ElementType: types.StringType, + }, + "numa_node": schema.Int64Attribute{ + Computed: true, + }, + }, + }, + }, + }, + "hp_memory": schema.MapAttribute{ + Computed: true, + ElementType: types.Int64Type, + }, + "pmd_cpu": schema.ListAttribute{ + Computed: true, + ElementType: types.Int64Type, + }, + }, + }, "gid": schema.Int64Attribute{ Computed: true, }, @@ -93,7 +123,7 @@ func MakeSchemaDataSourceNodeList() map[string]schema.Attribute { }, "isolated_cpus": schema.ListAttribute{ Computed: true, - ElementType: types.StringType, + ElementType: types.Int64Type, }, "lastcheck": schema.Int64Attribute{ Computed: true, @@ -245,7 +275,7 @@ func MakeSchemaDataSourceNodeList() map[string]schema.Attribute { }, "reserved_cpus": schema.ListAttribute{ Computed: true, - ElementType: types.StringType, + ElementType: types.Int64Type, }, "roles": schema.ListAttribute{ Computed: true, @@ -274,6 +304,9 @@ func MakeSchemaDataSourceNodeList() map[string]schema.Attribute { "type": schema.StringAttribute{ Computed: true, }, + "uefi_firmware_file": schema.StringAttribute{ + Computed: true, + }, "version": schema.StringAttribute{ Computed: true, }, diff --git a/internal/service/cloudbroker/vins/flattens/flatten_data_source_vins.go b/internal/service/cloudbroker/vins/flattens/flatten_data_source_vins.go index fc0cb0d..1434c13 100644 --- a/internal/service/cloudbroker/vins/flattens/flatten_data_source_vins.go +++ b/internal/service/cloudbroker/vins/flattens/flatten_data_source_vins.go @@ -337,10 +337,11 @@ func flattenReservations(ctx context.Context, items *vins.ListReservations) type tempSlice := make([]types.Object, 0, len(*items)) for _, item := range *items { temp := models.ReservationModel{ - IP: types.StringValue(item.IP), - MAC: types.StringValue(item.MAC), - Type: types.StringValue(item.Type), - VMID: types.Int64Value(int64(item.VMID)), + AccountID: types.Int64Value(int64(item.AccountID)), + IP: types.StringValue(item.IP), + MAC: types.StringValue(item.MAC), + Type: types.StringValue(item.Type), + VMID: types.Int64Value(int64(item.VMID)), } obj, diags := types.ObjectValueFrom(ctx, models.ItemReservations, temp) diff --git a/internal/service/cloudbroker/vins/models/model_data_source_vins.go b/internal/service/cloudbroker/vins/models/model_data_source_vins.go index 6eb2be3..55fab3a 100644 --- a/internal/service/cloudbroker/vins/models/model_data_source_vins.go +++ b/internal/service/cloudbroker/vins/models/model_data_source_vins.go @@ -175,10 +175,11 @@ type RecordDHCPConfigModel struct { } type ReservationModel struct { - IP types.String `tfsdk:"ip"` - MAC types.String `tfsdk:"mac"` - Type types.String `tfsdk:"type"` - VMID types.Int64 `tfsdk:"vm_id"` + AccountID types.Int64 `tfsdk:"account_id""` + IP types.String `tfsdk:"ip"` + MAC types.String `tfsdk:"mac"` + Type types.String `tfsdk:"type"` + VMID types.Int64 `tfsdk:"vm_id"` } type RecordNATModel struct { @@ -375,10 +376,11 @@ var ItemDHCPConfig = map[string]attr.Type{ } var ItemReservations = map[string]attr.Type{ - "ip": types.StringType, - "mac": types.StringType, - "type": types.StringType, - "vm_id": types.Int64Type, + "account_id": types.Int64Type, + "ip": types.StringType, + "mac": types.StringType, + "type": types.StringType, + "vm_id": types.Int64Type, } var ItemGW = map[string]attr.Type{ diff --git a/internal/service/cloudbroker/vins/schemas/schema_data_source_vins.go b/internal/service/cloudbroker/vins/schemas/schema_data_source_vins.go index 22410ed..4fb2a62 100644 --- a/internal/service/cloudbroker/vins/schemas/schema_data_source_vins.go +++ b/internal/service/cloudbroker/vins/schemas/schema_data_source_vins.go @@ -333,6 +333,9 @@ func MakeSchemaDataSourceVINS() map[string]schema.Attribute { Computed: true, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ + "account_id": schema.Int64Attribute{ + Computed: true, + }, "ip": schema.StringAttribute{ Computed: true, }, diff --git a/samples/cloudapi/kvmvm/resource_kvmvm/main.tf b/samples/cloudapi/kvmvm/resource_kvmvm/main.tf index edf7c55..d8bb454 100644 --- a/samples/cloudapi/kvmvm/resource_kvmvm/main.tf +++ b/samples/cloudapi/kvmvm/resource_kvmvm/main.tf @@ -229,7 +229,7 @@ resource "dynamix_kvmvm" "comp" { #тип сети #обязательный параметр #тип - строка - #возможные значения - "VINS", "EXTNET", "VFNIC", "DPDK" + #возможные значения - "VINS", "EXTNET", "VFNIC", "DPDK" (при выборе типа DPDK, необходимо указать hp_backed = true) net_type = "VINS" #id сети @@ -345,6 +345,12 @@ resource "dynamix_kvmvm" "comp" { cdrom_id = 344 } + #список ядер для использования в механизме vcpupinning. Количество указанных ядер должно быть равно количеству виртуальных процессоров ВМ + #игнорируется если cpu_pin=false или pin_to_stack=false + #опциональный параметр + #тип - массив целых чисел + preferred_cpu = [1234, 456] + #добавить компьют на стэк #опциональный параметр #тип - булев diff --git a/wiki/1.2.1/01.-Введение.md b/wiki/1.2.1/01.-Введение.md new file mode 100644 index 0000000..1230878 --- /dev/null +++ b/wiki/1.2.1/01.-Введение.md @@ -0,0 +1,7 @@ +DYNAMIX Terraform Provider версии 1.2.x позволяет управлять облачными ресурсами на платформе DYNAMIX версии 4.2.x и выше посредством Terraform. + +С помощью данного провайдера можно организовать программное управление вычислительными ресурсами (_compute_), ресурсными группами, сетевыми и дисковыми ресурсами, образами дисков, кластером, а также другими параметрами облачной платформы DYNAMIX. + +Если вы хорошо знакомы с инструментом Terraform и хотите максимально быстро начать использовать платформу DYNAMIX в своих Terraform-проектах, то можете сразу перейти к разделу [Пример работы](https://repository.basistech.ru/BASIS/terraform-provider-dynamix/src/branch/main/wiki/1.2.1/02.-Пример-работы.md), где приведён подробно откомментированный пример работы с основными видами ресурсов платформы. Если у вас всё же возникнут вопросы по облачной платформе DYNAMIX и порядку авторизации в ней, то обратитесь к главе [«Обзор облачной платформы DYNAMIX»](https://repository.basistech.ru/BASIS/terraform-provider-dynamix/src/branch/main/wiki/1.2.1/03.-Обзор-облачной-платформы-DYNAMIX.md). Также может оказаться полезной глава [«Инициализация Terraform провайдера DYNAMIX»](https://repository.basistech.ru/BASIS/terraform-provider-dynamix/src/branch/main/wiki/1.2.1/04.02-Инициализация-Terraform-провайдера-DYNAMIX.md). + +Если вы только начинаете использовать инструмент Terraform и облачную платформу DYNAMIX, то рекомендуем вам начать с главы [«Обзор облачной платформы DYNAMIX»](https://repository.basistech.ru/BASIS/terraform-provider-dynamix/src/branch/main/wiki/1.2.1/03.-Обзор-облачной-платформы-DYNAMIX.md), после чего изучить главы [«_Data source_ функции Terraform провайдера DYNAMIX»](https://repository.basistech.ru/BASIS/terraform-provider-dynamix/src/branch/main/wiki/1.2.1/06.-Data-source-функции-Terraform-провайдера-DYNAMIX.md) и [«_Resource_ функции Terraform провайдера DYNAMIX»](https://repository.basistech.ru/BASIS/terraform-provider-dynamix/src/branch/main/wiki/1.2.1/07.-Resource-функции-Terraform-провайдера-dynamix.md). Примеры, приведенные в этих разделах, помогут вам быстро освоить базовые приёмы работы с инструментом Terraform и провайдером DYNAMIX. diff --git a/wiki/1.2.1/02.-Пример-работы.md b/wiki/1.2.1/02.-Пример-работы.md new file mode 100644 index 0000000..580ba75 --- /dev/null +++ b/wiki/1.2.1/02.-Пример-работы.md @@ -0,0 +1,92 @@ +Данный раздел предназначен для тех, кто хорошо знаком с инструментом Terraform, а также имеет представление об основных понятиях и способах авторизации в облачной платформе DYNAMIX. + +Ниже приведён подробно откомментированный пример, показывающий, как создать виртуальный сервер (aka _compute_ на базе системы виртуализации KVM x86) в облачной платформе DYNAMIX с помощью соответствующего Terraform провайдера. Сервер будет создан в новой ресурсной группе, к нему будет подключён один предварительно созданный диск, у сервера будет прямое сетевое подключение во внешнюю сеть. + +Идентификатор образа операционной системы, на базе которого должен быть создан виртуальный сервер, считывается из облачной платформы с помощью _data source_ функции `dynamix_image`. + +Далее мы с помощью _resource_ функции `dynamix_resgroup` создаём новую ресурсную группу, в которую будет помещён этот виртуальный сервер. В качестве альтернативы, для получения информации об уже имеющейся ресурсной группе можно использовать _data source_ функцию с таким же названием. + +Затем с помощью _resource_ функции `dynamix_disk` создаётся диск, который будет подключён к виртуальному серверу в качестве дополнительного. Помимо этого дополнительного диска у сервера будет также и загрузочный диск, на который в процессе создания сервера клонируется выбранный образ операционной системы. + +Виртуальный сервер - в данном примере на базе системы виртуализации KVM x86 - создаётся посредством _resource_ функции `dynamix_kvmvm`. + +Только авторизованные в контроллере облачной платформы пользователи могут управлять облачными ресурсами. Подробнее о способах авторизации см. [Обзор облачной платформы DYNAMIX](https://repository.basistech.ru/BASIS/terraform-provider-dynamix/src/branch/main/wiki/1.2.1/03.-Обзор-облачной-платформы-DYNAMIX.md). + +```terraform +# 1. Initialize DYNAMIX plugin and connection to DYNAMIX cloud controller +# NOTE: in this example credentials are expected to come from +# DYNAMIX_APP_ID and DYNAMIX_APP_SECRET environmental variables - set them +# in the shell before calling terraform. +# Alternatively you may define plugin parameters app_id and app_secret in +# the TF file, however, this may not be secure if you plan to share this TF +# file with others. + +provider "dynamix" { + authenticator = "decs3o" + controller_url = "<>" # specify correct DYNAMIX controller URL, e.g. "https://ds1.digitalenergy.online" + oauth2_url = "<>" # specify corresponding DYNAMIX OAUTH2 URL, e.g. "https://sso.digitalenergy.online" + app_id = "<>" # application secret to access DYNAMIX cloud API in 'decs3o' and 'bvs' authentication mode, e.g. "ewqfrvea7s890avw804389qwguf234h0otfi3w4eiu" + app_secret = "<>" # application ID to access DYNAMIX cloud API in 'decs3o' and 'bvs' authentication mode, e.g. "ewqfrvea7s890avw804389qwguf234h0otfi3w4eiu" + # allow_unverified_ssl = true +} + +# 2. Load account to use - new VM will belong to this account +data "dynamix_account" "my_account" { + account_id = # Specify account ID +} + +# 3. Load OS image to use for VM deployment +data "dynamix_image" "os_image" { + image_id = # Specify OS image id, e.g. 1234. You can get accessible image id from data source "dynamix_image_list" +} + +# 4. Create new Resource Group in the selected account, new VM will be created in this RG +resource "dynamix_resgroup" "my_rg" { + name = "NewRgByTF" + account_id = data.dynamix_account.my_account.account_id + gid = # Grid (platform) ID + # if you want to set resource quota on this Resource Group, uncomment + # the following code fragment + # quota { + # cpu = 8 # CPU limit + # ram = 8912 # RAM limit in MB + # disk = 96 # disk volume limit in GB + #} +} + +# 5. Create extra disk, which will be attached to the new VM. +# This step is optional - if you do not want extra disks on your VM, skip it +# and comment out extra_disks parameter when creating VM below. +resource "dynamix_disk" "extra_disk" { + disk_name = "extra-disk-for-vm" + account_id = data.dynamix_account.my_account.account_id + gid = # Grid (platform) ID + size_max = 5 # disk size in GB + type = "D" # disk type, always use "D" for extra disks + sep_id = data.dynamix_image.os_image.sep_id # use the same SEP ID as the OS image + pool = "<>" # consult your DYNAMIX platform admin for configured storage pool names +} + +# 6. Create virtual machine (a compute of type KVM VM x86 in this example) +# Now that we have all necessary components at hand, we may create a virtual machine. +# This VM will be based on the previsouly obtained OS image, located in the specified +# Resource Group, directly connected to an external network, have a boot disk of +# specified size and one extra disk attached. +resource "dynamix_kvmvm" "my_new_vm" { + name = "tf-managed-vm" + driver = "KVM_X86" # Compute virtualization driver + rg_id = dynamix_resgroup.my_rg.id + cpu = 1 # CPU count + ram = 1024 # RAM size in MB, must be even number, ideally a power of 2 + boot_disk_size = 10 # Boot disk size in GB + image_id = data.dynamix_image.os_image.image_id + description = "Test KVM VM Compute managed by Terraform" + extra_disks = [ dynamix_disk.extra_disk.id ] + + network { + net_type = "EXTNET" + net_id = <> # specify external network ID to use, consult your DYNAMIX platform admin for correct IDs + # ip_address = "<>" # you may optionally request a specific IP address + } +} +``` diff --git a/wiki/1.2.1/03.-Обзор-облачной-платформы-DYNAMIX.md b/wiki/1.2.1/03.-Обзор-облачной-платформы-DYNAMIX.md new file mode 100644 index 0000000..ecd19c9 --- /dev/null +++ b/wiki/1.2.1/03.-Обзор-облачной-платформы-DYNAMIX.md @@ -0,0 +1,32 @@ +## Основные понятия +Ниже перечислены основные понятия с указанием соответствующих им аргументов в Terraform провайдере DYNAMIX. +1. **Контроллер облачной платформы DYNAMIX** – управляющее приложение, которое обеспечивает авторизацию пользователей и оркестрацию облачных ресурсов. + - Адрес контроллера задается в обязательном аргументе `controller_url` на стадии инициализации Terraform провайдера DYNAMIX. Например, `controller_url= "https://ds1.digitalenergy.online"` +2. **Авторизационный провайдер** – приложение, работающее по протоколу Oauth2, предназначенное для выпуска и валидации токенов доступа к контроллеру облачной платформы в соответствующих режимах авторизации. Все действия в платформе должны выполняться авторизованными пользователями, и авторизационное приложение позволяет получить токен доступа, действующий некоторое ограниченное время, наличие которого подтверждает успешную авторизацию. + - Адрес авторизационного провайдера задается в аргументе`oauth2_url` на стадии инициализации Terraform провайдера DYNAMIX. Например `oauth2_url= "https://sso.digitalenergy.online"` +3. **Подписчик** (_account_) – сущность, которая используется для группирования облачных ресурсов по принадлежности к определенному клиенту для целей учета потребления и биллинга. + - Имя подписчика задается аргументом `account_name` при вызове _resource_ или _data_ функций провайдера. Альтернативной является задание численного идентификатора подписчика в аргументе `account_id`. +4. **Пользователь** (_user_) – пользователь облачной инфраструктуры, представленный учетной записью. Чтобы получить возможность управлять облачными ресурсами (например, создавать виртуальные серверы или дискт) пользователь должен быть ассоциирован с одним или несколькими подписчиками и иметь соответствующие права, определяемые ролевой моделью, принятой в облачной платформе DYNAMIX. Для доступа к платформе пользователь должен авторизоваться одним из способов, описанных ниже в разделе «Способы авторизации». +5. **Ресурсная группа** (_resource group_) – способ группирования вычислительных ресурсов (например, виртуальных серверов по функциональному признаку или принадлежности к одному и тому же проекту). Ресурсную группу можно рассматривать как небольшой персональный дата-центр, в котором размещаются один или несколько серверов и виртуальных сетевых сегментов. Ресурсная группа идентифицируется по комбинации параметров `account` и `name`. Обратите внимание, что имя имя ресурсной группы уникально только в рамках одного и того же `account`. +6. **Вычислительный ресурс** (_compute_) - универсальная абстракция пользовательского сервера в платформе DYNAMIX. Благодаря использованию такой абстракции можно, например, создать одну виртуальную машину на базе KVM Intel x86, а другую - на базе KVM IBM Power, а потом управлять ими - изменять количество CPU/RAM, подключать/отключать диски и т.п. - одинаковым образом, не задумываясь об их архитектурных различиях. В то же время, так как типизация ресурсов в Terraform не поддерживает наследование, различные типы вычислительных ресурсов, доступных на платформе DYNAMIX и абстрагируемых через понятие унифицированный _compute_, в Terraform представлены разными типами (напр., свой тип для виртуальных серверов на базе KVM и свой тип для перспективных x86-совместимых bare metal серверов). +7. **Ресурс хранения** (_disk_) - универсальная абстракция дискового ресурса в платформе DYNAMIX. Платформа поддерживает различные типы систем хранения данных, но при этом управление созданными на разных системах хранения дисками осуществляется посредством унифицированного набора действий, например, "подключить диск к _compute_", "увеличить размер диска", "сделать мгновенный снимок диска", "настроить параметры быстродействия диска". +8. **Виртуальный сервер** – экземпляр _compute_, в основе технической реализации которого лежит виртуальная машина, работающая в облаке и доступна по сети. Виртуальный сервер характеризуется количеством выделенных ему CPU (аргумент`cpu`), объемом ОЗУ (`ram`), размером загрузочного диска (`boot_disk size`). При создании виртуального сервера на загрузочный диск устанавливается образ операционной системы, заданный в аргументе `image_id`. Помимо загрузочного диска к виртуальному серверу можно подключить несколько дисков для хранения прикладных данных, список которых задается аргументами `extra_disks`. Виртуальный сервер идентифицируется по комбинации аргументов `name` (имя сервера) и `rgid` (идентификатор ресурсной группы). Обратите внимание, что имя виртуального сервера `name` уникально только в рамках одной и той же ресурсной группы. +9. **Виртуальный сетевой сегмент** (_Virtual Network Segment_ или _ViNS_) - сетевой сегмент и обеспечивающая его функционирование виртуальная инфраструктура, которые пользователь может создавать для своих нужд на уровне ресурсной группы или подписчика (_account_). ViNS можно создать полностью изолированным от внешних сетей (см. ниже _External Network_) или с подключением во внешнюю сеть. Внутри ViNS работает DHCP-сервис, обеспечивающий управление IP адресами экземпляров _compute_, подключённых в этот ViNS. +10. **Внешняя сеть** (_External Network_) - сетевой сегмент, через который платформа DYNAMIX взаимодействует с внешними по отношению к ней сетевыми ресурсами. Например, в случае с публичным облаком на базе DYNAMIX в качестве внешней сети выступает сеть Интернет. В отличие от ViNS платформа не управляет внешней сетью, а лишь пользуется её ресурсами. В платформе может быть настроено несколько внешних сетей с различными диапазонами IP адресов, и существует механизм управления доступом пользователей к внешним сетям. +11. Сетевой доступ к экземпляру _compute_ (виртуальному серверу) реализуется через его подключение к ViNS и/или прямое подключение во внешнюю сеть (External Network). Один и тот же экземпляр _compute_ может одновременно иметь несколько подключений в разные ViNS и/или различные внешние сети. + +## Способы авторизации +Облачная платформа DYNAMIX поддерживает три базовых типа авторизации: +1. С использованием авторизационного провайдера, работающего по протоколу _Oauth2_. Данный способ является предпочтительным, так как обеспечивает бОльшую гибкость и безопасность. Для авторизации в этом режиме при инициализации Terrafrom провайдера DYNAMIX необходимо указать параметры `oauth2_url` и `controller_url`, а также предоставить одно из нижеперечисленного: + - Комбинация Application ID & Application secret, соответствующих пользователю, от имени которого будет осуществляться управление облачными ресурсами в текущей сессии. В процессе проверки предоставленных Application ID & Application secret модуль получает от авторизационного провайдера токен (JSON Web Token, JWT), который затем используется для доступа к указанному контроллеру DYNAMIX. Для авторизации по данному варианту, при инициализации Terraform провайдера DYNAMIX следует установить аргумент `authenticator=decs3o` и задать аргументы `app_id` и `app_secret` (или определить соответствующие переменные окружения `DYNAMIX_APP_ID` и `DYNAMIX_APP_SECRET`). + - JSON Web Token – заранее полученный от авторизационного провайдера токен доступа, ассоциированный с определенным пользователем, от имени которого будет осуществляться управление облачными ресурсами в текущей сессии. Для авторизации по данному варианту, при инициализации Terraform провайдера DYNAMIX следует установить аргумент `authenticator=jwt` и задать аргумент `jwt` (или определить переменную окружения `DYNAMIX_JWT`). +2. С использованием комбинации _имя пользователя : пароль_. Данный режим не использует внешних авторизационных провайдеров и подразумевает, что пользователь с такой комбинацией зарегистрирован непосредственно на указанном в параметре `controller_url` контроллере облачной платформы DYNAMIX. + - Чтобы провайдер авторизовался по данному варианту, при его инициализации следует установить аргумент `authenticator=legacy` и задать аргументы `user` и `password` (или определить соответствующие переменные окружения `DYNAMIX_USER` и `DYNAMIX_PASSWORD`). +3. С использованием авторизационного провайдера, работающего по протоколу _Oauth2_oidc_. Для авторизации в этом режиме при инициализации Terrafrom провайдера DYNAMIX необходимо указать параметры `oauth2_url` и `controller_url`, а также Application ID & Application secret, _имя пользователя и пароль_, соответствующих пользователю, от имени которого будет осуществляться управление облачными ресурсами в текущей сессии, и _имя домена_. В процессе проверки предоставленных Application ID & Application secret и пары _имя пользователя-пароль_ модуль получает от авторизационного провайдера токен (JSON Web Token, JWT), который затем используется для доступа к указанному контроллеру DYNAMIX. Для авторизации по данному варианту, при инициализации Terraform провайдера DYNAMIX следует установить аргумент `authenticator=bvs`, задать аргументы `app_id` и `app_secret` (или определить соответствующие переменные окружения `DYNAMIX_APP_ID` и `DYNAMIX_APP_SECRET`), `bvs_user` и `bvs_password` (или определить соответствующие переменные окружения `DYNAMIX_BVS_USER` и `DYNAMIX_BVS_PASSWORD`), а также указать `domain` (или определить соответствующие переменные окружения `DYNAMIX_DOMAIN`). + +После успешной авторизации пользователь (или приложение-клиент) получает доступ к ресурсам, находящимся под управлением соответствующего DYNAMIX контроллера. Доступ предоставляется в рамках подписчиков (_account_), с которыми ассоциирован данный пользователь (_user_), и в соответствии с присвоенными ему ролями. + +## Пользовательская и административная группы API +Пользовательская группа API - группа API платформы DYNAMIX, которая позволяет выполнять операции с платформой с правами обычного пользователя. Покрывает большую часть задач. +Административная группа API - группа API платформы DYNAMIX, которая позволяет выполнять операции с платформой с расширенными правами. Данные права подразумевают расширенный перечень операций над ресурсами, расширенный перечень ресурсов, расширенную информацию. Требуются права администратора для взаимодействия с этой группой API. +В Terraform провайдере DYNAMIX версии 1.2.1 реализованы функции только пользовательской группа API. diff --git a/wiki/1.2.1/04.-Начало-работы-с-terraform-провайдером-DYNAMIX.md b/wiki/1.2.1/04.-Начало-работы-с-terraform-провайдером-DYNAMIX.md new file mode 100644 index 0000000..edaa664 --- /dev/null +++ b/wiki/1.2.1/04.-Начало-работы-с-terraform-провайдером-DYNAMIX.md @@ -0,0 +1,6 @@ +Данный раздел описывает: +- Системные требования +- Установку провайдера +- Инициализацию провайдера +- Переключение режима работы между разными группами API +- Получение gid/grid_id площадки diff --git a/wiki/1.2.1/04.01-Установка-Terraform-провайдера-DYNAMIX.md b/wiki/1.2.1/04.01-Установка-Terraform-провайдера-DYNAMIX.md new file mode 100644 index 0000000..8c96fd4 --- /dev/null +++ b/wiki/1.2.1/04.01-Установка-Terraform-провайдера-DYNAMIX.md @@ -0,0 +1,147 @@ +## Системные требования + +Для запуска провайдера вам потребуется машина, на которой установлен Terraform. + +Кроме того, в связи с тем, что начиная с версии 0.12 Terraform изменил алгоритм поиска и инициализации локальных провайдеров, настройка данного провайдера для работы с Terraform 0.12 или более новыми версиями потребует выполнения ряда дополнительных действий. Подробнее см. [8.3 Настройка локального провайдера для работы с новыми версиями Terraform](https://repository.basistech.ru/BASIS/terraform-provider-dynamix/src/branch/main/wiki/1.2.1/08.-Полезные-советы.md#8-3-настройка-локального-провайдера-для-работы-с-новыми-версиями-terraform). + +## Установка +В релизном архиве находятся скрипты-инсталляторы. +Чтобы выполнить установку, необходимо: +1. Перейти по адресу: https://repository.basistech.ru/BASIS/terraform-provider-dynamix/releases +2. Выбрать необходимую версию провайдера подходящую под операционную систему. +3. Скачать архив. +4. Распаковать архив. +5. Выполнить скрипт установщика, `install.sh` или `install.bat` для Windows.
+*Для запуска `install.sh` не забудьте изменить права доступа к файлу* +```bash +chmod u+x install.sh +``` +6. Дождаться сообщения об успешной установке. Установщик выведет актуальный блок конфигурации провайдера, скопируйте его +```bash +terraform { + required_providers { + dynamix = { + version = "1.2.1" + source = "basistech.ru/tf/dynamix" + } + } +} +``` +7. После этого, создайте файл `main.tf` в рабочей директории, которая может находится в любом удобном для пользователя месте. +В данном примере, рабочая директория с файлом main.tf находится по пути: +```bash +~/work/tfdir/main.tf +``` +8. Вставьте в `main.tf` блок конфигурации провайдера, который был выведен на экран установщиком: +```terraform +terraform { + required_providers { + dynamix = { + version = "1.2.1" + source = "basistech.ru/tf/dynamix" + } + } +} +``` +9. Добавьте в файл блок с инициализацией провайдера. +```terraform +provider "dynamix" { + authenticator = "decs3o" + controller_url = "https://mr4.digitalenergy.online" + oauth2_url = "https://sso.digitalenergy.online" + allow_unverified_ssl = true +} +``` + +10. В консоли выполните команду +```bash +terraform init +``` + +11. В случае успешной установки, Terraform инициализирует провайдер и будет готов к дальнейшей работе. + +## Установка из релизов +Terraform провайдер DYNAMIX имеет скомпилированные релизные версии, которые расположены по адресу: [Релизы](https://repository.basistech.ru/BASIS/terraform-provider-dynamix/releases). +Чтобы выполнить установку из релиза, необходимо: +1. Перейти по адресу: https://repository.basistech.ru/BASIS/terraform-provider-dynamix/releases +2. Выбрать необходимую версию провайдера подходящую под операционную систему. +3. Скачать архив. +4. Распаковать архив. +5. Полученный файл (в директории `bin/`) необходимо поместить: +Linux: +```bash +~/.terraform.d/plugins/${host_name}/${namespace}/${type}/${version}/${target} +``` +Windows: +```powershell +%APPDATA%\terraform.d\plugins\${host_name}\${namespace}\${type}\${version}\${target} +``` +Где: +- host_name - имя хоста, держателя провайдера, например, basis +- namespace - пространство имен хоста, например decort +- type - тип провайдера, может совпадать с пространством имен, например, decort +- version - версия провайдера, например 4.3.0 +- target - архитектура операционной системы, например windows_amd64 + +В примере ниже используется путь до провайдера на машине с ОС Linux: + +```bash +~/.terraform.d/plugins/basis/basistech.ru/tf/dynamix/1.2.1/linux_amd64/tf-provider + ^ ^ ^ ^ ^ ^ + host_name | | | | | | + | | | | | + namespace | | | | | + | | | | + type | | | | + | | | + version | | | + | | + target | | + | + исполняемый файл | +``` + +6. После этого, создайте файл `main.tf` в рабочей директории, которая может находится в любом удобном для пользователя месте. +В данном примере, рабочая директория с файлом main.tf находится по пути: +```bash +~/work/tfdir/main.tf +``` +7. Добавьте в `main.tf` следующий блок +```terraform +terraform { + required_providers { + dynamix = { + source = "basistech.ru/tf/dynamix" + version = "1.2.1" + } + } +} +``` +В поле `version` указывается версия провайдера. +
+**ВНИМАНИЕ: Версии в блоке и в пути к исполняемому файлу провайдера должны совпадать!** + +В поле `source` помещается путь до репозитория с версией вида: + +```bash +${host_name}/${namespace}/${type} +``` + +**ВНИМАНИЕ: Версии в блоке и в пути к исполняемому файлу провайдера должны совпадать!** + +8. Добавьте в файл блок с инициализацией провайдера. +```terraform +provider "dynamix" { + authenticator = "decs3o" + controller_url = "https://mr4.digitalenergy.online" + oauth2_url = "https://sso.digitalenergy.online" + allow_unverified_ssl = true +} +``` + +9. В консоли выполните команду +```bash +terraform init +``` + +10. В случае успешной установки, Terraform инициализирует провайдер и будет готов к дальнейшей работе. diff --git a/wiki/1.2.1/04.02-Инициализация-Terraform-провайдера-DYNAMIX.md b/wiki/1.2.1/04.02-Инициализация-Terraform-провайдера-DYNAMIX.md new file mode 100644 index 0000000..6ec8a9c --- /dev/null +++ b/wiki/1.2.1/04.02-Инициализация-Terraform-провайдера-DYNAMIX.md @@ -0,0 +1,64 @@ +## Список аргументов для инициализации +Перед началом использования любой Terraform провайдер должен быть инициализирован. + +В процессе инициализации Terraform провайдера DYNAMIX проверяется корректность переданных аргументов и выполняется авторизация в указанном контроллере облачной инфраструктуры. Подробнее о способах авторизации в платформе DYNAMIX смотри соответствующий [раздел](https://repository.basistech.ru/BASIS/terraform-provider-dynamix/src/branch/main/wiki/1.2.1/03.-Обзор-облачной-платформы-DYNAMIX.md#способы-авторизации). + +При инициализации Terraform провайдера DYNAMIX используются следующие аргументы: + +| Аргумент | Переменная окружения | Описание | +| --- | --- | --- | +| allow_unverified_ssl | - | Если данный аргумент явно установлен в `true`, то провайдер **не будет** проверять SSL сертификаты при взаимодействии с авторизационным сервисом OAuth2 и контроллером облачной платформы.
Отключение проверок может быть полезным при работе в доверенной среде, использующей самоподписанные SSL сертификаты. Однако, так как отключение проверок несёт потенциальные риски безопасности, данную настройку следует использовать с осторожностью.
Разрешённые значения: `false` (значение по умолчанию) и `true`. | +| app_id | DYNAMIX_APP_ID | Идентификатор приложения (клиента) для авторизации в контроллере облачной платформы в режиме `decs3o` или `bvs`.
Аргументы `app_id` и `app_secret` являются обязательными для режимов авторизации `authenticator=decs3o` и `authenticator=bvs`.
Если `app_id` не задан в tf-файле, то провайдер будет использовать значение из переменной окружения `DYNAMIX_APP_ID`. | +| app_secret | DYNAMIX_APP_SECRET | Секретный код приложения (клиента) для авторизации в контроллере облачной платформы в режиме `decs3o` или `bvs`.
Аргументы `app_id` и `app_secret` являются обязательными для режимов авторизации `authenticator=decs3o` и `authenticator=bvs`.
Если `app_secret` не задан в tf-файле, то провайдер будет использовать значение из переменной окружения `DYNAMIX_APP_SECRET`. | +| authenticator | - | Режим авторизации при подключении к контроллеру облачной платформы.
Доступные режимы: `decs3o`, `legacy`, `jwt` или `bvs`.
Данный аргумент является обязательным. | +| bvs_user | DYNAMIX_BVS_USER | Имя пользователя для авторизации в контроллере облачной платформы в режиме `bvs`.
Аргументы `bvs_password` и `bvs_user` являются обязательными для режима авторизации `authenticator=bvs`.
Если `bvs_user` не задан в tf-файле, то провайдер будет использовать значение из переменной окружения `DYNAMIX_BVS_USER`. | +| bvs_password | DYNAMIX_BVS_PASSWORD | Пароль пользователя для авторизации в контроллере облачной платформы в режиме `bvs`.
Аргументы `bvs_user` и `bvs_password` являются обязательными для режима авторизации `authenticator=bvs`.
Если `bvs_password` не задан в tf-файле, то провайдер будет использовать значение из переменной окружения `DYNAMIX_BVS_PASSWORD`. | +| domain | DYNAMIX_DOMAIN | Имя домена в контроллере облачной платформы в режиме `bvs`.
Данный аргумент является обязательным.
Если `domain` не задан в tf-файле, то провайдер будет использовать значение из переменной окружения `DYNAMIX_DOMAIN`. | +| controller_url | DYNAMIX_CONTROLLER_URL | URL контроллера облачной платформы, через который будет осуществляться управление облачными ресурсами.
Данный аргумент является обязательным. | +| jwt | DYNAMIX_JWT | JSON Web Token (JWT), который используется для авторизации в контроллере облачной платформы в режиме `jwt`.
Данный аргумент является обязательным для режима авторизации `authenticator=jwt`.
Если `jwt` не задан в tf-файле, то провайдер будет использовать значение из переменной окружения `DYNAMIX_JWT` | +| oauth2_url | DYNAMIX_OAUTH2_URL | URL авторизационного сервиса OAuth2, который используется для управления доступом пользователей (или программных клиентов) к контроллеру облачной платформы.
Данный аргумент является обязательным для режимов авторизации `authenticator=decs3o`, `authenticator=bvs` и `authenticator=jwt`.
Если `oauth2_url` не задан в tf-файле, то провайдер будет использовать значение из переменной окружения `DYNAMIX_OAUTH2_URL` | +| password | DYNAMIX_PASSWORD | Пароль для авторизации в контроллере облачной платформы в режиме `legacy`.
Аргументы `password` и `user` являются обязательными для режима авторизации `authenticator=legacy`.
Если `password` не задан в tf-файле, то провайдер будет использовать значение из переменной окружения `DYNAMIX_PASSWORD`. | +| user | DYNAMIX_USER | Имя пользователя для авторизации в контроллере облачной платформы в режиме `legacy`.
Аргументы `user` и `password` являются обязательными для режима авторизации `authenticator=legacy`.
Если `user` не задан в tf-файле, то провайдер будет использовать значение из переменной окружения `DYNAMIX_USER`. | + +## Пример инициализации в режиме авторизации `decs3o` +Пример инициализации Terraform провайдера DYNAMIX: +```terraform +provider "dynamix" { + authenticator = "decs3o" + controller_url = "https://ctrl.decort.online" + oauth2_url = "https://oauth2.decort.online:7777" +} +``` + +В данном примере используется режим авторизации `decs3o`. + +Как отмечено выше, в данном режиме требуется указать аргументы `app_id` и `app_secret`, идентифицирующие пользователя (или приложение-клиент), от лица которого будут выполняться дальнейшие действия. Однако, так как данная информация является конфиденциальной (по сути, она эквивалентна паре _имя пользователя : пароль_), то в общем случае заносить такого рода данные в tf-файл не следует. Рекомендуется определять в среде запуска Terraform переменные окружения `DYNAMIX_APP_ID` и `DYNAMIX_APP_SECRET`, из которых провайдер извлечёт нужные данные. Приведенный пример подразумевает, что нужная информация будет получена из этих переменных окружения. + +Пользователь, от лица которого Terrafrom будет выполнять действия в облачной платформе, должен заранее создать пару _Application ID_ и _Application Secret_ в авторизационном приложении OAuth2. Именно эти значения, а также URL авторизационного приложения Oauth2, должны присваиваться аргументам `app_id`, `app_secret` и `oauth2_url` соответственно для успешной инициализации провайдера. + +Также обратите внимание на формат задания аргументов `controller_url` и `oauth2_url`. В общем случае они должны содержать идентификатор протокола (_https://_) и сетевой порт, если он отличается от порта по умолчанию (в примере для авторизационного сервиса OAuth2 указан порт _7777_). Эту информацию вы можете узнать у администратора вашей облачной инфраструктуры. + +## Пример инициализации в режиме авторизации `bvs` +Пример инициализации Terraform провайдера DYNAMIX: +```terraform +provider "dynamix" { + authenticator = "bvs" + controller_url = "https://delta.qa.loc" + oauth2_url = "https://bvs-delta.qa.loc:8443" + app_id = "delta" + app_secret = "" + bvs_password = "" + bvs_user = "" + domain = "dynamix" +} +``` + +В данном примере используется режим авторизации `bvs`. + +Как отмечено выше, в данном режиме требуется указать аргументы `app_id` - идентификатор площадки - delta, alpha, poc, etc. Можно найти на странице администратора по следующему пути: вкладка безопасность - клиентские сервисы - наименование площадки. `app_secret` - пароль площадки. Можно найти на странице администратора по следующему пути: вкладка безопасность - клиентские сервисы - наименование площадки (символ i) - поле "Пароль". Однако, так как данная информация является конфиденциальной, то в общем случае заносить такого рода данные в tf-файл не следует. Рекомендуется определять в среде запуска Terraform переменные окружения `DYNAMIX_APP_ID` и `DYNAMIX_APP_SECRET`, из которых провайдер извлечёт нужные данные. Приведенный пример подразумевает, что нужная информация будет получена из этих переменных окружения. +Также обязательными аргументами являются: `bvs_user` - имя пользователя, `bvs_password` - пароль пользователя. Рекомендуется не заносить их в tf-файл, а определять в среде запуска Terraform переменные окружения `DYNAMIX_BVS_USER` и `DYNAMIX_BVS_PASSWORD`, из которых провайдер извлечёт нужные данные. Приведенный пример подразумевает, что нужная информация будет получена из этих переменных окружения. +Домен для подключения `domain` - указывается наименование площадки. Данный аргумент является обязательным. Рекомендуется не заносить его в tf-файл, а определять в среде запуска Terraform переменную окружения `DYNAMIX_DOMAIN`, из которой провайдер извлечёт нужные данные. Приведенный пример подразумевает, что нужная информация будет получена из этих переменных окружения. + +Пользователь, от лица которого Terrafrom будет выполнять действия в облачной платформе, должен заранее получить от администратора _Application ID_ и _Application Secret_, _bvs user_ и _bvs password_, а также _domain_. А также осуществить первичный вход на платформу посредством браузера. + +Также обратите внимание на формат задания аргументов `controller_url` и `oauth2_url`. В общем случае они должны содержать идентификатор протокола (_https://_) и сетевой порт, если он отличается от порта по умолчанию (в примере для авторизационного сервиса OAuth2 указан порт _8443_). Эту информацию вы можете узнать у администратора вашей облачной инфраструктуры. diff --git a/wiki/1.2.1/04.03-Переключение-между-группами-API.md b/wiki/1.2.1/04.03-Переключение-между-группами-API.md new file mode 100644 index 0000000..79557f2 --- /dev/null +++ b/wiki/1.2.1/04.03-Переключение-между-группами-API.md @@ -0,0 +1,38 @@ +Так как платформа DYNAMIX предоставляет для работы две группы API, то terraform провайдер позволяет свободно переключать режимы работы между этими группами. +По умолчанию стоит пользовательская группа API. Ее можно сменить на административную группу. +Если прав у пользователя будет достаточно, то запрос будет выполнен, если нет, то будет ошибка: +```bash +Permission denied +``` +Которая говорит о том, что прав недостаточно. Тогда для выполнения операции обратитесь к администратору платформы. +Установка режима взаимодействия с группами API осуществляется через установку переменной окружения _DECORT_ADMIN_MODE_. +Для более подробного описания возможностей каждой группы API см. соответствующий раздел. + +## Переключение режима работы в Windows +Используйте сл. команду: +```Powershell +$Env:DECORT_ADMIN_MODE=1 +``` +Для отключения: +```Powershell +$Env:DECORT_ADMIN_MODE=0 +``` +## Переключение режима работы в Linux +Используйте сл. команду: +```bash +DECORT_ADMIN_MODE=1 +``` +или +```bash +export DECORT_ADMIN_MODE=1 +``` +Для отключения: +```bash +DECORT_ADMIN_MODE=0 +``` +или +```bash +export DECORT_ADMIN_MODE=0 +``` +**ОБРАТИТЕ ВНИМАНИЕ** +Переменные окружения создаются для терминальной сессии. В сл. раз их придется задавать еще раз, если требуется режим, отличный от пользовательского. diff --git a/wiki/1.2.1/04.04-Получение-gid-или-grid_id.md b/wiki/1.2.1/04.04-Получение-gid-или-grid_id.md new file mode 100644 index 0000000..1161149 --- /dev/null +++ b/wiki/1.2.1/04.04-Получение-gid-или-grid_id.md @@ -0,0 +1,17 @@ +Платформа может располагаться на нескольких площадках(grid). +Такие площадки имеют свой id. +Для создания некоторых ресурсов требуется ввести grid_id или gid площадки. +Получение gid различается для пользовательского и административного API. + +## Получение gid для пользовательского API +Для получения gid с помощью пользовательского API, необходимо получить информацию из _data_source_ функции _dynamix_locations_list_, как указано ниже: +```terraform +data "dynamix_locations_list" "ll" { + +} + +output "test" { + value = data.dynamix_locations_list.ll +} +``` +В файл состояния будет сохранен результат, где можно посмотреть доступные для работы площадки. diff --git a/wiki/1.2.1/04.05-Сборка-terraform-провайдера-в-образ.md b/wiki/1.2.1/04.05-Сборка-terraform-провайдера-в-образ.md new file mode 100644 index 0000000..c0a96bf --- /dev/null +++ b/wiki/1.2.1/04.05-Сборка-terraform-провайдера-в-образ.md @@ -0,0 +1,43 @@ +Образ приложения - современный способ запуска приложений. Образ приложения представляет собой контейнер, в который входит ОС и необходимые для работы приложения пакеты. +Способов создать образ приложения довольно много, для этого существуют программы контейнеризации: +- Docker +- Podman +- и другие +Образ представляет собой "зафиксированную" версию приложения, что означает, что никакие изменения в приложения внесены быть не могут. Так же означает то, что приложение не может создавать побочные файлы при работе. +Контейнер - это запущенный экземпляр образа. То есть, один образ может порождать множество контейнеров, каждый из которых будет включать в себя отдельный экземпляр приложения. +Одно из преимуществ работы приложения в контейнере - кроссплатформенность. Это преимущество обуславливается тем, что образ приложения уже включает в себя все необходимое для успешной работы приложения, в том числе операционную систему. Поэтому, пользователю достаточно установить на вычислительной машине программу, которая обеспечивает работу с образами приложений. + +## Docker +Docker является одной из самых популярных программ для работы с образами. +Docker позволяет: +- Создавать образы +- Запускать контейнеры +- Управлять контейнерами +- Управлять образами +Скачать и установить Docker можно по ссылке https://docs.docker.com/get-docker/ + +## Сборка terraform провайдера +### Требования: +- Docker +- git +- Компилятор языка GO += make +### Установка необходимых программ +1. Компилятор языка GO можно скачать и установить по ссылке: https://go.dev/dl/ +2. Docker можно скачать и установить по ссылке выше. +3. Git можно скачать и установить по ссылке: https://git-scm.com/ +4. Программа make входит в пакет установленных программ для ОС Linux. Для Windows можно воспользоваться инструкцией со stack overflow: https://stackoverflow.com/questions/32127524/how-to-install-and-use-make-in-windows +### Порядок действий +1. Склонировать репозиторий с провайдером: +```bash +git clone https://repository.basistech.ru/BASIS/terraform-provider-dynamix +``` +2. Перейти в директорию со скачанным кодом: +```bash +cd terraform-provider-dynamix +``` +3. Выполнить команду: +```bash +make image +``` +В результате выполнения данной последовательности, будет создан docker образ, который содержит в себе приложение terraform, terraform провайдер. diff --git a/wiki/1.2.1/05.-Работа-с-terraform.md b/wiki/1.2.1/05.-Работа-с-terraform.md new file mode 100644 index 0000000..675f2ea --- /dev/null +++ b/wiki/1.2.1/05.-Работа-с-terraform.md @@ -0,0 +1,4 @@ +Раздел описывает некоторые практики работы с terraform, которые могут быть полезны пользователю. +Раздел включает в себя следующие статьи: +- Импортирование ресурсов +- Работа с таймаутами diff --git a/wiki/1.2.1/05.01-Импортирование-ресурсов.md b/wiki/1.2.1/05.01-Импортирование-ресурсов.md new file mode 100644 index 0000000..6983e22 --- /dev/null +++ b/wiki/1.2.1/05.01-Импортирование-ресурсов.md @@ -0,0 +1,75 @@ +Импортирование ресурсов в terraform позволяет привести в соответствие состояние terraform (.tfstate) к состоянию ресурса в платформе. +Необходимость такого приведения возникает в нескольких случаях: +- Ресурс был создан через портал платформы, работа продолжается через terraform провайдер, +- Ресурс был создан через terraform провайдер, однако был изменен через портал платформы, +- Ресурс был создан через terraform провайдер, однако был изменен другим пользователем через terraform провайдер, +- И так далее + +Такие расхождения в состоянии ресурсов нередки, путей их решения несколько: +- Использовать импортирование ресурсов, +- Использовать общие файлы состояний ресурсов, к которым будут иметь доступ все участники, занятые в работе с платформой. +В текущем разделе рассматривается первый вариант. + +## Импортирование ресурсов +Импортирование ресурсов позволяет совершить запрос к платформе, чтобы сформировать файл состояния. +Чтобы совершить импортирование ресурсов необходимо ввести сл. команду: +```bash +terraform import . +``` +## Пример +Предположим, что у нас ресурс, описывающий диск: +```terraform +resource "dynamix_disk" "disk" { + account_id = 121212 + gid = 3333 + disk_name = "mySuperDisk" + size_max = 100500 +} +``` +Если запустить команду: +```bash +terraform apply +``` +То у нас будет создан новый диск. +Но, такой диск уже есть на площадке и мы хотели бы сформировать .tfstate для этого ресурса. +Поэтому, для начала, необходимо получить список дисков: +```terraform +data "dynamix_disk_list" "dl"{ + +} +output "test" { + value = data.dynamix_disk_list.dl +} +``` +В полученных данных необходимо найти требуемый диск, получить его id - параметр disk_id. Пусть это будет - 777777 +Теперь можно выполнить импортирование: +```bash +terraform import dynamix_disk.disk 777777 +``` +Команда должна успешно завершиться, появиться файл состояний, который позволит манипулировать ресурсом. + +## Ошибки при импортировании +При импортировании ресурса может возникнуть сл. ошибка: +```bash +Error: : required field is not set +``` +Где - наименование поля. +Ошибка возникает в том случае, если в описании ресурса отсутствует обязательное поле. +Например: +```terraform +resource "dynamix_disk" "disk" { + account_id = 121212 + gid = 3333 + size_max = 100500 +} +``` +В приведенном выше описании отсутствует поле disk_name, поэтому, при попытке импортирования возникнет ошибка. +Для ее устранения, необходимо выполнить запрос на получение списка дисков, найти недостающее поле, после чего добавить его в описание ресурса. +После этого повторить попытку импортирования. + +## Общий алгоритм устранения ошибок +1. Выполнить запрос импортирования +2. В случае ошибки - внести недостающие поля. +3. Повторить п.1. + + diff --git a/wiki/1.2.1/05.02-Работа-с-таймаутами.md b/wiki/1.2.1/05.02-Работа-с-таймаутами.md new file mode 100644 index 0000000..ecffe69 --- /dev/null +++ b/wiki/1.2.1/05.02-Работа-с-таймаутами.md @@ -0,0 +1,100 @@ +Terraform провайдер DYNAMIX поддерживает тонкую настройку таймаутов выполнения запросов к платформе. Таймауты необходимы для определения максимального времени выполнения запроса. При превышении этого времени соединение рвется и запрос считается невыполненным. +Таймауты применяются при работе с _resource_ функциями провайдера. _Data source_ функции по-умолчанию имеют таймаут в 20 минут и изменяться не может. + +## Стандартные таймауты terraform +| Операция | Время | Описание | +| --- | --- | --- | +| create | 20 минут | Создание ресурса | +| read | 20 минут | Чтение ресурса | +| update | 20 минут | Обновление ресурса | +| delete | 20 минут | Удаление ресурса | +| default | 20 минут | Значение по умолчанию. Устанавливает значение для всех операций | + +## Стандартные таймауты провайдера DYNAMIX +В провайдере DYNAMIX таймауты переопределены для того, чтобы уменьшить нагрузку на платформу. +| Операция | Время | Описание | +| --- | --- | --- | +| create | 10 минут | Создание ресурса | +| read | 5 минут | Чтение ресурса | +| update | 5 минут | Обновление ресурса | +| delete | 5 минут | Удаление ресурса | +| default | 5 минут | Значение по умолчанию. Устанавливает значение для всех операций | + +## Установка таймаутов +Все таймауты можно установить самостоятельно для каждого ресурса. +Для этого используется блок _timeouts_, который имеется в каждом ресурсе провайдера. +Пример: +```terraform +resource "dynamix_res" "res_name" { + timeouts { + create = "10m" + update = "1m" + delete = "2m" + read = "7m" + #default = "15m" + } +} +``` +Где: +- create - операция создания ресурса +- read - операция чтения ресурса +- update - операция обновления ресурса +- delete - операция удаления ресурса +- default - установит заданное время для всех операций +## Формат установления времени +Как видно из примера выше, провайдер принимает на вход строку вида: +``` +"" +``` +Где: +- time-num - число +- time-val - сокращенная запись значения временного отрезка. + +Таблица с временными отрезками: + +| Отрезок | Значение | +| --- | --- | +| n | наносекунда | +| ms | миллисекунда | +| s | секунда | +| m | минута | +| h | час | + +Примеры: +``` +"10m" +"1s" +"1h10m" +``` +И так далее + +## Работа с таймером через .tf-файл +В .tf-файле, в блоке ресурса можно задавать таймауты для операций над ресурсом, однако, при работе с таймаутом, следует помнить о правиле: +__В случае изменения таймаутов в .tf-файле, операции с новыми таймаутами будут производиться только после apply/plan/destroy__ +То есть, если изменить таймауты и выполнить операцию, то она выполнится со старыми таймаутами, а сл. операция уже будет выполнена с новыми таймаутами. +Это объясняется тем, что значения таймаутов считываются из файла состояний .tfstate при выполнении операции, и новые значения таймаутов попадут туда только при успешно выполненной операции. + +## Ошибки при работе с таймаутом +### context deadline exceeded +Если время таймаута слишком короткое, то можно получить сл. ошибку: +``` +context deadline exceeded +``` +Которая говорит, что было выполнено прерывание работы программы из-за истечения времени на операцию. +Для исправления можно увеличить размер окна таймаута и выполнить успешный запрос (например, с помощью терминала), чтобы новое значения таймаутов было добавлено в .tfstate. В противном случае, файл состояния придется править в ручную, либо удалить его и импортировать ресурс для формирования .tfstate. + +### 504 ошибка +Данная ошибка говорит о том, что сервер принудительно разорвал соединения из-за истечения времени на ответ. +В случае получения данной ошибки, обратитесь в службу технической поддержки. + +## Работа с таймаутами через терминал +Сл. команда выполнит операцию terraform с заданным таймаутом: +```bash +timeout