snapshot_delete_task.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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 snapshot
  15. import (
  16. "context"
  17. "database/sql"
  18. "yunion.io/x/cloudmux/pkg/cloudprovider"
  19. "yunion.io/x/jsonutils"
  20. "yunion.io/x/log"
  21. "yunion.io/x/pkg/errors"
  22. api "yunion.io/x/onecloud/pkg/apis/compute"
  23. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  24. "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
  25. "yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
  26. "yunion.io/x/onecloud/pkg/compute/models"
  27. "yunion.io/x/onecloud/pkg/util/logclient"
  28. )
  29. func init() {
  30. taskman.RegisterTask(SnapshotDeleteTask{})
  31. taskman.RegisterTask(BatchSnapshotsDeleteTask{})
  32. taskman.RegisterTask(GuestDeleteSnapshotsTask{})
  33. taskman.RegisterTask(DiskDeleteSnapshotsTask{})
  34. }
  35. /***************************** Snapshot Delete Task *****************************/
  36. type SnapshotDeleteTask struct {
  37. taskman.STask
  38. }
  39. func (self *SnapshotDeleteTask) OnRequestSnapshotFailed(ctx context.Context, snapshot *models.SSnapshot, data jsonutils.JSONObject) {
  40. self.TaskFailed(ctx, snapshot, data)
  41. }
  42. func (self *SnapshotDeleteTask) OnRequestSnapshot(ctx context.Context, snapshot *models.SSnapshot, data jsonutils.JSONObject) {
  43. err := snapshot.GetRegionDriver().OnSnapshotDelete(ctx, snapshot, self, data)
  44. if err != nil {
  45. self.TaskFailed(ctx, snapshot, jsonutils.NewString(err.Error()))
  46. }
  47. }
  48. func (self *SnapshotDeleteTask) OnManagedSnapshotDelete(ctx context.Context, snapshot *models.SSnapshot, data jsonutils.JSONObject) {
  49. snapshot.RealDelete(ctx, self.GetUserCred())
  50. self.TaskComplete(ctx, snapshot, nil)
  51. }
  52. func (self *SnapshotDeleteTask) OnKvmSnapshotDelete(ctx context.Context, snapshot *models.SSnapshot, data jsonutils.JSONObject) {
  53. snapshot.SetStatus(ctx, self.UserCred, api.SNAPSHOT_READY, "")
  54. if jsonutils.QueryBoolean(self.Params, "reload_disk", false) && snapshot.OutOfChain {
  55. self.SetStage("OnReloadDiskSnapshot", nil)
  56. self.OnReloadDiskSnapshot(ctx, snapshot, data)
  57. } else {
  58. self.SetStage("OnDeleteSnapshot", nil)
  59. self.OnDeleteSnapshot(ctx, snapshot, data)
  60. }
  61. }
  62. func (self *SnapshotDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
  63. snapshot := obj.(*models.SSnapshot)
  64. regionDriver := snapshot.GetRegionDriver()
  65. self.SetStage("OnRequestSnapshot", nil)
  66. err := regionDriver.RequestDeleteSnapshot(ctx, snapshot, self)
  67. if err != nil {
  68. if errors.Cause(err) == cloudprovider.ErrNotFound {
  69. self.ScheduleRun(jsonutils.Marshal(map[string]bool{"deleted": true}))
  70. return
  71. }
  72. self.TaskFailed(ctx, snapshot, jsonutils.NewString(err.Error()))
  73. }
  74. }
  75. func (self *SnapshotDeleteTask) OnDeleteSnapshot(ctx context.Context, snapshot *models.SSnapshot, data jsonutils.JSONObject) {
  76. if !jsonutils.QueryBoolean(data, "deleted", false) {
  77. log.Infof("OnDeleteSnapshot with no deleted")
  78. return
  79. }
  80. snapshot.SetStatus(ctx, self.UserCred, api.SNAPSHOT_READY, "OnDeleteSnapshot")
  81. snapshot.RealDelete(ctx, self.UserCred)
  82. self.TaskComplete(ctx, snapshot, nil)
  83. }
  84. func (self *SnapshotDeleteTask) OnDeleteSnapshotFailed(ctx context.Context, snapshot *models.SSnapshot, data jsonutils.JSONObject) {
  85. self.TaskFailed(ctx, snapshot, data)
  86. }
  87. func (self *SnapshotDeleteTask) OnReloadDiskSnapshot(ctx context.Context, snapshot *models.SSnapshot, data jsonutils.JSONObject) {
  88. if !jsonutils.QueryBoolean(data, "reopen", false) {
  89. log.Infof("OnReloadDiskSnapshot with no reopen")
  90. return
  91. }
  92. guest, err := snapshot.GetGuest()
  93. if err != nil {
  94. self.TaskFailed(ctx, snapshot, jsonutils.NewString(err.Error()))
  95. return
  96. }
  97. if snapshot.FakeDeleted {
  98. params := jsonutils.NewDict()
  99. disk, err := models.DiskManager.FetchById(snapshot.DiskId)
  100. if err != nil && err != sql.ErrNoRows {
  101. self.TaskFailed(ctx, snapshot, jsonutils.NewString(err.Error()))
  102. return
  103. }
  104. sDisk, _ := disk.(*models.SDisk)
  105. if sDisk.IsEncrypted() {
  106. if encryptInfo, err := sDisk.GetEncryptInfo(ctx, self.GetUserCred()); err != nil {
  107. self.TaskFailed(ctx, snapshot, jsonutils.NewString(err.Error()))
  108. return
  109. } else {
  110. params.Set("encrypt_info", jsonutils.Marshal(encryptInfo))
  111. }
  112. }
  113. params.Set("delete_snapshot", jsonutils.NewString(snapshot.Id))
  114. params.Set("disk_id", jsonutils.NewString(snapshot.DiskId))
  115. params.Set("auto_deleted", jsonutils.JSONTrue)
  116. self.SetStage("OnDeleteSnapshot", nil)
  117. drv, err := guest.GetDriver()
  118. if err != nil {
  119. self.TaskFailed(ctx, snapshot, jsonutils.NewString(err.Error()))
  120. return
  121. }
  122. err = drv.RequestDeleteSnapshot(ctx, guest, self, params)
  123. if err != nil {
  124. self.TaskFailed(ctx, snapshot, jsonutils.NewString(err.Error()))
  125. }
  126. } else {
  127. self.TaskComplete(ctx, snapshot, nil)
  128. }
  129. }
  130. func (self *SnapshotDeleteTask) TaskComplete(ctx context.Context, snapshot *models.SSnapshot, data jsonutils.JSONObject) {
  131. db.OpsLog.LogEvent(snapshot, db.ACT_SNAPSHOT_DELETE, snapshot.GetShortDesc(ctx), self.UserCred)
  132. logclient.AddActionLogWithStartable(self, snapshot, logclient.ACT_DELOCATE, nil, self.UserCred, true)
  133. notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{
  134. Obj: snapshot,
  135. Action: notifyclient.ActionDelete,
  136. })
  137. self.SetStageComplete(ctx, nil)
  138. guest, err := snapshot.GetGuest()
  139. if err != nil {
  140. log.Errorln(err.Error())
  141. return
  142. }
  143. guest.StartSyncstatus(ctx, self.UserCred, "")
  144. }
  145. func (self *SnapshotDeleteTask) TaskFailed(ctx context.Context, snapshot *models.SSnapshot, reason jsonutils.JSONObject) {
  146. snapshot.SetStatus(ctx, self.UserCred, api.SNAPSHOT_DELETE_FAILED, reason.String())
  147. db.OpsLog.LogEvent(snapshot, db.ACT_SNAPSHOT_DELETE_FAIL, reason, self.UserCred)
  148. logclient.AddActionLogWithStartable(self, snapshot, logclient.ACT_DELOCATE, reason, self.UserCred, false)
  149. self.SetStageFailed(ctx, reason)
  150. guest, err := snapshot.GetGuest()
  151. if err != nil {
  152. log.Errorln(err.Error())
  153. return
  154. }
  155. guest.StartSyncstatus(ctx, self.UserCred, "")
  156. }
  157. /***************************** Batch Snapshots Delete Task *****************************/
  158. type BatchSnapshotsDeleteTask struct {
  159. taskman.STask
  160. }
  161. func (self *BatchSnapshotsDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
  162. snapshot := obj.(*models.SSnapshot)
  163. self.StartStorageDeleteSnapshot(ctx, snapshot)
  164. }
  165. func (self *BatchSnapshotsDeleteTask) StartStorageDeleteSnapshot(ctx context.Context, snapshot *models.SSnapshot) {
  166. host, err := snapshot.GetHost()
  167. if err != nil {
  168. self.SetStageFailed(ctx, jsonutils.NewString(errors.Wrapf(err, "snapshot.GetHost").Error()))
  169. return
  170. }
  171. snapshotIds := []string{}
  172. err = self.Params.Unmarshal(&snapshotIds, "snapshot_ids")
  173. if err != nil {
  174. self.SetStageFailed(ctx, jsonutils.NewString(errors.Wrapf(err, "unmarshal snapshot ids").Error()))
  175. return
  176. }
  177. driver, err := host.GetHostDriver()
  178. if err != nil {
  179. self.SetStageFailed(ctx, jsonutils.NewString(errors.Wrapf(err, "GetHostDriver").Error()))
  180. return
  181. }
  182. self.SetStage("OnStorageDeleteSnapshot", nil)
  183. err = driver.RequestDeleteSnapshotsWithStorage(ctx, host, snapshot, self, snapshotIds)
  184. if err != nil {
  185. self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
  186. }
  187. }
  188. func (self *BatchSnapshotsDeleteTask) OnStorageDeleteSnapshot(ctx context.Context, snapshot *models.SSnapshot, data jsonutils.JSONObject) {
  189. snapshots := models.SnapshotManager.GetDiskSnapshots(snapshot.DiskId)
  190. for i := 0; i < len(snapshots); i++ {
  191. snapshots[i].RealDelete(ctx, self.UserCred)
  192. }
  193. self.SetStageComplete(ctx, nil)
  194. }
  195. type GuestDeleteSnapshotsTask struct {
  196. taskman.STask
  197. }
  198. func (self *GuestDeleteSnapshotsTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
  199. guest := obj.(*models.SGuest)
  200. instanceSnapshots, _ := guest.GetInstanceSnapshots()
  201. self.StartDeleteInstanceSnapshots(ctx, guest, instanceSnapshots)
  202. }
  203. func (self *GuestDeleteSnapshotsTask) StartDeleteInstanceSnapshots(
  204. ctx context.Context, guest *models.SGuest, instanceSnapshots []models.SInstanceSnapshot) {
  205. if len(instanceSnapshots) > 0 {
  206. instanceSnapshot := instanceSnapshots[0]
  207. instanceSnapshots := instanceSnapshots[1:]
  208. self.Params.Set("instance_snapshots", jsonutils.Marshal(instanceSnapshots))
  209. self.SetStage("OnInstanceSnapshotDelete", nil)
  210. instanceSnapshot.SetModelManager(models.InstanceSnapshotManager, &instanceSnapshot)
  211. instanceSnapshot.StartInstanceSnapshotDeleteTask(ctx, self.UserCred, self.Id)
  212. return
  213. }
  214. snapshots, _ := guest.GetDiskSnapshotsNotInInstanceSnapshots()
  215. self.StartDeleteDiskSnapshots(ctx, guest, snapshots)
  216. }
  217. func (self *GuestDeleteSnapshotsTask) OnInstanceSnapshotDelete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
  218. instanceSnapshots := make([]models.SInstanceSnapshot, 0)
  219. self.Params.Unmarshal(&instanceSnapshots, "instance_snapshots")
  220. self.StartDeleteInstanceSnapshots(ctx, guest, instanceSnapshots)
  221. }
  222. func (self *GuestDeleteSnapshotsTask) OnInstanceSnapshotDeleteFailed(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
  223. log.Errorln(data.String())
  224. instanceSnapshots := make([]models.SInstanceSnapshot, 0)
  225. self.Params.Unmarshal(&instanceSnapshots, "instance_snapshots")
  226. self.StartDeleteInstanceSnapshots(ctx, guest, instanceSnapshots)
  227. }
  228. func (self *GuestDeleteSnapshotsTask) StartDeleteDiskSnapshots(
  229. ctx context.Context, guest *models.SGuest, snapshots []models.SSnapshot) {
  230. if len(snapshots) > 0 {
  231. snapshot := snapshots[0]
  232. snapshots := snapshots[1:]
  233. self.Params.Set("snapshots", jsonutils.Marshal(snapshots))
  234. self.SetStage("OnSnapshotDelete", nil)
  235. snapshot.SetModelManager(models.SnapshotManager, &snapshot)
  236. snapshot.StartSnapshotDeleteTask(ctx, self.UserCred, false, self.Id, 0, 0)
  237. return
  238. }
  239. self.SetStageComplete(ctx, nil)
  240. }
  241. func (self *GuestDeleteSnapshotsTask) OnSnapshotDelete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
  242. snapshots := make([]models.SSnapshot, 0)
  243. self.Params.Unmarshal(&snapshots, "snapshots")
  244. self.StartDeleteDiskSnapshots(ctx, guest, snapshots)
  245. }
  246. func (self *GuestDeleteSnapshotsTask) OnSnapshotDeleteFailed(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
  247. log.Errorln(data.String())
  248. snapshots := make([]models.SSnapshot, 0)
  249. self.Params.Unmarshal(&snapshots, "snapshots")
  250. self.StartDeleteDiskSnapshots(ctx, guest, snapshots)
  251. }
  252. type DiskDeleteSnapshotsTask struct {
  253. taskman.STask
  254. }
  255. func (self *DiskDeleteSnapshotsTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
  256. disk := obj.(*models.SDisk)
  257. snapshots, _ := disk.GetSnapshotsNotInInstanceSnapshot()
  258. self.StartDeleteDiskSnapshots(ctx, disk, snapshots)
  259. }
  260. func (self *DiskDeleteSnapshotsTask) StartDeleteDiskSnapshots(
  261. ctx context.Context, disk *models.SDisk, snapshots []models.SSnapshot) {
  262. if len(snapshots) > 0 {
  263. snapshot := snapshots[0]
  264. snapshots := snapshots[1:]
  265. self.Params.Set("snapshots", jsonutils.Marshal(snapshots))
  266. self.SetStage("OnSnapshotDelete", nil)
  267. snapshot.SetModelManager(models.SnapshotManager, &snapshot)
  268. snapshot.StartSnapshotDeleteTask(ctx, self.UserCred, false, self.Id, 0, 0)
  269. return
  270. }
  271. self.SetStageComplete(ctx, nil)
  272. }
  273. func (self *DiskDeleteSnapshotsTask) OnSnapshotDelete(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
  274. snapshots := make([]models.SSnapshot, 0)
  275. self.Params.Unmarshal(&snapshots, "snapshots")
  276. self.StartDeleteDiskSnapshots(ctx, disk, snapshots)
  277. }
  278. func (self *DiskDeleteSnapshotsTask) OnSnapshotDeleteFailed(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
  279. log.Errorf("Delete disk snapshots failed %s", data.String())
  280. self.SetStageFailed(ctx, data)
  281. }