279 lines
7.9 KiB
Go
279 lines
7.9 KiB
Go
package create_ecs
|
||
|
||
import (
|
||
"encoding/base64"
|
||
"encoding/json"
|
||
"fmt"
|
||
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
|
||
ecs "github.com/alibabacloud-go/ecs-20140526/v3/client"
|
||
util "github.com/alibabacloud-go/tea-utils/v2/service"
|
||
"github.com/alibabacloud-go/tea/tea"
|
||
log "gitlink.org.cn/cloudream/common/pkgs/logger"
|
||
"time"
|
||
)
|
||
|
||
type AliCloud struct{}
|
||
|
||
var aliclient = &ecs.Client{}
|
||
|
||
// var requestParam = &ecs.RunInstancesRequest{}
|
||
var requestParam ecs.RunInstancesRequest
|
||
var aliConfigMap map[string]interface{}
|
||
|
||
func AliConfig(authConfigs map[string]interface{}, ecsConfigs map[string]interface{}) {
|
||
aliConfigMap = ecsConfigs
|
||
|
||
jsonData, err := json.Marshal(ecsConfigs)
|
||
if err != nil {
|
||
return
|
||
}
|
||
|
||
err = json.Unmarshal(jsonData, &requestParam)
|
||
if err != nil {
|
||
log.Error(err)
|
||
return
|
||
}
|
||
|
||
config := &openapi.Config{}
|
||
config.AccessKeyId = tea.String(authConfigs["AccessKeyId"].(string))
|
||
config.AccessKeySecret = tea.String(authConfigs["AccessKeySecret"].(string))
|
||
config.RegionId = requestParam.RegionId
|
||
aliclient, _ = ecs.NewClient(config)
|
||
}
|
||
|
||
// CreateServer 创建实例
|
||
func (a *AliCloud) CreateServer() (string, string, error) {
|
||
var instanceID string
|
||
var instanceIDArr string
|
||
|
||
tryErr := func() (_e error) {
|
||
defer func() {
|
||
if r := tea.Recover(recover()); r != nil {
|
||
_e = r
|
||
println(_e.Error())
|
||
}
|
||
}()
|
||
log.Info(tea.String("--------------------批量创建实例开始--------------------"))
|
||
responces, _err := aliclient.RunInstances(&requestParam)
|
||
if _err != nil {
|
||
println(_err.Error())
|
||
return _err
|
||
}
|
||
instanceID = tea.StringValue(util.ToJSONString(responces.Body.InstanceIdSets.InstanceIdSet[0]))
|
||
instanceIDArr = tea.StringValue(util.ToJSONString(responces.Body.InstanceIdSets.InstanceIdSet))
|
||
log.Info(tea.String("--------------------创建实例成功,实例ID:" + tea.StringValue(util.ToJSONString(responces.Body.InstanceIdSets.InstanceIdSet)) + "--------------------"))
|
||
|
||
return nil
|
||
}()
|
||
|
||
if tryErr != nil {
|
||
println(tryErr.Error())
|
||
var error = &tea.SDKError{}
|
||
if _t, ok := tryErr.(*tea.SDKError); ok {
|
||
error = _t
|
||
} else {
|
||
error.Message = tea.String(tryErr.Error())
|
||
}
|
||
log.Info(tea.String("--------------------创建实例失败:" + tea.StringValue(util.ToJSONString(error.Code)) + "--------------------"))
|
||
return "", "", tryErr
|
||
}
|
||
|
||
// 获取实例IP
|
||
ip, _ := getInstanceIP(instanceIDArr, *aliclient.RegionId)
|
||
println("ip: " + ip)
|
||
|
||
return instanceID, ip, nil
|
||
}
|
||
|
||
// RunCommand 执行指令
|
||
func (a *AliCloud) RunCommand(commands []string, instanceID string, timeout int) (string, error) {
|
||
var result string
|
||
for i := 0; i < len(commands); i++ {
|
||
log.Info("start execute command")
|
||
if i == len(commands)-3 {
|
||
println()
|
||
}
|
||
commandId, err := runShellCommand(commands[i], instanceID, *aliclient.RegionId)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
// 判断是否执行成功
|
||
log.Info("describe result")
|
||
_, result, err = describeInvocationResults(aliclient, instanceID, commandId, tea.String("utf-8"), timeout)
|
||
if err != nil {
|
||
log.Error("describeInvocationResults: " + err.Error())
|
||
return "", err
|
||
}
|
||
}
|
||
|
||
return result, nil
|
||
}
|
||
|
||
// DestroyServer 强制销毁实例
|
||
func (a *AliCloud) DeleteInstance(instanceID string) (string, error) {
|
||
result, err := aliclient.DeleteInstance(&ecs.DeleteInstanceRequest{
|
||
InstanceId: &instanceID,
|
||
Force: tea.Bool(true),
|
||
})
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
return tea.StringValue(result.Body.RequestId), nil
|
||
}
|
||
|
||
func (a *AliCloud) StopInstance(instanceID string) (string, error) {
|
||
result, err := aliclient.StopInstance(&ecs.StopInstanceRequest{
|
||
InstanceId: &instanceID,
|
||
ForceStop: tea.Bool(true),
|
||
})
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
return tea.StringValue(result.Body.RequestId), nil
|
||
}
|
||
|
||
func (a *AliCloud) RebootInstances(instanceID string) (string, error) {
|
||
result, err := aliclient.RebootInstances(&ecs.RebootInstancesRequest{
|
||
InstanceId: []*string{&instanceID},
|
||
RegionId: aliclient.RegionId,
|
||
})
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
return tea.StringValue(result.Body.RequestId), nil
|
||
}
|
||
|
||
func (a *AliCloud) StartInstances(instanceID string) (string, error) {
|
||
runtime := &util.RuntimeOptions{}
|
||
result, err := aliclient.StartInstanceWithOptions(&ecs.StartInstanceRequest{
|
||
InstanceId: &instanceID,
|
||
}, runtime)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
return tea.StringValue(result.Body.RequestId), nil
|
||
}
|
||
|
||
func runShellCommand(commandContent string, instanceID string, regionId string) (*string, error) {
|
||
commandRequest := ecs.RunCommandRequest{
|
||
InstanceId: []*string{&instanceID},
|
||
CommandContent: tea.String(commandContent),
|
||
Type: tea.String("RunShellScript"),
|
||
RegionId: ®ionId,
|
||
Timeout: tea.Int64(2000),
|
||
}
|
||
|
||
// 发起请求
|
||
response, err := aliclient.RunCommand(&commandRequest)
|
||
if err != nil {
|
||
fmt.Println("Error running command:", err)
|
||
return nil, err
|
||
}
|
||
|
||
fmt.Printf("Command ID: %s\n", response.Body.CommandId)
|
||
return response.Body.CommandId, nil
|
||
}
|
||
|
||
/**
|
||
* describeInvocationResults 查看云助手命令的执行结果
|
||
*/
|
||
func describeInvocationResults(client *ecs.Client, instanceId string, commandId *string, contentEncoding *string, timeout int) (_result bool, output string, _err error) {
|
||
//var output string
|
||
req := &ecs.DescribeInvocationResultsRequest{}
|
||
// 实例ID
|
||
req.InstanceId = &instanceId
|
||
// 可用区ID
|
||
req.RegionId = client.RegionId
|
||
// 脚本ID
|
||
req.CommandId = commandId
|
||
// 设置返回数据中Output字段的编码方式
|
||
req.ContentEncoding = contentEncoding
|
||
invocationResult := &ecs.DescribeInvocationResultsResponseBodyInvocationInvocationResultsInvocationResult{}
|
||
|
||
for i := 0; i <= timeout; i++ {
|
||
if i == timeout {
|
||
return _result, "", _err
|
||
}
|
||
|
||
resp, _err := client.DescribeInvocationResults(req)
|
||
if _err != nil {
|
||
return _result, "", _err
|
||
}
|
||
|
||
invocationResult = resp.Body.Invocation.InvocationResults.InvocationResult[0]
|
||
|
||
if tea.BoolValue(util.IsUnset(invocationResult.ExitCode)) {
|
||
time.Sleep(2 * time.Second)
|
||
continue
|
||
}
|
||
break
|
||
}
|
||
|
||
if !tea.BoolValue(util.IsUnset(invocationResult.InvocationStatus)) && tea.BoolValue(util.EqualString(invocationResult.InvocationStatus, tea.String("Aborted"))) {
|
||
log.Info(tea.String("执行失败 错误信息 " + tea.StringValue(invocationResult.ErrorInfo)))
|
||
_result = *tea.Bool(false)
|
||
return _result, "", _err
|
||
} else {
|
||
if tea.BoolValue(util.EqualString(tea.String(tea.ToString(tea.Int64Value(invocationResult.ExitCode))), tea.String("0"))) {
|
||
// 解码 Base64 字符串
|
||
decodedBytes, err := base64.StdEncoding.DecodeString(tea.StringValue(invocationResult.Output))
|
||
if err != nil {
|
||
fmt.Println("Error decoding Base64 string:", err)
|
||
return
|
||
}
|
||
|
||
// 将字节数组转换为字符串
|
||
output = string(decodedBytes)
|
||
fmt.Printf("execute result: %v\n", output)
|
||
} else {
|
||
log.Info(tea.String("错误码 " + tea.StringValue(invocationResult.ErrorCode) + " 错误信息 " + tea.StringValue(invocationResult.ErrorInfo)))
|
||
}
|
||
|
||
_result = *tea.Bool(true)
|
||
return _result, output, _err
|
||
}
|
||
|
||
}
|
||
|
||
func getInstanceIP(instanceID string, regionId string) (string, error) {
|
||
var ip string
|
||
|
||
// 定义检查状态的最大重试次数
|
||
maxRetries := 30
|
||
for i := 0; i < maxRetries; i++ {
|
||
req := &ecs.DescribeInstancesRequest{
|
||
InstanceIds: tea.String(instanceID),
|
||
RegionId: tea.String(regionId),
|
||
}
|
||
|
||
// 执行请求
|
||
resp, err := aliclient.DescribeInstances(req)
|
||
if err != nil {
|
||
fmt.Println("Error describing instance:", err)
|
||
return "", err
|
||
}
|
||
// 检查实例状态
|
||
for _, instance := range resp.Body.Instances.Instance {
|
||
fmt.Printf("Instance ID: %s, Status: %s\n", *instance.InstanceId, *instance.Status)
|
||
if *instance.Status == "Running" {
|
||
// 实例已运行,获取公网IP
|
||
if len(instance.PublicIpAddress.IpAddress) > 0 {
|
||
ip = *instance.PublicIpAddress.IpAddress[0]
|
||
return ip, nil
|
||
} else {
|
||
fmt.Println("Instance is running but has no public IP.")
|
||
}
|
||
}
|
||
}
|
||
time.Sleep(2 * time.Second)
|
||
}
|
||
|
||
return "", nil
|
||
}
|
||
|
||
func (a *AliCloud) AvailableCheck(instanceID string) bool {
|
||
// 待实现
|
||
|
||
return true
|
||
}
|