machine.go 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. package service
  2. import (
  3. "context"
  4. "fmt"
  5. "strings"
  6. "go-common/app/admin/ep/merlin/model"
  7. "go-common/library/ecode"
  8. "go-common/library/log"
  9. )
  10. // GenMachines create multiple machines.
  11. func (s *Service) GenMachines(c context.Context, gmr *model.GenMachinesRequest, u string) (err error) {
  12. var (
  13. ins []*model.CreateInstance
  14. cluster *model.Cluster
  15. hasMachine bool
  16. ms []*model.Machine
  17. )
  18. if hasMachine, err = s.dao.HasMachine(gmr.Name); err != nil {
  19. return
  20. }
  21. if hasMachine {
  22. err = ecode.MerlinDuplicateMachineNameErr
  23. return
  24. }
  25. if cluster, err = s.dao.QueryCluster(c, gmr.NetworkID); err != nil {
  26. return
  27. }
  28. if cluster == nil {
  29. err = ecode.MerlinInvalidClusterErr
  30. return
  31. }
  32. if err = cluster.Verify(); err != nil {
  33. return
  34. }
  35. pgmr := gmr.ToPaasGenMachineRequest(s.c.Paas.MachineLimitRatio)
  36. if ms, err = s.dao.InsertMachinesV2(u, gmr, pgmr); err != nil {
  37. return
  38. }
  39. //insert image log
  40. for _, m := range ms {
  41. hubImageLog := &model.HubImageLog{
  42. UserName: u,
  43. MachineID: m.ID,
  44. ImageSrc: gmr.Image,
  45. ImageTag: "",
  46. Status: model.ImageSuccess,
  47. OperateType: model.ImageNoSnapshot,
  48. }
  49. s.dao.InsertHubImageLog(hubImageLog)
  50. }
  51. if ins, err = s.dao.GenPaasMachines(c, pgmr); err != nil {
  52. return
  53. }
  54. for _, in := range ins {
  55. if in.InstanceCreateStatus == model.CreateFailedMachineInPaas {
  56. s.dao.UpdateMachineStatusByName(model.ImmediatelyFailedMachineInMerlin, in.InstanceName)
  57. }
  58. }
  59. return
  60. }
  61. // DelMachineWhenCanBeDel Del Machine When Can Be Del.
  62. func (s *Service) DelMachineWhenCanBeDel(c context.Context, id int64, username string) (instance *model.ReleaseInstance, err error) {
  63. var (
  64. machine *model.Machine
  65. )
  66. if machine, err = s.dao.QueryMachine(id); err != nil {
  67. return
  68. }
  69. if machine.IsCreating() {
  70. err = ecode.MerlinCanNotBeDel
  71. return
  72. }
  73. return s.DelMachine(c, id, username)
  74. }
  75. // DelMachine delete machine by giving id.
  76. func (s *Service) DelMachine(c context.Context, id int64, username string, beforeDelMachineFuncs ...model.BeforeDelMachineFunc) (instance *model.ReleaseInstance, err error) {
  77. for _, beforeDelMachine := range beforeDelMachineFuncs {
  78. if err = beforeDelMachine(c, id, username); err != nil {
  79. return
  80. }
  81. }
  82. return s.delMachineWithoutComponent(c, id, username)
  83. }
  84. func (s *Service) delMachineWithoutComponent(c context.Context, mID int64, username string) (instance *model.ReleaseInstance, err error) {
  85. var (
  86. machine *model.Machine
  87. )
  88. if machine, err = s.dao.QueryMachine(mID); err != nil {
  89. return
  90. }
  91. machineLog := &model.MachineLog{
  92. OperateType: model.DeleteForMachineLog,
  93. Username: username,
  94. MachineID: mID,
  95. }
  96. if instance, err = s.delMachineWithoutLog(c, machine, username); err != nil {
  97. machineLog.OperateResult = model.OperationFailedForMachineLog
  98. } else {
  99. machineLog.OperateResult = model.OperationSuccessForMachineLog
  100. }
  101. machineLog.OperateType = model.DeleteForMachineLog
  102. machineLog.Username = username
  103. machineLog.MachineID = machine.ID
  104. err = s.dao.InsertMachineLog(machineLog)
  105. return
  106. }
  107. func (s *Service) delMachineWithoutLog(c context.Context, machine *model.Machine, username string) (instance *model.ReleaseInstance, err error) {
  108. if instance, err = s.dao.DelPaasMachine(c, machine.ToPaasQueryAndDelMachineRequest()); err != nil {
  109. return
  110. }
  111. if err = s.dao.UpdateTaskStatusByMachines([]int64{machine.ID}, model.TaskDone); err != nil {
  112. return
  113. }
  114. if err = s.dao.DelMachine(machine.ID, username); err != nil {
  115. return
  116. }
  117. if err = s.SendMailDeleteMachine(username, machine); err != nil {
  118. err = nil
  119. log.Error("Send mail failed (%v)", err)
  120. }
  121. return
  122. }
  123. // QueryMachineDetail query detail information of machine.
  124. func (s *Service) QueryMachineDetail(c context.Context, mID int64) (detail model.MachineDetail, err error) {
  125. var (
  126. machine *model.Machine
  127. passMachineDetail *model.PaasMachineDetail
  128. cluster *model.Cluster
  129. nodes []*model.MachineNode
  130. isSnapShot bool
  131. )
  132. if machine, err = s.dao.QueryMachine(mID); err != nil {
  133. return
  134. }
  135. if passMachineDetail, err = s.dao.QueryPaasMachine(c, machine.ToPaasQueryAndDelMachineRequest()); err != nil {
  136. return
  137. }
  138. if cluster, err = s.dao.QueryCluster(c, machine.NetworkID); err != nil {
  139. return
  140. }
  141. if cluster == nil {
  142. err = ecode.MerlinInvalidClusterErr
  143. return
  144. }
  145. if err = cluster.Verify(); err != nil {
  146. return
  147. }
  148. if nodes, err = s.dao.QueryMachineNodes(mID); err != nil {
  149. return
  150. }
  151. isSnapShot = strings.Contains(passMachineDetail.Image, s.c.BiliHub.MachineTagPri)
  152. detail = model.MachineDetail{
  153. Machine: *machine,
  154. Nodes: nodes,
  155. PaasMachineDetail: passMachineDetail.ConvertUnits(),
  156. Name: machine.Name,
  157. NetworkName: cluster.Networks[0].Name,
  158. IsSnapShot: isSnapShot,
  159. }
  160. return
  161. }
  162. // QueryMachinePackages query packages of machine.
  163. func (s *Service) QueryMachinePackages(c context.Context) (mp []*model.MachinePackage, err error) {
  164. return s.dao.FindAllMachinePackages()
  165. }
  166. //QueryMachines query multiple machines and update machine status
  167. func (s *Service) QueryMachines(c context.Context, session string, qmr *model.QueryMachineRequest) (p *model.PaginateMachine, err error) {
  168. var (
  169. machines []*model.Machine
  170. total int64
  171. cluster *model.Cluster
  172. podNames []string
  173. treeInstance *model.TreeInstance
  174. mapping map[string]*model.TreeInstance
  175. )
  176. if mapping, err = s.QueryTreeInstanceForMerlin(c, session, &qmr.TreeNode); err != nil {
  177. return
  178. }
  179. for k := range mapping {
  180. podNames = append(podNames, k)
  181. }
  182. if total, machines, err = s.dao.QueryMachines(podNames, qmr); err != nil {
  183. return
  184. }
  185. genMachines := make([]model.GenMachine, len(machines))
  186. for i, m := range machines {
  187. if cluster, err = s.dao.QueryCluster(c, m.NetworkID); err != nil {
  188. return
  189. }
  190. genMachines[i] = model.GenMachine{
  191. Machine: *m,
  192. ClusterName: cluster.Name,
  193. NetworkName: cluster.Networks[0].Name,
  194. }
  195. treeInstance = mapping[m.PodName]
  196. if treeInstance != nil {
  197. genMachines[i].IP = treeInstance.InternalIP
  198. }
  199. }
  200. p = &model.PaginateMachine{
  201. PageNum: qmr.PageNum,
  202. PageSize: qmr.PageSize,
  203. Total: total,
  204. Machines: genMachines,
  205. }
  206. return
  207. }
  208. // QueryMachineLogs query machine logs.
  209. func (s *Service) QueryMachineLogs(c context.Context, queryRequest *model.QueryMachineLogRequest) (p *model.PaginateMachineLog, err error) {
  210. var (
  211. total int64
  212. machineLogs []*model.AboundMachineLog
  213. )
  214. if total, machineLogs, err = s.dao.FindMachineLogs(queryRequest); err != nil {
  215. return
  216. }
  217. p = &model.PaginateMachineLog{
  218. PageNum: queryRequest.PageNum,
  219. PageSize: queryRequest.PageSize,
  220. Total: total,
  221. MachineLogs: machineLogs,
  222. }
  223. return
  224. }
  225. // QueryMachineStatus query the status of machine.
  226. func (s *Service) QueryMachineStatus(c context.Context, machineID int64) (msr *model.MachineStatusResponse, err error) {
  227. var m *model.Machine
  228. if m, err = s.dao.QueryMachine(machineID); err != nil {
  229. return
  230. }
  231. if m.IsFailed() || m.IsDeleted() {
  232. return
  233. }
  234. if msr, err = s.verifyPassStatus(c, m, true); err != nil {
  235. return
  236. }
  237. return
  238. }
  239. // TransferMachine Transfer Machine.
  240. func (s *Service) TransferMachine(c context.Context, machineID int64, username, receiver string) (status int, err error) {
  241. var (
  242. machine *model.Machine
  243. treePath string
  244. treeRoles []*model.TreeRole
  245. isReceiverAccessTreeNode bool
  246. )
  247. if _, err = s.dao.FindUserByUserName(receiver); err != nil {
  248. err = ecode.MerlinUserNotExist
  249. return
  250. }
  251. if machine, err = s.dao.QueryMachine(machineID); err != nil {
  252. return
  253. }
  254. // 查看接受者有无机器所在服务树节点权限
  255. treePath = machine.BusinessUnit + "." + machine.Project + "." + machine.App
  256. if treeRoles, err = s.dao.TreeRolesAsPlatform(c, treePath); err != nil {
  257. return
  258. }
  259. for _, treeRole := range treeRoles {
  260. if treeRole.UserName == receiver {
  261. isReceiverAccessTreeNode = true
  262. break
  263. }
  264. }
  265. if !isReceiverAccessTreeNode {
  266. err = ecode.MerlinUserNoAccessTreeNode
  267. return
  268. }
  269. machineLog := &model.MachineLog{
  270. OperateType: model.TransferForMachineLog,
  271. Username: username,
  272. MachineID: machineID,
  273. }
  274. if err = s.dao.UpdateMachineUser(machineID, receiver); err != nil {
  275. machineLog.OperateResult = model.OperationFailedForMachineLog
  276. } else {
  277. machineLog.OperateResult = model.OperationSuccessForMachineLog
  278. //send mail
  279. mailHeader := fmt.Sprintf("机器:[%s] 被用户[%s]从用户[%s]名下转移至用户[%s]", machine.Name, username, machine.Username, receiver)
  280. var sendMailUsers []string
  281. sendMailUsers = append(sendMailUsers, username)
  282. sendMailUsers = append(sendMailUsers, receiver)
  283. sendMailUsers = append(sendMailUsers, machine.Username)
  284. s.SendMailForMultiUsers(c, sendMailUsers, mailHeader)
  285. }
  286. err = s.dao.InsertMachineLog(machineLog)
  287. return
  288. }
  289. func (s *Service) verifyPassStatus(c context.Context, m *model.Machine, targetCreating bool) (msr *model.MachineStatusResponse, err error) {
  290. var (
  291. ms *model.MachineStatus
  292. b bool
  293. status int
  294. shadow *model.MachineStatusResponse
  295. )
  296. if msr = model.InstanceMachineStatusResponse(m.Status); msr != nil {
  297. return
  298. }
  299. if ms, err = s.dao.QueryPaasMachineStatus(c, m.ToPaasQueryAndDelMachineRequest()); err != nil {
  300. return
  301. }
  302. if b, err = s.TreeMachineIsExist(c, m.PodName, m.ToTreeNode()); err != nil {
  303. return
  304. }
  305. shadow = ms.ToMachineStatusResponse()
  306. if b {
  307. shadow.SynTree = model.True
  308. } else {
  309. shadow.SynTree = model.False
  310. }
  311. if targetCreating {
  312. status = shadow.CreatingMachineStatus()
  313. } else {
  314. status = shadow.FailedMachineStatus()
  315. }
  316. if err = s.dao.UpdateMachineStatus(m.ID, status); err != nil {
  317. return
  318. }
  319. msr = shadow
  320. return
  321. }