disk_rbd.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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 storageman
  15. import (
  16. "context"
  17. "fmt"
  18. "yunion.io/x/cloudmux/pkg/cloudprovider"
  19. "yunion.io/x/jsonutils"
  20. "yunion.io/x/log"
  21. "yunion.io/x/pkg/appctx"
  22. "yunion.io/x/pkg/errors"
  23. "yunion.io/x/pkg/utils"
  24. "yunion.io/x/onecloud/pkg/apis"
  25. api "yunion.io/x/onecloud/pkg/apis/compute"
  26. container_storage "yunion.io/x/onecloud/pkg/hostman/container/storage"
  27. deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
  28. "yunion.io/x/onecloud/pkg/hostman/hostutils"
  29. "yunion.io/x/onecloud/pkg/httperrors"
  30. "yunion.io/x/onecloud/pkg/util/qemuimg"
  31. "yunion.io/x/onecloud/pkg/util/seclib2"
  32. )
  33. var _ IDisk = (*SRBDDisk)(nil)
  34. type SRBDDisk struct {
  35. SBaseDisk
  36. }
  37. func NewRBDDisk(storage IStorage, id string) *SRBDDisk {
  38. var ret = new(SRBDDisk)
  39. ret.SBaseDisk = *NewBaseDisk(storage, id)
  40. return ret
  41. }
  42. func (d *SRBDDisk) GetType() string {
  43. return api.STORAGE_RBD
  44. }
  45. func (d *SRBDDisk) Probe() error {
  46. storage := d.Storage.(*SRbdStorage)
  47. exist, err := storage.IsImageExist(d.Id)
  48. if err != nil {
  49. return errors.Wrapf(err, "IsImageExist")
  50. }
  51. if !exist {
  52. return cloudprovider.ErrNotFound
  53. }
  54. return nil
  55. }
  56. func (d *SRBDDisk) getPath() string {
  57. return d.Storage.(*SRbdStorage).getDiskPath(d.Id)
  58. }
  59. func (d *SRBDDisk) GetPath() string {
  60. storage := d.Storage.(*SRbdStorage)
  61. return fmt.Sprintf("%s%s", d.getPath(), storage.getStorageConfString())
  62. }
  63. func (d *SRBDDisk) GetFormat() (string, error) {
  64. return "raw", nil
  65. }
  66. func (d *SRBDDisk) GetSnapshotDir() string {
  67. return ""
  68. }
  69. func (d *SRBDDisk) GetDiskDesc() jsonutils.JSONObject {
  70. storage := d.Storage.(*SRbdStorage)
  71. sizeMb, _ := storage.getImageSizeMb(d.Id)
  72. desc := map[string]interface{}{
  73. "disk_id": d.Id,
  74. "disk_format": "raw",
  75. "disk_path": d.getPath(),
  76. "disk_size": sizeMb,
  77. }
  78. return jsonutils.Marshal(desc)
  79. }
  80. func (d *SRBDDisk) GetDiskSetupScripts(idx int) string {
  81. return fmt.Sprintf("DISK_%d='%s'\n", idx, d.GetPath())
  82. }
  83. func (d *SRBDDisk) DeleteAllSnapshot(skipRecycle bool) error {
  84. return fmt.Errorf("Not Impl")
  85. }
  86. func (d *SRBDDisk) Delete(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  87. p := params.(api.DiskDeleteInput)
  88. storage := d.Storage.(*SRbdStorage)
  89. return nil, storage.deleteImage(d.Id, p.SkipRecycle != nil && *p.SkipRecycle)
  90. }
  91. func (d *SRBDDisk) OnRebuildRoot(ctx context.Context, params api.DiskAllocateInput) error {
  92. if len(params.BackingDiskId) == 0 {
  93. _, err := d.Delete(ctx, api.DiskDeleteInput{})
  94. return err
  95. }
  96. storage := d.Storage.(*SRbdStorage)
  97. storageConf := d.Storage.GetStorageConf()
  98. pool, _ := storageConf.GetString("pool")
  99. return storage.renameImage(pool, d.Id, params.BackingDiskId)
  100. }
  101. func (d *SRBDDisk) Resize(ctx context.Context, params *SDiskResizeInput) (jsonutils.JSONObject, error) {
  102. diskInfo := params.DiskInfo
  103. storage := d.Storage.(*SRbdStorage)
  104. sizeMb, _ := diskInfo.Int("size")
  105. if err := storage.resizeImage(d.Id, uint64(sizeMb)); err != nil {
  106. return nil, err
  107. }
  108. resizeFsInfo := &deployapi.DiskInfo{
  109. Path: d.GetPath(),
  110. DiskId: d.GetId(),
  111. }
  112. if err := d.ResizeFs(resizeFsInfo, params.GuestDesc); err != nil {
  113. log.Errorf("Resize fs %s fail %s", d.GetPath(), err)
  114. return nil, errors.Wrapf(err, "resize fs %s", d.GetPath())
  115. }
  116. return d.GetDiskDesc(), nil
  117. }
  118. func (d *SRBDDisk) PrepareSaveToGlance(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  119. if err := d.Probe(); err != nil {
  120. return nil, err
  121. }
  122. imageName := fmt.Sprintf("image_cache_%s_%s", d.Id, appctx.AppContextTaskId(ctx))
  123. imageCache := storageManager.GetStoragecacheById(d.Storage.GetStoragecacheId())
  124. if imageCache == nil {
  125. return nil, fmt.Errorf("failed to find image cache for prepare save to glance")
  126. }
  127. storage := d.Storage.(*SRbdStorage)
  128. pool, _ := storage.GetStorageConf().GetString("pool")
  129. if err := storage.cloneImage(ctx, pool, d.Id, imageCache.GetPath(), imageName); err != nil {
  130. log.Errorf("clone image %s from pool %s to %s/%s error: %v", d.Id, pool, imageCache.GetPath(), imageName, err)
  131. return nil, err
  132. }
  133. return jsonutils.Marshal(map[string]string{"backup": imageName}), nil
  134. }
  135. func (d *SRBDDisk) CleanupSnapshots(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  136. storage := d.Storage.(*SRbdStorage)
  137. return nil, storage.deleteSnapshot(d.Id, "")
  138. }
  139. func (d *SRBDDisk) PrepareMigrate(liveMigrate bool) ([]string, string, bool, error) {
  140. return nil, "", false, fmt.Errorf("Not support")
  141. }
  142. func (d *SRBDDisk) CreateFromTemplate(ctx context.Context, imageId string, format string, size int64, encryptInfo *apis.SEncryptInfo) (jsonutils.JSONObject, error) {
  143. ret, err := d.createFromTemplate(ctx, imageId, format)
  144. if err != nil {
  145. return nil, err
  146. }
  147. retSize, _ := ret.Int("disk_size")
  148. log.Infof("REQSIZE: %d, RETSIZE: %d", size, retSize)
  149. if size > retSize {
  150. params := new(SDiskResizeInput)
  151. diskInfo := jsonutils.NewDict()
  152. diskInfo.Set("size", jsonutils.NewInt(size))
  153. params.DiskInfo = diskInfo
  154. return d.Resize(ctx, params)
  155. }
  156. return ret, nil
  157. }
  158. func (d *SRBDDisk) createFromTemplate(ctx context.Context, imageId, format string) (jsonutils.JSONObject, error) {
  159. var imageCacheManager = storageManager.GetStoragecacheById(d.Storage.GetStoragecacheId())
  160. if imageCacheManager == nil {
  161. return nil, fmt.Errorf("failed to find image cache manger for storage %s", d.Storage.GetStorageName())
  162. }
  163. input := api.CacheImageInput{
  164. ImageId: imageId,
  165. Zone: d.GetZoneId(),
  166. }
  167. imageCache, err := imageCacheManager.AcquireImage(ctx, input, nil)
  168. if err != nil {
  169. return nil, errors.Wrapf(err, "AcquireImage")
  170. }
  171. defer imageCacheManager.ReleaseImage(ctx, imageId)
  172. storage := d.Storage.(*SRbdStorage)
  173. storage.deleteImage(d.Id, false) //重装系统时,需要删除以前的系统盘
  174. err = storage.cloneImage(ctx, imageCacheManager.GetPath(), imageCache.GetName(), storage.Pool, d.Id)
  175. if err != nil {
  176. return nil, errors.Wrapf(err, "cloneImage(%s)", imageCache.GetName())
  177. }
  178. return d.GetDiskDesc(), nil
  179. }
  180. func (d *SRBDDisk) CreateFromRemoteHostImage(ctx context.Context, url string, size int64, encryptInfo *apis.SEncryptInfo) error {
  181. return fmt.Errorf("Not support")
  182. }
  183. func (d *SRBDDisk) CreateRaw(ctx context.Context, sizeMb int, diskFormat string, fsFormat string, fsFeatures *api.DiskFsFeatures, encryptInfo *apis.SEncryptInfo, diskId string, back string) (jsonutils.JSONObject, error) {
  184. if encryptInfo != nil {
  185. return nil, errors.Wrap(httperrors.ErrNotSupported, "rbd not support encryptInfo")
  186. }
  187. storage := d.Storage.(*SRbdStorage)
  188. if err := storage.createImage(diskId, uint64(sizeMb)); err != nil {
  189. return nil, err
  190. }
  191. diskInfo := &deployapi.DiskInfo{
  192. Path: d.GetPath(),
  193. }
  194. if utils.IsInStringArray(fsFormat, api.SUPPORTED_FS) {
  195. if err := d.FormatFs(fsFormat, nil, diskId, diskInfo); err != nil {
  196. return nil, errors.Wrap(err, "FormatFs")
  197. }
  198. }
  199. return d.GetDiskDesc(), nil
  200. }
  201. func (d *SRBDDisk) PostCreateFromRemoteHostImage(string) {
  202. log.Errorf("Not support PostCreateFromRemoteHostImage")
  203. }
  204. func (d *SRBDDisk) DiskBackup(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  205. diskBackup := params.(*SDiskBackup)
  206. storage := d.Storage.(*SRbdStorage)
  207. sizeMb, err := storage.createBackup(ctx, d.Id, diskBackup)
  208. if err != nil {
  209. return nil, err
  210. }
  211. data := jsonutils.NewDict()
  212. data.Set("size_mb", jsonutils.NewInt(int64(sizeMb)))
  213. return data, nil
  214. }
  215. func (d *SRBDDisk) CreateSnapshot(snapshotId string, encryptKey string, encFormat qemuimg.TEncryptFormat, encAlg seclib2.TSymEncAlg) error {
  216. storage := d.Storage.(*SRbdStorage)
  217. return storage.createSnapshot(d.Id, snapshotId)
  218. }
  219. func (d *SRBDDisk) ConvertSnapshotRelyOnReloadDisk(convertSnapshotId string, encryptInfo apis.SEncryptInfo) (func() error, error) {
  220. return nil, nil
  221. }
  222. func (d *SRBDDisk) DeleteSnapshot(snapshotId, convertSnapshot string, blockStream bool, encryptInfo apis.SEncryptInfo) error {
  223. storage := d.Storage.(*SRbdStorage)
  224. return storage.deleteSnapshot(d.Id, snapshotId)
  225. }
  226. func (d *SRBDDisk) DiskSnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  227. snapshotId, ok := params.(string)
  228. if !ok {
  229. return nil, hostutils.ParamsError
  230. }
  231. err := d.CreateSnapshot(snapshotId, "", "", "")
  232. if err != nil {
  233. return nil, err
  234. }
  235. ret := jsonutils.NewDict()
  236. storage := d.Storage.(*SRbdStorage)
  237. size, err := storage.getSnapshotSize(d.Id, snapshotId)
  238. if err != nil {
  239. log.Errorf("failed get snapshot %s size %s", snapshotId, err)
  240. } else {
  241. ret.Set("snapshot_size_mb", jsonutils.NewInt(size/1024/1024))
  242. }
  243. return ret, nil
  244. }
  245. func (d *SRBDDisk) DiskDeleteSnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  246. snapshotId, ok := params.(string)
  247. if !ok {
  248. return nil, hostutils.ParamsError
  249. }
  250. err := d.DeleteSnapshot(snapshotId, "", false, apis.SEncryptInfo{})
  251. if err != nil {
  252. return nil, err
  253. } else {
  254. res := jsonutils.NewDict()
  255. res.Set("deleted", jsonutils.JSONTrue)
  256. return res, nil
  257. }
  258. }
  259. func (d *SRBDDisk) ResetFromSnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  260. resetParams, ok := params.(*SDiskReset)
  261. if !ok {
  262. return nil, hostutils.ParamsError
  263. }
  264. diskId := resetParams.BackingDiskId
  265. if len(diskId) == 0 {
  266. diskId = d.GetId()
  267. }
  268. storage := d.Storage.(*SRbdStorage)
  269. return nil, storage.resetDisk(diskId, resetParams.SnapshotId)
  270. }
  271. func (d *SRBDDisk) CreateFromRbdSnapshot(ctx context.Context, snapshot, srcDiskId, srcPool string) error {
  272. storage := d.Storage.(*SRbdStorage)
  273. pool, _ := storage.StorageConf.GetString("pool")
  274. return storage.cloneFromSnapshot(srcDiskId, srcPool, snapshot, d.GetId(), pool)
  275. }
  276. func (d *SRBDDisk) IsFile() bool {
  277. return false
  278. }
  279. func (d *SRBDDisk) GetContainerStorageDriver() (container_storage.IContainerStorage, error) {
  280. drv := container_storage.GetDriver(container_storage.STORAGE_TYPE_RBD)
  281. if drv == nil {
  282. return nil, errors.Wrap(errors.ErrNotImplemented, "RBD container storage driver not registered")
  283. }
  284. return drv, nil
  285. }