Skip to content

Commit aa8aa97

Browse files
authored
feat/cvm-sys-disk-modify (#870)
* feat/cvm-sys-disk-modify * fix: update changelog
1 parent 4f610a8 commit aa8aa97

File tree

4 files changed

+133
-55
lines changed

4 files changed

+133
-55
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 1.61.11 (February 22, 2022)
2+
3+
ENHANCEMENTS:
4+
5+
* resource `tencentcloud_instance` support System Disk size and DiskType modification
6+
17
## 1.61.10 (February 22, 2022)
28

39
ENHANCEMENTS:

tencentcloud/resource_tc_instance.go

Lines changed: 123 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -330,17 +330,15 @@ func resourceTencentCloudInstance() *schema.Resource {
330330
Type: schema.TypeString,
331331
Optional: true,
332332
Default: CVM_DISK_TYPE_CLOUD_PREMIUM,
333-
ForceNew: true,
334333
ValidateFunc: validateAllowedStringValue(CVM_DISK_TYPE),
335-
Description: "System disk type. For more information on limits of system disk types, see [Storage Overview](https://intl.cloud.tencent.com/document/product/213/4952). Valid values: `LOCAL_BASIC`: local disk, `LOCAL_SSD`: local SSD disk, `CLOUD_SSD`: SSD, `CLOUD_PREMIUM`: Premium Cloud Storage. NOTE: `CLOUD_BASIC`, `LOCAL_BASIC` and `LOCAL_SSD` are deprecated.",
334+
Description: "System disk type. For more information on limits of system disk types, see [Storage Overview](https://intl.cloud.tencent.com/document/product/213/4952). Valid values: `LOCAL_BASIC`: local disk, `LOCAL_SSD`: local SSD disk, `CLOUD_SSD`: SSD, `CLOUD_PREMIUM`: Premium Cloud Storage. NOTE: 1. `CLOUD_BASIC`, `LOCAL_BASIC` and `LOCAL_SSD` are deprecated; 2. If modified, the instance may force stop.",
336335
},
337336
"system_disk_size": {
338337
Type: schema.TypeInt,
339338
Optional: true,
340339
Default: 50,
341-
ForceNew: true,
342340
ValidateFunc: validateIntegerInRange(50, 1000),
343-
Description: "Size of the system disk. Valid value ranges: (50~1000). and unit is GB. Default is 50GB.",
341+
Description: "Size of the system disk. Valid value ranges: (50~1000). and unit is GB. Default is 50GB. If modified, the instance may force stop.",
344342
},
345343
"system_disk_id": {
346344
Type: schema.TypeString,
@@ -841,13 +839,17 @@ func resourceTencentCloudInstanceRead(d *schema.ResourceData, meta interface{})
841839
cvmService := CvmService{
842840
client: client,
843841
}
842+
cbsService := CbsService{client: client}
844843
var instance *cvm.Instance
845844
var errRet error
846845
err := resource.Retry(readRetryTimeout, func() *resource.RetryError {
847846
instance, errRet = cvmService.DescribeInstanceById(ctx, instanceId)
848847
if errRet != nil {
849848
return retryError(errRet, InternalError)
850849
}
850+
if instance != nil && instance.LatestOperationState != nil && *instance.LatestOperationState == "OPERATING" {
851+
return resource.RetryableError(fmt.Errorf("waiting for instance %s operation", *instance.InstanceId))
852+
}
851853
return nil
852854
})
853855
if err != nil {
@@ -921,7 +923,6 @@ func resourceTencentCloudInstanceRead(d *schema.ResourceData, meta interface{})
921923
diskSizeMap := map[string]*uint64{}
922924
if len(instance.DataDisks) > 0 {
923925
var diskIds []*string
924-
cbsService := CbsService{client: meta.(*TencentCloudClient).apiV3Conn}
925926
for i := range instance.DataDisks {
926927
disk := instance.DataDisks[i]
927928
diskIds = append(diskIds, disk.DiskId)
@@ -1258,23 +1259,7 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
12581259
d.SetPartial("key_name")
12591260
}
12601261
}
1261-
/* not available now
1262-
if d.HasChange("system_disk_size") {
1263-
size := d.Get("system_disk_size").(int)
1264-
//diskId := d.Get("system_disk_id").(string)
1265-
req := cvm.NewResizeInstanceDisksRequest()
1266-
req.InstanceId = &instanceId
1267-
req.SystemDisk = &cvm.SystemDisk{
1268-
DiskSize: helper.IntInt64(size),
1269-
}
12701262

1271-
err := cvmService.ResizeInstanceDisks(ctx, req)
1272-
if err != nil {
1273-
return fmt.Errorf("error: an error occured when modifying system_disk, reason: %s", err.Error())
1274-
}
1275-
instanceStoppedByDiskResize = true
1276-
d.SetPartial("system_disk_size")
1277-
}*/
12781263
if d.HasChange("data_disks") {
12791264
o, n := d.GetChange("data_disks")
12801265
ov := o.([]interface{})
@@ -1309,45 +1294,59 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
13091294
var flag bool
13101295
if d.HasChange("running_flag") {
13111296
flag = d.Get("running_flag").(bool)
1312-
if flag {
1313-
err = cvmService.StartInstance(ctx, instanceId)
1297+
if err := switchInstance(&cvmService, ctx, d, flag); err != nil {
1298+
return err
1299+
}
1300+
d.SetPartial("running_flag")
1301+
}
1302+
1303+
if d.HasChange("system_disk_size") || d.HasChange("system_disk_type") {
1304+
1305+
size := d.Get("system_disk_size").(int)
1306+
diskType := d.Get("system_disk_type").(string)
1307+
//diskId := d.Get("system_disk_id").(string)
1308+
req := cvm.NewResizeInstanceDisksRequest()
1309+
req.InstanceId = &instanceId
1310+
req.ForceStop = helper.Bool(true)
1311+
req.SystemDisk = &cvm.SystemDisk{
1312+
DiskSize: helper.IntInt64(size),
1313+
DiskType: &diskType,
1314+
}
1315+
1316+
err := cvmService.ResizeInstanceDisks(ctx, req)
1317+
if err != nil {
1318+
return fmt.Errorf("an error occured when modifying system_disk, reason: %s", err.Error())
1319+
}
1320+
1321+
err = resource.Retry(readRetryTimeout, func() *resource.RetryError {
1322+
instance, err := cvmService.DescribeInstanceById(ctx, instanceId)
13141323
if err != nil {
1315-
return err
1324+
return resource.NonRetryableError(err)
13161325
}
1317-
err = resource.Retry(2*readRetryTimeout, func() *resource.RetryError {
1318-
instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId)
1319-
if errRet != nil {
1320-
return retryError(errRet, InternalError)
1326+
if instance != nil && instance.LatestOperationState != nil {
1327+
if *instance.InstanceState == "FAILED" {
1328+
return resource.NonRetryableError(fmt.Errorf("instance operation failed"))
13211329
}
1322-
if instance != nil && *instance.InstanceState == CVM_STATUS_RUNNING {
1323-
return nil
1330+
if *instance.InstanceState == "OPERATING" {
1331+
return resource.RetryableError(fmt.Errorf("instance operating"))
13241332
}
1325-
return resource.RetryableError(fmt.Errorf("cvm instance status is %s, retry...", *instance.InstanceState))
1326-
})
1327-
if err != nil {
1328-
return err
13291333
}
1330-
} else {
1331-
stoppedMode := d.Get("stopped_mode").(string)
1332-
err = cvmService.StopInstance(ctx, instanceId, stoppedMode)
1333-
if err != nil {
1334-
return err
1335-
}
1336-
err = resource.Retry(2*readRetryTimeout, func() *resource.RetryError {
1337-
instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId)
1338-
if errRet != nil {
1339-
return retryError(errRet, InternalError)
1334+
if instance != nil && instance.SystemDisk != nil {
1335+
//wait until disk result as expected
1336+
if *instance.SystemDisk.DiskType != diskType || int(*instance.SystemDisk.DiskSize) != size {
1337+
return resource.RetryableError(fmt.Errorf("waiting for expanding success"))
13401338
}
1341-
if instance != nil && *instance.InstanceState == CVM_STATUS_STOPPED {
1342-
return nil
1343-
}
1344-
return resource.RetryableError(fmt.Errorf("cvm instance status is %s, retry...", *instance.InstanceState))
1345-
})
1346-
if err != nil {
1347-
return err
13481339
}
1340+
return nil
1341+
})
1342+
1343+
if err != nil {
1344+
return err
13491345
}
1350-
d.SetPartial("running_flag")
1346+
1347+
d.SetPartial("system_disk_size")
1348+
d.SetPartial("system_disk_type")
1349+
13511350
}
13521351

13531352
if d.HasChange("instance_type") {
@@ -1581,3 +1580,75 @@ func resourceTencentCloudInstanceDelete(d *schema.ResourceData, meta interface{}
15811580

15821581
return nil
15831582
}
1583+
1584+
func switchInstance(cvmService *CvmService, ctx context.Context, d *schema.ResourceData, flag bool) (err error) {
1585+
instanceId := d.Id()
1586+
if flag {
1587+
err = cvmService.StartInstance(ctx, instanceId)
1588+
if err != nil {
1589+
return err
1590+
}
1591+
err = resource.Retry(2*readRetryTimeout, func() *resource.RetryError {
1592+
instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId)
1593+
if errRet != nil {
1594+
return retryError(errRet, InternalError)
1595+
}
1596+
if instance != nil && *instance.InstanceState == CVM_STATUS_RUNNING {
1597+
return nil
1598+
}
1599+
return resource.RetryableError(fmt.Errorf("cvm instance status is %s, retry...", *instance.InstanceState))
1600+
})
1601+
if err != nil {
1602+
return err
1603+
}
1604+
} else {
1605+
stoppedMode := d.Get("stopped_mode").(string)
1606+
skipStopApi := false
1607+
err = resource.Retry(writeRetryTimeout, func() *resource.RetryError {
1608+
// when retry polling instance status, stop instance should skipped
1609+
if !skipStopApi {
1610+
err := cvmService.StopInstance(ctx, instanceId, stoppedMode)
1611+
if err != nil {
1612+
return resource.NonRetryableError(err)
1613+
}
1614+
}
1615+
instance, err := cvmService.DescribeInstanceById(ctx, instanceId)
1616+
if err != nil {
1617+
return resource.NonRetryableError(err)
1618+
}
1619+
if instance == nil {
1620+
return resource.NonRetryableError(fmt.Errorf("instance %s not found", instanceId))
1621+
}
1622+
1623+
if instance.LatestOperationState != nil {
1624+
operationState := *instance.LatestOperationState
1625+
if operationState == "OPERATING" {
1626+
skipStopApi = true
1627+
return resource.RetryableError(fmt.Errorf("instance %s stop operating, retrying", instanceId))
1628+
}
1629+
if operationState == "FAILED" {
1630+
skipStopApi = false
1631+
return resource.RetryableError(fmt.Errorf("instance %s stop failed, retrying", instanceId))
1632+
}
1633+
}
1634+
return nil
1635+
})
1636+
if err != nil {
1637+
return err
1638+
}
1639+
err = resource.Retry(2*readRetryTimeout, func() *resource.RetryError {
1640+
instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId)
1641+
if errRet != nil {
1642+
return retryError(errRet, InternalError)
1643+
}
1644+
if instance != nil && *instance.InstanceState == CVM_STATUS_STOPPED {
1645+
return nil
1646+
}
1647+
return resource.RetryableError(fmt.Errorf("cvm instance status is %s, retry...", *instance.InstanceState))
1648+
})
1649+
if err != nil {
1650+
return err
1651+
}
1652+
}
1653+
return nil
1654+
}

tencentcloud/resource_tc_instance_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ func TestAccTencentCloudInstanceWithDataDisk(t *testing.T) {
125125
testAccCheckTencentCloudDataSourceID(id),
126126
testAccCheckTencentCloudInstanceExists(id),
127127
resource.TestCheckResourceAttr(id, "instance_status", "RUNNING"),
128-
resource.TestCheckResourceAttr(id, "system_disk_size", "50"),
128+
resource.TestCheckResourceAttr(id, "system_disk_size", "100"),
129129
resource.TestCheckResourceAttr(id, "system_disk_type", "CLOUD_PREMIUM"),
130130
resource.TestCheckResourceAttr(id, "data_disks.0.data_disk_type", "CLOUD_PREMIUM"),
131131
resource.TestCheckResourceAttr(id, "data_disks.0.data_disk_size", "150"),
@@ -633,6 +633,7 @@ resource "tencentcloud_instance" "foo" {
633633
instance_type = data.tencentcloud_instance_types.default.instance_types.0.instance_type
634634
635635
system_disk_type = "CLOUD_PREMIUM"
636+
system_disk_size = 100
636637
637638
data_disks {
638639
data_disk_type = "CLOUD_PREMIUM"

website/docs/r/instance.html.markdown

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,8 @@ The following arguments are supported:
172172
* `stopped_mode` - (Optional) Billing method of a pay-as-you-go instance after shutdown. Available values: `KEEP_CHARGING`,`STOP_CHARGING`. Default `KEEP_CHARGING`.
173173
* `subnet_id` - (Optional) The ID of a VPC subnet. If you want to create instances in a VPC network, this parameter must be set.
174174
* `system_disk_id` - (Optional) System disk snapshot ID used to initialize the system disk. When system disk type is `LOCAL_BASIC` and `LOCAL_SSD`, disk id is not supported.
175-
* `system_disk_size` - (Optional, ForceNew) Size of the system disk. Valid value ranges: (50~1000). and unit is GB. Default is 50GB.
176-
* `system_disk_type` - (Optional, ForceNew) System disk type. For more information on limits of system disk types, see [Storage Overview](https://intl.cloud.tencent.com/document/product/213/4952). Valid values: `LOCAL_BASIC`: local disk, `LOCAL_SSD`: local SSD disk, `CLOUD_SSD`: SSD, `CLOUD_PREMIUM`: Premium Cloud Storage. NOTE: `CLOUD_BASIC`, `LOCAL_BASIC` and `LOCAL_SSD` are deprecated.
175+
* `system_disk_size` - (Optional) Size of the system disk. Valid value ranges: (50~1000). and unit is GB. Default is 50GB. If modified, the instance may force stop.
176+
* `system_disk_type` - (Optional) System disk type. For more information on limits of system disk types, see [Storage Overview](https://intl.cloud.tencent.com/document/product/213/4952). Valid values: `LOCAL_BASIC`: local disk, `LOCAL_SSD`: local SSD disk, `CLOUD_SSD`: SSD, `CLOUD_PREMIUM`: Premium Cloud Storage. NOTE: 1. `CLOUD_BASIC`, `LOCAL_BASIC` and `LOCAL_SSD` are deprecated; 2. If modified, the instance may force stop.
177177
* `tags` - (Optional) A mapping of tags to assign to the resource. For tag limits, please refer to [Use Limits](https://intl.cloud.tencent.com/document/product/651/13354).
178178
* `user_data_raw` - (Optional, ForceNew) The user data to be injected into this instance, in plain text. Conflicts with `user_data`. Up to 16 KB after base64 encoded.
179179
* `user_data` - (Optional, ForceNew) The user data to be injected into this instance. Must be base64 encoded and up to 16 KB.

0 commit comments

Comments
 (0)