megrez/routers/api/v1/admin/instance/modify.go
2025-03-30 01:25:21 +08:00

143 lines
3.8 KiB
Go

package instances
import (
"megrez/models"
"megrez/routers/api/v1/middleware"
"megrez/services/database"
"megrez/services/dispatcher"
"megrez/services/redis"
"strconv"
"github.com/kataras/iris/v12"
)
type modifyReqStruct struct {
CpuOnly bool `json:"cpu_only"`
GpuCount *int `json:"gpu_count"`
VolumeSize *int `json:"volume_size"`
}
func modifyHandler(ctx iris.Context) {
l.SetFunction("modifyHandler")
id, err := ctx.Params().GetUint("id")
if err != nil {
middleware.Error(ctx, middleware.CodeBadRequest, iris.StatusBadRequest)
return
}
var req modifyReqStruct
err = ctx.ReadJSON(&req)
if err != nil {
middleware.Error(ctx, middleware.CodeBadRequest, iris.StatusBadRequest)
return
}
if req.CpuOnly {
req.GpuCount = nil
}
if req.GpuCount != nil {
if *req.GpuCount < 0 {
middleware.Error(ctx, middleware.CodeBadRequest, iris.StatusBadRequest)
return
}
}
if req.VolumeSize != nil {
if *req.VolumeSize < 50 {
middleware.Error(ctx, middleware.CodeBadRequest, iris.StatusBadRequest)
return
}
}
instance := models.Instances{
ID: id,
}
result := database.DB.First(&instance)
if result.Error != nil {
l.Error("query instance error: %v", result.Error)
middleware.Error(ctx, middleware.CodeInstanceQueryError, iris.StatusInternalServerError)
return
}
if instance.Status != models.InstanceStatusStopped {
middleware.Error(ctx, middleware.CodeInstanceStatusError, iris.StatusBadRequest)
return
}
hasChanges := false
if req.CpuOnly != instance.CpuOnly {
hasChanges = true
}
if req.GpuCount != nil && *req.GpuCount != instance.GpuCount {
hasChanges = true
}
if req.VolumeSize != nil && *req.VolumeSize != instance.VolumeSize {
hasChanges = true
}
if !hasChanges {
middleware.Error(ctx, middleware.CodeBadRequest, iris.StatusBadRequest)
return
}
server := models.Servers{
ID: instance.ServerID,
}
result = database.DB.First(&server)
if result.Error != nil {
l.Error("query server error: %v", result.Error)
middleware.Error(ctx, middleware.CodeServerQueryError, iris.StatusInternalServerError)
return
}
if req.GpuCount != nil {
remainGpu, err := redis.RawDB.IncrBy(ctx, "remain_gpu:server:"+strconv.Itoa(int(server.ID)), int64(-*req.GpuCount)).Result()
if err != nil {
l.Error("incrby gpu num error: %v", err)
middleware.Error(ctx, middleware.CodeServerQueryError, iris.StatusInternalServerError)
return
}
if remainGpu < 0 {
redis.RawDB.IncrBy(ctx, "remain_gpu:server:"+strconv.Itoa(int(server.ID)), int64(*req.GpuCount))
middleware.Error(ctx, middleware.CodeResourceInsufficient, iris.StatusBadRequest)
return
}
}
if req.VolumeSize != nil {
remainVolume, err := redis.RawDB.IncrBy(ctx, "remain_volume:server:"+strconv.Itoa(int(server.ID)), int64(instance.VolumeSize-*req.VolumeSize)).Result()
if err != nil {
l.Error("incrby volume size error: %v", err)
middleware.Error(ctx, middleware.CodeServerQueryError, iris.StatusInternalServerError)
return
}
if remainVolume < 0 {
redis.RawDB.IncrBy(ctx, "remain_volume:server:"+strconv.Itoa(int(server.ID)), int64(*req.VolumeSize-instance.VolumeSize))
middleware.Error(ctx, middleware.CodeResourceInsufficient, iris.StatusBadRequest)
return
}
}
status := instance.Status
result = database.DB.Model(&instance).Update("status", models.InstanceStatusModifying)
if result.Error != nil {
l.Error("update instance status error: %v", result.Error)
middleware.Error(ctx, middleware.CodeServerSaveError, iris.StatusInternalServerError)
return
}
dispatcherData := dispatcher.Data{
Type: dispatcher.Modify,
InstanceID: instance.ID,
Status: status,
CpuOnly: req.CpuOnly,
GpuCount: req.GpuCount,
VolumeSize: req.VolumeSize,
}
dispatcher.Push(instance.ServerID, dispatcherData)
middleware.Success(ctx)
}