disk_create_task.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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 disk
  15. import (
  16. "context"
  17. "fmt"
  18. "yunion.io/x/jsonutils"
  19. "yunion.io/x/log"
  20. "yunion.io/x/pkg/errors"
  21. "yunion.io/x/pkg/util/stringutils"
  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. type DiskCreateTask struct {
  30. SDiskBaseTask
  31. }
  32. func (self *DiskCreateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
  33. disk := obj.(*models.SDisk)
  34. storage, _ := disk.GetStorage()
  35. storagecache := storage.GetStoragecache()
  36. imageId := disk.GetTemplateId()
  37. // use image only if disk not created from snapshot or backup
  38. if len(imageId) > 0 && len(disk.SnapshotId) == 0 && len(disk.BackupId) == 0 {
  39. self.SetStage("OnStorageCacheImageComplete", nil)
  40. cacheImageFmt, err := disk.GetCacheImageFormat(ctx)
  41. if err != nil {
  42. self.OnStartAllocateFailed(ctx, disk, jsonutils.NewString(err.Error()))
  43. return
  44. }
  45. input := api.CacheImageInput{
  46. ImageId: imageId,
  47. Format: cacheImageFmt,
  48. ParentTaskId: self.GetTaskId(),
  49. }
  50. guest := disk.GetGuest()
  51. if guest != nil {
  52. input.ServerId = guest.Id
  53. }
  54. storagecache.StartImageCacheTask(ctx, self.UserCred, input)
  55. } else {
  56. self.OnStorageCacheImageComplete(ctx, disk, nil)
  57. }
  58. }
  59. func (self *DiskCreateTask) OnStorageCacheImageComplete(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
  60. rebuild, _ := self.GetParams().Bool("rebuild")
  61. snapshot, _ := self.GetParams().GetString("snapshot")
  62. if rebuild {
  63. db.OpsLog.LogEvent(disk, db.ACT_DELOCATE, disk.GetShortDesc(ctx), self.GetUserCred())
  64. } else {
  65. guest := disk.GetGuest()
  66. if guest != nil {
  67. guest.SetStatus(ctx, self.GetUserCred(), api.VM_CREATE_DISK, "OnStorageCacheImageComplete")
  68. }
  69. }
  70. storage, err := disk.GetStorage()
  71. if err != nil {
  72. self.OnStartAllocateFailed(ctx, disk, jsonutils.NewString(errors.Wrapf(err, "disk.GetStorage").Error()))
  73. return
  74. }
  75. host, err := disk.GetMasterHost(storage)
  76. if err != nil {
  77. self.OnStartAllocateFailed(ctx, disk, jsonutils.NewString(errors.Wrapf(err, "GetMasterHost").Error()))
  78. return
  79. }
  80. db.OpsLog.LogEvent(disk, db.ACT_ALLOCATING, disk.GetShortDesc(ctx), self.GetUserCred())
  81. disk.SetStatus(ctx, self.GetUserCred(), api.DISK_STARTALLOC, fmt.Sprintf("Disk start alloc use host %s(%s)", host.Name, host.Id))
  82. if rebuild && storage.StorageType == api.STORAGE_RBD {
  83. if count, _ := disk.GetSnapshotCount(); count > 0 {
  84. backingDiskId := stringutils.UUID4()
  85. self.Params.Set("backing_disk_id", jsonutils.NewString(backingDiskId))
  86. }
  87. }
  88. self.SetStage("OnDiskReady", nil)
  89. if err := disk.StartAllocate(ctx, host, storage, self.GetTaskId(), self.GetUserCred(), rebuild, snapshot, self); err != nil {
  90. self.OnStartAllocateFailed(ctx, disk, jsonutils.NewString(err.Error()))
  91. }
  92. }
  93. func (self *DiskCreateTask) OnStartAllocateFailed(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
  94. disk.SetStatus(ctx, self.UserCred, api.DISK_ALLOC_FAILED, data.String())
  95. logclient.AddActionLogWithStartable(self, disk, logclient.ACT_ALLOCATE, data, self.UserCred, false)
  96. notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{
  97. Obj: disk,
  98. Action: notifyclient.ActionCreate,
  99. IsFail: true,
  100. })
  101. self.SetStageFailed(ctx, data)
  102. }
  103. func (self *DiskCreateTask) OnDiskReady(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
  104. diskSize, _ := data.Int("disk_size")
  105. if _, err := db.Update(disk, func() error {
  106. disk.DiskSize = int(diskSize)
  107. diskFromat, _ := data.GetString("disk_format")
  108. if len(diskFromat) > 0 {
  109. disk.DiskFormat = diskFromat
  110. }
  111. disk.AccessPath, _ = data.GetString("disk_path")
  112. return nil
  113. }); err != nil {
  114. log.Errorf("update disk info error: %v", err)
  115. }
  116. if jsonutils.QueryBoolean(self.Params, "rebuild", false) {
  117. backingDiskId, _ := self.Params.GetString("backing_disk_id")
  118. if len(backingDiskId) > 0 {
  119. err := disk.UpdataSnapshotsBackingDisk(backingDiskId)
  120. if err != nil {
  121. log.Errorf("update disk snapshots backing disk fiailed %s", err)
  122. }
  123. }
  124. }
  125. disk.SetStatus(ctx, self.UserCred, api.DISK_READY, "")
  126. self.CleanHostSchedCache(disk)
  127. db.OpsLog.LogEvent(disk, db.ACT_ALLOCATE, disk.GetShortDesc(ctx), self.UserCred)
  128. notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{
  129. Obj: disk,
  130. Action: notifyclient.ActionCreate,
  131. })
  132. if !self.IsSubtask() {
  133. guest := disk.GetGuest()
  134. if guest != nil {
  135. // just sync guest status
  136. self.SetStage("OnGuestSyncstatusComplete", nil)
  137. guest.StartSyncstatus(ctx, self.GetUserCred(), self.GetTaskId())
  138. return
  139. }
  140. }
  141. self.SetStageComplete(ctx, nil)
  142. }
  143. func (self *DiskCreateTask) OnDiskReadyFailed(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
  144. rebuild, _ := self.GetParams().Bool("rebuild")
  145. status := api.DISK_ALLOC_FAILED
  146. if rebuild {
  147. status = api.DISK_REBUILD_FAILED
  148. }
  149. disk.SetStatus(ctx, self.UserCred, status, data.String())
  150. logclient.AddActionLogWithStartable(self, disk, logclient.ACT_ALLOCATE, data, self.UserCred, false)
  151. notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{
  152. Obj: disk,
  153. Action: notifyclient.ActionCreate,
  154. IsFail: true,
  155. })
  156. self.SetStageFailed(ctx, data)
  157. }
  158. func (self *DiskCreateTask) OnGuestSyncstatusComplete(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
  159. self.SetStageComplete(ctx, nil)
  160. }
  161. func (self *DiskCreateTask) OnGuestSyncstatusCompleteFailed(ctx context.Context, disk *models.SDisk, err jsonutils.JSONObject) {
  162. // ??? why
  163. log.Errorf("OnGuestSyncstatusCompleteFailed: %s", err.String())
  164. self.SetStageFailed(ctx, err)
  165. }
  166. func init() {
  167. taskman.RegisterTask(DiskCreateTask{})
  168. }