guest_image_delete_task.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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 tasks
  15. import (
  16. "context"
  17. "fmt"
  18. "yunion.io/x/jsonutils"
  19. "yunion.io/x/log"
  20. api "yunion.io/x/onecloud/pkg/apis/image"
  21. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  22. "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
  23. "yunion.io/x/onecloud/pkg/image/models"
  24. "yunion.io/x/onecloud/pkg/image/options"
  25. "yunion.io/x/onecloud/pkg/util/logclient"
  26. )
  27. type GuestImageDeleteTask struct {
  28. taskman.STask
  29. }
  30. func init() {
  31. taskman.RegisterTask(GuestImageDeleteTask{})
  32. }
  33. func (task *GuestImageDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
  34. guestImage := obj.(*models.SGuestImage)
  35. isPurge := jsonutils.QueryBoolean(task.Params, "purge", false)
  36. isOverridePendingDelete := jsonutils.QueryBoolean(task.Params, "override_pending_delete", false)
  37. if options.Options.EnablePendingDelete && !isPurge && !isOverridePendingDelete {
  38. if guestImage.PendingDeleted {
  39. task.SetStageComplete(ctx, nil)
  40. } else {
  41. task.startPendingDelete(ctx, guestImage)
  42. }
  43. } else {
  44. task.startDelete(ctx, guestImage)
  45. }
  46. }
  47. func (task *GuestImageDeleteTask) startPendingDelete(ctx context.Context, guestImage *models.SGuestImage) {
  48. images, err := models.GuestImageJointManager.GetByGuestImageId(guestImage.GetId())
  49. if err != nil {
  50. task.taskFailed(ctx, guestImage, jsonutils.NewString(err.Error()))
  51. }
  52. for i := range images {
  53. image, err := images[i].GetImage()
  54. if err != nil {
  55. log.Errorf("subimage %d GetImage fail %s", i, err)
  56. continue
  57. }
  58. if !image.IsGuestImage.IsTrue() {
  59. continue
  60. }
  61. image.StopTorrents()
  62. err = image.DoPendingDelete(ctx, task.UserCred)
  63. if err != nil {
  64. task.taskFailed(ctx, guestImage, jsonutils.NewString(fmt.Sprintf("image %s pending delete failed", images[i].GetId())))
  65. return
  66. }
  67. }
  68. err = guestImage.DoPendingDelete(ctx, task.UserCred)
  69. if err != nil {
  70. task.taskFailed(ctx, guestImage, jsonutils.NewString(fmt.Sprintf("guest image %s pending delete failed", guestImage.GetId())))
  71. return
  72. }
  73. task.SetStageComplete(ctx, nil)
  74. }
  75. func (task *GuestImageDeleteTask) startDelete(ctx context.Context, guestImage *models.SGuestImage) {
  76. subImages, err := models.GuestImageJointManager.GetByGuestImageId(guestImage.GetId())
  77. if err != nil {
  78. task.taskFailed(ctx, guestImage, jsonutils.NewString(err.Error()))
  79. return
  80. }
  81. for i := range subImages {
  82. image, err := subImages[i].GetImage()
  83. if err != nil {
  84. log.Errorf("subimage %d GetImage fail %s", i, err)
  85. continue
  86. }
  87. // delete guestImageJoint
  88. err = subImages[i].Delete(ctx, task.UserCred)
  89. if err != nil {
  90. task.taskFailed(ctx, guestImage, jsonutils.NewString(fmt.Sprintf("fail to remove GuestImageJoin %d: %s", i, err)))
  91. return
  92. }
  93. if !image.IsGuestImage.IsTrue() {
  94. continue
  95. }
  96. err = image.Remove(ctx, task.UserCred)
  97. if err != nil {
  98. task.taskFailed(ctx, guestImage, jsonutils.NewString(fmt.Sprintf("fail to remove %s: %s", image.GetPath(""), err)))
  99. return
  100. }
  101. err = image.SetStatus(ctx, task.UserCred, api.IMAGE_STATUS_DELETED, "delete")
  102. if err != nil {
  103. task.taskFailed(ctx, guestImage, jsonutils.NewString(fmt.Sprintf("fail to set image %s status ", image.GetId())))
  104. return
  105. }
  106. err = image.RealDelete(ctx, task.UserCred)
  107. if err != nil {
  108. task.taskFailed(ctx, guestImage, jsonutils.NewString(fmt.Sprintf("fail to real delete image %s", image.GetId())))
  109. return
  110. }
  111. }
  112. err = guestImage.SetStatus(ctx, task.UserCred, api.IMAGE_STATUS_DELETED, "delete")
  113. if err != nil {
  114. task.taskFailed(ctx, guestImage, jsonutils.NewString(fmt.Sprintf("fail to set guest image status %s", guestImage.GetId())))
  115. return
  116. }
  117. err = guestImage.RealDelete(ctx, task.UserCred)
  118. if err != nil {
  119. task.taskFailed(ctx, guestImage, jsonutils.NewString(fmt.Sprintf("fail to real delete guest image %s", guestImage.GetId())))
  120. return
  121. }
  122. task.SetStageComplete(ctx, nil)
  123. }
  124. func (task *GuestImageDeleteTask) taskFailed(ctx context.Context, guestImage *models.SGuestImage, reason jsonutils.JSONObject) {
  125. log.Errorf("Guest Image %s delete failed: %s", guestImage.Id, reason)
  126. db.OpsLog.LogEvent(guestImage, db.ACT_IMAGE_DELETE_FAIL, reason, task.UserCred)
  127. logclient.AddActionLogWithContext(ctx, guestImage, logclient.ACT_DELETE, reason, task.UserCred, false)
  128. task.SetStageFailed(ctx, reason)
  129. }