base.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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 storagedrivers
  15. import (
  16. "context"
  17. "database/sql"
  18. "fmt"
  19. "yunion.io/x/jsonutils"
  20. "yunion.io/x/pkg/errors"
  21. "yunion.io/x/pkg/utils"
  22. api "yunion.io/x/onecloud/pkg/apis/compute"
  23. "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
  24. "yunion.io/x/onecloud/pkg/compute/models"
  25. "yunion.io/x/onecloud/pkg/httperrors"
  26. "yunion.io/x/onecloud/pkg/mcclient"
  27. )
  28. type SBaseStorageDriver struct {
  29. }
  30. func (self *SBaseStorageDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.StorageCreateInput) error {
  31. return fmt.Errorf("Not Implement ValidateCreateData")
  32. }
  33. func (self *SBaseStorageDriver) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, storage *models.SStorage, data jsonutils.JSONObject) {
  34. }
  35. func (self *SBaseStorageDriver) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, input api.StorageUpdateInput) (api.StorageUpdateInput, error) {
  36. return input, nil
  37. }
  38. func (self *SBaseStorageDriver) DoStorageUpdateTask(ctx context.Context, userCred mcclient.TokenCredential, storage *models.SStorage, task taskman.ITask) error {
  39. task.ScheduleRun(nil)
  40. return nil
  41. }
  42. func (self *SBaseStorageDriver) ValidateSnapshotDelete(ctx context.Context, snapshot *models.SSnapshot) error {
  43. if snapshot.RefCount > 0 {
  44. return httperrors.NewBadRequestError("Snapshot reference(by disk) count > 0, can not delete")
  45. }
  46. return nil
  47. }
  48. func (self *SBaseStorageDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, input *api.SnapshotCreateInput) error {
  49. guests := disk.GetGuests()
  50. if len(guests) != 1 {
  51. return httperrors.NewBadRequestError("Disk %s dosen't attach guest ?", disk.Id)
  52. }
  53. guest := guests[0]
  54. if len(guest.BackupHostId) > 0 {
  55. return httperrors.NewBadRequestError(
  56. "Disk attached Guest has backup, Can't create snapshot")
  57. }
  58. if !utils.IsInStringArray(guest.Status, []string{api.VM_RUNNING, api.VM_READY}) {
  59. return httperrors.NewInvalidStatusError("Cannot do snapshot when VM in status %s", guest.Status)
  60. }
  61. return nil
  62. }
  63. func (self *SBaseStorageDriver) RequestCreateSnapshot(ctx context.Context, snapshot *models.SSnapshot, task taskman.ITask) error {
  64. guest, err := snapshot.GetGuest()
  65. if err != nil {
  66. return err
  67. }
  68. var params = jsonutils.NewDict()
  69. params.Set("disk_id", jsonutils.NewString(snapshot.DiskId))
  70. params.Set("snapshot_id", jsonutils.NewString(snapshot.Id))
  71. nt, err := taskman.TaskManager.NewTask(ctx, "GuestDiskSnapshotTask", guest, task.GetUserCred(), params, task.GetTaskId(), "", nil)
  72. if err != nil {
  73. return err
  74. }
  75. nt.ScheduleRun(nil)
  76. return nil
  77. }
  78. func (self *SBaseStorageDriver) RequestDeleteSnapshot(ctx context.Context, snapshot *models.SSnapshot, task taskman.ITask) error {
  79. guest, err := snapshot.GetGuest()
  80. if err != nil {
  81. if err != sql.ErrNoRows {
  82. return err
  83. }
  84. }
  85. if guest == nil {
  86. var host *models.SHost
  87. disk, err := models.DiskManager.FetchById(snapshot.DiskId)
  88. if err != nil && err != sql.ErrNoRows {
  89. return errors.Wrap(err, "get disk by snapshot")
  90. }
  91. if disk != nil {
  92. sDisk := disk.(*models.SDisk)
  93. if hostId := sDisk.GetLastAttachedHost(ctx, task.GetUserCred()); hostId != "" {
  94. host = models.HostManager.FetchHostById(hostId)
  95. }
  96. } else {
  97. if hostId := snapshot.GetMetadata(ctx, api.DISK_META_LAST_ATTACHED_HOST, task.GetUserCred()); hostId != "" {
  98. host = models.HostManager.FetchHostById(hostId)
  99. }
  100. }
  101. if host == nil {
  102. storage := snapshot.GetStorage()
  103. host, err = storage.GetMasterHost()
  104. if err != nil {
  105. return err
  106. }
  107. }
  108. convertSnapshot, err := models.SnapshotManager.GetConvertSnapshot(snapshot)
  109. if err != nil && err != sql.ErrNoRows {
  110. return errors.Wrap(err, "get convert snapshot")
  111. }
  112. params := jsonutils.NewDict()
  113. params.Set("delete_snapshot", jsonutils.NewString(snapshot.Id))
  114. params.Set("disk_id", jsonutils.NewString(snapshot.DiskId))
  115. if disk != nil {
  116. sDisk, _ := disk.(*models.SDisk)
  117. if sDisk.IsEncrypted() {
  118. if encryptInfo, err := sDisk.GetEncryptInfo(ctx, task.GetUserCred()); err != nil {
  119. return errors.Wrap(err, "faild get encryptInfo")
  120. } else {
  121. params.Set("encrypt_info", jsonutils.Marshal(encryptInfo))
  122. }
  123. }
  124. }
  125. if !snapshot.OutOfChain {
  126. if convertSnapshot != nil {
  127. params.Set("convert_snapshot", jsonutils.NewString(convertSnapshot.Id))
  128. } else if disk != nil {
  129. params.Set("block_stream", jsonutils.JSONTrue)
  130. } else {
  131. params.Set("auto_deleted", jsonutils.JSONTrue)
  132. }
  133. } else {
  134. params.Set("auto_deleted", jsonutils.JSONTrue)
  135. }
  136. drv, err := host.GetHostDriver()
  137. if err != nil {
  138. return err
  139. }
  140. return drv.RequestDeleteSnapshotWithoutGuest(ctx, host, snapshot, params, task)
  141. }
  142. drv, err := guest.GetDriver()
  143. if err != nil {
  144. return err
  145. }
  146. if jsonutils.QueryBoolean(task.GetParams(), "reload_disk", false) && snapshot.OutOfChain {
  147. guest.SetStatus(ctx, task.GetUserCred(), api.VM_SNAPSHOT, "Start Reload Snapshot")
  148. params := jsonutils.NewDict()
  149. params.Set("disk_id", jsonutils.NewString(snapshot.DiskId))
  150. return drv.RequestReloadDiskSnapshot(ctx, guest, task, params)
  151. } else {
  152. convertSnapshot, err := models.SnapshotManager.GetConvertSnapshot(snapshot)
  153. if err != nil && err != sql.ErrNoRows {
  154. return errors.Wrap(err, "get convert snapshot")
  155. }
  156. snapshot.SetStatus(ctx, task.GetUserCred(), api.SNAPSHOT_DELETING, "On SnapshotDeleteTask StartDeleteSnapshot")
  157. params := jsonutils.NewDict()
  158. params.Set("delete_snapshot", jsonutils.NewString(snapshot.Id))
  159. params.Set("disk_id", jsonutils.NewString(snapshot.DiskId))
  160. disk, err := models.DiskManager.FetchById(snapshot.DiskId)
  161. if err != nil && err != sql.ErrNoRows {
  162. return errors.Wrap(err, "get disk by snapshot")
  163. }
  164. sDisk, _ := disk.(*models.SDisk)
  165. if sDisk.IsEncrypted() {
  166. if encryptInfo, err := sDisk.GetEncryptInfo(ctx, task.GetUserCred()); err != nil {
  167. return errors.Wrap(err, "faild get encryptInfo")
  168. } else {
  169. params.Set("encrypt_info", jsonutils.Marshal(encryptInfo))
  170. }
  171. }
  172. if !snapshot.OutOfChain {
  173. if convertSnapshot != nil {
  174. params.Set("convert_snapshot", jsonutils.NewString(convertSnapshot.Id))
  175. } else {
  176. params.Set("block_stream", jsonutils.JSONTrue)
  177. }
  178. } else {
  179. params.Set("auto_deleted", jsonutils.JSONTrue)
  180. }
  181. taskParams := task.GetParams()
  182. if taskParams.Contains("snapshot_total_count") {
  183. totalCnt, _ := taskParams.Get("snapshot_total_count")
  184. params.Set("snapshot_total_count", totalCnt)
  185. deletedCnt, _ := taskParams.Get("deleted_snapshot_count")
  186. params.Set("deleted_snapshot_count", deletedCnt)
  187. }
  188. guest.SetStatus(ctx, task.GetUserCred(), api.VM_SNAPSHOT_DELETE, "Start Delete Snapshot")
  189. return drv.RequestDeleteSnapshot(ctx, guest, task, params)
  190. }
  191. }
  192. func (self *SBaseStorageDriver) SnapshotIsOutOfChain(disk *models.SDisk) bool {
  193. return false
  194. }
  195. func (self *SBaseStorageDriver) OnDiskReset(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, snapshot *models.SSnapshot, data jsonutils.JSONObject) error {
  196. return disk.CleanUpDiskSnapshots(ctx, userCred, snapshot)
  197. }