rbd.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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. "fmt"
  18. "strings"
  19. "github.com/pkg/errors"
  20. "yunion.io/x/jsonutils"
  21. "yunion.io/x/log"
  22. "yunion.io/x/pkg/util/httputils"
  23. api "yunion.io/x/onecloud/pkg/apis/compute"
  24. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  25. "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
  26. "yunion.io/x/onecloud/pkg/compute/models"
  27. "yunion.io/x/onecloud/pkg/httperrors"
  28. "yunion.io/x/onecloud/pkg/mcclient"
  29. )
  30. type SRbdStorageDriver struct {
  31. SBaseStorageDriver
  32. }
  33. func init() {
  34. driver := SRbdStorageDriver{}
  35. models.RegisterStorageDriver(&driver)
  36. }
  37. func (self *SRbdStorageDriver) GetStorageType() string {
  38. return api.STORAGE_RBD
  39. }
  40. func (self *SRbdStorageDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.StorageCreateInput) error {
  41. input.StorageConf = jsonutils.NewDict()
  42. if len(input.RbdMonHost) == 0 {
  43. return httperrors.NewMissingParameterError("rbd_mon_host")
  44. }
  45. input.MonHost = strings.ReplaceAll(input.RbdMonHost, " ", "")
  46. if len(input.RbdPool) == 0 {
  47. return httperrors.NewMissingParameterError("rbd_pool")
  48. }
  49. input.Pool = strings.Trim(input.RbdPool, " ")
  50. input.Key = strings.Trim(input.RbdKey, " ")
  51. input.RadosMonOpTimeout = input.RbdRadosMonOpTimeout
  52. if input.RadosMonOpTimeout <= 0 {
  53. input.RadosMonOpTimeout = api.RBD_DEFAULT_MON_TIMEOUT
  54. }
  55. input.RadosOsdOpTimeout = input.RbdRadosOsdOpTimeout
  56. if input.RadosOsdOpTimeout <= 0 {
  57. input.RadosOsdOpTimeout = api.RBD_DEFAULT_OSD_TIMEOUT
  58. }
  59. input.ClientMountTimeout = input.RbdClientMountTimeout
  60. if input.ClientMountTimeout <= 0 {
  61. input.ClientMountTimeout = api.RBD_DEFAULT_MOUNT_TIMEOUT
  62. }
  63. storages := []models.SStorage{}
  64. q := models.StorageManager.Query().Equals("storage_type", api.STORAGE_RBD)
  65. err := db.FetchModelObjects(models.StorageManager, q, &storages)
  66. if err != nil {
  67. return httperrors.NewGeneralError(err)
  68. }
  69. for i := 0; i < len(storages); i++ {
  70. host, _ := storages[i].StorageConf.GetString("mon_host")
  71. pool, _ := storages[i].StorageConf.GetString("pool")
  72. if input.MonHost == host && input.Pool == pool {
  73. return httperrors.NewDuplicateResourceError("This RBD Storage[%s/%s] has already exist", storages[i].Name, input.Pool)
  74. }
  75. }
  76. enableMessengerV2 := false
  77. if input.EnableMessengerV2 != nil {
  78. enableMessengerV2 = *input.EnableMessengerV2
  79. }
  80. autoCacheImages := false
  81. if input.AutoCacheImages != nil {
  82. autoCacheImages = *input.AutoCacheImages
  83. }
  84. input.StorageConf.Update(
  85. jsonutils.Marshal(map[string]interface{}{
  86. "mon_host": input.MonHost,
  87. "pool": input.Pool,
  88. "key": input.Key,
  89. "rados_mon_op_timeout": input.RadosMonOpTimeout,
  90. "rados_osd_op_timeout": input.RadosOsdOpTimeout,
  91. "client_mount_timeout": input.ClientMountTimeout,
  92. "enable_messenger_v2": enableMessengerV2,
  93. "auto_cache_images": autoCacheImages,
  94. }))
  95. return nil
  96. }
  97. func (self *SRbdStorageDriver) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, input api.StorageUpdateInput) (api.StorageUpdateInput, error) {
  98. for k, v := range map[string]int{
  99. "rados_mon_op_timeout": input.RbdRadosMonOpTimeout,
  100. "rados_osd_op_timeout": input.RbdRadosOsdOpTimeout,
  101. "client_mount_timeout": input.RbdClientMountTimeout} {
  102. if v > 0 {
  103. input.StorageConf.Set(k, jsonutils.NewInt(int64(v)))
  104. input.UpdateStorageConf = true
  105. }
  106. }
  107. if input.EnableMessengerV2 != nil {
  108. input.StorageConf.Set("enable_messenger_v2", jsonutils.NewBool(*input.EnableMessengerV2))
  109. input.UpdateStorageConf = true
  110. }
  111. if input.AutoCacheImages != nil {
  112. input.StorageConf.Set("auto_cache_images", jsonutils.NewBool(*input.AutoCacheImages))
  113. input.UpdateStorageConf = true
  114. }
  115. if len(input.RbdKey) > 0 {
  116. input.StorageConf.Set("key", jsonutils.NewString(strings.Trim(input.RbdKey, " ")))
  117. input.UpdateStorageConf = true
  118. }
  119. return input, nil
  120. }
  121. func (self *SRbdStorageDriver) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, storage *models.SStorage, data jsonutils.JSONObject) {
  122. storages := []models.SStorage{}
  123. q := models.StorageManager.Query().Equals("storage_type", api.STORAGE_RBD)
  124. if err := db.FetchModelObjects(models.StorageManager, q, &storages); err != nil {
  125. log.Errorf("fetch storages error: %v", err)
  126. return
  127. }
  128. newRbdHost, _ := data.GetString("rbd_mon_host")
  129. newRbdKey, _ := data.GetString("rbd_key")
  130. for i := 0; i < len(storages); i++ {
  131. rbdHost, _ := storages[i].StorageConf.GetString("mon_host")
  132. rbdKey, _ := storages[i].StorageConf.GetString("key")
  133. if newRbdHost == rbdHost && newRbdKey == rbdKey {
  134. _, err := db.Update(storage, func() error {
  135. storage.StoragecacheId = storages[i].StoragecacheId
  136. return nil
  137. })
  138. if err != nil {
  139. log.Errorf("Update storagecacheId error: %v", err)
  140. return
  141. }
  142. }
  143. }
  144. if len(storage.StoragecacheId) == 0 {
  145. sc := &models.SStoragecache{}
  146. sc.SetModelManager(models.StoragecacheManager, sc)
  147. sc.Name = fmt.Sprintf("imagecache-%s", storage.Id)
  148. pool, _ := data.GetString("rbd_pool")
  149. sc.Path = fmt.Sprintf("rbd:%s", pool)
  150. if err := models.StoragecacheManager.TableSpec().Insert(ctx, sc); err != nil {
  151. log.Errorf("insert storagecache for storage %s error: %v", storage.Name, err)
  152. return
  153. }
  154. _, err := db.Update(storage, func() error {
  155. storage.StoragecacheId = sc.Id
  156. return nil
  157. })
  158. if err != nil {
  159. log.Errorf("update storagecache info for storage %s error: %v", storage.Name, err)
  160. }
  161. }
  162. }
  163. func (self *SRbdStorageDriver) DoStorageUpdateTask(ctx context.Context, userCred mcclient.TokenCredential, storage *models.SStorage, task taskman.ITask) error {
  164. subtask, err := taskman.TaskManager.NewTask(ctx, "RbdStorageUpdateTask", storage, task.GetUserCred(), task.GetParams(), task.GetTaskId(), "", nil)
  165. if err != nil {
  166. return err
  167. }
  168. subtask.ScheduleRun(nil)
  169. return nil
  170. }
  171. func (self *SRbdStorageDriver) ValidateSnapshotDelete(ctx context.Context, snapshot *models.SSnapshot) error {
  172. return nil
  173. }
  174. func (self *SRbdStorageDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, input *api.SnapshotCreateInput) error {
  175. return nil
  176. }
  177. func (self *SRbdStorageDriver) RequestCreateSnapshot(ctx context.Context, snapshot *models.SSnapshot, task taskman.ITask) error {
  178. disk, err := snapshot.GetDisk()
  179. if err != nil {
  180. return errors.Wrap(err, "snapshot get disk")
  181. }
  182. storage := snapshot.GetStorage()
  183. host, err := storage.GetMasterHost()
  184. if err != nil {
  185. return errors.Wrapf(err, "storage.GetMasterHost")
  186. }
  187. url := fmt.Sprintf("%s/disks/%s/snapshot/%s", host.ManagerUri, storage.Id, disk.Id)
  188. header := task.GetTaskRequestHeader()
  189. params := jsonutils.NewDict()
  190. params.Set("snapshot_id", jsonutils.NewString(snapshot.Id))
  191. _, _, err = httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, params, false)
  192. if err != nil {
  193. return errors.Wrap(err, "request create snapshot")
  194. }
  195. return nil
  196. }
  197. func (self *SRbdStorageDriver) RequestDeleteSnapshot(ctx context.Context, snapshot *models.SSnapshot, task taskman.ITask) error {
  198. storage := snapshot.GetStorage()
  199. host, err := storage.GetMasterHost()
  200. if err != nil {
  201. return errors.Wrapf(err, "storage.GetMasterHost")
  202. }
  203. url := fmt.Sprintf("%s/disks/%s/delete-snapshot/%s", host.ManagerUri, storage.Id, snapshot.DiskId)
  204. header := task.GetTaskRequestHeader()
  205. params := jsonutils.NewDict()
  206. params.Set("snapshot_id", jsonutils.NewString(snapshot.Id))
  207. _, _, err = httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, params, false)
  208. if err != nil {
  209. return errors.Wrap(err, "request delete snapshot")
  210. }
  211. return nil
  212. }
  213. func (self *SRbdStorageDriver) SnapshotIsOutOfChain(disk *models.SDisk) bool {
  214. return true
  215. }
  216. func (self *SRbdStorageDriver) OnDiskReset(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, snapshot *models.SSnapshot, data jsonutils.JSONObject) error {
  217. return nil
  218. }