JCC-CSScheduler/executor/internal/task/create_ecs/alicloud.go

279 lines
7.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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: &regionId,
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
}