diff --git a/CHANGELOG.md b/CHANGELOG.md index f29d116..dd0e081 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,18 +1,16 @@ -## Version 4.7.2 +## Version 4.7.3 -### Исправлено +### Добавлено -#### flipgroup +#### kvmvm | Идентификатор
задачи | Описание | | --- | --- | -| BATF-647 | Изменен тип поля `ClientIDs` c []string на []uint64 в data source `decort_flipgroup_list` в cloudapi/flipgroup | +| BATF-648 | Обязательные поля `net_type, net_id` в опциональный блок `libvirt_settings` в resource `decort_cb_kvmvm` в cloudbroker/kvmvm | +| BATF-648 | Опциональное поле `mtu` в опциональный блок `network` в resources `decort_cb_kvmvm, decort_kvmvm` в cloudbroker/kvmvm и cloudapi/kvmvm | -#### k8s -| Идентификатор
задачи | Описание | -| --- | --- | -| BATF-646 | Исправлена ошибка с записью `k8s_id` при создании resource `decort_k8s_wg` в cloudapi/k8s | +### Удалено -#### lb +#### kvmvm | Идентификатор
задачи | Описание | | --- | --- | -| BATF-647 | Исправлена ошибка создания resources `decort_lb` и `decort_cb_lb` при `ExtNetID` или `VINSID` равных 0 в cloudapi/lb и cloudbroker/lb | +| BATF-648 | Обязательное поле `mac` в опциональном блок `libvirt_settings` в resource `decort_cb_kvmvm` в cloudbroker/kvmvm | \ No newline at end of file diff --git a/Makefile b/Makefile index e278dab..b806f8e 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ ZIPDIR = ./zip BINARY=${NAME} WORKPATH= ./examples/terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAMESPACE}/${VERSION}/${OS_ARCH} MAINPATH = ./cmd/decort/ -VERSION=4.7.2 +VERSION=4.7.3 OS_ARCH=$(shell go env GOHOSTOS)_$(shell go env GOHOSTARCH) FILES = ${BINARY}_${VERSION}_darwin_amd64\ diff --git a/README_EN.md b/README_EN.md deleted file mode 100644 index 061a176..0000000 --- a/README_EN.md +++ /dev/null @@ -1,168 +0,0 @@ -# terraform-provider-decort - -Terraform provider for Digital Energy Cloud Orchestration Technology (DECORT) platform - -## Mapping of platform versions with provider versions - -| DECORT API version | Terraform provider version | -| ------ | ------ | -| 3.8.5 | 3.4.x | -| 3.8.0 - 3.8.4 | 3.3.1 | -| 3.7.x | rc-1.25 | -| 3.6.x | rc-1.10 | -| до 3.6.0 | [terraform-provider-decs](https://github.com/rudecs/terraform-provider-decs) | - -## Working modes - -The provider support two working modes: - -- User mode, -- Administator mode. - Use flag DECORT_ADMIN_MODE for swithcing beetwen modes. - See user guide at https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki - -## Features - -- Work with Compute instances, -- Work with disks, -- Work with k8s, -- Work with image, -- Work with reource groups, -- Work with VINS, -- Work with pfw, -- Work with accounts, -- Work with snapshots, -- Work with pcidevice. -- Work with sep, -- Work with vgpu, -- Work with bservice, -- Work with extnets, -- Work with locations, -- Work with load balancers. - -This provider supports Import operations on pre-existing resources. - -See user guide at https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki - -## Get Started - -Two ways for starting: - -1. Installing via binary packages -2. Manual installing - -### Installing via binary packages - -1. Download and install terraform: https://learn.hashicorp.com/tutorials/terraform/install-cli?in=terraform/aws-get-started -2. Create a file `main.tf` and add to it next section. - -```terraform -provider "decort" { - authenticator = "decs3o" - #controller_url = - controller_url = "https://ds1.digitalenergy.online" - #oauth2_url = - oauth2_url = "https://sso.digitalenergy.online" - allow_unverified_ssl = true -} -``` - -3. Execute next command - -``` -terraform init -``` - -The Provider will automatically install on your computer from the terrafrom registry. - -### Manual installing - -1. Download and install Go Programming Language: https://go.dev/dl/ -2. Download and install terraform: https://learn.hashicorp.com/tutorials/terraform/install-cli?in=terraform/aws-get-started -3. Clone provider's repo: - -```bash -git clone https://github.com/rudecs/terraform-provider-decort.git -``` - -4. Change directory to clone provider's and execute next command - -```bash -go build -o terraform-provider-decort -``` - -If you have experience with _makefile_, you can change `Makefile`'s paramters and execute next command - -```bash -make build -``` - -5. Now move compilled file to: - Linux: - -```bash -~/.terraform.d/plugins/${host_name}/${namespace}/${type}/${version}/${target} -``` - -Windows: - -```powershell -%APPDATA%\terraform.d\plugins\${host_name}/${namespace}/${type}/${version}/${target} -``` - -NOTE: for Windows OS `%APP_DATA%` is a cataloge, where will place terraform files. -Example: - -- host_name - digitalenergy.online -- namespace - decort -- type - decort -- version - 1.2 -- target - windows_amd64 - -6. After all, create a file `main.tf`. -7. Add to the file next code section - -```terraform -terraform { - required_providers { - decort = { - version = "1.2" - source = "digitalenergy.online/decort/decort" - } - } -} -``` - -`version`- field for provider's version -Required -String -Note: Versions in code section and in a repository must be equal! - -`source` - path to repository with provider's version - -```bash -${host_name}/${namespace}/${type} -``` - -NOTE: all paramters must be equal to the repository path! - -8. Execute command in your terminal - -```bash -terraform init -``` - -9. If everything all right - you got green message in your terminal! - -More details about the provider's building process: https://learn.hashicorp.com/tutorials/terraform/provider-use?in=terraform/providers - -## Examples and Samples - -- Examples: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki -- Samples: see in repository `samples` - -Terraform schemas in: - -- See in repository `docs` - -Good work! diff --git a/bin/tfplugindocs b/bin/tfplugindocs deleted file mode 100755 index cdf3392..0000000 Binary files a/bin/tfplugindocs and /dev/null differ diff --git a/docs/resources/cb_kvmvm.md b/docs/resources/cb_kvmvm.md index 977ce5a..07120f6 100644 --- a/docs/resources/cb_kvmvm.md +++ b/docs/resources/cb_kvmvm.md @@ -198,7 +198,8 @@ Read-Only: Required: -- `mac` (String) +- `net_id` (Number) ID of the network +- `net_type` (String) Type of the network Optional: @@ -221,6 +222,7 @@ Required: Optional: - `ip_address` (String) Optional IP address to assign to this connection. This IP should belong to the selected network and free for use. +- `mtu` (Number) Maximum transmission unit, used only for DPDK type, must be 1-9216 - `weight` (Number) weight the network if you need to sort network list, the smallest attach first. zero or null weight attach last Read-Only: diff --git a/docs/resources/kvmvm.md b/docs/resources/kvmvm.md index d78ea96..178ab0d 100644 --- a/docs/resources/kvmvm.md +++ b/docs/resources/kvmvm.md @@ -196,6 +196,7 @@ Required: Optional: - `ip_address` (String) Optional IP address to assign to this connection. This IP should belong to the selected network and free for use. +- `mtu` (Number) Maximum transmission unit, used only for DPDK type, must be 1-9216 - `weight` (Number) weight the network if you need to sort network list, the smallest attach first. zero or null weight attach last Read-Only: diff --git a/go.mod b/go.mod index 9c23fde..213d7d0 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 github.com/sirupsen/logrus v1.9.0 golang.org/x/net v0.23.0 - repository.basistech.ru/BASIS/decort-golang-sdk v1.9.1 + repository.basistech.ru/BASIS/decort-golang-sdk v1.9.2 ) require ( diff --git a/go.sum b/go.sum index fb6c500..c7822ef 100644 --- a/go.sum +++ b/go.sum @@ -273,5 +273,5 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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.9.1 h1:MibzMI7ewzxuf2jj32JSGFXSEwtR2557JL/Fq9AqKjI= -repository.basistech.ru/BASIS/decort-golang-sdk v1.9.1/go.mod h1:OaUynHHuSjWMzpfyoL4au6oLcUogqUkPPBKA15pbHWo= +repository.basistech.ru/BASIS/decort-golang-sdk v1.9.2 h1:MPH1tMQrDN1Gri4FrQP3cx60uR3uZioEDb707D88/7c= +repository.basistech.ru/BASIS/decort-golang-sdk v1.9.2/go.mod h1:OaUynHHuSjWMzpfyoL4au6oLcUogqUkPPBKA15pbHWo= diff --git a/internal/service/cloudapi/kvmvm/flattens.go b/internal/service/cloudapi/kvmvm/flattens.go index 2ce2e3f..3511c5e 100644 --- a/internal/service/cloudapi/kvmvm/flattens.go +++ b/internal/service/cloudapi/kvmvm/flattens.go @@ -316,6 +316,7 @@ func flattenNetwork(networks []interface{}, interfaces compute.ListInterfaces) [ "net_type": network.NetType, "ip_address": network.IPAddress, "mac": network.MAC, + "mtu": network.MTU, "weight": flattenNetworkWeight(networks, network.NetID, network.NetType), } res = append(res, temp) diff --git a/internal/service/cloudapi/kvmvm/network_subresource.go b/internal/service/cloudapi/kvmvm/network_subresource.go index b6f7df2..9030f93 100644 --- a/internal/service/cloudapi/kvmvm/network_subresource.go +++ b/internal/service/cloudapi/kvmvm/network_subresource.go @@ -158,6 +158,15 @@ func networkSubresourceSchemaMake() map[string]*schema.Schema { Computed: true, Description: "weight the network if you need to sort network list, the smallest attach first. zero or null weight attach last", }, + + "mtu": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + //Default: 1500, + ValidateFunc: validation.IntBetween(1, 9216), + Description: "Maximum transmission unit, used only for DPDK type, must be 1-9216", + }, } return rets } diff --git a/internal/service/cloudapi/kvmvm/resource_compute.go b/internal/service/cloudapi/kvmvm/resource_compute.go index 9fdb919..5c106b8 100644 --- a/internal/service/cloudapi/kvmvm/resource_compute.go +++ b/internal/service/cloudapi/kvmvm/resource_compute.go @@ -162,6 +162,10 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf NetID: uint64(netInterfaceVal["net_id"].(int)), } + if reqInterface.NetType == "DPDK" { + reqInterface.MTU = uint64(netInterfaceVal["mtu"].(int)) + } + ipaddr, ipSet := netInterfaceVal["ip_address"] if ipSet { reqInterface.IPAddr = ipaddr.(string) @@ -2439,6 +2443,15 @@ func ResourceCompute() *schema.Resource { StateContext: schema.ImportStatePassthroughContext, }, + CustomizeDiff: func(ctx context.Context, diff *schema.ResourceDiff, i interface{}) error { + if diff.HasChanges() || diff.HasChanges("network", "affinity_rules", "anti_affinity_rules", + "disks", "extra_disks", "tags", "port_forwarding", "user_access", "snapshot", "pci_devices") { + diff.SetNewComputed("updated_time") + diff.SetNewComputed("updated_by") + } + return nil + }, + Timeouts: &schema.ResourceTimeout{ Create: &constants.Timeout600s, Read: &constants.Timeout300s, diff --git a/internal/service/cloudapi/kvmvm/utility_compute.go b/internal/service/cloudapi/kvmvm/utility_compute.go index ded1fa7..973259e 100644 --- a/internal/service/cloudapi/kvmvm/utility_compute.go +++ b/internal/service/cloudapi/kvmvm/utility_compute.go @@ -224,7 +224,7 @@ func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData needStart := false - if oldSet.(*schema.Set).Len() == len(detachMap) || oldSet.(*schema.Set).Len() == 0 { + if oldSet.(*schema.Set).Len() == len(detachMap) || oldSet.(*schema.Set).Len() == 0 || hasDPDKnetwork(attachMap) { computeId, _ := strconv.ParseUint(d.Id(), 10, 64) if err := utilityComputeStop(ctx, computeId, m); err != nil { apiErrCount++ @@ -259,6 +259,10 @@ func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData req.IPAddr = netData["ip_address"].(string) } + if req.NetType == "DPDK" { + req.MTU = uint64(netData["mtu"].(int)) + } + _, err := c.CloudAPI().Compute().NetAttach(ctx, req) if err != nil { log.Errorf("utilityComputeNetworksConfigure: failed to attach net ID %d of type %s to Compute ID %s: %s", @@ -285,6 +289,15 @@ func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData return nil } +func hasDPDKnetwork(networkAttachMap []map[string]interface{}) bool { + for _, elem := range networkAttachMap { + if elem["net_type"].(string) == "DPDK" { + return true + } + } + return false +} + func utilityComputeCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (compute.RecordCompute, error) { c := m.(*controller.ControllerCfg) computeId, _ := strconv.ParseUint(d.Id(), 10, 64) @@ -374,12 +387,12 @@ func differenceNetwork(oldList, newList []interface{}) (detachMap, changeIpMap, found := false for _, newNetwork := range newList { newMap := newNetwork.(map[string]interface{}) - if newMap["net_type"] == oldMap["net_type"] && newMap["net_id"] == oldMap["net_id"] && newMap["weight"] == oldMap["weight"] { - if (newMap["net_type"].(string) == "EXTNET" || newMap["net_type"].(string) == "VINS") && newMap["ip_address"] != oldMap["ip_address"] { + if newMap["net_type"] == oldMap["net_type"] && newMap["net_id"] == oldMap["net_id"] && newMap["weight"] == oldMap["weight"] && (newMap["mtu"] == oldMap["mtu"] || newMap["mtu"].(int) == 0) { + if (newMap["net_type"].(string) == "EXTNET" || newMap["net_type"].(string) == "VINS") && (newMap["ip_address"] != oldMap["ip_address"] && newMap["ip_address"].(string) != "") { changeIpMap = append(changeIpMap, newMap) found = true break - } else if newMap["ip_address"] == oldMap["ip_address"] { + } else if newMap["ip_address"] == oldMap["ip_address"] || newMap["ip_address"].(string) == "" { found = true break } @@ -396,8 +409,10 @@ func differenceNetwork(oldList, newList []interface{}) (detachMap, changeIpMap, found := false for _, oldNetwork := range oldList { oldMap := oldNetwork.(map[string]interface{}) - if newMap["net_type"] == oldMap["net_type"] && newMap["net_id"] == oldMap["net_id"] && newMap["weight"] == oldMap["weight"] { - if newMap["ip_address"] == oldMap["ip_address"] || ((newMap["net_type"].(string) == "EXTNET" || newMap["net_type"].(string) == "VINS") && newMap["ip_address"] != oldMap["ip_address"]) { + if newMap["net_type"] == oldMap["net_type"] && newMap["net_id"] == oldMap["net_id"] && newMap["weight"] == oldMap["weight"] && (newMap["mtu"] == oldMap["mtu"] || newMap["mtu"].(int) == 0) { + if newMap["ip_address"] == oldMap["ip_address"] || newMap["ip_address"].(string) == "" || + ((newMap["net_type"].(string) == "EXTNET" || newMap["net_type"].(string) == "VINS") && + newMap["ip_address"] != oldMap["ip_address"] && newMap["ip_address"].(string) != "") { found = true break } diff --git a/internal/service/cloudbroker/kvmvm/flattens.go b/internal/service/cloudbroker/kvmvm/flattens.go index b28e385..934563c 100644 --- a/internal/service/cloudbroker/kvmvm/flattens.go +++ b/internal/service/cloudbroker/kvmvm/flattens.go @@ -695,7 +695,6 @@ func parseComputeInterfacesToNetworks(networks []interface{}, ifaces compute.Lis log.Debugf("parseComputeInterfacesToNetworks: called for %d ifaces", length) result := []interface{}{} - for _, value := range ifaces { elem := make(map[string]interface{}) // Keys in this map should correspond to the Schema definition for "network" @@ -703,6 +702,7 @@ func parseComputeInterfacesToNetworks(networks []interface{}, ifaces compute.Lis elem["net_type"] = value.NetType elem["ip_address"] = value.IPAddress elem["mac"] = value.MAC + elem["mtu"] = value.MTU elem["weight"] = flattenNetworkWeight(networks, value.NetID, value.NetType) result = append(result, elem) diff --git a/internal/service/cloudbroker/kvmvm/resource_compute.go b/internal/service/cloudbroker/kvmvm/resource_compute.go index 4007a8a..deb38ce 100644 --- a/internal/service/cloudbroker/kvmvm/resource_compute.go +++ b/internal/service/cloudbroker/kvmvm/resource_compute.go @@ -75,10 +75,6 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf createReqX86.StackID = uint64(stackID.(int)) } - if start, ok := d.GetOk("started"); ok { - createReqX86.Start = start.(bool) - } - if ipaType, ok := d.GetOk("ipa_type"); ok { createReqX86.IPAType = ipaType.(string) } @@ -116,6 +112,10 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf NetID: uint64(netInterfaceVal["net_id"].(int)), } + if reqInterface.NetType == "DPDK" { + reqInterface.MTU = uint64(netInterfaceVal["mtu"].(int)) + } + ipaddr, ipSet := netInterfaceVal["ip_address"] if ipSet { reqInterface.IPAddr = ipaddr.(string) @@ -208,6 +208,11 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf warnings := dc.Warnings{} + simpleCompRec, err := utilityComputeCheckPresence(ctx, d, m) + if err != nil { + warnings.Add(err) + } + cleanup := false defer func() { if cleanup { @@ -255,6 +260,41 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf } } + if libvirtSettings, ok := d.GetOk("libvirt_settings"); ok { + if libvirtSettings.(*schema.Set).Len() > 0 { + lvs := libvirtSettings.(*schema.Set).List() + for _, elem := range lvs { + netLibvirtMap := elem.(map[string]interface{}) + + netType := netLibvirtMap["net_type"].(string) + netId := uint64(netLibvirtMap["net_id"].(int)) + var mac string + for _, iface := range simpleCompRec.Interfaces { + if iface.NetID == netId && iface.NetType == netType { + mac = iface.MAC + break + } + } + log.Debugf("resourceComputeCreate: Configure libvirt virtio interface parameters on Network with type %s and id %d", netType, netId) + req := compute.SetNetConfigRequest{ + ComputeID: computeId, + MAC: mac, + TXMode: netLibvirtMap["txmode"].(string), + IOEventFD: netLibvirtMap["ioeventfd"].(string), + EventIDx: netLibvirtMap["event_idx"].(string), + Queues: uint64(netLibvirtMap["queues"].(int)), + RXQueueSize: uint64(netLibvirtMap["rx_queue_size"].(int)), + TXQueueSize: uint64(netLibvirtMap["tx_queue_size"].(int)), + } + + _, err := c.CloudBroker().Compute().SetNetConfig(ctx, req) + if err != nil { + warnings.Add(err) + } + } + } + } + if start, ok := d.GetOk("started"); ok && start.(bool) { req := compute.StartRequest{ComputeID: computeId} log.Debugf("resourceComputeCreate: starting Compute ID %d after completing its resource configuration", computeId) @@ -485,31 +525,6 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf } } } - - if ars, ok := d.GetOk("libvirt_settings"); ok { - log.Debugf("resourceComputeCreate: Configure libvirt virtio interface parameters on ComputeID: %d", computeId) - settings := ars.(*schema.Set).List() - if len(settings) > 0 { - for _, v := range settings { - settingsConv := v.(map[string]interface{}) - req := compute.SetNetConfigRequest{ - ComputeID: computeId, - MAC: settingsConv["mac"].(string), - TXMode: settingsConv["txmode"].(string), - IOEventFD: settingsConv["ioeventfd"].(string), - EventIDx: settingsConv["event_idx"].(string), - Queues: uint64(settingsConv["queues"].(int)), - RXQueueSize: uint64(settingsConv["rx_queue_size"].(int)), - TXQueueSize: uint64(settingsConv["tx_queue_size"].(int)), - } - - _, err := c.CloudBroker().Compute().SetNetConfig(ctx, req) - if err != nil { - warnings.Add(err) - } - } - } - } } log.Debugf("resourceComputeCreate: new Compute ID %d, name %s creation sequence complete", computeId, d.Get("name").(string)) @@ -664,7 +679,7 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf } } - if d.HasChange("network") { + if d.HasChanges("network", "libvirt_settings") { err = utilityComputeNetworksConfigure(ctx, d, m) // pass do_delta = true to apply changes, if any if err != nil { return diag.FromErr(err) @@ -773,12 +788,6 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf } } - if d.HasChange("libvirt_settings") { - if err := utilityComputeUpdateLibvirtSettings(ctx, d, m); err != nil { - return diag.FromErr(err) - } - } - return append(resourceComputeRead(ctx, d, m), warnings.Get()...) } @@ -829,6 +838,15 @@ func ResourceCompute() *schema.Resource { return &schema.Resource{ SchemaVersion: 1, + CustomizeDiff: func(ctx context.Context, diff *schema.ResourceDiff, i interface{}) error { + if diff.HasChanges() || diff.HasChanges("libvirt_settings", "network", "affinity_rules", "anti_affinity_rules", + "disks", "extra_disks", "tags", "port_forwarding", "user_access", "snapshot", "pci_devices") { + diff.SetNewComputed("updated_time") + diff.SetNewComputed("updated_by") + } + return nil + }, + CreateContext: resourceComputeCreate, ReadContext: resourceComputeRead, UpdateContext: resourceComputeUpdate, diff --git a/internal/service/cloudbroker/kvmvm/schema.go b/internal/service/cloudbroker/kvmvm/schema.go index 496833c..23ecd36 100644 --- a/internal/service/cloudbroker/kvmvm/schema.go +++ b/internal/service/cloudbroker/kvmvm/schema.go @@ -3012,13 +3012,11 @@ func resourceComputeSchemaMake() map[string]*schema.Schema { ValidateFunc: validation.StringInSlice([]string{"EXTNET", "VINS", "VFNIC", "DPDK"}, false), // observe case while validating Description: "Type of the network for this connection, either EXTNET or VINS.", }, - "net_id": { Type: schema.TypeInt, Required: true, Description: "ID of the network for this connection.", }, - "ip_address": { Type: schema.TypeString, Optional: true, @@ -3026,24 +3024,82 @@ func resourceComputeSchemaMake() map[string]*schema.Schema { DiffSuppressFunc: networkSubresIPAddreDiffSupperss, Description: "Optional IP address to assign to this connection. This IP should belong to the selected network and free for use.", }, - "mac": { Type: schema.TypeString, Computed: true, Description: "MAC address associated with this connection. MAC address is assigned automatically.", }, - "weight": { Type: schema.TypeInt, Optional: true, Computed: true, Description: "weight the network if you need to sort network list, the smallest attach first. zero or null weight attach last", }, + "mtu": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + //Default: 1500, + ValidateFunc: validation.IntBetween(1, 9216), + Description: "Maximum transmission unit, used only for DPDK type, must be 1-9216", + }, }, }, Description: "Optional network connection(s) for this compute. You may specify several network blocks, one for each connection.", }, + "libvirt_settings": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "net_type": { + Type: schema.TypeString, + Required: true, + StateFunc: statefuncs.StateFuncToUpper, + ValidateFunc: validation.StringInSlice([]string{"VINS", "VFNIC", "DPDK"}, false), // observe case while validating + Description: "Type of the network", + }, + "net_id": { + Type: schema.TypeInt, + Required: true, + Description: "ID of the network", + }, + "txmode": { + Type: schema.TypeString, + Default: "", + Optional: true, + }, + "ioeventfd": { + Type: schema.TypeString, + Default: "", + Optional: true, + }, + "event_idx": { + Type: schema.TypeString, + Default: "", + Optional: true, + }, + "queues": { + Type: schema.TypeInt, + Default: 0, + Optional: true, + }, + "rx_queue_size": { + Type: schema.TypeInt, + Default: 0, + Optional: true, + }, + "tx_queue_size": { + Type: schema.TypeInt, + Default: 0, + Optional: true, + }, + }, + }, + Description: "Configure libvirt virtio interface parameters. You can only delete values locally. Data on the platform cannot be deleted.", + }, + "affinity_label": { Type: schema.TypeString, Optional: true, @@ -3412,43 +3468,6 @@ func resourceComputeSchemaMake() map[string]*schema.Schema { }, Description: "ID of the connected pci devices", }, - "libvirt_settings": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "mac": { - Type: schema.TypeString, - Required: true, - }, - "txmode": { - Type: schema.TypeString, - Optional: true, - }, - "ioeventfd": { - Type: schema.TypeString, - Optional: true, - }, - "event_idx": { - Type: schema.TypeString, - Optional: true, - }, - "queues": { - Type: schema.TypeInt, - Optional: true, - }, - "rx_queue_size": { - Type: schema.TypeInt, - Optional: true, - }, - "tx_queue_size": { - Type: schema.TypeInt, - Optional: true, - }, - }, - }, - Description: "Configure libvirt virtio interface parameters. You can only delete values locally. Data on the platform cannot be deleted.", - }, // Computed properties "account_id": { Type: schema.TypeInt, diff --git a/internal/service/cloudbroker/kvmvm/utility_compute.go b/internal/service/cloudbroker/kvmvm/utility_compute.go index 538011f..e87292b 100644 --- a/internal/service/cloudbroker/kvmvm/utility_compute.go +++ b/internal/service/cloudbroker/kvmvm/utility_compute.go @@ -629,7 +629,11 @@ func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData needStart := false - if oldSet.(*schema.Set).Len() == len(detachMap) || oldSet.(*schema.Set).Len() == 0 { + oldLibvirtSet, newLibvirtSet := d.GetChange("libvirt_settings") + addedLibvirtSettings := (newLibvirtSet.(*schema.Set).Difference(oldLibvirtSet.(*schema.Set))).List() + libvirtSettingsMap := addAttachedNetwork(addedLibvirtSettings, newLibvirtSet.(*schema.Set).List(), attachMap) + + if oldSet.(*schema.Set).Len() == len(detachMap) || oldSet.(*schema.Set).Len() == 0 || len(libvirtSettingsMap) > 0 || hasDPDKnetwork(attachMap) { if err := utilityComputeStop(ctx, d, m); err != nil { apiErrCount++ lastSavedError = err @@ -659,6 +663,10 @@ func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData NetID: uint64(netData["net_id"].(int)), } + if req.NetType == "DPDK" { + req.MTU = uint64(netData["mtu"].(int)) + } + if netData["ip_address"].(string) != "" { req.IPAddr = netData["ip_address"].(string) } @@ -672,6 +680,51 @@ func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData } } + if len(libvirtSettingsMap) > 0 { + computeId, _ := strconv.ParseUint(d.Id(), 10, 64) + computeRec, err := utilityComputeCheckPresence(ctx, d, m) + if err != nil { + log.Errorf("utilityComputeNetworksConfigure: failed to read information about compute with ID %s: %s", + d.Id(), err) + apiErrCount++ + lastSavedError = err + } + + if computeRec != nil { + log.Debugf("utilityComputeNetworksConfigure: libvirt virtio set has %d items for Compute ID %s", len(attachMap), d.Id()) + for _, libvirtSetting := range libvirtSettingsMap { + netType := libvirtSetting["net_type"].(string) + netId := uint64(libvirtSetting["net_id"].(int)) + var mac string + for _, iface := range computeRec.Interfaces { + if iface.NetID == netId && iface.NetType == netType { + mac = iface.MAC + break + } + } + log.Debugf("utilityComputeNetworksConfigure: Configure libvirt virtio interface parameters on Network with type %s and id %d", netType, netId) + req := compute.SetNetConfigRequest{ + ComputeID: computeId, + MAC: mac, + TXMode: libvirtSetting["txmode"].(string), + IOEventFD: libvirtSetting["ioeventfd"].(string), + EventIDx: libvirtSetting["event_idx"].(string), + Queues: uint64(libvirtSetting["queues"].(int)), + RXQueueSize: uint64(libvirtSetting["rx_queue_size"].(int)), + TXQueueSize: uint64(libvirtSetting["tx_queue_size"].(int)), + } + + _, err := c.CloudBroker().Compute().SetNetConfig(ctx, req) + if err != nil { + log.Errorf("utilityComputeNetworksConfigure: failed to set net config to net ID %d of type %s to Compute ID %s: %s", + netId, netType, d.Id(), err) + apiErrCount++ + lastSavedError = err + } + } + } + } + if needStart { computeId, _ := strconv.ParseUint(d.Id(), 10, 64) if numErr, err := utilityComputeStart(ctx, computeId, m); err != nil { @@ -698,12 +751,12 @@ func differenceNetwork(oldList, newList []interface{}) (detachMap, changeIpMap, found := false for _, newNetwork := range newList { newMap := newNetwork.(map[string]interface{}) - if newMap["net_type"] == oldMap["net_type"] && newMap["net_id"] == oldMap["net_id"] && newMap["weight"] == oldMap["weight"] { - if (newMap["net_type"].(string) == "EXTNET" || newMap["net_type"].(string) == "VINS") && newMap["ip_address"] != oldMap["ip_address"] { + if newMap["net_type"] == oldMap["net_type"] && newMap["net_id"] == oldMap["net_id"] && newMap["weight"] == oldMap["weight"] && (newMap["mtu"] == oldMap["mtu"] || newMap["mtu"].(int) == 0) { + if (newMap["net_type"].(string) == "EXTNET" || newMap["net_type"].(string) == "VINS") && (newMap["ip_address"] != oldMap["ip_address"] && newMap["ip_address"].(string) != "") { changeIpMap = append(changeIpMap, newMap) found = true break - } else if newMap["ip_address"] == oldMap["ip_address"] { + } else if newMap["ip_address"] == oldMap["ip_address"] || newMap["ip_address"].(string) == "" { found = true break } @@ -720,8 +773,10 @@ func differenceNetwork(oldList, newList []interface{}) (detachMap, changeIpMap, found := false for _, oldNetwork := range oldList { oldMap := oldNetwork.(map[string]interface{}) - if newMap["net_type"] == oldMap["net_type"] && newMap["net_id"] == oldMap["net_id"] && newMap["weight"] == oldMap["weight"] { - if newMap["ip_address"] == oldMap["ip_address"] || ((newMap["net_type"].(string) == "EXTNET" || newMap["net_type"].(string) == "VINS") && newMap["ip_address"] != oldMap["ip_address"]) { + if newMap["net_type"] == oldMap["net_type"] && newMap["net_id"] == oldMap["net_id"] && newMap["weight"] == oldMap["weight"] && (newMap["mtu"] == oldMap["mtu"] || newMap["mtu"].(int) == 0) { + if newMap["ip_address"] == oldMap["ip_address"] || newMap["ip_address"].(string) == "" || + ((newMap["net_type"].(string) == "EXTNET" || newMap["net_type"].(string) == "VINS") && + newMap["ip_address"] != oldMap["ip_address"] && newMap["ip_address"].(string) != "") { found = true break } @@ -736,6 +791,49 @@ func differenceNetwork(oldList, newList []interface{}) (detachMap, changeIpMap, return } +func hasDPDKnetwork(networkAttachMap []map[string]interface{}) bool { + for _, elem := range networkAttachMap { + if elem["net_type"].(string) == "DPDK" { + return true + } + } + return false +} + +// addAttachedNetwork adds libvirt_settings of attached networks to the libvirt_settings settings list +func addAttachedNetwork(addedLibvirtSettings []interface{}, newLibvirtSettings []interface{}, networkAttachMap []map[string]interface{}) (addedLibvirtSettingsMap []map[string]interface{}) { + addedLibvirtSettingsMap = make([]map[string]interface{}, 0) + + for _, attach := range networkAttachMap { + found := false + for _, elem := range addedLibvirtSettings { + addedLVSMap := elem.(map[string]interface{}) + if attach["net_id"] == addedLVSMap["net_id"] && attach["net_type"] == addedLVSMap["net_type"] { + found = true + break + } + } + if found { + continue + } + for _, elem := range newLibvirtSettings { + newVirtSettingMap := elem.(map[string]interface{}) + if attach["net_id"] == newVirtSettingMap["net_id"] && attach["net_type"] == newVirtSettingMap["net_type"] { + addedLibvirtSettingsMap = append(addedLibvirtSettingsMap, newVirtSettingMap) + found = true + break + } + } + } + + for _, elem := range addedLibvirtSettings { + addedLVSMap := elem.(map[string]interface{}) + addedLibvirtSettingsMap = append(addedLibvirtSettingsMap, addedLVSMap) + } + + return +} + func utilityComputeUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) error { c := m.(*controller.ControllerCfg) @@ -1015,36 +1113,6 @@ func utilityComputeUpdatePciDevices(ctx context.Context, d *schema.ResourceData, return nil } -func utilityComputeUpdateLibvirtSettings(ctx context.Context, d *schema.ResourceData, m interface{}) error { - c := m.(*controller.ControllerCfg) - computeId, _ := strconv.ParseUint(d.Id(), 10, 64) - oldSet, newSet := d.GetChange("libvirt_settings") - - added := (newSet.(*schema.Set).Difference(oldSet.(*schema.Set))).List() - if len(added) > 0 { - for _, v := range added { - settingsConv := v.(map[string]interface{}) - req := compute.SetNetConfigRequest{ - ComputeID: computeId, - MAC: settingsConv["mac"].(string), - TXMode: settingsConv["txmode"].(string), - IOEventFD: settingsConv["ioeventfd"].(string), - EventIDx: settingsConv["event_idx"].(string), - Queues: uint64(settingsConv["queues"].(int)), - RXQueueSize: uint64(settingsConv["rx_queue_size"].(int)), - TXQueueSize: uint64(settingsConv["tx_queue_size"].(int)), - } - - _, err := c.CloudBroker().Compute().SetNetConfig(ctx, req) - if err != nil { - return err - } - } - } - - return nil -} - func utilityComputeUpdateTags(ctx context.Context, d *schema.ResourceData, m interface{}) error { c := m.(*controller.ControllerCfg) @@ -1510,7 +1578,7 @@ func utilityComputeStop(ctx context.Context, d *schema.ResourceData, m interface req.Depresent = depresent } - log.Debugf("utilityComputeNetworksConfigure: stopping compute %d", req.ComputeID) + log.Debugf("utilityComputeStop: stopping compute %d", req.ComputeID) _, err := c.CloudBroker().Compute().Stop(ctx, req) if err != nil { return err @@ -1522,7 +1590,7 @@ func utilityComputeStart(ctx context.Context, computeID uint64, m interface{}) ( c := m.(*controller.ControllerCfg) startReq := compute.StartRequest{ComputeID: computeID} - log.Debugf("utilityComputeNetworksConfigure: starting compute %d", computeID) + log.Debugf("utilityComputeStart: starting compute %d", computeID) _, err := c.CloudBroker().Compute().Start(ctx, startReq) if err != nil { return 1, err diff --git a/samples/cloudapi/kvmvm/resource_kvmvm/main.tf b/samples/cloudapi/kvmvm/resource_kvmvm/main.tf index 2fa1375..300c6de 100644 --- a/samples/cloudapi/kvmvm/resource_kvmvm/main.tf +++ b/samples/cloudapi/kvmvm/resource_kvmvm/main.tf @@ -288,6 +288,13 @@ resource "decort_kvmvm" "comp" { #опциональный параметр #тип - целое число weight = 15 + + #максимальный объём данных, который может быть передан за одну итерацию + #используется только с сетями типа "DPDK" + #возможные значения - 1-9216 + #опциональный параметр + #тип - целое число + mtu = 1500 } #добавление и удаление тэгов diff --git a/samples/cloudbroker/kvmvm/resource_kvmvm/main.tf b/samples/cloudbroker/kvmvm/resource_kvmvm/main.tf index e0bd4da..1749f2f 100644 --- a/samples/cloudbroker/kvmvm/resource_kvmvm/main.tf +++ b/samples/cloudbroker/kvmvm/resource_kvmvm/main.tf @@ -283,7 +283,6 @@ resource "decort_cb_kvmvm" "comp" { #обязательный параметр #возможные значения - "VINS", "EXTNET", "VFNIC", "DPDK" #тип - строка - #net_type = "VINS" #ID сети @@ -302,6 +301,13 @@ resource "decort_cb_kvmvm" "comp" { #опциональный параметр #тип - целое число #weight = 15 + + #максимальный объём данных, который может быть передан за одну итерацию + #используется только с сетями типа "DPDK" + #возможные значения - 1-9216 + #опциональный параметр + #тип - целое число + #mtu = 1500 #} #добавление и удаление тэгов @@ -485,10 +491,16 @@ resource "decort_cb_kvmvm" "comp" { #удаление блока удалит настройки только локально, состояние на платформе не изменится #тип - блок #libvirt_settings { - #mac адреc + #тип сети #обязательный параметр + #возможные значения - "VINS", "VFNIC", "DPDK" #тип - строка - #mac = "52:54:00:00:19:e1" + #net_type = "VINS" + + #ID сети + #обязательный параметр + #тип - целое число + #net_id = 1234 #tx mode #опциональный параметр diff --git a/wiki/4.7.3/01.-Введение.md b/wiki/4.7.3/01.-Введение.md new file mode 100644 index 0000000..96dd210 --- /dev/null +++ b/wiki/4.7.3/01.-Введение.md @@ -0,0 +1,7 @@ +DECORT Terraform Provider версии 4.7.x позволяет управлять облачными ресурсами на платформе Digital Energy Cloud Orchestration Technology (DECORT) версии 4.1.x и выше посредством Terraform. + +С помощью данного провайдера можно организовать программное управление вычислительными ресурсами (_compute_), ресурсными группами, сетевыми и дисковыми ресурсами, образами дисков, кластером, а также другими параметрами облачной платформы DECORT. + +Если вы хорошо знакомы с инструментом Terraform и хотите максимально быстро начать использовать платформу DECORT в своих Terraform-проектах, то можете сразу перейти к разделу [Пример работы](https://repository.basistech.ru/BASIS/terraform-provider-decort/src/branch/main/wiki/4.7.3/02.-Пример-работы.md), где приведён подробно откомментированный пример работы с основными видами ресурсов платформы. Если у вас всё же возникнут вопросы по облачной платформе DECORT и порядку авторизации в ней, то обратитесь к главе [«Обзор облачной платформы DECORT»](https://repository.basistech.ru/BASIS/terraform-provider-decort/src/branch/main/wiki/4.7.3/03.-Обзор-облачной-платформы-DECORT.md). Также может оказаться полезной глава [«Инициализация Terraform провайдера DECORT»](https://repository.basistech.ru/BASIS/terraform-provider-decort/src/branch/main/wiki/4.7.3/04.02-Инициализация-Terraform-провайдера-DECORT.md). + +Если вы только начинаете использовать инструмент Terraform и облачную платформу DECORT, то рекомендуем вам начать с главы [«Обзор облачной платформы DECORT»](https://repository.basistech.ru/BASIS/terraform-provider-decort/src/branch/main/wiki/4.7.3/03.-Обзор-облачной-платформы-DECORT.md), после чего изучить главы [«_Data source_ функции Terraform провайдера DECORT»](https://repository.basistech.ru/BASIS/terraform-provider-decort/src/branch/main/wiki/4.7.3/06.-Data-source-функции-Terraform-провайдера-DECORT.md) и [«_Resource_ функции Terraform провайдера DECORT»](https://repository.basistech.ru/BASIS/terraform-provider-decort/src/branch/main/wiki/4.7.3/07.-Resource-функции-Terraform-провайдера-DECORT.md). Примеры, приведенные в этих разделах, помогут вам быстро освоить базовые приёмы работы с инструментом Terraform и провайдером DECORT. diff --git a/wiki/4.7.3/02.-Пример-работы.md b/wiki/4.7.3/02.-Пример-работы.md new file mode 100644 index 0000000..a924087 --- /dev/null +++ b/wiki/4.7.3/02.-Пример-работы.md @@ -0,0 +1,92 @@ +Данный раздел предназначен для тех, кто хорошо знаком с инструментом Terraform, а также имеет представление об основных понятиях и способах авторизации в облачной платформе DECORT. + +Ниже приведён подробно откомментированный пример, показывающий, как создать виртуальный сервер (aka _compute_ на базе системы виртуализации KVM x86) в облачной платформе DECORT с помощью соответствующего Terraform провайдера. Сервер будет создан в новой ресурсной группе, к нему будет подключён один предварительно созданный диск, у сервера будет прямое сетевое подключение во внешнюю сеть. + +Идентификатор образа операционной системы, на базе которого должен быть создан виртуальный сервер, считывается из облачной платформы с помощью _data source_ функции `decort_image`. + +Далее мы с помощью _resource_ функции `decort_resgroup` создаём новую ресурсную группу, в которую будет помещён этот виртуальный сервер. В качестве альтернативы, для получения информации об уже имеющейся ресурсной группе можно использовать _data source_ функцию с таким же названием. + +Затем с помощью _resource_ функции `decort_disk` создаётся диск, который будет подключён к виртуальному серверу в качестве дополнительного. Помимо этого дополнительного диска у сервера будет также и загрузочный диск, на который в процессе создания сервера клонируется выбранный образ операционной системы. + +Виртуальный сервер - в данном примере на базе системы виртуализации KVM x86 - создаётся посредством _resource_ функции `decort_kvmvm`. + +Только авторизованные в контроллере облачной платформы пользователи могут управлять облачными ресурсами. Подробнее о способах авторизации см. [Обзор облачной платформы DECORT](https://repository.basistech.ru/BASIS/terraform-provider-decort/src/branch/main/wiki/4.7.3/03.-Обзор-облачной-платформы-DECORT.md). + +```terraform +# 1. Initialize DECORT plugin and connection to DECORT cloud controller +# NOTE: in this example credentials are expected to come from +# DECORT_APP_ID and DECORT_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 "decort" { + authenticator = "decs3o" + controller_url = "<>" # specify correct DECORT controller URL, e.g. "https://ds1.digitalenergy.online" + oauth2_url = "<>" # specify corresponding DECORT OAUTH2 URL, e.g. "https://sso.digitalenergy.online" + app_id = "<>" # application secret to access DECORT cloud API in 'decs3o' and 'bvs' authentication mode, e.g. "ewqfrvea7s890avw804389qwguf234h0otfi3w4eiu" + app_secret = "<>" # application ID to access DECORT 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 "decort_account" "my_account" { + account_id = # Specify account ID +} + +# 3. Load OS image to use for VM deployment +data "decort_image" "os_image" { + image_id = # Specify OS image id, e.g. 1234. You can get accessible image id from data source "decort_image_list" +} + +# 4. Create new Resource Group in the selected account, new VM will be created in this RG +resource "decort_resgroup" "my_rg" { + name = "NewRgByTF" + account_id = data.decort_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 "decort_disk" "extra_disk" { + disk_name = "extra-disk-for-vm" + account_id = data.decort_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.decort_image.os_image.sep_id # use the same SEP ID as the OS image + pool = "<>" # consult your DECORT 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 "decort_kvmvm" "my_new_vm" { + name = "tf-managed-vm" + driver = "KVM_X86" # Compute virtualization driver + rg_id = decort_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.decort_image.os_image.image_id + description = "Test KVM VM Compute managed by Terraform" + extra_disks = [ decort_disk.extra_disk.id ] + + network { + net_type = "EXTNET" + net_id = <> # specify external network ID to use, consult your DECORT platform admin for correct IDs + # ip_address = "<>" # you may optionally request a specific IP address + } +} +``` diff --git a/wiki/4.7.3/03.-Обзор-облачной-платформы-DECORT.md b/wiki/4.7.3/03.-Обзор-облачной-платформы-DECORT.md new file mode 100644 index 0000000..938223a --- /dev/null +++ b/wiki/4.7.3/03.-Обзор-облачной-платформы-DECORT.md @@ -0,0 +1,31 @@ +## Основные понятия +Ниже перечислены основные понятия с указанием соответствующих им аргументов в Terraform провайдере DECORT. +1. **Контроллер облачной платформы DECORT** – управляющее приложение, которое обеспечивает авторизацию пользователей и оркестрацию облачных ресурсов. + - Адрес контроллера задается в обязательном аргументе `controller_url` на стадии инициализации Terraform провайдера DECORT. Например, `controller_url= "https://ds1.digitalenergy.online"` +2. **Авторизационный провайдер** – приложение, работающее по протоколу Oauth2, предназначенное для выпуска и валидации токенов доступа к контроллеру облачной платформы в соответствующих режимах авторизации. Все действия в платформе должны выполняться авторизованными пользователями, и авторизационное приложение позволяет получить токен доступа, действующий некоторое ограниченное время, наличие которого подтверждает успешную авторизацию. + - Адрес авторизационного провайдера задается в аргументе`oauth2_url` на стадии инициализации Terraform провайдера DECORT. Например `oauth2_url= "https://sso.digitalenergy.online"` +3. **Подписчик** (_account_) – сущность, которая используется для группирования облачных ресурсов по принадлежности к определенному клиенту для целей учета потребления и биллинга. + - Имя подписчика задается аргументом `account_name` при вызове _resource_ или _data_ функций провайдера. Альтернативной является задание численного идентификатора подписчика в аргументе `account_id`. +4. **Пользователь** (_user_) – пользователь облачной инфраструктуры, представленный учетной записью. Чтобы получить возможность управлять облачными ресурсами (например, создавать виртуальные серверы или дискт) пользователь должен быть ассоциирован с одним или несколькими подписчиками и иметь соответствующие права, определяемые ролевой моделью, принятой в облачной платформе DECORT. Для доступа к платформе пользователь должен авторизоваться одним из способов, описанных ниже в разделе «Способы авторизации». +5. **Ресурсная группа** (_resource group_) – способ группирования вычислительных ресурсов (например, виртуальных серверов по функциональному признаку или принадлежности к одному и тому же проекту). Ресурсную группу можно рассматривать как небольшой персональный дата-центр, в котором размещаются один или несколько серверов и виртуальных сетевых сегментов. Ресурсная группа идентифицируется по комбинации параметров `account` и `name`. Обратите внимание, что имя имя ресурсной группы уникально только в рамках одного и того же `account`. +6. **Вычислительный ресурс** (_compute_) - универсальная абстракция пользовательского сервера в платформе DECORT. Благодаря использованию такой абстракции можно, например, создать одну виртуальную машину на базе KVM Intel x86, а другую - на базе KVM IBM Power, а потом управлять ими - изменять количество CPU/RAM, подключать/отключать диски и т.п. - одинаковым образом, не задумываясь об их архитектурных различиях. В то же время, так как типизация ресурсов в Terraform не поддерживает наследование, различные типы вычислительных ресурсов, доступных на платформе DECORT и абстрагируемых через понятие унифицированный _compute_, в Terraform представлены разными типами (напр., свой тип для виртуальных серверов на базе KVM и свой тип для перспективных x86-совместимых bare metal серверов). +7. **Ресурс хранения** (_disk_) - универсальная абстракция дискового ресурса в платформе DECORT. Платформа поддерживает различные типы систем хранения данных, но при этом управление созданными на разных системах хранения дисками осуществляется посредством унифицированного набора действий, например, "подключить диск к _compute_", "увеличить размер диска", "сделать мгновенный снимок диска", "настроить параметры быстродействия диска". +8. **Виртуальный сервер** – экземпляр _compute_, в основе технической реализации которого лежит виртуальная машина, работающая в облаке DECORT и доступна по сети. Виртуальный сервер характеризуется количеством выделенных ему 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_) - сетевой сегмент, через который платформа DECORT взаимодействует с внешними по отношению к ней сетевыми ресурсами. Например, в случае с публичным облаком на базе DECORT в качестве внешней сети выступает сеть Интернет. В отличие от ViNS платформа не управляет внешней сетью, а лишь пользуется её ресурсами. В платформе может быть настроено несколько внешних сетей с различными диапазонами IP адресов, и существует механизм управления доступом пользователей к внешним сетям. +11. Сетевой доступ к экземпляру _compute_ (виртуальному серверу) реализуется через его подключение к ViNS и/или прямое подключение во внешнюю сеть (External Network). Один и тот же экземпляр _compute_ может одновременно иметь несколько подключений в разные ViNS и/или различные внешние сети. + +## Способы авторизации +Облачная платформа DECORT поддерживает три базовых типа авторизации: +1. С использованием авторизационного провайдера, работающего по протоколу _Oauth2_. Данный способ является предпочтительным, так как обеспечивает бОльшую гибкость и безопасность. Для авторизации в этом режиме при инициализации Terrafrom провайдера DECORT необходимо указать параметры `oauth2_url` и `controller_url`, а также предоставить одно из нижеперечисленного: + - Комбинация Application ID & Application secret, соответствующих пользователю, от имени которого будет осуществляться управление облачными ресурсами в текущей сессии. В процессе проверки предоставленных Application ID & Application secret модуль получает от авторизационного провайдера токен (JSON Web Token, JWT), который затем используется для доступа к указанному контроллеру DECORT. Для авторизации по данному варианту, при инициализации Terraform провайдера DECORT следует установить аргумент `authenticator=decs3o` и задать аргументы `app_id` и `app_secret` (или определить соответствующие переменные окружения `DECORT_APP_ID` и `DECORT_APP_SECRET`). + - JSON Web Token – заранее полученный от авторизационного провайдера токен доступа, ассоциированный с определенным пользователем, от имени которого будет осуществляться управление облачными ресурсами в текущей сессии. Для авторизации по данному варианту, при инициализации Terraform провайдера DECORT следует установить аргумент `authenticator=jwt` и задать аргумент `jwt` (или определить переменную окружения `DECORT_JWT`). +2. С использованием комбинации _имя пользователя : пароль_. Данный режим не использует внешних авторизационных провайдеров и подразумевает, что пользователь с такой комбинацией зарегистрирован непосредственно на указанном в параметре `controller_url` контроллере облачной платформы DECORT. + - Чтобы провайдер авторизовался по данному варианту, при его инициализации следует установить аргумент `authenticator=legacy` и задать аргументы `user` и `password` (или определить соответствующие переменные окружения `DECORT_USER` и `DECORT_PASSWORD`). +3. С использованием авторизационного провайдера, работающего по протоколу _Oauth2_oidc_. Для авторизации в этом режиме при инициализации Terrafrom провайдера DECORT необходимо указать параметры `oauth2_url` и `controller_url`, а также Application ID & Application secret, _имя пользователя и пароль_, соответствующих пользователю, от имени которого будет осуществляться управление облачными ресурсами в текущей сессии, и _имя домена_. В процессе проверки предоставленных Application ID & Application secret и пары _имя пользователя-пароль_ модуль получает от авторизационного провайдера токен (JSON Web Token, JWT), который затем используется для доступа к указанному контроллеру DECORT. Для авторизации по данному варианту, при инициализации Terraform провайдера DECORT следует установить аргумент `authenticator=bvs`, задать аргументы `app_id` и `app_secret` (или определить соответствующие переменные окружения `DECORT_APP_ID` и `DECORT_APP_SECRET`), `bvs_user` и `bvs_password` (или определить соответствующие переменные окружения `DECORT_BVS_USER` и `DECORT_BVS_PASSWORD`), а также указать `domain` (или определить соответствующие переменные окружения `DECORT_DOMAIN`). + +После успешной авторизации пользователь (или приложение-клиент) получает доступ к ресурсам, находящимся под управлением соответствующего DECORT контроллера. Доступ предоставляется в рамках подписчиков (_account_), с которыми ассоциирован данный пользователь (_user_), и в соответствии с присвоенными ему ролями. + +## Пользовательская и административная группы API +Пользовательская группа API - группа API платформы DECORT, которая позволяет выполнять операции с платформой с правами обычного пользователя. Покрывает большую часть задач. +Административная группа API - группа API платформы DECORT, которая позволяет выполнять операции с платформой с расширенными правами. Данные права подразумевают расширенный перечень операций над ресурсами, расширенный перечень ресурсов, расширенную информацию. Требуются права администратора для взаимодействия с этой группой API. diff --git a/wiki/4.7.3/04.-Начало-работы-с-terraform-провайдером-DECORT.md b/wiki/4.7.3/04.-Начало-работы-с-terraform-провайдером-DECORT.md new file mode 100644 index 0000000..edaa664 --- /dev/null +++ b/wiki/4.7.3/04.-Начало-работы-с-terraform-провайдером-DECORT.md @@ -0,0 +1,6 @@ +Данный раздел описывает: +- Системные требования +- Установку провайдера +- Инициализацию провайдера +- Переключение режима работы между разными группами API +- Получение gid/grid_id площадки diff --git a/wiki/4.7.3/04.01-Установка-Terraform-провайдера-DECORT.md b/wiki/4.7.3/04.01-Установка-Terraform-провайдера-DECORT.md new file mode 100644 index 0000000..100329c --- /dev/null +++ b/wiki/4.7.3/04.01-Установка-Terraform-провайдера-DECORT.md @@ -0,0 +1,150 @@ +## Системные требования + +Для запуска провайдера вам потребуется машина, на которой установлен Terraform. + +Кроме того, в связи с тем, что начиная с версии 0.12 Terraform изменил алгоритм поиска и инициализации локальных провайдеров, настройка данного провайдера для работы с Terraform 0.12 или более новыми версиями потребует выполнения ряда дополнительных действий. Подробнее см. [8.3 Настройка локального провайдера для работы с новыми версиями Terraform](https://repository.basistech.ru/BASIS/terraform-provider-decort/src/branch/main/wiki/4.7.3/08.-Полезные-советы#user-content-8-3-настройка-локального-провайдера-для-работы-с-новыми-версиями-terraform.md). + +## Установка +Начиная с версии провайдера `4.3.0` в релизном архиве находятся скрипты-инсталляторы. +Чтобы выполнить установку, необходимо: +1. Перейти по адресу: https://repository.basistech.ru/BASIS/terraform-provider-decort/releases +2. Выбрать необходимую версию провайдера подходящую под операционную систему. +3. Скачать архив. +4. Распаковать архив. +5. Выполнить скрипт установщика, `install.sh` или `install.bat` для Windows.
+*Для запуска `install.sh` не забудьте изменить права доступа к файлу* +```bash +chmod u+x install.sh +``` +6. Дождаться сообщения об успешной установке. Установщик выведет актуальный блок конфигурации провайдера, скопируйте его +```bash +DECORT provider version 4.3.0 has been successfully installed + +Copy this provider configuration to main.tf file: +terraform { + required_providers { + decort = { + version = "4.3.0" + source = "basis/decort/decort" + } + } +} +``` +7. После этого, создайте файл `main.tf` в рабочей директории, которая может находится в любом удобном для пользователя месте. +В данном примере, рабочая директория с файлом main.tf находится по пути: +```bash +~/work/tfdir/main.tf +``` +8. Вставьте в `main.tf` блок конфигурации провайдера, который был выведен на экран установщиком: +```terraform +terraform { + required_providers { + decort = { + version = "4.3.0" + source = "basis/decort/decort" + } + } +} +``` +9. Добавьте в файл блок с инициализацией провайдера. +```terraform +provider "decort" { + 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 провайдер DECORT имеет скомпилированные релизные версии, которые расположены по адресу: [Релизы](https://repository.basistech.ru/BASIS/terraform-provider-decort/releases). +Чтобы выполнить установку из релиза, необходимо: +1. Перейти по адресу: https://repository.basistech.ru/BASIS/terraform-provider-decort/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/decort/decort/4.3.0/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 { + decort = { + version = "4.3.0" + source = "basis/decort/decort" + } + } +} +``` +В поле `version` указывается версия провайдера. +
+**ВНИМАНИЕ: Версии в блоке и в пути к исполняемому файлу провайдера должны совпадать!** + +В поле `source` помещается путь до репозитория с версией вида: + +```bash +${host_name}/${namespace}/${type} +``` + +**ВНИМАНИЕ: Версии в блоке и в пути к исполняемому файлу провайдера должны совпадать!** + +8. Добавьте в файл блок с инициализацией провайдера. +```terraform +provider "decort" { + 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/4.7.3/04.02-Инициализация-Terraform-провайдера-DECORT.md b/wiki/4.7.3/04.02-Инициализация-Terraform-провайдера-DECORT.md new file mode 100644 index 0000000..46b15c9 --- /dev/null +++ b/wiki/4.7.3/04.02-Инициализация-Terraform-провайдера-DECORT.md @@ -0,0 +1,64 @@ +## Список аргументов для инициализации +Перед началом использования любой Terraform провайдер должен быть инициализирован. + +В процессе инициализации Terraform провайдера DECORT проверяется корректность переданных аргументов и выполняется авторизация в указанном контроллере облачной инфраструктуры. Подробнее о способах авторизации в платформе DECORT смотри соответствующий [раздел](https://repository.basistech.ru/BASIS/terraform-provider-decort/src/branch/main/wiki/4.7.3/03.-Обзор-облачной-платформы-DECORT#user-content-способы-авторизации.md). + +При инициализации Terraform провайдера DECORT используются следующие аргументы: + +| Аргумент | Переменная окружения | Описание | +| --- | --- | --- | +| allow_unverified_ssl | - | Если данный аргумент явно установлен в `true`, то провайдер **не будет** проверять SSL сертификаты при взаимодействии с авторизационным сервисом OAuth2 и контроллером облачной платформы.
Отключение проверок может быть полезным при работе в доверенной среде, использующей самоподписанные SSL сертификаты. Однако, так как отключение проверок несёт потенциальные риски безопасности, данную настройку следует использовать с осторожностью.
Разрешённые значения: `false` (значение по умолчанию) и `true`. | +| app_id | DECORT_APP_ID | Идентификатор приложения (клиента) для авторизации в контроллере облачной платформы в режиме `decs3o` или `bvs`.
Аргументы `app_id` и `app_secret` являются обязательными для режимов авторизации `authenticator=decs3o` и `authenticator=bvs`.
Если `app_id` не задан в tf-файле, то провайдер будет использовать значение из переменной окружения `DECORT_APP_ID`. | +| app_secret | DECORT_APP_SECRET | Секретный код приложения (клиента) для авторизации в контроллере облачной платформы в режиме `decs3o` или `bvs`.
Аргументы `app_id` и `app_secret` являются обязательными для режимов авторизации `authenticator=decs3o` и `authenticator=bvs`.
Если `app_secret` не задан в tf-файле, то провайдер будет использовать значение из переменной окружения `DECORT_APP_SECRET`. | +| authenticator | - | Режим авторизации при подключении к контроллеру облачной платформы.
Доступные режимы: `decs3o`, `legacy`, `jwt` или `bvs`.
Данный аргумент является обязательным. | +| bvs_user | DECORT_BVS_USER | Имя пользователя для авторизации в контроллере облачной платформы в режиме `bvs`.
Аргументы `bvs_password` и `bvs_user` являются обязательными для режима авторизации `authenticator=bvs`.
Если `bvs_user` не задан в tf-файле, то провайдер будет использовать значение из переменной окружения `DECORT_BVS_USER`. | +| bvs_password | DECORT_BVS_PASSWORD | Пароль пользователя для авторизации в контроллере облачной платформы в режиме `bvs`.
Аргументы `bvs_user` и `bvs_password` являются обязательными для режима авторизации `authenticator=bvs`.
Если `bvs_password` не задан в tf-файле, то провайдер будет использовать значение из переменной окружения `DECORT_BVS_PASSWORD`. | +| domain | DECORT_DOMAIN | Имя домена в контроллере облачной платформы в режиме `bvs`.
Данный аргумент является обязательным.
Если `domain` не задан в tf-файле, то провайдер будет использовать значение из переменной окружения `DECORT_DOMAIN`. | +| controller_url | DECORT_CONTROLLER_URL | URL контроллера облачной платформы, через который будет осуществляться управление облачными ресурсами.
Данный аргумент является обязательным. | +| jwt | DECORT_JWT | JSON Web Token (JWT), который используется для авторизации в контроллере облачной платформы в режиме `jwt`.
Данный аргумент является обязательным для режима авторизации `authenticator=jwt`.
Если `jwt` не задан в tf-файле, то провайдер будет использовать значение из переменной окружения `DECORT_JWT` | +| oauth2_url | DECORT_OAUTH2_URL | URL авторизационного сервиса OAuth2, который используется для управления доступом пользователей (или программных клиентов) к контроллеру облачной платформы.
Данный аргумент является обязательным для режимов авторизации `authenticator=decs3o`, `authenticator=bvs` и `authenticator=jwt`.
Если `oauth2_url` не задан в tf-файле, то провайдер будет использовать значение из переменной окружения `DECORT_OAUTH2_URL` | +| password | DECORT_PASSWORD | Пароль для авторизации в контроллере облачной платформы в режиме `legacy`.
Аргументы `password` и `user` являются обязательными для режима авторизации `authenticator=legacy`.
Если `password` не задан в tf-файле, то провайдер будет использовать значение из переменной окружения `DECORT_PASSWORD`. | +| user | DECORT_USER | Имя пользователя для авторизации в контроллере облачной платформы в режиме `legacy`.
Аргументы `user` и `password` являются обязательными для режима авторизации `authenticator=legacy`.
Если `user` не задан в tf-файле, то провайдер будет использовать значение из переменной окружения `DECORT_USER`. | + +## Пример инициализации в режиме авторизации `decs3o` +Пример инициализации Terraform провайдера DECORT: +```terraform +provider "decort" { + authenticator = "decs3o" + controller_url = "https://ctrl.decort.online" + oauth2_url = "https://oauth2.decort.online:7777" +} +``` + +В данном примере используется режим авторизации `decs3o`. + +Как отмечено выше, в данном режиме требуется указать аргументы `app_id` и `app_secret`, идентифицирующие пользователя (или приложение-клиент), от лица которого будут выполняться дальнейшие действия. Однако, так как данная информация является конфиденциальной (по сути, она эквивалентна паре _имя пользователя : пароль_), то в общем случае заносить такого рода данные в tf-файл не следует. Рекомендуется определять в среде запуска Terraform переменные окружения `DECORT_APP_ID` и `DECORT_APP_SECRET`, из которых провайдер извлечёт нужные данные. Приведенный пример подразумевает, что нужная информация будет получена из этих переменных окружения. + +Пользователь, от лица которого Terrafrom будет выполнять действия в облачной платформе, должен заранее создать пару _Application ID_ и _Application Secret_ в авторизационном приложении OAuth2. Именно эти значения, а также URL авторизационного приложения Oauth2, должны присваиваться аргументам `app_id`, `app_secret` и `oauth2_url` соответственно для успешной инициализации провайдера. + +Также обратите внимание на формат задания аргументов `controller_url` и `oauth2_url`. В общем случае они должны содержать идентификатор протокола (_https://_) и сетевой порт, если он отличается от порта по умолчанию (в примере для авторизационного сервиса OAuth2 указан порт _7777_). Эту информацию вы можете узнать у администратора вашей облачной инфраструктуры DECORT. + +## Пример инициализации в режиме авторизации `bvs` +Пример инициализации Terraform провайдера DECORT: +```terraform +provider "decort" { + 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 переменные окружения `DECORT_APP_ID` и `DECORT_APP_SECRET`, из которых провайдер извлечёт нужные данные. Приведенный пример подразумевает, что нужная информация будет получена из этих переменных окружения. +Также обязательными аргументами являются: `bvs_user` - имя пользователя, `bvs_password` - пароль пользователя. Рекомендуется не заносить их в tf-файл, а определять в среде запуска Terraform переменные окружения `DECORT_BVS_USER` и `DECORT_BVS_PASSWORD`, из которых провайдер извлечёт нужные данные. Приведенный пример подразумевает, что нужная информация будет получена из этих переменных окружения. +Домен для подключения `domain` - указывается наименование площадки. Данный аргумент является обязательным. Рекомендуется не заносить его в tf-файл, а определять в среде запуска Terraform переменную окружения `DECORT_DOMAIN`, из которой провайдер извлечёт нужные данные. Приведенный пример подразумевает, что нужная информация будет получена из этих переменных окружения. + +Пользователь, от лица которого Terrafrom будет выполнять действия в облачной платформе, должен заранее получить от администратора _Application ID_ и _Application Secret_, _bvs user_ и _bvs password_, а также _domain_. А также осуществить первичный вход на платформу посредством браузера. + +Также обратите внимание на формат задания аргументов `controller_url` и `oauth2_url`. В общем случае они должны содержать идентификатор протокола (_https://_) и сетевой порт, если он отличается от порта по умолчанию (в примере для авторизационного сервиса OAuth2 указан порт _8443_). Эту информацию вы можете узнать у администратора вашей облачной инфраструктуры DECORT. diff --git a/wiki/4.7.3/04.03-Переключение-между-группами-API.md b/wiki/4.7.3/04.03-Переключение-между-группами-API.md new file mode 100644 index 0000000..fb722ac --- /dev/null +++ b/wiki/4.7.3/04.03-Переключение-между-группами-API.md @@ -0,0 +1,38 @@ +Так как платформа DECORT предоставляет для работы две группы 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/4.7.3/04.04-Получение-gid-или-grid_id.md b/wiki/4.7.3/04.04-Получение-gid-или-grid_id.md new file mode 100644 index 0000000..4b316ac --- /dev/null +++ b/wiki/4.7.3/04.04-Получение-gid-или-grid_id.md @@ -0,0 +1,31 @@ +Платформа может располагаться на нескольких площадках(grid). +Такие площадки имеют свой id. +Для создания некоторых ресурсов требуется ввести grid_id или gid площадки. +Получение gid различается для пользовательского и административного API. + +## Получение gid для пользовательского API +Для получения gid с помощью пользовательского API, необходимо получить информацию из _data_source_ функции _decort_locations_list_, как указано ниже: +```terraform +data "decort_locations_list" "ll" { + +} + +output "test" { + value = data.decort_locations_list.ll +} +``` +В файл состояния будет сохранен результат, где можно посмотреть доступные для работы площадки. + +## Получение gid для административного API +Для получения gid с помощью административного API, необходимо получить информацию из _data_source_ функции _decort_grid_list_, как указано ниже: +```terraform +data "decort_grid_list" "gl" { + +} + +output "test" { + value = data.decort_grid_list.gl +} + +``` +В файл состояния будет сохранен результат, где можно посмотреть доступные для работы площадки. diff --git a/wiki/4.7.3/04.05-Сборка-terraform-провайдера-в-образ.md b/wiki/4.7.3/04.05-Сборка-terraform-провайдера-в-образ.md new file mode 100644 index 0000000..02bc8b7 --- /dev/null +++ b/wiki/4.7.3/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://github.com/rudecs/terraform-provider-decort.git +``` +2. Перейти в директорию со скачанным кодом: +```bash +cd terraform-provider-decort +``` +3. Выполнить команду: +```bash +make image +``` +В результате выполнения данной последовательности, будет создан docker образ, который содержит в себе приложение terraform, terraform провайдер. diff --git a/wiki/4.7.3/05.-Работа-с-terraform.md b/wiki/4.7.3/05.-Работа-с-terraform.md new file mode 100644 index 0000000..675f2ea --- /dev/null +++ b/wiki/4.7.3/05.-Работа-с-terraform.md @@ -0,0 +1,4 @@ +Раздел описывает некоторые практики работы с terraform, которые могут быть полезны пользователю. +Раздел включает в себя следующие статьи: +- Импортирование ресурсов +- Работа с таймаутами diff --git a/wiki/4.7.3/05.01-Импортирование-ресурсов.md b/wiki/4.7.3/05.01-Импортирование-ресурсов.md new file mode 100644 index 0000000..8a419d3 --- /dev/null +++ b/wiki/4.7.3/05.01-Импортирование-ресурсов.md @@ -0,0 +1,75 @@ +Импортирование ресурсов в terraform позволяет привести в соответствие состояние terraform (.tfstate) к состоянию ресурса в платформе. +Необходимость такого приведения возникает в нескольких случаях: +- Ресурс был создан через портал платформы, работа продолжается через terraform провайдер, +- Ресурс был создан через terraform провайдер, однако был изменен через портал платформы, +- Ресурс был создан через terraform провайдер, однако был изменен другим пользователем через terraform провайдер, +- И так далее + +Такие расхождения в состоянии ресурсов нередки, путей их решения несколько: +- Использовать импортирование ресурсов, +- Использовать общие файлы состояний ресурсов, к которым будут иметь доступ все участники, занятые в работе с платформой. +В текущем разделе рассматривается первый вариант. + +## Импортирование ресурсов +Импортирование ресурсов позволяет совершить запрос к платформе, чтобы сформировать файл состояния. +Чтобы совершить импортирование ресурсов необходимо ввести сл. команду: +```bash +terraform import . +``` +## Пример +Предположим, что у нас ресурс, описывающий диск: +```terraform +resource "decort_disk" "disk" { + account_id = 121212 + gid = 3333 + disk_name = "mySuperDisk" + size_max = 100500 +} +``` +Если запустить команду: +```bash +terraform apply +``` +То у нас будет создан новый диск. +Но, такой диск уже есть на площадке и мы хотели бы сформировать .tfstate для этого ресурса. +Поэтому, для начала, необходимо получить список дисков: +```terraform +data "decort_disk_list" "dl"{ + +} +output "test" { + value = data.decort_disk_list.dl +} +``` +В полученных данных необходимо найти требуемый диск, получить его id - параметр disk_id. Пусть это будет - 777777 +Теперь можно выполнить импортирование: +```bash +terraform import decort_disk.disk 777777 +``` +Команда должна успешно завершиться, появиться файл состояний, который позволит манипулировать ресурсом. + +## Ошибки при импортировании +При импортировании ресурса может возникнуть сл. ошибка: +```bash +Error: : required field is not set +``` +Где - наименование поля. +Ошибка возникает в том случае, если в описании ресурса отсутствует обязательное поле. +Например: +```terraform +resource "decort_disk" "disk" { + account_id = 121212 + gid = 3333 + size_max = 100500 +} +``` +В приведенном выше описании отсутствует поле disk_name, поэтому, при попытке импортирования возникнет ошибка. +Для ее устранения, необходимо выполнить запрос на получение списка дисков, найти недостающее поле, после чего добавить его в описание ресурса. +После этого повторить попытку импортирования. + +## Общий алгоритм устранения ошибок +1. Выполнить запрос импортирования +2. В случае ошибки - внести недостающие поля. +3. Повторить п.1. + + diff --git a/wiki/4.7.3/05.02-Работа-с-таймаутами.md b/wiki/4.7.3/05.02-Работа-с-таймаутами.md new file mode 100644 index 0000000..9a739b4 --- /dev/null +++ b/wiki/4.7.3/05.02-Работа-с-таймаутами.md @@ -0,0 +1,100 @@ +Terraform провайдер DECORT поддерживает тонкую настройку таймаутов выполнения запросов к платформе. Таймауты необходимы для определения максимального времени выполнения запроса. При превышении этого времени соединение рвется и запрос считается невыполненным. +Таймауты применяются при работе с _resource_ функциями провайдера. _Data source_ функции по-умолчанию имеют таймаут в 20 минут и изменяться не может. + +## Стандартные таймауты terraform +| Операция | Время | Описание | +| --- | --- | --- | +| create | 20 минут | Создание ресурса | +| read | 20 минут | Чтение ресурса | +| update | 20 минут | Обновление ресурса | +| delete | 20 минут | Удаление ресурса | +| default | 20 минут | Значение по умолчанию. Устанавливает значение для всех операций | + +## Стандартные таймауты провайдера DECORT +В провайдере DECORT таймауты переопределены для того, чтобы уменьшить нагрузку на платформу. +| Операция | Время | Описание | +| --- | --- | --- | +| create | 10 минут | Создание ресурса | +| read | 5 минут | Чтение ресурса | +| update | 5 минут | Обновление ресурса | +| delete | 5 минут | Удаление ресурса | +| default | 5 минут | Значение по умолчанию. Устанавливает значение для всех операций | + +## Установка таймаутов +Все таймауты можно установить самостоятельно для каждого ресурса. +Для этого используется блок _timeouts_, который имеется в каждом ресурсе провайдера. +Пример: +```terraform +resource "decort_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