disk_create_task.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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. self.SetStageFailed(ctx, data)
  97. }
  98. func (self *DiskCreateTask) OnDiskReady(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
  99. diskSize, _ := data.Int("disk_size")
  100. if _, err := db.Update(disk, func() error {
  101. disk.DiskSize = int(diskSize)
  102. diskFromat, _ := data.GetString("disk_format")
  103. if len(diskFromat) > 0 {
  104. disk.DiskFormat = diskFromat
  105. }
  106. disk.AccessPath, _ = data.GetString("disk_path")
  107. return nil
  108. }); err != nil {
  109. log.Errorf("update disk info error: %v", err)
  110. }
  111. if jsonutils.QueryBoolean(self.Params, "rebuild", false) {
  112. backingDiskId, _ := self.Params.GetString("backing_disk_id")
  113. if len(backingDiskId) > 0 {
  114. err := disk.UpdataSnapshotsBackingDisk(backingDiskId)
  115. if err != nil {
  116. log.Errorf("update disk snapshots backing disk fiailed %s", err)
  117. }
  118. }
  119. }
  120. disk.SetStatus(ctx, self.UserCred, api.DISK_READY, "")
  121. self.CleanHostSchedCache(disk)
  122. db.OpsLog.LogEvent(disk, db.ACT_ALLOCATE, disk.GetShortDesc(ctx), self.UserCred)
  123. notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{
  124. Obj: disk,
  125. Action: notifyclient.ActionCreate,
  126. })
  127. if !self.IsSubtask() {
  128. guest := disk.GetGuest()
  129. if guest != nil {
  130. // just sync guest status
  131. self.SetStage("OnGuestSyncstatusComplete", nil)
  132. guest.StartSyncstatus(ctx, self.GetUserCred(), self.GetTaskId())
  133. return
  134. }
  135. }
  136. self.SetStageComplete(ctx, nil)
  137. }
  138. func (self *DiskCreateTask) OnDiskReadyFailed(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
  139. rebuild, _ := self.GetParams().Bool("rebuild")
  140. status := api.DISK_ALLOC_FAILED
  141. if rebuild {
  142. status = api.DISK_REBUILD_FAILED
  143. }
  144. disk.SetStatus(ctx, self.UserCred, status, data.String())
  145. logclient.AddActionLogWithStartable(self, disk, logclient.ACT_ALLOCATE, data, self.UserCred, false)
  146. self.SetStageFailed(ctx, data)
  147. }
  148. func (self *DiskCreateTask) OnGuestSyncstatusComplete(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
  149. self.SetStageComplete(ctx, nil)
  150. }
  151. func (self *DiskCreateTask) OnGuestSyncstatusCompleteFailed(ctx context.Context, disk *models.SDisk, err jsonutils.JSONObject) {
  152. // ??? why
  153. log.Errorf("OnGuestSyncstatusCompleteFailed: %s", err.String())
  154. self.SetStageFailed(ctx, err)
  155. }
  156. func init() {
  157. taskman.RegisterTask(DiskCreateTask{})
  158. }