guest_rescue_task.go 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package guest
  15. import (
  16. "context"
  17. "yunion.io/x/jsonutils"
  18. api "yunion.io/x/onecloud/pkg/apis/compute"
  19. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  20. "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
  21. "yunion.io/x/onecloud/pkg/compute/models"
  22. "yunion.io/x/onecloud/pkg/util/logclient"
  23. )
  24. type StartRescueTask struct {
  25. SGuestBaseTask
  26. }
  27. func init() {
  28. taskman.RegisterTask(StartRescueTask{})
  29. }
  30. func (self *StartRescueTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
  31. // Flow: stop -> modify startvm script for rescue -> start
  32. guest := obj.(*models.SGuest)
  33. // Check if guest is running
  34. if guest.Status == api.VM_RUNNING {
  35. self.StopServer(ctx, guest)
  36. } else {
  37. self.PrepareRescue(ctx, guest)
  38. }
  39. }
  40. func (self *StartRescueTask) StopServer(ctx context.Context, guest *models.SGuest) {
  41. db.OpsLog.LogEvent(guest, db.ACT_STOPPING, nil, self.UserCred)
  42. guest.SetStatus(ctx, self.UserCred, api.VM_STOPPING, "StopServer")
  43. self.SetStage("OnServerStopComplete", nil)
  44. guest.StartGuestStopTask(ctx, self.UserCred, 0, true, false, self.GetTaskId())
  45. }
  46. func (self *StartRescueTask) OnServerStopComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
  47. db.OpsLog.LogEvent(guest, db.ACT_STOP, guest.GetShortDesc(ctx), self.UserCred)
  48. logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_STOP, guest.GetShortDesc(ctx), self.UserCred, true)
  49. self.PrepareRescue(ctx, guest)
  50. }
  51. func (self *StartRescueTask) OnServerStopCompleteFailed(ctx context.Context, guest *models.SGuest, err jsonutils.JSONObject) {
  52. guest.SetStatus(ctx, self.UserCred, api.VM_STOP_FAILED, err.String())
  53. db.OpsLog.LogEvent(guest, db.ACT_STOP_FAIL, err, self.UserCred)
  54. logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_STOP, err, self.UserCred, false)
  55. self.SetStageFailed(ctx, err)
  56. }
  57. func (self *StartRescueTask) PrepareRescue(ctx context.Context, guest *models.SGuest) {
  58. db.OpsLog.LogEvent(guest, db.ACT_START_RESCUE, nil, self.UserCred)
  59. guest.SetStatus(ctx, self.UserCred, api.VM_START_RESCUE, "PrepareRescue")
  60. host, _ := guest.GetHost()
  61. drv, err := guest.GetDriver()
  62. if err != nil {
  63. self.OnRescuePrepareCompleteFailed(ctx, guest, jsonutils.NewString(err.Error()))
  64. return
  65. }
  66. err = drv.RequestStartRescue(ctx, self, jsonutils.NewDict(), host, guest)
  67. if err != nil {
  68. self.OnRescuePrepareCompleteFailed(ctx, guest, jsonutils.NewString(err.Error()))
  69. return
  70. }
  71. self.OnRescuePrepareComplete(ctx, guest, nil)
  72. }
  73. func (self *StartRescueTask) OnRescuePrepareComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
  74. db.OpsLog.LogEvent(guest, db.ACT_START_RESCUE, guest.GetShortDesc(ctx), self.UserCred)
  75. logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_START_RESCUE, guest.GetShortDesc(ctx), self.UserCred, true)
  76. guest.UpdateRescueMode(true)
  77. self.RescueStartServer(ctx, guest)
  78. }
  79. func (self *StartRescueTask) OnRescuePrepareCompleteFailed(ctx context.Context, guest *models.SGuest, err jsonutils.JSONObject) {
  80. guest.SetStatus(ctx, self.UserCred, api.VM_START_RESCUE_FAILED, err.String())
  81. db.OpsLog.LogEvent(guest, db.ACT_STOP_FAIL, err, self.UserCred)
  82. logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_STOP, err, self.UserCred, false)
  83. guest.UpdateRescueMode(false)
  84. self.SetStageFailed(ctx, err)
  85. }
  86. func (self *StartRescueTask) RescueStartServer(ctx context.Context, guest *models.SGuest) {
  87. guest.SetStatus(ctx, self.UserCred, api.VM_START_RESCUE, "RescueStartServer")
  88. self.SetStage("OnRescueStartServerComplete", nil)
  89. // Set Guest rescue params to guest start params
  90. host, _ := guest.GetHost()
  91. drv, err := guest.GetDriver()
  92. if err != nil {
  93. self.OnRescueStartServerCompleteFailed(ctx, guest, jsonutils.NewString(err.Error()))
  94. return
  95. }
  96. err = drv.RequestStartOnHost(ctx, guest, host, self.UserCred, self)
  97. if err != nil {
  98. self.OnRescueStartServerCompleteFailed(ctx, guest, jsonutils.NewString(err.Error()))
  99. return
  100. }
  101. }
  102. func (self *StartRescueTask) OnRescueStartServerComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
  103. db.OpsLog.LogEvent(guest, db.ACT_START_RESCUE, guest.GetShortDesc(ctx), self.UserCred)
  104. logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_START_RESCUE, guest.GetShortDesc(ctx), self.UserCred, true)
  105. self.SetStageComplete(ctx, nil)
  106. }
  107. func (self *StartRescueTask) OnRescueStartServerCompleteFailed(ctx context.Context, obj db.IStandaloneModel, err jsonutils.JSONObject) {
  108. guest := obj.(*models.SGuest)
  109. guest.SetStatus(ctx, self.UserCred, api.VM_START_RESCUE_FAILED, err.String())
  110. db.OpsLog.LogEvent(guest, db.ACT_START_RESCUE_FAILED, guest.GetShortDesc(ctx), self.UserCred)
  111. logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_START, guest.GetShortDesc(ctx), self.UserCred, true)
  112. }
  113. type StopRescueTask struct {
  114. SGuestBaseTask
  115. }
  116. func init() {
  117. taskman.RegisterTask(StopRescueTask{})
  118. }
  119. func (self *StopRescueTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
  120. // Flow: stop -> modify startvm script for rescue -> start
  121. guest := obj.(*models.SGuest)
  122. // Check if guest is running
  123. if guest.Status == api.VM_RUNNING || guest.Status == api.VM_RESCUE {
  124. self.StopServer(ctx, guest)
  125. } else {
  126. self.ClearRescue(ctx, guest)
  127. }
  128. }
  129. func (self *StopRescueTask) StopServer(ctx context.Context, guest *models.SGuest) {
  130. db.OpsLog.LogEvent(guest, db.ACT_STOPPING, nil, self.UserCred)
  131. guest.SetStatus(ctx, self.UserCred, api.VM_STOPPING, "StopServer")
  132. self.SetStage("OnServerStopComplete", nil)
  133. guest.StartGuestStopTask(ctx, self.UserCred, 0, true, false, self.GetTaskId())
  134. }
  135. func (self *StopRescueTask) OnServerStopComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
  136. db.OpsLog.LogEvent(guest, db.ACT_STOP, guest.GetShortDesc(ctx), self.UserCred)
  137. logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_STOP, guest.GetShortDesc(ctx), self.UserCred, true)
  138. self.ClearRescue(ctx, guest)
  139. }
  140. func (self *StopRescueTask) OnServerStopCompleteFailed(ctx context.Context, guest *models.SGuest, err jsonutils.JSONObject) {
  141. guest.SetStatus(ctx, self.UserCred, api.VM_STOP_FAILED, err.String())
  142. db.OpsLog.LogEvent(guest, db.ACT_STOP_FAIL, err, self.UserCred)
  143. logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_STOP, err, self.UserCred, false)
  144. self.SetStageFailed(ctx, err)
  145. }
  146. func (self *StopRescueTask) ClearRescue(ctx context.Context, guest *models.SGuest) {
  147. db.OpsLog.LogEvent(guest, db.ACT_STOP_RESCUE, nil, self.UserCred)
  148. guest.SetStatus(ctx, self.UserCred, api.VM_STOP_RESCUE, "ClearRescue")
  149. self.OnRescueClearComplete(ctx, guest, nil)
  150. }
  151. func (self *StopRescueTask) OnRescueClearComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
  152. db.OpsLog.LogEvent(guest, db.ACT_STOP_RESCUE, guest.GetShortDesc(ctx), self.UserCred)
  153. logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_STOP_RESCUE, guest.GetShortDesc(ctx), self.UserCred, true)
  154. if err := guest.UpdateRescueMode(false); err != nil {
  155. self.OnRescueClearCompleteFailed(ctx, guest, jsonutils.NewString(err.Error()))
  156. return
  157. }
  158. self.RescueStartServer(ctx, guest)
  159. }
  160. func (self *StopRescueTask) OnRescueClearCompleteFailed(ctx context.Context, guest *models.SGuest, err jsonutils.JSONObject) {
  161. guest.SetStatus(ctx, self.UserCred, api.VM_STOP_RESCUE_FAILED, err.String())
  162. db.OpsLog.LogEvent(guest, db.ACT_STOP_RESCUE_FAILED, err, self.UserCred)
  163. logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_STOP_RESCUE, err, self.UserCred, false)
  164. self.SetStageFailed(ctx, err)
  165. }
  166. func (self *StopRescueTask) RescueStartServer(ctx context.Context, guest *models.SGuest) {
  167. guest.SetStatus(ctx, self.UserCred, api.VM_STARTING, "RescueStartServer")
  168. self.SetStage("OnRescueStartServerComplete", nil)
  169. // Set Guest rescue params to guest start params
  170. host, _ := guest.GetHost()
  171. drv, err := guest.GetDriver()
  172. if err != nil {
  173. self.OnRescueStartServerCompleteFailed(ctx, guest, jsonutils.NewString(err.Error()))
  174. return
  175. }
  176. err = drv.RequestStartOnHost(ctx, guest, host, self.UserCred, self)
  177. if err != nil {
  178. self.OnRescueStartServerCompleteFailed(ctx, guest, jsonutils.NewString(err.Error()))
  179. return
  180. }
  181. }
  182. func (self *StopRescueTask) OnRescueStartServerComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
  183. db.OpsLog.LogEvent(guest, db.ACT_START, guest.GetShortDesc(ctx), self.UserCred)
  184. logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_START, guest.GetShortDesc(ctx), self.UserCred, true)
  185. // Set guest status to rescue running
  186. guest.SetStatus(ctx, self.UserCred, api.VM_RUNNING, "OnRescueStartServerComplete")
  187. self.SetStageComplete(ctx, nil)
  188. }
  189. func (self *StopRescueTask) OnRescueStartServerCompleteFailed(ctx context.Context, obj db.IStandaloneModel, err jsonutils.JSONObject) {
  190. guest := obj.(*models.SGuest)
  191. guest.SetStatus(ctx, self.UserCred, api.VM_START_FAILED, err.String())
  192. db.OpsLog.LogEvent(guest, db.ACT_START_FAIL, guest.GetShortDesc(ctx), self.UserCred)
  193. logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_START, guest.GetShortDesc(ctx), self.UserCred, true)
  194. }