操作指南

最佳实践

故障处理

API 文档

文档中心 > 云服务器 > 操作指南 > 实例 > 销毁/退还实例 > 使用 API 销毁/退还包年包月实例及挂载的云硬盘

使用 API 销毁/退还包年包月实例及挂载的云硬盘

最近更新时间:2021-10-19 17:42:51

操作场景

本文档使用了腾讯云开发者工具套件(SDK)3.0及云 API 接口,实现在销毁包年包月云服务器实例时,同时销毁已挂载至该实例的所有包年包月云硬盘。本文档适用于销毁仅含有包年包月云硬盘的包年包月云服务器,提供 Python 及 Go 两种语言的示例代码,请您结合实际情况进行使用。

注意

销毁/退还云服务器实例及云硬盘所造成的影响请参见 相关影响

前提条件

  • 已具备计费模式为包年包月的云服务器实例,且该实例已挂载云硬盘。
  • 已前往 API 密钥管理 页面获取 SecretID 及 SecretKey。

操作步骤

安装依赖环境及 SDK

请根据您实际使用的开发语言,安装对应依赖环境及 SDK:

  1. 安装 Go 1.9 或其以上版本,并设置 GOPATH 等所需环境变量。详情请参见 Golang 官网
  2. 执行以下命令,安装 GO SDK。更多信息请参见 Tencent Cloud SDK 3.0 for Go
    go get github.com/tencentcloud/tencentcloud-sdk-go@latest

运行示例代码

示例代码如下,您可根据实际情况进行使用:

main 程序示例代码:

package main

import (
"termins" // 导入package
)

func main() {
var id = "xxxxxx" // 请替换为实际使用的 SecretID
var key = "xxxxxx" // 请替换为实际使用的 SecretKey
var region = "ap-beijing"
ins := "ins-irmer45l"
termins.NewTerminateInstancesAndCbs(id, key, region).Process(ins)
}

销毁实例及云硬盘示例代码:
package termins

import (
"fmt"
cbs "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cbs/v20170312"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312"
"strings"
"time"
)

type TerminateInstancesAndCbs struct {
Credential \*common.Credential
Region string
CbsClient \*cbs.Client
CvmClient \*cvm.Client
}

func NewTerminateInstancesAndCbs(secretId string, secretKey string, region string) \*TerminateInstancesAndCbs {
credential := common.NewCredential(secretId, secretKey)

cpfCbs := profile.NewClientProfile()
cpfCbs.HttpProfile.Endpoint = "cbs.tencentcloudapi.com"
cbsClient, _ := cbs.NewClient(credential, region, cpfCbs)

cpfCvm := profile.NewClientProfile()
cpfCvm.HttpProfile.Endpoint = "cvm.tencentcloudapi.com"
cvmClient, _ := cvm.NewClient(credential, region, cpfCvm)

return &TerminateInstancesAndCbs{Credential: credential, Region: region, CbsClient: cbsClient, CvmClient: cvmClient}
}

func (c \*TerminateInstancesAndCbs) TerminateInstance(instanceId string) (cvmApiErrors []string){
request := cvm.NewTerminateInstancesRequest()
request.InstanceIds = common.StringPtrs([]string{instanceId})

for i := 0; i < 5; i ++ {
response, err := c.CvmClient.TerminateInstances(request)
if \_, ok := err.(\*errors.TencentCloudSDKError); ok {
cvmApiErrors = append(cvmApiErrors, fmt.Sprintf("Got API error when terminating %s: %s", instanceId, err))
time.Sleep(3 \* time.Second)
continue
}
if err != nil { // 非SDK错误
panic(err)
}
fmt.Printf("TerminateInstance: %s, resp: %s", instanceId, response.ToJsonString())
return []string{}
}
return cvmApiErrors
}

func (c \*TerminateInstancesAndCbs) DescribeDisksForInstances(instanceId string) ([]string, error) {
request := cbs.NewDescribeDisksRequest()
request.Filters = []\*cbs.Filter {
{
Values: common.StringPtrs([]string{instanceId}),
Name: common.StringPtr("instance-id"),
},
}
response, err := c.CbsClient.DescribeDisks(request)
if \_, ok := err.(\*errors.TencentCloudSDKError); ok {
fmt.Printf("An API error has returned: %s", err)
return []string{}, err
}
if err != nil {
panic(err)
}
var cbsIds []string
for \_, disk := range response.Response.DiskSet {
if \*disk.DiskUsage == "DATA_DISK" {
cbsIds = append(cbsIds, \*disk.DiskId)
}
}
return cbsIds, nil
}

func (c \*TerminateInstancesAndCbs) CheckTerminateInstanceSuccess(instanceId string) (result bool, cvmApiErrors []string){
request := cvm.NewDescribeInstancesRequest()
request.InstanceIds = common.StringPtrs([]string{instanceId})

for i := 0; i < 30; i ++ {
response, err := c.CvmClient.DescribeInstances(request)

if err != nil { // 非SDK错误
panic(err)
}
if \_, ok := err.(\*errors.TencentCloudSDKError); ! ok {
fmt.Printf("Describe instance %s: resp: %s", instanceId, response.ToJsonString())
// 后付费实例
if \*response.Response.TotalCount == 0 {
return true, []string{}
}
// 预付费实例
if *response.Response.TotalCount == 1 && \*response.Response.InstanceSet[0].InstanceState == "SHUTDOWN" {
return true, []string{}
}
} else {
cvmApiErrors = append(cvmApiErrors, fmt.Sprintf("Got API error when describing %s: %s", instanceId, err))
}
time.Sleep(6 \* time.Second)
}
return false, cvmApiErrors
}

func (c \*TerminateInstancesAndCbs) DetachDisks(diskIds []string) (result bool, cbsApiErrors []string){
request := cbs.NewDetachDisksRequest()
request.DiskIds = common.StringPtrs(diskIds)

for i := 0; i < 5; i ++ {
response, err := c.CbsClient.DetachDisks(request)
if \_, ok := err.(\*errors.TencentCloudSDKError); ! ok {
return true, []string{}
}
if err != nil { // 非SDK错误
panic(err)
}
fmt.Printf("Detach Disks: %s, resp: %s", strings.Join(diskIds, ","), response.ToJsonString())
cbsApiErrors = append(cbsApiErrors, fmt.Sprintf("Got API error when detaching disks: %s", err))
time.Sleep(3 \* time.Second)
}
return false, cbsApiErrors
}

func (c \*TerminateInstancesAndCbs) CheckDisksDetached(diskIds []string) (result bool, cbsApiErrors []string) {
second := 60 * 3
count := len(diskIds)

request := cbs.NewDescribeDisksRequest()
request.DiskIds = common.StringPtrs(diskIds)

for ; second > 0; second -= 3 {
response, err := c.CbsClient.DescribeDisks(request)
if \_, ok := err.(\*errors.TencentCloudSDKError); ! ok {
// 检查是否所有磁盘都已经解挂
cnt := count
for \_, disk := range response.Response.DiskSet {
if \*disk.Attached == false {
cnt -= 1
}
}
if cnt == 0 {
return true, []string{}
}
}
if err != nil { // 非SDK错误
panic(err)
}
cbsApiErrors = append(cbsApiErrors, fmt.Sprintf("Got API error when terminating disks: %s", err))
time.Sleep(3 \* time.Second)
}
return false, []string{}
}

func (c \*TerminateInstancesAndCbs) TerminateDisks(diskIds []string) (result bool, cbsApiErrors []string){

request := cbs.NewTerminateDisksRequest()
request.DiskIds = common.StringPtrs(diskIds)

for i := 0; i < 10; i ++ {
response, err := c.CbsClient.TerminateDisks(request)
if \_, ok := err.(\*errors.TencentCloudSDKError); ! ok {
return true, []string{}
}
if err != nil { // 非SDK错误
panic(err)
}
fmt.Printf("TerminateDisks: %s, resp: %s", strings.Join(diskIds, ","), response.ToJsonString())
cbsApiErrors = append(cbsApiErrors, fmt.Sprintf("Got API error when terminating disks: %s", err))
time.Sleep(6 \* time.Second)
}
return false, cbsApiErrors
}

func (c \*TerminateInstancesAndCbs) Process(instanceId string) {
// 从cvm实例中获取磁盘实例id
cbsIds, desDiskError := c.DescribeDisksForInstances(instanceId)
if desDiskError != nil {
panic(desDiskError)
}

// 销毁实例
termInsErrors := c.TerminateInstance(instanceId)
if len(termInsErrors) != 0 {
panic(termInsErrors)
}

// 检查实例是否处于shutdown状态
checkTermInsRes, checkTermInsErrors := c.CheckTerminateInstanceSuccess(instanceId)
if ! checkTermInsRes {
panic(checkTermInsErrors)
}

// 解挂磁盘
if len(cbsIds) == 0 {
return
}
detachDisksRes, detachDisksError := c.DetachDisks(cbsIds)
if ! detachDisksRes {
panic(detachDisksError)
}

// 检查磁盘是否已经解挂
checkDetachDisksRes, checkDetachDisksErrors := c.CheckDisksDetached(cbsIds)
if ! checkDetachDisksRes {
panic(checkDetachDisksErrors)
}

// 销毁磁盘
termDisksRes, termDisksErrors := c.TerminateDisks(cbsIds)
if ! termDisksRes {
panic(termDisksErrors)
}
}

目录