358 lines
9.5 KiB
Go
358 lines
9.5 KiB
Go
|
package service
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"strings"
|
||
|
|
||
|
"go-common/app/admin/ep/merlin/model"
|
||
|
"go-common/library/ecode"
|
||
|
"go-common/library/log"
|
||
|
)
|
||
|
|
||
|
// GenMachines create multiple machines.
|
||
|
func (s *Service) GenMachines(c context.Context, gmr *model.GenMachinesRequest, u string) (err error) {
|
||
|
var (
|
||
|
ins []*model.CreateInstance
|
||
|
cluster *model.Cluster
|
||
|
hasMachine bool
|
||
|
ms []*model.Machine
|
||
|
)
|
||
|
if hasMachine, err = s.dao.HasMachine(gmr.Name); err != nil {
|
||
|
return
|
||
|
}
|
||
|
if hasMachine {
|
||
|
err = ecode.MerlinDuplicateMachineNameErr
|
||
|
return
|
||
|
}
|
||
|
if cluster, err = s.dao.QueryCluster(c, gmr.NetworkID); err != nil {
|
||
|
return
|
||
|
}
|
||
|
if cluster == nil {
|
||
|
err = ecode.MerlinInvalidClusterErr
|
||
|
return
|
||
|
}
|
||
|
if err = cluster.Verify(); err != nil {
|
||
|
return
|
||
|
}
|
||
|
pgmr := gmr.ToPaasGenMachineRequest(s.c.Paas.MachineLimitRatio)
|
||
|
if ms, err = s.dao.InsertMachinesV2(u, gmr, pgmr); err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
//insert image log
|
||
|
for _, m := range ms {
|
||
|
hubImageLog := &model.HubImageLog{
|
||
|
UserName: u,
|
||
|
MachineID: m.ID,
|
||
|
ImageSrc: gmr.Image,
|
||
|
ImageTag: "",
|
||
|
Status: model.ImageSuccess,
|
||
|
OperateType: model.ImageNoSnapshot,
|
||
|
}
|
||
|
s.dao.InsertHubImageLog(hubImageLog)
|
||
|
}
|
||
|
|
||
|
if ins, err = s.dao.GenPaasMachines(c, pgmr); err != nil {
|
||
|
return
|
||
|
}
|
||
|
for _, in := range ins {
|
||
|
if in.InstanceCreateStatus == model.CreateFailedMachineInPaas {
|
||
|
s.dao.UpdateMachineStatusByName(model.ImmediatelyFailedMachineInMerlin, in.InstanceName)
|
||
|
}
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// DelMachineWhenCanBeDel Del Machine When Can Be Del.
|
||
|
func (s *Service) DelMachineWhenCanBeDel(c context.Context, id int64, username string) (instance *model.ReleaseInstance, err error) {
|
||
|
var (
|
||
|
machine *model.Machine
|
||
|
)
|
||
|
if machine, err = s.dao.QueryMachine(id); err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if machine.IsCreating() {
|
||
|
err = ecode.MerlinCanNotBeDel
|
||
|
return
|
||
|
}
|
||
|
|
||
|
return s.DelMachine(c, id, username)
|
||
|
|
||
|
}
|
||
|
|
||
|
// DelMachine delete machine by giving id.
|
||
|
func (s *Service) DelMachine(c context.Context, id int64, username string, beforeDelMachineFuncs ...model.BeforeDelMachineFunc) (instance *model.ReleaseInstance, err error) {
|
||
|
for _, beforeDelMachine := range beforeDelMachineFuncs {
|
||
|
if err = beforeDelMachine(c, id, username); err != nil {
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
return s.delMachineWithoutComponent(c, id, username)
|
||
|
}
|
||
|
|
||
|
func (s *Service) delMachineWithoutComponent(c context.Context, mID int64, username string) (instance *model.ReleaseInstance, err error) {
|
||
|
var (
|
||
|
machine *model.Machine
|
||
|
)
|
||
|
if machine, err = s.dao.QueryMachine(mID); err != nil {
|
||
|
return
|
||
|
}
|
||
|
machineLog := &model.MachineLog{
|
||
|
OperateType: model.DeleteForMachineLog,
|
||
|
Username: username,
|
||
|
MachineID: mID,
|
||
|
}
|
||
|
if instance, err = s.delMachineWithoutLog(c, machine, username); err != nil {
|
||
|
machineLog.OperateResult = model.OperationFailedForMachineLog
|
||
|
} else {
|
||
|
machineLog.OperateResult = model.OperationSuccessForMachineLog
|
||
|
}
|
||
|
machineLog.OperateType = model.DeleteForMachineLog
|
||
|
machineLog.Username = username
|
||
|
machineLog.MachineID = machine.ID
|
||
|
err = s.dao.InsertMachineLog(machineLog)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (s *Service) delMachineWithoutLog(c context.Context, machine *model.Machine, username string) (instance *model.ReleaseInstance, err error) {
|
||
|
if instance, err = s.dao.DelPaasMachine(c, machine.ToPaasQueryAndDelMachineRequest()); err != nil {
|
||
|
return
|
||
|
}
|
||
|
if err = s.dao.UpdateTaskStatusByMachines([]int64{machine.ID}, model.TaskDone); err != nil {
|
||
|
return
|
||
|
}
|
||
|
if err = s.dao.DelMachine(machine.ID, username); err != nil {
|
||
|
return
|
||
|
}
|
||
|
if err = s.SendMailDeleteMachine(username, machine); err != nil {
|
||
|
err = nil
|
||
|
log.Error("Send mail failed (%v)", err)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// QueryMachineDetail query detail information of machine.
|
||
|
func (s *Service) QueryMachineDetail(c context.Context, mID int64) (detail model.MachineDetail, err error) {
|
||
|
var (
|
||
|
machine *model.Machine
|
||
|
passMachineDetail *model.PaasMachineDetail
|
||
|
cluster *model.Cluster
|
||
|
nodes []*model.MachineNode
|
||
|
isSnapShot bool
|
||
|
)
|
||
|
if machine, err = s.dao.QueryMachine(mID); err != nil {
|
||
|
return
|
||
|
}
|
||
|
if passMachineDetail, err = s.dao.QueryPaasMachine(c, machine.ToPaasQueryAndDelMachineRequest()); err != nil {
|
||
|
return
|
||
|
}
|
||
|
if cluster, err = s.dao.QueryCluster(c, machine.NetworkID); err != nil {
|
||
|
return
|
||
|
}
|
||
|
if cluster == nil {
|
||
|
err = ecode.MerlinInvalidClusterErr
|
||
|
return
|
||
|
}
|
||
|
if err = cluster.Verify(); err != nil {
|
||
|
return
|
||
|
}
|
||
|
if nodes, err = s.dao.QueryMachineNodes(mID); err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
isSnapShot = strings.Contains(passMachineDetail.Image, s.c.BiliHub.MachineTagPri)
|
||
|
|
||
|
detail = model.MachineDetail{
|
||
|
Machine: *machine,
|
||
|
Nodes: nodes,
|
||
|
PaasMachineDetail: passMachineDetail.ConvertUnits(),
|
||
|
Name: machine.Name,
|
||
|
NetworkName: cluster.Networks[0].Name,
|
||
|
IsSnapShot: isSnapShot,
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// QueryMachinePackages query packages of machine.
|
||
|
func (s *Service) QueryMachinePackages(c context.Context) (mp []*model.MachinePackage, err error) {
|
||
|
return s.dao.FindAllMachinePackages()
|
||
|
}
|
||
|
|
||
|
//QueryMachines query multiple machines and update machine status
|
||
|
func (s *Service) QueryMachines(c context.Context, session string, qmr *model.QueryMachineRequest) (p *model.PaginateMachine, err error) {
|
||
|
var (
|
||
|
machines []*model.Machine
|
||
|
total int64
|
||
|
cluster *model.Cluster
|
||
|
podNames []string
|
||
|
treeInstance *model.TreeInstance
|
||
|
mapping map[string]*model.TreeInstance
|
||
|
)
|
||
|
if mapping, err = s.QueryTreeInstanceForMerlin(c, session, &qmr.TreeNode); err != nil {
|
||
|
return
|
||
|
}
|
||
|
for k := range mapping {
|
||
|
podNames = append(podNames, k)
|
||
|
}
|
||
|
|
||
|
if total, machines, err = s.dao.QueryMachines(podNames, qmr); err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
genMachines := make([]model.GenMachine, len(machines))
|
||
|
for i, m := range machines {
|
||
|
if cluster, err = s.dao.QueryCluster(c, m.NetworkID); err != nil {
|
||
|
return
|
||
|
}
|
||
|
genMachines[i] = model.GenMachine{
|
||
|
Machine: *m,
|
||
|
ClusterName: cluster.Name,
|
||
|
NetworkName: cluster.Networks[0].Name,
|
||
|
}
|
||
|
treeInstance = mapping[m.PodName]
|
||
|
if treeInstance != nil {
|
||
|
genMachines[i].IP = treeInstance.InternalIP
|
||
|
}
|
||
|
}
|
||
|
p = &model.PaginateMachine{
|
||
|
PageNum: qmr.PageNum,
|
||
|
PageSize: qmr.PageSize,
|
||
|
Total: total,
|
||
|
Machines: genMachines,
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// QueryMachineLogs query machine logs.
|
||
|
func (s *Service) QueryMachineLogs(c context.Context, queryRequest *model.QueryMachineLogRequest) (p *model.PaginateMachineLog, err error) {
|
||
|
var (
|
||
|
total int64
|
||
|
machineLogs []*model.AboundMachineLog
|
||
|
)
|
||
|
if total, machineLogs, err = s.dao.FindMachineLogs(queryRequest); err != nil {
|
||
|
return
|
||
|
}
|
||
|
p = &model.PaginateMachineLog{
|
||
|
PageNum: queryRequest.PageNum,
|
||
|
PageSize: queryRequest.PageSize,
|
||
|
Total: total,
|
||
|
MachineLogs: machineLogs,
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// QueryMachineStatus query the status of machine.
|
||
|
func (s *Service) QueryMachineStatus(c context.Context, machineID int64) (msr *model.MachineStatusResponse, err error) {
|
||
|
var m *model.Machine
|
||
|
if m, err = s.dao.QueryMachine(machineID); err != nil {
|
||
|
return
|
||
|
}
|
||
|
if m.IsFailed() || m.IsDeleted() {
|
||
|
return
|
||
|
}
|
||
|
if msr, err = s.verifyPassStatus(c, m, true); err != nil {
|
||
|
return
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// TransferMachine Transfer Machine.
|
||
|
func (s *Service) TransferMachine(c context.Context, machineID int64, username, receiver string) (status int, err error) {
|
||
|
var (
|
||
|
machine *model.Machine
|
||
|
treePath string
|
||
|
treeRoles []*model.TreeRole
|
||
|
isReceiverAccessTreeNode bool
|
||
|
)
|
||
|
|
||
|
if _, err = s.dao.FindUserByUserName(receiver); err != nil {
|
||
|
err = ecode.MerlinUserNotExist
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if machine, err = s.dao.QueryMachine(machineID); err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// 查看接受者有无机器所在服务树节点权限
|
||
|
treePath = machine.BusinessUnit + "." + machine.Project + "." + machine.App
|
||
|
|
||
|
if treeRoles, err = s.dao.TreeRolesAsPlatform(c, treePath); err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
for _, treeRole := range treeRoles {
|
||
|
if treeRole.UserName == receiver {
|
||
|
isReceiverAccessTreeNode = true
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if !isReceiverAccessTreeNode {
|
||
|
err = ecode.MerlinUserNoAccessTreeNode
|
||
|
return
|
||
|
}
|
||
|
|
||
|
machineLog := &model.MachineLog{
|
||
|
OperateType: model.TransferForMachineLog,
|
||
|
Username: username,
|
||
|
MachineID: machineID,
|
||
|
}
|
||
|
|
||
|
if err = s.dao.UpdateMachineUser(machineID, receiver); err != nil {
|
||
|
machineLog.OperateResult = model.OperationFailedForMachineLog
|
||
|
|
||
|
} else {
|
||
|
machineLog.OperateResult = model.OperationSuccessForMachineLog
|
||
|
|
||
|
//send mail
|
||
|
mailHeader := fmt.Sprintf("机器:[%s] 被用户[%s]从用户[%s]名下转移至用户[%s]", machine.Name, username, machine.Username, receiver)
|
||
|
|
||
|
var sendMailUsers []string
|
||
|
sendMailUsers = append(sendMailUsers, username)
|
||
|
sendMailUsers = append(sendMailUsers, receiver)
|
||
|
sendMailUsers = append(sendMailUsers, machine.Username)
|
||
|
|
||
|
s.SendMailForMultiUsers(c, sendMailUsers, mailHeader)
|
||
|
}
|
||
|
|
||
|
err = s.dao.InsertMachineLog(machineLog)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (s *Service) verifyPassStatus(c context.Context, m *model.Machine, targetCreating bool) (msr *model.MachineStatusResponse, err error) {
|
||
|
var (
|
||
|
ms *model.MachineStatus
|
||
|
b bool
|
||
|
status int
|
||
|
shadow *model.MachineStatusResponse
|
||
|
)
|
||
|
if msr = model.InstanceMachineStatusResponse(m.Status); msr != nil {
|
||
|
return
|
||
|
}
|
||
|
if ms, err = s.dao.QueryPaasMachineStatus(c, m.ToPaasQueryAndDelMachineRequest()); err != nil {
|
||
|
return
|
||
|
}
|
||
|
if b, err = s.TreeMachineIsExist(c, m.PodName, m.ToTreeNode()); err != nil {
|
||
|
return
|
||
|
}
|
||
|
shadow = ms.ToMachineStatusResponse()
|
||
|
if b {
|
||
|
shadow.SynTree = model.True
|
||
|
} else {
|
||
|
shadow.SynTree = model.False
|
||
|
}
|
||
|
if targetCreating {
|
||
|
status = shadow.CreatingMachineStatus()
|
||
|
} else {
|
||
|
status = shadow.FailedMachineStatus()
|
||
|
}
|
||
|
if err = s.dao.UpdateMachineStatus(m.ID, status); err != nil {
|
||
|
return
|
||
|
}
|
||
|
msr = shadow
|
||
|
return
|
||
|
}
|