go-common/app/admin/ep/merlin/service/machine.go
2019-04-22 18:49:16 +08:00

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
}