Files
ai/models/server.go
2023-06-05 10:16:51 +08:00

181 lines
5.7 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 models
import (
"encoding/json"
"fmt"
"main/configs"
"net/http"
"time"
"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"
)
type Server struct {
ID int `json:"id" gorm:"primary_key"`
Name string `json:"name"`
Type string `json:"type"` // (訓練|推理)
IP string `json:"ip"`
Port int `json:"port"`
Status string `json:"status"` // (異常|初始化|閒置|就緒|工作中|關閉中)
UserName string `json:"username"`
Password string `json:"password"`
Models []map[string]interface{} `json:"models" gorm:"-"` // 數據庫不必保存
CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"`
UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"`
}
type Config struct {
TencentCloud struct {
SecretId string `yaml:"SecretId"`
SecretKey string `yaml:"SecretKey"`
} `yaml:"TencentCloud"`
}
// 通過腾讯云API創建服務器
func CreateServerByTencentCloud(SecretId, SecretKey string) error {
credential := common.NewCredential(SecretId, SecretKey)
cpf := profile.NewClientProfile()
cpf.HttpProfile.Endpoint = "cvm.tencentcloudapi.com"
client, err := cvm.NewClient(credential, "ap-shanghai", cpf)
if err != nil {
return fmt.Errorf("初始化騰訊雲SDK客戶端失敗: %v", err)
}
// 实例化一个请求对象,每个接口都会对应一个request对象
request := cvm.NewRunInstancesRequest()
// 指定啓動模板, 以創建指定規格的服務器
request.LaunchTemplate = &cvm.LaunchTemplate{
LaunchTemplateId: common.StringPtr("lt-ks6y5evh"),
}
// 返回的resp是一个RunInstancesResponse的实例与请求对象对应
response, err := client.RunInstances(request)
if _, ok := err.(*errors.TencentCloudSDKError); ok {
return fmt.Errorf("已返回 API 错误: %v", err)
}
if err != nil {
return fmt.Errorf("运行实例失败: %v", err)
}
// 输出json格式的字符串回包
fmt.Printf("%s", response.ToJsonString())
return nil
}
// 通過腾讯云API註銷指定的服務器
func TerminateServerByTencentCloud(SecretId, SecretKey string) error {
credential := common.NewCredential(SecretId, SecretKey)
cpf := profile.NewClientProfile()
cpf.HttpProfile.Endpoint = "cvm.tencentcloudapi.com"
client, err := cvm.NewClient(credential, "ap-shanghai", cpf)
if err != nil {
return fmt.Errorf("初始化騰訊雲SDK客戶端失敗: %v", err)
}
// 实例化一个请求对象,每个接口都会对应一个request对象
request := cvm.NewTerminateInstancesRequest()
// 指定要註銷的服務器ID
request.InstanceIds = []*string{common.StringPtr("ins-q0z8ev39")}
// 返回的resp是一个TerminateInstancesResponse的实例与请求对象对应
response, err := client.TerminateInstances(request)
if _, ok := err.(*errors.TencentCloudSDKError); ok {
return fmt.Errorf("已返回 API 错误: %v", err)
}
if err != nil {
return fmt.Errorf("註銷實例失敗: %v", err)
}
// 输出json格式的字符串回包
fmt.Printf("%s", response.ToJsonString())
return nil
}
// 檢查騰訊雲中的服務器狀態
func CheckServerStatusByTencentCloud(SecretId, SecretKey string) error {
credential := common.NewCredential(SecretId, SecretKey)
cpf := profile.NewClientProfile()
cpf.HttpProfile.Endpoint = "cvm.tencentcloudapi.com"
client, err := cvm.NewClient(credential, "ap-shanghai", cpf)
if err != nil {
return fmt.Errorf("初始化騰訊雲SDK客戶端失敗: %v", err)
}
// 实例化一个请求对象,每个接口都会对应一个request对象
request := cvm.NewDescribeInstancesRequest()
// 返回的resp是一个DescribeInstancesResponse的实例与请求对象对应
response, err := client.DescribeInstances(request)
if _, ok := err.(*errors.TencentCloudSDKError); ok {
return fmt.Errorf("已返回 API 错误: %v", err)
}
if err != nil {
return fmt.Errorf("运行实例失败: %v", err)
}
// 输出json格式的字符串回包
fmt.Printf("%s", response.ToJsonString())
// 解析JSON
var data map[string]interface{}
if err := json.Unmarshal([]byte(response.ToJsonString()), &data); err != nil {
return err
}
fmt.Println(data["TotalCount"])
fmt.Println(data["InstanceSet"])
// TODO: 判斷每臺服務器狀態
return nil
}
func (server *Server) CheckStatus() error {
switch server.Type {
case "訓練":
resp, err := http.Get(fmt.Sprintf("http://%s:%d/dreambooth/status", server.IP, server.Port))
if err != nil {
server.Status = "異常"
return err
}
defer resp.Body.Close()
// 解碼JSON
var data map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
return err
}
// 解碼JSON
var current_state map[string]interface{}
if err := json.Unmarshal([]byte(data["current_state"].(string)), &current_state); err != nil {
return err
}
//log.Println("current_state:", current_state)
// 檢查服務器是否正常
if !current_state["active"].(bool) {
server.Status = "異常"
return fmt.Errorf("服務器狀態異常: active=false")
}
server.Status = "正常"
case "推理":
server.Status = "異常"
default:
server.Status = "異常"
}
// 檢查服務器是否正常
return nil
}
func init() {
configs.ORMDB().AutoMigrate(&Server{})
// 檢查所有服務器的狀態, 無效的服務器設置為異常
var servers []Server
configs.ORMDB().Find(&servers)
for _, server := range servers {
server.CheckStatus()
}
}