Compare commits

...

8 Commits

Author SHA1 Message Date
bd95fa8b78 4.9.10 2026-04-16 16:23:13 +03:00
dayterr
0720d7f6be 4.9.9 2026-03-10 16:13:03 +03:00
dayterr
a475cf3f75 4.9.9 2026-03-06 16:11:37 +03:00
476a09ed53 4.9.8 2026-02-26 18:00:29 +03:00
bbf45adfeb 4.9.7 2026-02-06 16:28:22 +03:00
987fef81d7 4.9.6 2025-12-22 15:43:18 +03:00
dayterr
f44c69003b 4.9.5 2025-11-07 15:34:39 +03:00
22897c3bf5 4.9.4 2025-08-12 12:30:26 +03:00
33 changed files with 3793 additions and 125 deletions

View File

@@ -1,9 +1,8 @@
## Version 4.9.3
## Version 4.9.10
### Исправлено
### Добавлено
#### kvmvm
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BATF-1016 | Ошибка при изменении полей `ram` и `cpu`, приводящая к невозможности измения параметров виртуальной машины в resources `decort_kvmvm` и `decort_cb_kvmvm` в cloudapi/kvmvm и в cloudbroker/kvmvm |
| BATF-1018 | Ошибка при изменении поля `started`, приводящая к невозможности запуска виртуальной машины в resources `decort_kvmvm` в cloudapi/kvmvm |
| BATF-1270 | Опциональное поле `iotune` в блоке `disks` в resource `decort_kvmvm` в cloudapi/kvmvm и в resource `decort_cb_kvmvm` в cloudbroker/kvmvm |

View File

@@ -7,7 +7,7 @@ ZIPDIR = ./zip
BINARY=${NAME}
WORKPATH= ./examples/terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAMESPACE}/${VERSION}/${OS_ARCH}
MAINPATH = ./cmd/decort/
VERSION=4.9.3
VERSION=4.9.10
OS_ARCH=$(shell go env GOHOSTOS)_$(shell go env GOHOSTARCH)
FILES = ${BINARY}_${VERSION}_darwin_amd64\

View File

@@ -2,7 +2,7 @@
Terraform provider для платформы Digital Energy Cloud Orchestration Technology (DECORT)
## Соответсвие версий платформы версиям провайдера
## Соответствие версий платформы версиям провайдера
| Версия DECORT API | Версия провайдера Terraform |
| ------ | ------ |

View File

@@ -183,6 +183,7 @@ Optional:
- `desc` (String) Optional description
- `disk_type` (String) The type of disk in terms of its role in compute: 'B=Boot, D=Data'
- `image_id` (Number) Specify image id for create disk from template
- `iotune` (Block List, Max: 1) (see [below for nested schema](#nestedblock--disks--iotune))
- `node_ids` (Set of Number)
- `permanently` (Boolean) Disk deletion status
- `pool` (String) Pool name; by default will be chosen automatically
@@ -196,6 +197,26 @@ Read-Only:
- `size_max` (Number)
- `size_used` (Number)
<a id="nestedblock--disks--iotune"></a>
### Nested Schema for `disks.iotune`
Optional:
- `read_bytes_sec` (Number)
- `read_bytes_sec_max` (Number)
- `read_iops_sec` (Number)
- `read_iops_sec_max` (Number)
- `size_iops_sec` (Number)
- `total_bytes_sec` (Number)
- `total_bytes_sec_max` (Number)
- `total_iops_sec` (Number)
- `total_iops_sec_max` (Number)
- `write_bytes_sec` (Number)
- `write_bytes_sec_max` (Number)
- `write_iops_sec` (Number)
- `write_iops_sec_max` (Number)
<a id="nestedblock--libvirt_settings"></a>
### Nested Schema for `libvirt_settings`

View File

@@ -177,6 +177,7 @@ Optional:
- `desc` (String) Optional description
- `disk_type` (String) The type of disk in terms of its role in compute: 'B=Boot, D=Data'
- `image_id` (Number) Specify image id for create disk from template
- `iotune` (Block List, Max: 1) (see [below for nested schema](#nestedblock--disks--iotune))
- `permanently` (Boolean) Disk deletion status
- `pool` (String) Pool name; by default will be chosen automatically
- `sep_id` (Number) Storage endpoint provider ID; by default the same with boot disk
@@ -189,6 +190,26 @@ Read-Only:
- `size_max` (Number)
- `size_used` (Number)
<a id="nestedblock--disks--iotune"></a>
### Nested Schema for `disks.iotune`
Optional:
- `read_bytes_sec` (Number)
- `read_bytes_sec_max` (Number)
- `read_iops_sec` (Number)
- `read_iops_sec_max` (Number)
- `size_iops_sec` (Number)
- `total_bytes_sec` (Number)
- `total_bytes_sec_max` (Number)
- `total_iops_sec` (Number)
- `total_iops_sec_max` (Number)
- `write_bytes_sec` (Number)
- `write_bytes_sec_max` (Number)
- `write_iops_sec` (Number)
- `write_iops_sec_max` (Number)
<a id="nestedblock--network"></a>
### Nested Schema for `network`
@@ -276,6 +297,7 @@ Read-Only:
- `disk_name` (String)
- `disk_type` (String)
- `image_id` (Number)
- `iotune` (List of Object) (see [below for nested schema](#nestedobjatt--boot_disk--iotune))
- `permanently` (Boolean)
- `pool` (String)
- `present_to` (Map of Number)
@@ -285,6 +307,26 @@ Read-Only:
- `size_max` (Number)
- `size_used` (Number)
<a id="nestedobjatt--boot_disk--iotune"></a>
### Nested Schema for `boot_disk.iotune`
Read-Only:
- `read_bytes_sec` (Number)
- `read_bytes_sec_max` (Number)
- `read_iops_sec` (Number)
- `read_iops_sec_max` (Number)
- `size_iops_sec` (Number)
- `total_bytes_sec` (Number)
- `total_bytes_sec_max` (Number)
- `total_iops_sec` (Number)
- `total_iops_sec_max` (Number)
- `write_bytes_sec` (Number)
- `write_bytes_sec_max` (Number)
- `write_iops_sec` (Number)
- `write_iops_sec_max` (Number)
<a id="nestedatt--interfaces"></a>
### Nested Schema for `interfaces`

View File

@@ -0,0 +1,421 @@
package disks
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)
func resourceDiskV1() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"account_id": {
Type: schema.TypeInt,
Required: true,
//ForceNew: true,
Description: "The unique ID of the subscriber-owner of the disk",
},
"disk_name": {
Type: schema.TypeString,
Required: true,
Description: "Name of disk",
},
"size_max": {
Type: schema.TypeInt,
Required: true,
Description: "Size in GB",
},
"gid": {
Type: schema.TypeInt,
Required: true,
//ForceNew: true,
Description: "ID of the grid (platform)",
},
"pool": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Pool for disk location",
},
"sep_id": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "Storage endpoint provider ID to create disk",
},
"desc": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Description of disk",
},
"type": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringInSlice([]string{"D", "B", "T"}, false),
Description: "The type of disk in terms of its role in compute: 'B=Boot, D=Data, T=Temp'",
},
"detach": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Detaching the disk from compute",
},
"permanently": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Whether to completely delete the disk, works only with non attached disks",
},
"shareable": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"iotune": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"read_bytes_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "Number of bytes to read per second",
},
"read_bytes_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "Maximum number of bytes to read",
},
"read_iops_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "Number of io read operations per second",
},
"read_iops_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "Maximum number of io read operations",
},
"size_iops_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "Size of io operations",
},
"total_bytes_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "Total size bytes per second",
},
"total_bytes_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "Maximum total size of bytes per second",
},
"total_iops_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "Total number of io operations per second",
},
"total_iops_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "Maximum total number of io operations per second",
},
"write_bytes_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "Number of bytes to write per second",
},
"write_bytes_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "Maximum number of bytes to write per second",
},
"write_iops_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "Number of write operations per second",
},
"write_iops_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "Maximum number of write operations per second",
},
},
},
},
"present_to": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"disk_id": {
Type: schema.TypeInt,
Computed: true,
Description: "Disk ID. Duplicates the value of the ID parameter",
},
"account_name": {
Type: schema.TypeString,
Computed: true,
Description: "The name of the subscriber '(account') to whom this disk belongs",
},
"acl": {
Type: schema.TypeString,
Computed: true,
},
// "boot_partition": {
// Type: schema.TypeInt,
// Computed: true,
// Description: "Number of disk partitions",
// },
"computes": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"compute_id": {
Type: schema.TypeString,
Computed: true,
},
"compute_name": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"created_time": {
Type: schema.TypeInt,
Computed: true,
Description: "Created time",
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
Description: "Deleted time",
},
"destruction_time": {
Type: schema.TypeInt,
Computed: true,
Description: "Time of final deletion",
},
"devicename": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the device",
},
// "disk_path": {
// Type: schema.TypeString,
// Computed: true,
// Description: "Disk path",
// },
// "guid": {
// Type: schema.TypeInt,
// Computed: true,
// Description: "Disk ID on the storage side",
// },
"image_id": {
Type: schema.TypeInt,
Computed: true,
Description: "Image ID",
},
"images": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Description: "IDs of images using the disk",
},
// "iqn": {
// Type: schema.TypeString,
// Computed: true,
// Description: "Disk IQN",
// },
// "login": {
// Type: schema.TypeString,
// Computed: true,
// Description: "Login to access the disk",
// },
// "milestones": {
// Type: schema.TypeInt,
// Computed: true,
// Description: "Milestones",
// },
"order": {
Type: schema.TypeInt,
Computed: true,
Description: "Disk order",
},
"params": {
Type: schema.TypeString,
Computed: true,
Description: "Disk params",
},
"parent_id": {
Type: schema.TypeInt,
Computed: true,
Description: "ID of the parent disk",
},
// "passwd": {
// Type: schema.TypeString,
// Computed: true,
// Description: "Password to access the disk",
// },
"pci_slot": {
Type: schema.TypeInt,
Computed: true,
Description: "ID of the pci slot to which the disk is connected",
},
// "purge_attempts": {
// Type: schema.TypeInt,
// Computed: true,
// Description: "Number of deletion attempts",
// },
"purge_time": {
Type: schema.TypeInt,
Computed: true,
Description: "Time of the last deletion attempt",
},
"replication": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"disk_id": {
Type: schema.TypeInt,
Computed: true,
},
"pool_id": {
Type: schema.TypeString,
Computed: true,
},
"role": {
Type: schema.TypeString,
Computed: true,
},
"self_volume_id": {
Type: schema.TypeString,
Computed: true,
},
"storage_id": {
Type: schema.TypeString,
Computed: true,
},
"volume_id": {
Type: schema.TypeString,
Computed: true,
},
},
},
Description: "Replication status",
},
// "reality_device_number": {
// Type: schema.TypeInt,
// Computed: true,
// Description: "Reality device number",
// },
// "reference_id": {
// Type: schema.TypeString,
// Computed: true,
// Description: "ID of the reference to the disk",
// },
"res_id": {
Type: schema.TypeString,
Computed: true,
Description: "Resource ID",
},
"res_name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the resource",
},
"role": {
Type: schema.TypeString,
Computed: true,
Description: "Disk role",
},
"sep_type": {
Type: schema.TypeString,
Computed: true,
Description: "Type SEP. Defines the type of storage system and contains one of the values set in the cloud platform",
},
"size_used": {
Type: schema.TypeFloat,
Computed: true,
Description: "Number of used space, in GB",
},
"snapshots": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"guid": {
Type: schema.TypeString,
Computed: true,
Description: "ID of the snapshot",
},
"label": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the snapshot",
},
"res_id": {
Type: schema.TypeString,
Computed: true,
Description: "Reference to the snapshot",
},
"snap_set_guid": {
Type: schema.TypeString,
Computed: true,
Description: "The set snapshot ID",
},
"snap_set_time": {
Type: schema.TypeInt,
Computed: true,
Description: "The set time of the snapshot",
},
"timestamp": {
Type: schema.TypeInt,
Computed: true,
Description: "Snapshot time",
},
},
},
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: "Disk status",
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
Description: "Technical status of the disk",
},
"vmid": {
Type: schema.TypeInt,
Computed: true,
Description: "Virtual Machine ID (Deprecated)",
},
},
}
}

View File

@@ -783,7 +783,7 @@ func resourceDiskSchemaMake() map[string]*schema.Schema {
func ResourceDisk() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
SchemaVersion: 2,
CreateContext: resourceDiskCreate,
ReadContext: resourceDiskRead,
@@ -803,5 +803,12 @@ func ResourceDisk() *schema.Resource {
},
Schema: resourceDiskSchemaMake(),
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceDiskV1().CoreConfigSchema().ImpliedType(),
Upgrade: resourceDiskUpgradeV1,
Version: 1,
},
},
}
}

View File

@@ -0,0 +1,14 @@
package disks
import (
"context"
log "github.com/sirupsen/logrus"
)
func resourceDiskUpgradeV1(ctx context.Context, rawState map[string]interface{}, meta any) (map[string]interface{}, error) {
log.Debug("resourceDiskUpgradeV1: upgrading state")
rawState["present_to"] = make(map[string]uint64)
return rawState, nil
}

View File

@@ -0,0 +1,782 @@
package image
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/statefuncs"
)
func resourceImageFromBlankComputeSchemaV1() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"compute_id": {
Type: schema.TypeInt,
Required: true,
Description: "Compute Id",
},
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of the rescue disk",
},
"boot_type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"bios", "uefi"}, true),
Description: "Boot type of image BIOS or UEFI",
},
"type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"linux", "windows", "other"}, true),
Description: "Image type linux, windows or other",
},
"username": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Optional username for the image",
},
"password": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Optional password for the image",
},
"account_id": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "AccountId to make the image exclusive",
},
"sep_id": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "storage endpoint provider ID",
},
"pool_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "pool for image create",
},
"hot_resize": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
Description: "Does this machine supports hot resize",
},
"async_mode": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "create an image in async/sync mode",
},
"image_id": {
Type: schema.TypeInt,
Computed: true,
},
"unc_path": {
Type: schema.TypeString,
Computed: true,
},
"ckey": {
Type: schema.TypeString,
Computed: true,
},
"acl": {
Type: schema.TypeString,
Computed: true,
},
"architecture": {
Type: schema.TypeString,
Computed: true,
},
"bootable": {
Type: schema.TypeBool,
Computed: true,
},
"compute_ci_id": {
Type: schema.TypeInt,
Computed: true,
},
"cd_presented_to": {
Type: schema.TypeString,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
"drivers": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"enabled": {
Type: schema.TypeBool,
Computed: true,
},
"gid": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"history": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"guid": {
Type: schema.TypeString,
Computed: true,
},
"id": {
Type: schema.TypeInt,
Computed: true,
},
"timestamp": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
"last_modified": {
Type: schema.TypeInt,
Computed: true,
},
"link_to": {
Type: schema.TypeInt,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"image_name": {
Type: schema.TypeString,
Computed: true,
},
"network_interface_naming": {
Type: schema.TypeString,
Computed: true,
},
"provider_name": {
Type: schema.TypeString,
Computed: true,
},
"purge_attempts": {
Type: schema.TypeInt,
Computed: true,
},
"present_to": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"res_id": {
Type: schema.TypeString,
Computed: true,
},
"rescuecd": {
Type: schema.TypeBool,
Computed: true,
},
"shared_with": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"size": {
Type: schema.TypeInt,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
"version": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceImageFromBlankDiskSchemaV1() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"disk_id": {
Type: schema.TypeInt,
Required: true,
Description: "Disk Id",
},
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of the rescue disk",
},
"boot_type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"bios", "uefi"}, true),
Description: "Boot type of image BIOS or UEFI",
},
"type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"linux", "windows", "other"}, true),
Description: "Image type linux, windows or other",
},
"architecture": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"X86_64"}, true),
Description: "binary architecture of this image, one of X86_64",
},
"username": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Optional username for the image",
},
"password": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Optional password for the image",
},
"account_id": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "AccountId to make the image exclusive",
},
"sep_id": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "storage endpoint provider ID",
},
"pool_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "pool for image create",
},
"drivers": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{
StateFunc: statefuncs.StateFuncToUpper,
ValidateFunc: validation.StringInSlice([]string{"SVA_KVM_X86", "KVM_X86"}, false), // observe case while validating
Type: schema.TypeString,
},
Description: "List of types of compute suitable for image. Example: [ \"KVM_X86\" ]",
},
"bootable": {
Type: schema.TypeBool,
Optional: true,
Default: true,
Description: "bootable image",
},
"hot_resize": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
Description: "Does this machine supports hot resize",
},
"async_mode": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "create an image in async/sync mode",
},
"image_id": {
Type: schema.TypeInt,
Computed: true,
},
"unc_path": {
Type: schema.TypeString,
Computed: true,
},
"ckey": {
Type: schema.TypeString,
Computed: true,
},
"acl": {
Type: schema.TypeString,
Computed: true,
},
"compute_ci_id": {
Type: schema.TypeInt,
Computed: true,
},
"cd_presented_to": {
Type: schema.TypeString,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
"enabled": {
Type: schema.TypeBool,
Computed: true,
},
"gid": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"history": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"guid": {
Type: schema.TypeString,
Computed: true,
},
"id": {
Type: schema.TypeInt,
Computed: true,
},
"timestamp": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
"last_modified": {
Type: schema.TypeInt,
Computed: true,
},
"link_to": {
Type: schema.TypeInt,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"image_name": {
Type: schema.TypeString,
Computed: true,
},
"network_interface_naming": {
Type: schema.TypeString,
Computed: true,
},
"provider_name": {
Type: schema.TypeString,
Computed: true,
},
"purge_attempts": {
Type: schema.TypeInt,
Computed: true,
},
"present_to": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"res_id": {
Type: schema.TypeString,
Computed: true,
},
"rescuecd": {
Type: schema.TypeBool,
Computed: true,
},
"shared_with": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"size": {
Type: schema.TypeInt,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
"version": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func dataSourceImageExtendSchemaV1() map[string]*schema.Schema {
return map[string]*schema.Schema{
"image_id": {
Type: schema.TypeInt,
Required: true,
},
"show_all": {
Type: schema.TypeBool,
Default: false,
Optional: true,
},
"unc_path": {
Type: schema.TypeString,
Computed: true,
},
"ckey": {
Type: schema.TypeString,
Computed: true,
},
"account_id": {
Type: schema.TypeInt,
Computed: true,
},
"acl": {
Type: schema.TypeString,
Computed: true,
},
"architecture": {
Type: schema.TypeString,
Computed: true,
},
"boot_type": {
Type: schema.TypeString,
Computed: true,
},
"bootable": {
Type: schema.TypeBool,
Computed: true,
},
"compute_ci_id": {
Type: schema.TypeInt,
Computed: true,
},
"cd_presented_to": {
Type: schema.TypeString,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
"drivers": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"enabled": {
Type: schema.TypeBool,
Computed: true,
},
"gid": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"history": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"guid": {
Type: schema.TypeString,
Computed: true,
},
"id": {
Type: schema.TypeInt,
Computed: true,
},
"timestamp": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
"hot_resize": {
Type: schema.TypeBool,
Computed: true,
},
"last_modified": {
Type: schema.TypeInt,
Computed: true,
},
"link_to": {
Type: schema.TypeInt,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"image_name": {
Type: schema.TypeString,
Computed: true,
},
"network_interface_naming": {
Type: schema.TypeString,
Computed: true,
},
"password": {
Type: schema.TypeString,
Computed: true,
},
"pool_name": {
Type: schema.TypeString,
Computed: true,
},
"provider_name": {
Type: schema.TypeString,
Computed: true,
},
"purge_attempts": {
Type: schema.TypeInt,
Computed: true,
},
"present_to": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"res_id": {
Type: schema.TypeString,
Computed: true,
},
"rescuecd": {
Type: schema.TypeBool,
Computed: true,
},
"sep_id": {
Type: schema.TypeInt,
Computed: true,
},
"shared_with": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"size": {
Type: schema.TypeInt,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
"type": {
Type: schema.TypeString,
Computed: true,
},
"username": {
Type: schema.TypeString,
Computed: true,
},
"version": {
Type: schema.TypeString,
Computed: true,
},
}
}
func resourceMainImageSchemaV1(sch map[string]*schema.Schema) map[string]*schema.Schema {
delete(sch, "show_all")
sch["name"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "Name of the rescue disk",
}
sch["url"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "URL where to download media from",
}
sch["image_id"] = &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "image id",
}
sch["boot_type"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"bios", "uefi"}, true),
Description: "Boot type of image bios or uefi",
}
sch["type"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"linux", "windows", "other"}, true),
Description: "Image type linux, windows or other",
}
sch["hot_resize"] = &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
Description: "Does this machine supports hot resize",
}
sch["username"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Optional username for the image",
}
sch["password"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Optional password for the image",
}
sch["account_id"] = &schema.Schema{
Type: schema.TypeInt,
Required: true,
Description: "AccountId to make the image exclusive",
}
sch["username_dl"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Description: "username for upload binary media",
}
sch["password_dl"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Description: "password for upload binary media",
}
sch["pool_name"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "pool for image create",
}
sch["sep_id"] = &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "storage endpoint provider ID",
}
sch["architecture"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringInSlice([]string{"X86_64"}, true),
Description: "binary architecture of this image, one of X86_64",
}
sch["drivers"] = &schema.Schema{
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
}
sch["network_interface_naming"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringInSlice([]string{"eth", "ens"}, true),
Description: "select a network interface naming pattern for your Linux machine. eth - onboard, ens - pci slot naming",
}
return sch
}
func resourceImageSchemaV1() *schema.Resource {
return &schema.Resource{Schema: resourceMainImageSchemaV1(dataSourceImageExtendSchemaV1())}
}
func resourceMainImageVirtualSchemaV1(sch map[string]*schema.Schema) map[string]*schema.Schema {
delete(sch, "show_all")
sch["name"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "Name of the rescue disk",
}
sch["link_to"] = &schema.Schema{
Type: schema.TypeInt,
Required: true,
Description: "ID of real image to link this virtual image to upon creation",
}
sch["image_id"] = &schema.Schema{
Type: schema.TypeInt,
Computed: true,
Description: "Image id",
}
return sch
}
func resourceImageVirtualSchemaV1() *schema.Resource {
return &schema.Resource{Schema: resourceMainImageVirtualSchemaV1(dataSourceImageExtendSchemaV1())}
}

View File

@@ -235,7 +235,7 @@ func resourceImageUpdate(ctx context.Context, d *schema.ResourceData, m interfac
func ResourceImage() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
SchemaVersion: 2,
CreateContext: resourceImageCreate,
ReadContext: resourceImageRead,
@@ -255,5 +255,12 @@ func ResourceImage() *schema.Resource {
},
Schema: resourceImageSchemaMake(dataSourceImageExtendSchemaMake()),
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceImageSchemaV1().CoreConfigSchema().ImpliedType(),
Upgrade: resourcePresentToUpgradeV1,
Version: 1,
},
},
}
}

View File

@@ -255,7 +255,7 @@ func resourceImageFromBlankComputeUpdate(ctx context.Context, d *schema.Resource
func ResourceImageFromBlankCompute() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
SchemaVersion: 2,
CreateContext: resourceImageFromBlankComputeCreate,
ReadContext: resourceImageFromBlankComputeRead,
@@ -275,6 +275,13 @@ func ResourceImageFromBlankCompute() *schema.Resource {
},
Schema: resourceImageFromBlankComputeSchemaMake(),
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceImageFromBlankComputeSchemaV1().CoreConfigSchema().ImpliedType(),
Upgrade: resourcePresentToUpgradeV1,
Version: 1,
},
},
}
}

View File

@@ -245,7 +245,7 @@ func resourceImageFromPlatformDiskUpdate(ctx context.Context, d *schema.Resource
func ResourceImageFromPlatformDisk() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
SchemaVersion: 2,
CreateContext: resourceImageFromPlatformDiskCreate,
ReadContext: resourceImageFromPlatformDiskRead,
@@ -265,6 +265,13 @@ func ResourceImageFromPlatformDisk() *schema.Resource {
},
Schema: resourceImageFromPlatformDiskSchemaMake(),
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceImageFromBlankDiskSchemaV1().CoreConfigSchema().ImpliedType(),
Upgrade: resourcePresentToUpgradeV1,
Version: 1,
},
},
}
}

View File

@@ -107,7 +107,7 @@ func resourceImageVirtualLink(ctx context.Context, d *schema.ResourceData, m int
func ResourceImageVirtual() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
SchemaVersion: 2,
CreateContext: resourceImageVirtualCreate,
ReadContext: resourceImageRead,
@@ -127,5 +127,12 @@ func ResourceImageVirtual() *schema.Resource {
},
Schema: resourceImageVirtualSchemaMake(dataSourceImageExtendSchemaMake()),
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceImageVirtualSchemaV1().CoreConfigSchema().ImpliedType(),
Upgrade: resourcePresentToUpgradeV1,
Version: 1,
},
},
}
}

View File

@@ -0,0 +1,14 @@
package image
import (
"context"
log "github.com/sirupsen/logrus"
)
func resourcePresentToUpgradeV1(ctx context.Context, rawState map[string]interface{}, meta any) (map[string]interface{}, error) {
log.Debug("resourcePresentToUpgradeV1: upgrading state")
rawState["present_to"] = make(map[string]uint64)
return rawState, nil
}

View File

@@ -276,10 +276,6 @@ func flattenBootDisk(bootDisk *compute.ItemComputeDisk) []map[string]interface{}
func flattenComputeDisksDemo(disksList compute.ListComputeDisks, disksBlocks, extraDisks []interface{}, bootDiskId uint64) []map[string]interface{} {
res := make([]map[string]interface{}, 0, len(disksList))
if len(disksBlocks) == 0 {
return res
}
sort.Slice(disksList, func(i, j int) bool {
return disksList[i].ID < disksList[j].ID
})
@@ -291,7 +287,11 @@ func flattenComputeDisksDemo(disksList compute.ListComputeDisks, disksBlocks, ex
continue
}
pernamentlyValue := disksBlocks[indexDataDisks].(map[string]interface{})["permanently"].(bool)
permanentlyValue := false
if indexDataDisks < len(disksBlocks) {
permanentlyValue = disksBlocks[indexDataDisks].(map[string]interface{})["permanently"].(bool)
}
temp := map[string]interface{}{
"disk_name": disk.Name,
@@ -305,8 +305,9 @@ func flattenComputeDisksDemo(disksList compute.ListComputeDisks, disksBlocks, ex
"desc": disk.Description,
"image_id": disk.ImageID,
"size": disk.SizeMax,
"permanently": pernamentlyValue,
"permanently": permanentlyValue,
"present_to": disk.PresentTo,
"iotune": flattenIotune(disk.IOTune),
}
res = append(res, temp)
indexDataDisks++
@@ -447,6 +448,9 @@ func flattenCompute(d *schema.ResourceData, computeRec compute.RecordCompute, pc
d.Set("boot_type", computeRec.BootType)
d.Set("hot_resize", computeRec.HotResize)
d.Set("network_interface_naming", computeRec.NetworkInterfaceNaming)
d.Set("cpu_pin", computeRec.CPUPin)
d.Set("numa_affinity", computeRec.NumaAffinity)
d.Set("hp_backed", computeRec.HPBacked)
d.Set("enabled", false)
if computeRec.Status == status.Enabled {

View File

@@ -297,7 +297,7 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf
loaderType, loaderTypeOk := d.GetOk("loader_type")
bootType, bootTypeOk := d.GetOk("boot_type")
hotResize, hotResizeOk := d.GetOk("hot_resize")
hotResize, hotResizeOk := d.GetOkExists("hot_resize")
networkInterfaceNaming, networkInterfaceNamingOk := d.GetOk("network_interface_naming")
if loaderTypeOk {
@@ -587,6 +587,12 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf
}
}
if _, ok := d.GetOk("disks"); ok {
if err := utilityComputeCreateIOTune(ctx, d, m); err != nil {
warnings.Add(err)
}
}
}
log.Debugf("resourceComputeCreate: new Compute ID %d, name %s creation sequence complete", computeId, d.Get("name").(string))
@@ -901,10 +907,15 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf
}
}
// Note bene: numa_affinity, cpu_pin and hp_backed, cpu, ram are not allowed to be changed for compute in STARTED tech status.
// 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 isStopRequired bool
if d.HasChanges("numa_affinity", "cpu_pin", "hp_backed", "chipset", "preferred_cpu") && d.Get("started").(bool) {
if d.HasChanges("numa_affinity", "cpu_pin", "hp_backed", "chipset", "preferred_cpu", "hot_resize") && d.Get("started").(bool) {
isStopRequired = true
}
old, new := d.GetChange("cpu")
if old.(int) > new.(int) && d.Get("started").(bool) && d.Get("force_resize").(bool) {
isStopRequired = true
}
if isStopRequired {
@@ -1058,6 +1069,7 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf
addedDisks := make([]interface{}, 0)
resizedDisks := make([]interface{}, 0)
renamedDisks := make([]interface{}, 0)
iotuneUpdatedDisks := make([]interface{}, 0)
oldDisks, newDisks := d.GetChange("disks")
oldConv := oldDisks.([]interface{})
@@ -1095,18 +1107,12 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf
if isRenameDisk(oldConv, el) {
renamedDisks = append(renamedDisks, el)
}
if isChangeIOTuneDisk(oldConv, el) {
iotuneUpdatedDisks = append(iotuneUpdatedDisks, el)
}
}
if len(deletedDisks) > 0 {
stopReq := compute.StopRequest{
ComputeID: computeRec.ID,
Force: false,
}
_, err := c.CloudAPI().Compute().Stop(ctx, stopReq)
if err != nil {
return diag.FromErr(err)
}
for _, disk := range deletedDisks {
diskConv := disk.(map[string]interface{})
@@ -1127,14 +1133,7 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf
return diag.FromErr(err)
}
}
req := compute.StartRequest{
ComputeID: computeRec.ID,
AltBootID: 0,
}
_, err = c.CloudAPI().Compute().Start(ctx, req)
if err != nil {
return diag.FromErr(err)
}
}
if len(addedDisks) > 0 {
@@ -1164,10 +1163,33 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf
if diskConv["image_id"].(int) != 0 {
req.ImageID = uint64(diskConv["image_id"].(int))
}
_, err := c.CloudAPI().Compute().DiskAdd(ctx, req)
diskID, err := c.CloudAPI().Compute().DiskAdd(ctx, req)
if err != nil {
return diag.FromErr(err)
}
if iotuneRaw, ok := diskConv["iotune"].([]interface{}); ok && len(iotuneRaw) > 0 {
iotuneMap := iotuneRaw[0].(map[string]interface{})
limitReq := disks.LimitIORequest{
DiskID: diskID,
ReadBytesSec: uint64(iotuneMap["read_bytes_sec"].(int)),
ReadBytesSecMax: uint64(iotuneMap["read_bytes_sec_max"].(int)),
ReadIOPSSec: uint64(iotuneMap["read_iops_sec"].(int)),
ReadIOPSSecMax: uint64(iotuneMap["read_iops_sec_max"].(int)),
SizeIOPSSec: uint64(iotuneMap["size_iops_sec"].(int)),
TotalBytesSec: uint64(iotuneMap["total_bytes_sec"].(int)),
TotalBytesSecMax: uint64(iotuneMap["total_bytes_sec_max"].(int)),
TotalIOPSSec: uint64(iotuneMap["total_iops_sec"].(int)),
TotalIOPSSecMax: uint64(iotuneMap["total_iops_sec_max"].(int)),
WriteBytesSec: uint64(iotuneMap["write_bytes_sec"].(int)),
WriteBytesSecMax: uint64(iotuneMap["write_bytes_sec_max"].(int)),
WriteIOPSSec: uint64(iotuneMap["write_iops_sec"].(int)),
WriteIOPSSecMax: uint64(iotuneMap["write_iops_sec_max"].(int)),
}
_, err := c.CloudAPI().Disks().LimitIO(ctx, limitReq)
if err != nil {
return diag.FromErr(err)
}
}
}
}
@@ -1205,6 +1227,46 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf
}
}
}
if len(iotuneUpdatedDisks) > 0 {
for _, disk := range iotuneUpdatedDisks {
diskConv := disk.(map[string]interface{})
if diskConv["disk_type"].(string) == "B" {
continue
}
diskID := uint64(diskConv["disk_id"].(int))
if diskID == 0 {
continue
}
iotuneRaw := diskConv["iotune"].([]interface{})
if len(iotuneRaw) == 0 {
continue
}
iotuneMap := iotuneRaw[0].(map[string]interface{})
req := disks.LimitIORequest{
DiskID: diskID,
ReadBytesSec: uint64(iotuneMap["read_bytes_sec"].(int)),
ReadBytesSecMax: uint64(iotuneMap["read_bytes_sec_max"].(int)),
ReadIOPSSec: uint64(iotuneMap["read_iops_sec"].(int)),
ReadIOPSSecMax: uint64(iotuneMap["read_iops_sec_max"].(int)),
SizeIOPSSec: uint64(iotuneMap["size_iops_sec"].(int)),
TotalBytesSec: uint64(iotuneMap["total_bytes_sec"].(int)),
TotalBytesSecMax: uint64(iotuneMap["total_bytes_sec_max"].(int)),
TotalIOPSSec: uint64(iotuneMap["total_iops_sec"].(int)),
TotalIOPSSecMax: uint64(iotuneMap["total_iops_sec_max"].(int)),
WriteBytesSec: uint64(iotuneMap["write_bytes_sec"].(int)),
WriteBytesSecMax: uint64(iotuneMap["write_bytes_sec_max"].(int)),
WriteIOPSSec: uint64(iotuneMap["write_iops_sec"].(int)),
WriteIOPSSecMax: uint64(iotuneMap["write_iops_sec_max"].(int)),
}
_, err := c.CloudAPI().Disks().LimitIO(ctx, req)
if err != nil {
return diag.FromErr(err)
}
}
}
}
if d.HasChange("affinity_label") {
@@ -1765,32 +1827,6 @@ func resourceComputeDelete(ctx context.Context, d *schema.ResourceData, m interf
c := m.(*controller.ControllerCfg)
computeId, _ := strconv.ParseUint(d.Id(), 10, 64)
if start, ok := d.GetOk("started"); ok {
if start.(bool) {
req := compute.StopRequest{ComputeID: computeId}
log.Debugf("resourceComputeDelete: stoping Compute ID %d", computeId)
if _, err := c.CloudAPI().Compute().Stop(ctx, req); err != nil {
diag.FromErr(err)
}
}
}
pciList, ok := d.GetOk("pci_devices")
if d.Get("permanently").(bool) && ok {
pciDevices := pciList.(*schema.Set).List()
for _, v := range pciDevices {
pciID := v.(int)
req := compute.DetachPCIDeviceRequest{
ComputeID: computeId,
DeviceID: uint64(pciID),
}
_, err := c.CloudAPI().Compute().DetachPCIDevice(ctx, req)
if err != nil {
return diag.FromErr(err)
}
}
}
req := compute.DeleteRequest{
ComputeID: computeId,
Permanently: d.Get("permanently").(bool),
@@ -1852,8 +1888,84 @@ func disksSubresourceSchemaMake() map[string]*schema.Schema {
"permanently": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Disk deletion status",
},
"iotune": {
Type: schema.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"read_bytes_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"read_bytes_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"read_iops_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"read_iops_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"size_iops_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"total_bytes_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"total_bytes_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"total_iops_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"total_iops_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"write_bytes_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"write_bytes_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"write_iops_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"write_iops_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
},
},
},
"disk_id": {
Type: schema.TypeInt,
Computed: true,

View File

@@ -40,6 +40,7 @@ import (
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/compute"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/disks"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -433,3 +434,118 @@ func differenceNetwork(oldList, newList []interface{}) (detachMap, changeIpMap,
return
}
func utilityComputeCreateIOTune(ctx context.Context, d *schema.ResourceData, m interface{}) error {
c := m.(*controller.ControllerCfg)
diskList := d.Get("disks").([]interface{})
iotuneArr := make([]interface{}, 0, len(diskList))
hasAny := false
for _, elem := range diskList {
diskVal := elem.(map[string]interface{})
iotune := diskVal["iotune"].([]interface{})
iotuneArr = append(iotuneArr, iotune)
if len(iotune) > 0 {
hasAny = true
}
}
if !hasAny {
return nil
}
computeRec, err := utilityComputeCheckPresence(ctx, d, m)
if err != nil {
return err
}
bootDisk := findBootDisk(computeRec.Disks)
computeDisksIDs := getComputeDiskIDs(computeRec.Disks, diskList, d.Get("extra_disks").(*schema.Set).List(), bootDisk.ID)
for i, diskID := range computeDisksIDs {
if i >= len(iotuneArr) {
continue
}
iotune, ok := iotuneArr[i].([]interface{})
if !ok || len(iotune) == 0 {
continue
}
iotuneMap := iotune[0].(map[string]interface{})
req := disks.LimitIORequest{
DiskID: diskID.(uint64),
ReadBytesSec: uint64(iotuneMap["read_bytes_sec"].(int)),
ReadBytesSecMax: uint64(iotuneMap["read_bytes_sec_max"].(int)),
ReadIOPSSec: uint64(iotuneMap["read_iops_sec"].(int)),
ReadIOPSSecMax: uint64(iotuneMap["read_iops_sec_max"].(int)),
SizeIOPSSec: uint64(iotuneMap["size_iops_sec"].(int)),
TotalBytesSec: uint64(iotuneMap["total_bytes_sec"].(int)),
TotalBytesSecMax: uint64(iotuneMap["total_bytes_sec_max"].(int)),
TotalIOPSSec: uint64(iotuneMap["total_iops_sec"].(int)),
TotalIOPSSecMax: uint64(iotuneMap["total_iops_sec_max"].(int)),
WriteBytesSec: uint64(iotuneMap["write_bytes_sec"].(int)),
WriteBytesSecMax: uint64(iotuneMap["write_bytes_sec_max"].(int)),
WriteIOPSSec: uint64(iotuneMap["write_iops_sec"].(int)),
WriteIOPSSecMax: uint64(iotuneMap["write_iops_sec_max"].(int)),
}
_, err := c.CloudAPI().Disks().LimitIO(ctx, req)
if err != nil {
return err
}
}
return nil
}
func getComputeDiskIDs(disksList compute.ListComputeDisks, disksBlocks, extraDisks []interface{}, bootDiskId uint64) []interface{} {
res := make([]interface{}, 0)
if len(disksBlocks) == 0 {
return res
}
sort.Slice(disksList, func(i, j int) bool {
return disksList[i].ID < disksList[j].ID
})
for _, disk := range disksList {
if disk.ID == bootDiskId || findInExtraDisks(uint(disk.ID), extraDisks) { //skip main bootdisk and extraDisks
continue
}
res = append(res, disk.ID)
}
return res
}
func isChangeIOTuneDisk(els []interface{}, el interface{}) bool {
for _, elOld := range els {
elOldConv := elOld.(map[string]interface{})
elConv := el.(map[string]interface{})
if elOldConv["disk_id"].(int) != elConv["disk_id"].(int) {
continue
}
oldIOTune := elOldConv["iotune"].([]interface{})
newIOTune := elConv["iotune"].([]interface{})
if len(oldIOTune) == 0 && len(newIOTune) == 0 {
return false
}
if len(oldIOTune) == 0 || len(newIOTune) == 0 {
return true
}
oldMap := oldIOTune[0].(map[string]interface{})
newMap := newIOTune[0].(map[string]interface{})
return oldMap["read_bytes_sec"].(int) != newMap["read_bytes_sec"].(int) ||
oldMap["read_bytes_sec_max"].(int) != newMap["read_bytes_sec_max"].(int) ||
oldMap["read_iops_sec"].(int) != newMap["read_iops_sec"].(int) ||
oldMap["read_iops_sec_max"].(int) != newMap["read_iops_sec_max"].(int) ||
oldMap["size_iops_sec"].(int) != newMap["size_iops_sec"].(int) ||
oldMap["total_bytes_sec"].(int) != newMap["total_bytes_sec"].(int) ||
oldMap["total_bytes_sec_max"].(int) != newMap["total_bytes_sec_max"].(int) ||
oldMap["total_iops_sec"].(int) != newMap["total_iops_sec"].(int) ||
oldMap["total_iops_sec_max"].(int) != newMap["total_iops_sec_max"].(int) ||
oldMap["write_bytes_sec"].(int) != newMap["write_bytes_sec"].(int) ||
oldMap["write_bytes_sec_max"].(int) != newMap["write_bytes_sec_max"].(int) ||
oldMap["write_iops_sec"].(int) != newMap["write_iops_sec"].(int) ||
oldMap["write_iops_sec_max"].(int) != newMap["write_iops_sec_max"].(int)
}
return false
}

View File

@@ -0,0 +1,391 @@
package disks
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)
func resourceDiskV1() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"account_id": {
Type: schema.TypeInt,
Required: true,
//ForceNew: true,
},
"gid": {
Type: schema.TypeInt,
Required: true,
//ForceNew: true,
},
"disk_name": {
Type: schema.TypeString,
Required: true,
},
"type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"D", "B", "T"}, false),
Description: "The type of disk in terms of its role in compute: 'B=Boot, D=Data, T=Temp'",
},
"desc": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"size_max": {
Type: schema.TypeInt,
Required: true,
},
"ssd_size": {
Type: schema.TypeInt,
Optional: true,
},
"iops": {
Type: schema.TypeInt,
Optional: true,
Description: "max IOPS disk can perform",
},
"sep_id": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"pool": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"node_ids": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"detach": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "detach disk from machine first",
},
"permanently": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "whether to completely delete the disk, works only with non attached disks",
},
"shareable": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"restore": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "restore deleting disk",
},
"account_name": {
Type: schema.TypeString,
Computed: true,
},
"acl": {
Type: schema.TypeString,
Computed: true,
},
"boot_partition": {
Type: schema.TypeInt,
Computed: true,
},
"computes": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"compute_id": {
Type: schema.TypeString,
Computed: true,
},
"compute_name": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"created_time": {
Type: schema.TypeInt,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"destruction_time": {
Type: schema.TypeInt,
Computed: true,
},
"devicename": {
Type: schema.TypeString,
Computed: true,
},
"disk_path": {
Type: schema.TypeString,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"disk_id": {
Type: schema.TypeInt,
Computed: true,
},
"image_id": {
Type: schema.TypeInt,
Computed: true,
},
"images": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"iotune": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"read_bytes_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"read_bytes_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"read_iops_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"read_iops_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"size_iops_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"total_bytes_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"total_bytes_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"total_iops_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"total_iops_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"write_bytes_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"write_bytes_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"write_iops_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"write_iops_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
},
},
},
"iqn": {
Type: schema.TypeString,
Computed: true,
},
"login": {
Type: schema.TypeString,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"order": {
Type: schema.TypeInt,
Computed: true,
},
"params": {
Type: schema.TypeString,
Computed: true,
},
"parent_id": {
Type: schema.TypeInt,
Computed: true,
},
"passwd": {
Type: schema.TypeString,
Computed: true,
},
"pci_slot": {
Type: schema.TypeInt,
Computed: true,
},
"present_to": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"purge_attempts": {
Type: schema.TypeInt,
Computed: true,
},
"purge_time": {
Type: schema.TypeInt,
Computed: true,
},
"replication": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"disk_id": {
Type: schema.TypeInt,
Computed: true,
},
"pool_id": {
Type: schema.TypeString,
Computed: true,
},
"role": {
Type: schema.TypeString,
Computed: true,
},
"self_volume_id": {
Type: schema.TypeString,
Computed: true,
},
"storage_id": {
Type: schema.TypeString,
Computed: true,
},
"volume_id": {
Type: schema.TypeString,
Computed: true,
},
},
},
Description: "Replication status",
},
"reality_device_number": {
Type: schema.TypeInt,
Computed: true,
},
"reference_id": {
Type: schema.TypeString,
Computed: true,
},
"res_id": {
Type: schema.TypeString,
Computed: true,
},
"res_name": {
Type: schema.TypeString,
Computed: true,
},
"role": {
Type: schema.TypeString,
Computed: true,
},
"sep_type": {
Type: schema.TypeString,
Computed: true,
},
"size_used": {
Type: schema.TypeFloat,
Computed: true,
},
"snapshots": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"guid": {
Type: schema.TypeString,
Computed: true,
},
"label": {
Type: schema.TypeString,
Computed: true,
},
"reference_id": {
Type: schema.TypeString,
Computed: true,
},
"res_id": {
Type: schema.TypeString,
Computed: true,
},
"snap_set_guid": {
Type: schema.TypeString,
Computed: true,
},
"snap_set_time": {
Type: schema.TypeInt,
Computed: true,
},
"timestamp": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
"vmid": {
Type: schema.TypeInt,
Computed: true,
},
},
}
}

View File

@@ -407,7 +407,7 @@ func resourceDiskChangeNodes(ctx context.Context, d *schema.ResourceData, m inte
func ResourceDisk() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
SchemaVersion: 2,
CreateContext: resourceDiskCreate,
ReadContext: resourceDiskRead,
@@ -427,5 +427,12 @@ func ResourceDisk() *schema.Resource {
},
Schema: resourceDiskSchemaMake(),
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceDiskV1().CoreConfigSchema().ImpliedType(),
Upgrade: resourceDiskUpgradeV1,
Version: 1,
},
},
}
}

View File

@@ -0,0 +1,14 @@
package disks
import (
"context"
log "github.com/sirupsen/logrus"
)
func resourceDiskUpgradeV1(ctx context.Context, rawState map[string]interface{}, meta any) (map[string]interface{}, error) {
log.Debug("resourceDiskUpgradeV1: upgrading state")
rawState["present_to"] = make(map[string]uint64)
return rawState, nil
}

File diff suppressed because it is too large Load Diff

View File

@@ -222,7 +222,7 @@ func resourceImageCDROMEdit(ctx context.Context, d *schema.ResourceData, m inter
func ResourceCDROMImage() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
SchemaVersion: 2,
CreateContext: resourceCDROMImageCreate,
ReadContext: resourceCDROMImageRead,
@@ -242,5 +242,12 @@ func ResourceCDROMImage() *schema.Resource {
},
Schema: resourceCDROMImageSchemaMake(),
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceCDROMImageV1().CoreConfigSchema().ImpliedType(),
Upgrade: resourcePresentTOUpgradeV1,
Version: 1,
},
},
}
}

View File

@@ -353,7 +353,7 @@ func resourceImageEdit(ctx context.Context, d *schema.ResourceData, m interface{
func ResourceImage() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
SchemaVersion: 2,
CreateContext: resourceImageCreate,
ReadContext: resourceImageRead,
@@ -373,5 +373,12 @@ func ResourceImage() *schema.Resource {
},
Schema: resourceImageSchemaMake(),
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceImageV1().CoreConfigSchema().ImpliedType(),
Upgrade: resourcePresentTOUpgradeV1,
Version: 1,
},
},
}
}

View File

@@ -261,7 +261,7 @@ func resourceImageFromBlankComputeUpdate(ctx context.Context, d *schema.Resource
func ResourceImageFromBlankCompute() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
SchemaVersion: 2,
CreateContext: resourceImageFromBlankComputeCreate,
ReadContext: resourceImageFromBlankComputeRead,
@@ -281,5 +281,12 @@ func ResourceImageFromBlankCompute() *schema.Resource {
},
Schema: resourceImageFromBlankComputeSchemaMake(),
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceImageFromBlankComputeV1().CoreConfigSchema().ImpliedType(),
Upgrade: resourcePresentTOUpgradeV1,
Version: 1,
},
},
}
}

View File

@@ -268,7 +268,7 @@ func resourceImageFromPlatformDiskUpdate(ctx context.Context, d *schema.Resource
func ResourceImageFromPlatformDisk() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
SchemaVersion: 2,
CreateContext: resourceImageFromPlatformDiskCreate,
ReadContext: resourceImageFromPlatformDiskRead,
@@ -288,5 +288,12 @@ func ResourceImageFromPlatformDisk() *schema.Resource {
},
Schema: resourceImageFromPlatformDiskSchemaMake(),
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceImageFromPlatformDiskV1().CoreConfigSchema().ImpliedType(),
Upgrade: resourcePresentTOUpgradeV1,
Version: 1,
},
},
}
}

View File

@@ -189,7 +189,7 @@ func resourceImageLink(ctx context.Context, d *schema.ResourceData, m interface{
func ResourceVirtualImage() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
SchemaVersion: 2,
CreateContext: resourceVirtualImageCreate,
ReadContext: resourceVirtualImageRead,
@@ -209,5 +209,12 @@ func ResourceVirtualImage() *schema.Resource {
},
Schema: resourceVirtualImageSchemaMake(),
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceVirtualImageV1().CoreConfigSchema().ImpliedType(),
Upgrade: resourcePresentTOUpgradeV1,
Version: 1,
},
},
}
}

View File

@@ -0,0 +1,14 @@
package image
import (
"context"
log "github.com/sirupsen/logrus"
)
func resourcePresentTOUpgradeV1(ctx context.Context, rawState map[string]interface{}, meta any) (map[string]interface{}, error) {
log.Debug("resourcePresentTOUpgradeV1: upgrading state")
rawState["present_to"] = make(map[string]uint64)
return rawState, nil
}

View File

@@ -103,6 +103,12 @@ func flattenCompute(d *schema.ResourceData, computeRec *compute.RecordCompute, p
d.Set("boot_type", computeRec.BootType)
d.Set("hot_resize", computeRec.HotResize)
d.Set("network_interface_naming", computeRec.NetworkInterfaceNaming)
d.Set("numa_affinity", computeRec.NumaAffinity)
d.Set("cpu_pin", computeRec.CPUPin)
d.Set("hp_backed", computeRec.HPBacked)
d.Set("started", computeRec.TechStatus == "STARTED")
return nil
}
@@ -221,10 +227,6 @@ func flattenQOS(qos compute.QOS) []map[string]interface{} {
func flattenComputeDisks(disksList compute.ListDisks, disksBlocks, extraDisks []interface{}, bootDiskId uint64) []map[string]interface{} {
res := make([]map[string]interface{}, 0, len(disksList))
if len(disksBlocks) == 0 {
return res
}
sort.Slice(disksList, func(i, j int) bool {
return disksList[i].ID < disksList[j].ID
})
@@ -236,8 +238,14 @@ func flattenComputeDisks(disksList compute.ListDisks, disksBlocks, extraDisks []
continue
}
pernamentlyValue := disksBlocks[indexDataDisks].(map[string]interface{})["permanently"].(bool)
nodeIds := disksBlocks[indexDataDisks].(map[string]interface{})["node_ids"].(*schema.Set)
permanentlyValue := false
var nodeIds *schema.Set
if indexDataDisks < len(disksBlocks) {
log.Debug("entering indexDataDisks < len(disksBlocks)", indexDataDisks < len(disksBlocks), indexDataDisks, len(disksBlocks))
permanentlyValue = disksBlocks[indexDataDisks].(map[string]interface{})["permanently"].(bool)
nodeIds = disksBlocks[indexDataDisks].(map[string]interface{})["node_ids"].(*schema.Set)
}
temp := map[string]interface{}{
"disk_name": disk.Name,
@@ -252,8 +260,9 @@ func flattenComputeDisks(disksList compute.ListDisks, disksBlocks, extraDisks []
"shareable": disk.Shareable,
"size_used": disk.SizeUsed,
"size_max": disk.SizeMax,
"permanently": pernamentlyValue,
"permanently": permanentlyValue,
"present_to": disk.PresentTo,
"iotune": flattenIOTune(disk.IOTune),
}
res = append(res, temp)
indexDataDisks++

View File

@@ -251,7 +251,7 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf
loaderType, loaderTypeOk := d.GetOk("loader_type")
bootType, bootTypeOk := d.GetOk("boot_type")
hotResize, hotResizeOk := d.GetOk("hot_resize")
hotResize, hotResizeOk := d.GetOkExists("hot_resize")
networkInterfaceNaming, networkInterfaceNamingOk := d.GetOk("network_interface_naming")
if loaderTypeOk {
@@ -585,6 +585,9 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf
if err != nil {
warnings.Add(err)
}
if err := utilityComputeCreateIOTune(ctx, d, m); err != nil {
warnings.Add(err)
}
}
}
@@ -875,33 +878,6 @@ func resourceComputeDelete(ctx context.Context, d *schema.ResourceData, m interf
c := m.(*controller.ControllerCfg)
computeId, _ := strconv.ParseUint(d.Id(), 10, 64)
if start, ok := d.GetOk("started"); ok {
if start.(bool) {
req := compute.StopRequest{ComputeID: computeId}
log.Debugf("resourceComputeDelete: stoping Compute ID %d", computeId)
if _, err := c.CloudBroker().Compute().Stop(ctx, req); err != nil {
diag.FromErr(err)
}
}
}
pciList, ok := d.GetOk("pci_devices")
if d.Get("permanently").(bool) && ok {
pciDevices := pciList.(*schema.Set).List()
for _, v := range pciDevices {
pciID := v.(int)
req := compute.DetachPCIDeviceRequest{
ComputeID: computeId,
DeviceID: uint64(pciID),
}
_, err := c.CloudBroker().Compute().DetachPciDevice(ctx, req)
if err != nil {
return diag.FromErr(err)
}
}
}
req := compute.DeleteRequest{
ComputeID: computeId,
Permanently: d.Get("permanently").(bool),

View File

@@ -3499,6 +3499,81 @@ func resourceComputeSchemaMake() map[string]*schema.Schema {
Type: schema.TypeInt,
Computed: true,
},
"iotune": {
Type: schema.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"read_bytes_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"read_bytes_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"read_iops_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"read_iops_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"size_iops_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"total_bytes_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"total_bytes_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"total_iops_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"total_iops_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"write_bytes_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"write_bytes_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"write_iops_sec": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"write_iops_sec_max": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
},
},
},
},
},
},

View File

@@ -111,7 +111,13 @@ func utilityComputeResize(ctx context.Context, d *schema.ResourceData, m interfa
c := m.(*controller.ControllerCfg)
computeId, _ := strconv.ParseUint(d.Id(), 10, 64)
if d.Get("started").(bool) {
var isStopRequired bool
old, new := d.GetChange("cpu")
if d.Get("started").(bool) && (old.(int) > new.(int)) && d.Get("force_resize").(bool) {
isStopRequired = true
}
if isStopRequired {
stopReq := compute.StopRequest{
ComputeID: computeId,
Force: false,
@@ -176,7 +182,7 @@ func utilityComputeResize(ctx context.Context, d *schema.ResourceData, m interfa
}
}
if d.Get("started").(bool) {
if isStopRequired {
if _, err := c.CloudBroker().Compute().Start(ctx, compute.StartRequest{ComputeID: computeId}); err != nil {
return err
}
@@ -227,6 +233,7 @@ func utilityComputeUpdateDisks(ctx context.Context, d *schema.ResourceData, m in
addedDisks := make([]interface{}, 0)
resizedDisks := make([]interface{}, 0)
renamedDisks := make([]interface{}, 0)
iotuneUpdatedDisks := make([]interface{}, 0)
presentNewDisks := make([]interface{}, 0)
presentOldDisks := make([]interface{}, 0)
@@ -272,18 +279,12 @@ func utilityComputeUpdateDisks(ctx context.Context, d *schema.ResourceData, m in
if isRenameDisk(oldConv, el) {
renamedDisks = append(renamedDisks, el)
}
if isChangeIOTuneDisk(oldConv, el) {
iotuneUpdatedDisks = append(iotuneUpdatedDisks, el)
}
}
if len(deletedDisks) > 0 {
stopReq := compute.StopRequest{
ComputeID: computeId,
Force: false,
}
_, err := c.CloudBroker().Compute().Stop(ctx, stopReq)
if err != nil {
return err
}
for _, disk := range deletedDisks {
diskConv := disk.(map[string]interface{})
@@ -302,14 +303,7 @@ func utilityComputeUpdateDisks(ctx context.Context, d *schema.ResourceData, m in
return err
}
}
req := compute.StartRequest{
ComputeID: computeId,
AltBootID: 0,
}
_, err = c.CloudBroker().Compute().Start(ctx, req)
if err != nil {
return err
}
}
if len(addedDisks) > 0 {
@@ -359,6 +353,29 @@ func utilityComputeUpdateDisks(ctx context.Context, d *schema.ResourceData, m in
}
}
}
if iotuneRaw, ok := diskConv["iotune"].([]interface{}); ok && len(iotuneRaw) > 0 {
iotuneMap := iotuneRaw[0].(map[string]interface{})
limitReq := disks.LimitIORequest{
DiskID: diskID,
ReadBytesSec: uint64(iotuneMap["read_bytes_sec"].(int)),
ReadBytesSecMax: uint64(iotuneMap["read_bytes_sec_max"].(int)),
ReadIOPSSec: uint64(iotuneMap["read_iops_sec"].(int)),
ReadIOPSSecMax: uint64(iotuneMap["read_iops_sec_max"].(int)),
SizeIOPSSec: uint64(iotuneMap["size_iops_sec"].(int)),
TotalBytesSec: uint64(iotuneMap["total_bytes_sec"].(int)),
TotalBytesSecMax: uint64(iotuneMap["total_bytes_sec_max"].(int)),
TotalIOPSSec: uint64(iotuneMap["total_iops_sec"].(int)),
TotalIOPSSecMax: uint64(iotuneMap["total_iops_sec_max"].(int)),
WriteBytesSec: uint64(iotuneMap["write_bytes_sec"].(int)),
WriteBytesSecMax: uint64(iotuneMap["write_bytes_sec_max"].(int)),
WriteIOPSSec: uint64(iotuneMap["write_iops_sec"].(int)),
WriteIOPSSecMax: uint64(iotuneMap["write_iops_sec_max"].(int)),
}
_, err := c.CloudBroker().Disks().LimitIO(ctx, limitReq)
if err != nil {
return err
}
}
if err != nil {
return err
}
@@ -400,6 +417,46 @@ func utilityComputeUpdateDisks(ctx context.Context, d *schema.ResourceData, m in
}
}
if len(iotuneUpdatedDisks) > 0 {
for _, disk := range iotuneUpdatedDisks {
diskConv := disk.(map[string]interface{})
if diskConv["disk_type"].(string) == "B" {
continue
}
diskID := uint64(diskConv["disk_id"].(int))
if diskID == 0 {
continue
}
iotuneRaw := diskConv["iotune"].([]interface{})
if len(iotuneRaw) == 0 {
continue
}
iotuneMap := iotuneRaw[0].(map[string]interface{})
req := disks.LimitIORequest{
DiskID: diskID,
ReadBytesSec: uint64(iotuneMap["read_bytes_sec"].(int)),
ReadBytesSecMax: uint64(iotuneMap["read_bytes_sec_max"].(int)),
ReadIOPSSec: uint64(iotuneMap["read_iops_sec"].(int)),
ReadIOPSSecMax: uint64(iotuneMap["read_iops_sec_max"].(int)),
SizeIOPSSec: uint64(iotuneMap["size_iops_sec"].(int)),
TotalBytesSec: uint64(iotuneMap["total_bytes_sec"].(int)),
TotalBytesSecMax: uint64(iotuneMap["total_bytes_sec_max"].(int)),
TotalIOPSSec: uint64(iotuneMap["total_iops_sec"].(int)),
TotalIOPSSecMax: uint64(iotuneMap["total_iops_sec_max"].(int)),
WriteBytesSec: uint64(iotuneMap["write_bytes_sec"].(int)),
WriteBytesSecMax: uint64(iotuneMap["write_bytes_sec_max"].(int)),
WriteIOPSSec: uint64(iotuneMap["write_iops_sec"].(int)),
WriteIOPSSecMax: uint64(iotuneMap["write_iops_sec_max"].(int)),
}
_, err := c.CloudBroker().Disks().LimitIO(ctx, req)
if err != nil {
return err
}
}
}
for i := range presentNewDisks {
newDisk := presentNewDisks[i].(map[string]interface{})
oldDisk := presentOldDisks[i].(map[string]interface{})
@@ -921,7 +978,7 @@ func utilityComputeUpdate(ctx context.Context, d *schema.ResourceData, m interfa
// 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 isStopRequired bool
if d.HasChanges("numa_affinity", "cpu_pin", "hp_backed", "chipset", "preferred_cpu") && d.Get("started").(bool) {
if d.HasChanges("numa_affinity", "cpu_pin", "hp_backed", "chipset", "preferred_cpu", "hot_resize") && d.Get("started").(bool) {
isStopRequired = true
}
if isStopRequired {
@@ -1648,6 +1705,66 @@ func utilityComputeStart(ctx context.Context, computeID uint64, m interface{}) (
return 0, nil
}
func utilityComputeCreateIOTune(ctx context.Context, d *schema.ResourceData, m interface{}) error {
c := m.(*controller.ControllerCfg)
diskList := d.Get("disks").([]interface{})
iotuneArr := make([]interface{}, 0, len(diskList))
hasAny := false
for _, elem := range diskList {
diskVal := elem.(map[string]interface{})
iotune := diskVal["iotune"].([]interface{})
iotuneArr = append(iotuneArr, iotune)
if len(iotune) > 0 {
hasAny = true
}
}
if !hasAny {
return nil
}
computeRec, err := utilityComputeCheckPresence(ctx, d, m)
if err != nil {
return err
}
bootDisk := findBootDisk(computeRec.Disks)
computeDisksIDs := getComputeDiskIDs(computeRec.Disks, diskList, d.Get("extra_disks").(*schema.Set).List(), bootDisk.ID)
for i, diskID := range computeDisksIDs {
if i >= len(iotuneArr) {
continue
}
iotune, ok := iotuneArr[i].([]interface{})
if !ok || len(iotune) == 0 {
continue
}
iotuneMap := iotune[0].(map[string]interface{})
req := disks.LimitIORequest{
DiskID: diskID.(uint64),
ReadBytesSec: uint64(iotuneMap["read_bytes_sec"].(int)),
ReadBytesSecMax: uint64(iotuneMap["read_bytes_sec_max"].(int)),
ReadIOPSSec: uint64(iotuneMap["read_iops_sec"].(int)),
ReadIOPSSecMax: uint64(iotuneMap["read_iops_sec_max"].(int)),
SizeIOPSSec: uint64(iotuneMap["size_iops_sec"].(int)),
TotalBytesSec: uint64(iotuneMap["total_bytes_sec"].(int)),
TotalBytesSecMax: uint64(iotuneMap["total_bytes_sec_max"].(int)),
TotalIOPSSec: uint64(iotuneMap["total_iops_sec"].(int)),
TotalIOPSSecMax: uint64(iotuneMap["total_iops_sec_max"].(int)),
WriteBytesSec: uint64(iotuneMap["write_bytes_sec"].(int)),
WriteBytesSecMax: uint64(iotuneMap["write_bytes_sec_max"].(int)),
WriteIOPSSec: uint64(iotuneMap["write_iops_sec"].(int)),
WriteIOPSSecMax: uint64(iotuneMap["write_iops_sec_max"].(int)),
}
_, err := c.CloudBroker().Disks().LimitIO(ctx, req)
if err != nil {
return err
}
}
return nil
}
func utilityComputeCreatePresentDisk(ctx context.Context, d *schema.ResourceData, m interface{}) error {
c := m.(*controller.ControllerCfg)
var errs error
@@ -1693,6 +1810,40 @@ func utilityComputeCreatePresentDisk(ctx context.Context, d *schema.ResourceData
return errs
}
func isChangeIOTuneDisk(els []interface{}, el interface{}) bool {
for _, elOld := range els {
elOldConv := elOld.(map[string]interface{})
elConv := el.(map[string]interface{})
if elOldConv["disk_id"].(int) != elConv["disk_id"].(int) {
continue
}
oldIOTune := elOldConv["iotune"].([]interface{})
newIOTune := elConv["iotune"].([]interface{})
if len(oldIOTune) == 0 && len(newIOTune) == 0 {
return false
}
if len(oldIOTune) == 0 || len(newIOTune) == 0 {
return true
}
oldMap := oldIOTune[0].(map[string]interface{})
newMap := newIOTune[0].(map[string]interface{})
return oldMap["read_bytes_sec"].(int) != newMap["read_bytes_sec"].(int) ||
oldMap["read_bytes_sec_max"].(int) != newMap["read_bytes_sec_max"].(int) ||
oldMap["read_iops_sec"].(int) != newMap["read_iops_sec"].(int) ||
oldMap["read_iops_sec_max"].(int) != newMap["read_iops_sec_max"].(int) ||
oldMap["size_iops_sec"].(int) != newMap["size_iops_sec"].(int) ||
oldMap["total_bytes_sec"].(int) != newMap["total_bytes_sec"].(int) ||
oldMap["total_bytes_sec_max"].(int) != newMap["total_bytes_sec_max"].(int) ||
oldMap["total_iops_sec"].(int) != newMap["total_iops_sec"].(int) ||
oldMap["total_iops_sec_max"].(int) != newMap["total_iops_sec_max"].(int) ||
oldMap["write_bytes_sec"].(int) != newMap["write_bytes_sec"].(int) ||
oldMap["write_bytes_sec_max"].(int) != newMap["write_bytes_sec_max"].(int) ||
oldMap["write_iops_sec"].(int) != newMap["write_iops_sec"].(int) ||
oldMap["write_iops_sec_max"].(int) != newMap["write_iops_sec_max"].(int)
}
return false
}
func isResizeDisk(els []interface{}, el interface{}) bool {
for _, elOld := range els {
elOldConv := elOld.(map[string]interface{})

View File

@@ -185,6 +185,27 @@ resource "decort_kvmvm" "comp" {
#опциональный параметр
#тип - булев
#permanently = false
#настройки лимитов операций ввода/вывода диска
#опциональный параметр
#тип - блок
#тип вложенных полей - целое число
#используется при создании и обновлении
#iotune {
#read_bytes_sec = 0
#read_bytes_sec_max = 0
#read_iops_sec = 0
#read_iops_sec_max = 0
#size_iops_sec = 0
#total_bytes_sec = 0
#total_bytes_sec_max = 0
#total_iops_sec = 3000
#total_iops_sec_max = 0
#write_bytes_sec = 0
#write_bytes_sec_max = 0
#write_iops_sec = 0
#write_iops_sec_max = 0
#}
#}
#правила affinity

View File

@@ -194,6 +194,27 @@ resource "decort_cb_kvmvm" "comp" {
#опциональный параметр
#тип - булев
#permanently = false
#настройки лимитов операций ввода/вывода диска
#опциональный параметр
#тип - блок
#тип вложенных полей - целое число
#используется при создании и обновлении
#iotune {
#read_bytes_sec = 0
#read_bytes_sec_max = 0
#read_iops_sec = 0
#read_iops_sec_max = 0
#size_iops_sec = 0
#total_bytes_sec = 0
#total_bytes_sec_max = 0
#total_iops_sec = 3000
#total_iops_sec_max = 0
#write_bytes_sec = 0
#write_bytes_sec_max = 0
#write_iops_sec = 0
#write_iops_sec_max = 0
#}
#}
#правила affinity