storage_rbd.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  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. "os"
  19. "path"
  20. "path/filepath"
  21. "yunion.io/x/jsonutils"
  22. "yunion.io/x/log"
  23. "yunion.io/x/pkg/errors"
  24. "yunion.io/x/pkg/gotypes"
  25. "yunion.io/x/pkg/util/qemuimgfmt"
  26. "yunion.io/x/pkg/utils"
  27. apis2 "yunion.io/x/onecloud/pkg/apis"
  28. api "yunion.io/x/onecloud/pkg/apis/compute"
  29. hostapi "yunion.io/x/onecloud/pkg/apis/host"
  30. deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
  31. "yunion.io/x/onecloud/pkg/hostman/hostdeployer/deployclient"
  32. "yunion.io/x/onecloud/pkg/hostman/hostutils"
  33. "yunion.io/x/onecloud/pkg/hostman/options"
  34. modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
  35. "yunion.io/x/onecloud/pkg/mcclient/modules/image"
  36. "yunion.io/x/onecloud/pkg/util/cephutils"
  37. "yunion.io/x/onecloud/pkg/util/procutils"
  38. "yunion.io/x/onecloud/pkg/util/qemuimg"
  39. )
  40. const (
  41. RBD_FEATURE = 3
  42. RBD_ORDER = 22 //为rbd对应到rados中每个对象的大小,默认为4MB
  43. )
  44. type sStorageConf struct {
  45. MonHost string
  46. Key string
  47. Pool string
  48. // https://docs.ceph.com/en/latest/rados/configuration/msgr2/
  49. // The messenger v2 protocol, or msgr2, is the second major
  50. // revision on Ceph’s on-wire protocol.
  51. EnableMessengerV2 bool
  52. RadosMonOpTimeout int
  53. RadosOsdOpTimeout int
  54. ClientMountTimeout int
  55. }
  56. type SRbdStorage struct {
  57. SBaseStorage
  58. sStorageConf
  59. }
  60. func NewRBDStorage(manager *SStorageManager, path string) *SRbdStorage {
  61. var ret = new(SRbdStorage)
  62. ret.SBaseStorage = *NewBaseStorage(manager, path)
  63. ret.sStorageConf = sStorageConf{}
  64. return ret
  65. }
  66. type SRbdStorageFactory struct {
  67. }
  68. func (factory *SRbdStorageFactory) NewStorage(manager *SStorageManager, mountPoint string) IStorage {
  69. return NewRBDStorage(manager, mountPoint)
  70. }
  71. func (factory *SRbdStorageFactory) StorageType() string {
  72. return api.STORAGE_RBD
  73. }
  74. func init() {
  75. registerStorageFactory(&SRbdStorageFactory{})
  76. }
  77. func (s *SRbdStorage) StorageType() string {
  78. return api.STORAGE_RBD
  79. }
  80. func (s *SRbdStorage) IsLocal() bool {
  81. return false
  82. }
  83. func (s *SRbdStorage) GetSnapshotPathByIds(diskId, snapshotId string) string {
  84. return ""
  85. }
  86. func (s *SRbdStorage) getCephClient(pool string) (*cephutils.CephClient, error) {
  87. if pool == "" {
  88. pool = s.Pool
  89. }
  90. return cephutils.NewClient(s.MonHost, s.Key, pool, s.EnableMessengerV2, s.RadosMonOpTimeout, s.RadosOsdOpTimeout, s.ClientMountTimeout)
  91. }
  92. func (s *SRbdStorage) getClient() (*cephutils.CephClient, error) {
  93. return s.getCephClient("")
  94. }
  95. func (s *SRbdStorage) IsSnapshotExist(diskId, snapshotId string) (bool, error) {
  96. client, err := s.getClient()
  97. if err != nil {
  98. return false, errors.Wrapf(err, "GetClient")
  99. }
  100. defer client.Close()
  101. img, err := client.GetImage(diskId)
  102. if err != nil {
  103. return false, errors.Wrapf(err, "GetImage")
  104. }
  105. return img.IsSnapshotExist(snapshotId)
  106. }
  107. func (s *SRbdStorage) GetSnapshotDir() string {
  108. return ""
  109. }
  110. func (s *SRbdStorage) GetFuseTmpPath() string {
  111. return ""
  112. }
  113. func (s *SRbdStorage) GetFuseMountPath() string {
  114. return ""
  115. }
  116. func (s *SRbdStorage) GetImgsaveBackupPath() string {
  117. return ""
  118. }
  119. func (s *SRbdStorage) getStorageConfDir() string {
  120. workspacePath := filepath.Dir(options.HostOptions.ServersPath)
  121. cephConfDir := path.Join(workspacePath, "ceph_config", s.StorageId)
  122. return cephConfDir
  123. }
  124. // Tip Configuration values containing :, @, or = can be escaped with a leading \ character.
  125. func (s *SRbdStorage) getStorageConfString() string {
  126. cephConfDir := s.getStorageConfDir()
  127. cephConfPath := path.Join(cephConfDir, "ceph.conf")
  128. return ":" + fmt.Sprintf("conf=%s", cephConfPath)
  129. }
  130. func (s *SRbdStorage) listImages() ([]string, error) {
  131. client, err := s.getClient()
  132. if err != nil {
  133. return nil, errors.Wrapf(err, "GetClient")
  134. }
  135. defer client.Close()
  136. return client.ListImages()
  137. }
  138. func (s *SRbdStorage) IsImageExist(name string) (bool, error) {
  139. images, err := s.listImages()
  140. if err != nil {
  141. return false, errors.Wrapf(err, "listImages")
  142. }
  143. if utils.IsInStringArray(name, images) {
  144. return true, nil
  145. }
  146. return false, nil
  147. }
  148. func (s *SRbdStorage) getImageSizeMb(name string) (uint64, error) {
  149. client, err := s.getClient()
  150. if err != nil {
  151. return 0, errors.Wrapf(err, "GetClient")
  152. }
  153. defer client.Close()
  154. img, err := client.GetImage(name)
  155. if err != nil {
  156. return 0, errors.Wrapf(err, "GetImage")
  157. }
  158. info, err := img.GetInfo()
  159. if err != nil {
  160. return 0, errors.Wrapf(err, "GetInfo")
  161. }
  162. return uint64(info.SizeByte) / 1024 / 1024, nil
  163. }
  164. func (s *SRbdStorage) resizeImage(name string, sizeMb uint64) error {
  165. client, err := s.getClient()
  166. if err != nil {
  167. return errors.Wrapf(err, "GetClient")
  168. }
  169. defer client.Close()
  170. img, err := client.GetImage(name)
  171. if err != nil {
  172. return errors.Wrapf(err, "GetImage")
  173. }
  174. info, err := img.GetInfo()
  175. if err != nil {
  176. return errors.Wrapf(err, "img.GetInfo")
  177. }
  178. if uint64(info.SizeByte/1024/1024) >= sizeMb {
  179. return nil
  180. }
  181. return img.Resize(int64(sizeMb))
  182. }
  183. func (s *SRbdStorage) deleteImage(name string, skipRecycle bool) error {
  184. client, err := s.getClient()
  185. if err != nil {
  186. return errors.Wrapf(err, "GetClient")
  187. }
  188. defer client.Close()
  189. img, err := client.GetImage(name)
  190. if err != nil {
  191. if errors.Cause(err) == errors.ErrNotFound {
  192. return nil
  193. }
  194. return errors.Wrapf(err, "GetImage")
  195. }
  196. return img.Delete()
  197. }
  198. func (s *SRbdStorage) cloneImage(ctx context.Context, srcPool string, srcImage string, destPool string, destImage string) error {
  199. cli, err := s.getClient()
  200. if err != nil {
  201. return errors.Wrapf(err, "GetClient")
  202. }
  203. defer cli.Close()
  204. srcCli := cli.Child(srcPool)
  205. img, err := srcCli.GetImage(srcImage)
  206. if err != nil {
  207. return errors.Wrapf(err, "GetImage")
  208. }
  209. _, err = img.Clone(ctx, destPool, destImage)
  210. if err != nil {
  211. return errors.Wrap(err, "Clone")
  212. }
  213. return nil
  214. }
  215. func (s *SRbdStorage) cloneFromSnapshot(srcImage, srcPool, srcSnapshot, newImage, pool string) error {
  216. cli, err := s.getClient()
  217. if err != nil {
  218. return errors.Wrapf(err, "GetClient")
  219. }
  220. defer cli.Close()
  221. srcCli := cli.Child(srcPool)
  222. img, err := srcCli.GetImage(srcImage)
  223. if err != nil {
  224. return errors.Wrapf(err, "GetImage(%s/%s)", srcPool, srcImage)
  225. }
  226. snap, err := img.GetSnapshot(srcSnapshot)
  227. if err != nil {
  228. return errors.Wrapf(err, "GetSnapshot(%s)", srcSnapshot)
  229. }
  230. _, err = snap.Clone(pool, newImage, true)
  231. if err != nil {
  232. return errors.Wrap(err, "Clone")
  233. }
  234. return nil
  235. }
  236. func (s *SRbdStorage) createImage(name string, sizeMb uint64) error {
  237. client, err := s.getClient()
  238. if err != nil {
  239. return errors.Wrapf(err, "GetClient")
  240. }
  241. defer client.Close()
  242. _, err = client.CreateImage(name, int64(sizeMb))
  243. return err
  244. }
  245. func (s *SRbdStorage) renameImage(pool string, src string, dest string) error {
  246. cli, err := s.getClient()
  247. if err != nil {
  248. return errors.Wrapf(err, "GetClient")
  249. }
  250. defer cli.Close()
  251. srcCli := cli.Child(pool)
  252. img, err := srcCli.GetImage(src)
  253. if err != nil {
  254. return errors.Wrapf(err, "GetImage")
  255. }
  256. return img.Rename(dest)
  257. }
  258. func (s *SRbdStorage) resetDisk(diskId string, snapshotId string) error {
  259. client, err := s.getClient()
  260. if err != nil {
  261. return errors.Wrapf(err, "GetClient")
  262. }
  263. defer client.Close()
  264. img, err := client.GetImage(diskId)
  265. if err != nil {
  266. return errors.Wrapf(err, "GetImage")
  267. }
  268. snap, err := img.GetSnapshot(snapshotId)
  269. if err != nil {
  270. return errors.Wrapf(err, "GetSnapshot")
  271. }
  272. return snap.Rollback()
  273. }
  274. func (s *SRbdStorage) createBackup(ctx context.Context, diskId string, diskBackup *SDiskBackup) (int, error) {
  275. client, err := s.getClient()
  276. if err != nil {
  277. return 0, errors.Wrapf(err, "GetClient")
  278. }
  279. defer client.Close()
  280. img, err := client.GetImage(diskId)
  281. if err != nil {
  282. return 0, errors.Wrapf(err, "GetImage")
  283. }
  284. snap, err := img.GetSnapshot(diskBackup.SnapshotId)
  285. if err != nil {
  286. return 0, errors.Wrapf(err, "unable to GetSnapshot %s of Image %s", diskBackup.SnapshotId, diskId)
  287. }
  288. backupName := fmt.Sprintf("backup_%s", diskBackup.BackupId)
  289. // no need to flattern, as image will be delete right after backup
  290. backupImg, err := snap.Clone(s.sStorageConf.Pool, backupName, false)
  291. if err != nil {
  292. return 0, errors.Wrapf(err, "unable to Clone snap %s", fmt.Sprintf("%s@%s", diskId, diskBackup.SnapshotId))
  293. }
  294. defer backupImg.Delete()
  295. srcPath := fmt.Sprintf("rbd:%s%s", backupImg.GetName(), s.getStorageConfString())
  296. size, err := doBackupDisk(ctx, srcPath, diskBackup)
  297. if err != nil {
  298. return 0, errors.Wrap(err, "doBackupDisk")
  299. }
  300. return size, nil
  301. }
  302. func (s *SRbdStorage) createSnapshot(diskId string, snapshotId string) error {
  303. client, err := s.getClient()
  304. if err != nil {
  305. return errors.Wrapf(err, "GetClient")
  306. }
  307. defer client.Close()
  308. img, err := client.GetImage(diskId)
  309. if err != nil {
  310. return errors.Wrapf(err, "GetImage")
  311. }
  312. _, err = img.CreateSnapshot(snapshotId)
  313. return err
  314. }
  315. func (s *SRbdStorage) deleteSnapshot(diskId string, snapshotId string) error {
  316. client, err := s.getClient()
  317. if err != nil {
  318. return errors.Wrapf(err, "GetClient")
  319. }
  320. defer client.Close()
  321. img, err := client.GetImage(diskId)
  322. if err != nil {
  323. return errors.Wrapf(err, "GetImage")
  324. }
  325. snap, err := img.GetSnapshot(snapshotId)
  326. if err != nil {
  327. return errors.Wrapf(err, "GetSnapshot")
  328. }
  329. return snap.Delete()
  330. }
  331. func (s *SRbdStorage) getSnapshotSize(diskId string, snapshotId string) (int64, error) {
  332. client, err := s.getClient()
  333. if err != nil {
  334. return -1, errors.Wrapf(err, "GetClient")
  335. }
  336. defer client.Close()
  337. img, err := client.GetImage(diskId)
  338. if err != nil {
  339. return -1, errors.Wrapf(err, "GetImage")
  340. }
  341. snapSize, err := img.GetSnapshotUsedSize(diskId, snapshotId)
  342. if err != nil {
  343. return -1, errors.Wrapf(err, "GetSnapshot")
  344. }
  345. return snapSize, nil
  346. }
  347. func (s *SRbdStorage) SyncStorageSize() (api.SHostStorageStat, error) {
  348. stat := api.SHostStorageStat{
  349. StorageId: s.StorageId,
  350. }
  351. client, err := s.getClient()
  352. if err != nil {
  353. return stat, errors.Wrapf(err, "GetClient")
  354. }
  355. defer client.Close()
  356. capacity, err := client.GetCapacity()
  357. if err != nil {
  358. return stat, errors.Wrapf(err, "GetCapacity")
  359. }
  360. stat.CapacityMb = capacity.CapacitySizeKb / 1024
  361. stat.ActualCapacityUsedMb = capacity.UsedCapacitySizeKb / 1024
  362. return stat, nil
  363. }
  364. func (s *SRbdStorage) GetCapacityMb() int {
  365. capa, err := s.getRbdCapacity()
  366. if err != nil {
  367. return -1
  368. }
  369. return int(capa.CapacitySizeKb) / 1024
  370. }
  371. func (s *SRbdStorage) getRbdCapacity() (*cephutils.SCapacity, error) {
  372. client, err := s.getClient()
  373. if err != nil {
  374. return nil, errors.Wrap(err, "getClient")
  375. }
  376. defer client.Close()
  377. capacity, err := client.GetCapacity()
  378. if err != nil {
  379. return nil, errors.Wrap(err, "GetCapacity")
  380. }
  381. return capacity, nil
  382. }
  383. func (s *SRbdStorage) SyncStorageInfo() (jsonutils.JSONObject, error) {
  384. content := map[string]interface{}{}
  385. if len(s.StorageId) > 0 {
  386. capacity, err := s.getRbdCapacity()
  387. if err != nil {
  388. reason := jsonutils.Marshal(map[string]string{"reason": errors.Wrapf(err, "GetCapacity").Error()})
  389. return modules.Storages.PerformAction(hostutils.GetComputeSession(context.Background()), s.StorageId, api.STORAGE_OFFLINE, reason)
  390. }
  391. content = map[string]interface{}{
  392. "name": s.StorageName,
  393. "capacity": capacity.CapacitySizeKb / 1024,
  394. "actual_capacity_used": capacity.UsedCapacitySizeKb / 1024,
  395. "status": api.STORAGE_ONLINE,
  396. "zone": s.GetZoneId(),
  397. }
  398. return modules.Storages.Put(hostutils.GetComputeSession(context.Background()), s.StorageId, jsonutils.Marshal(content))
  399. }
  400. return modules.Storages.Get(hostutils.GetComputeSession(context.Background()), s.StorageName, jsonutils.Marshal(content))
  401. }
  402. func (s *SRbdStorage) GetDiskById(diskId string) (IDisk, error) {
  403. s.DiskLock.Lock()
  404. defer s.DiskLock.Unlock()
  405. for i := 0; i < len(s.Disks); i++ {
  406. if s.Disks[i].GetId() == diskId {
  407. err := s.Disks[i].Probe()
  408. if err != nil {
  409. return nil, errors.Wrapf(err, "disk.Prob")
  410. }
  411. return s.Disks[i], nil
  412. }
  413. }
  414. var disk = NewRBDDisk(s, diskId)
  415. if disk.Probe() == nil {
  416. s.Disks = append(s.Disks, disk)
  417. return disk, nil
  418. }
  419. return nil, errors.ErrNotFound
  420. }
  421. func (s *SRbdStorage) CreateDisk(diskId string) IDisk {
  422. s.DiskLock.Lock()
  423. defer s.DiskLock.Unlock()
  424. disk := NewRBDDisk(s, diskId)
  425. s.Disks = append(s.Disks, disk)
  426. return disk
  427. }
  428. func (s *SRbdStorage) Accessible() error {
  429. client, err := s.getClient()
  430. if err != nil {
  431. return errors.Wrapf(err, "GetClient")
  432. }
  433. defer client.Close()
  434. _, err = client.GetCapacity()
  435. return err
  436. }
  437. func (s *SRbdStorage) Detach() error {
  438. return nil
  439. }
  440. func (s *SRbdStorage) SaveToGlance(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  441. info, ok := params.(SStorageSaveToGlanceInfo)
  442. if !ok {
  443. return nil, hostutils.ParamsError
  444. }
  445. data := info.DiskInfo
  446. rbdImageCache := storageManager.GetStoragecacheById(s.GetStoragecacheId())
  447. if rbdImageCache == nil {
  448. return nil, fmt.Errorf("failed to find storage image cache for storage %s", s.GetStorageName())
  449. }
  450. imagePath, _ := data.GetString("image_path")
  451. compress := jsonutils.QueryBoolean(data, "compress", true)
  452. format, _ := data.GetString("format")
  453. imageId, _ := data.GetString("image_id")
  454. imageName := "image_cache_" + imageId
  455. if err := s.renameImage(rbdImageCache.GetPath(), imagePath, imageName); err != nil {
  456. return nil, err
  457. }
  458. imagePath = fmt.Sprintf("rbd:%s/%s%s", rbdImageCache.GetPath(), imageName, s.getStorageConfString())
  459. if err := s.saveToGlance(ctx, imageId, imagePath, compress, format); err != nil {
  460. log.Errorf("Save to glance failed: %s", err)
  461. s.onSaveToGlanceFailed(ctx, imageId, err.Error())
  462. }
  463. rbdImageCache.LoadImageCache(imageId)
  464. _, err := hostutils.RemoteStoragecacheCacheImage(ctx, rbdImageCache.GetId(), imageId, "active", imagePath)
  465. if err != nil {
  466. log.Errorf("Fail to remote cache image: %v", err)
  467. }
  468. return nil, nil
  469. }
  470. func (s *SRbdStorage) saveToGlance(ctx context.Context, imageId, imagePath string, compress bool, format string) error {
  471. diskInfo := &deployapi.DiskInfo{
  472. Path: imagePath,
  473. }
  474. ret, err := deployclient.GetDeployClient().SaveToGlance(context.Background(),
  475. &deployapi.SaveToGlanceParams{DiskInfo: diskInfo, Compress: compress})
  476. if err != nil {
  477. return err
  478. }
  479. tmpPath := "/opt/cloud/tmp"
  480. err = os.MkdirAll(tmpPath, 0755)
  481. if err != nil {
  482. log.Errorf("failed mkdir %s", tmpPath)
  483. return errors.Wrap(err, "os.MkdirAll")
  484. }
  485. tmpFileDir, err := os.MkdirTemp(tmpPath, "ceph_save_images")
  486. if err != nil {
  487. log.Errorf("fail to obtain tempFile for ceph save glance image: %s", err)
  488. return errors.Wrap(err, "os.MkdirTemp")
  489. }
  490. defer func() {
  491. log.Debugf("clean up temp dir for glance image save %s", tmpFileDir)
  492. output, err := procutils.NewRemoteCommandAsFarAsPossible("rm", "-fr", tmpFileDir).Output()
  493. if err != nil {
  494. log.Errorf("rm %s fail %s %s", tmpFileDir, output, err)
  495. }
  496. }()
  497. tmpImageFile := filepath.Join(tmpFileDir, imageId)
  498. if len(format) == 0 {
  499. format = options.HostOptions.DefaultImageSaveFormat
  500. }
  501. img, err := qemuimg.NewQemuImage(imagePath)
  502. if err != nil {
  503. return errors.Wrapf(err, "NewQemuImage %s", imagePath)
  504. }
  505. _, err = img.Clone(tmpImageFile, qemuimgfmt.String2ImageFormat(format), compress)
  506. if err != nil {
  507. return errors.Wrapf(err, "Clone %s", tmpImageFile)
  508. }
  509. f, err := os.Open(tmpImageFile)
  510. if err != nil {
  511. return err
  512. }
  513. defer os.Remove(tmpImageFile)
  514. defer f.Close()
  515. finfo, err := f.Stat()
  516. if err != nil {
  517. return err
  518. }
  519. size := finfo.Size()
  520. var params = jsonutils.NewDict()
  521. if len(ret.OsInfo) > 0 {
  522. params.Set("os_type", jsonutils.NewString(ret.OsInfo))
  523. }
  524. releaseInfoToParams(ret.ReleaseInfo, params)
  525. params.Set("image_id", jsonutils.NewString(imageId))
  526. _, err = image.Images.Upload(hostutils.GetImageSession(ctx), params, f, size)
  527. return err
  528. }
  529. func (s *SRbdStorage) CreateSnapshotFormUrl(ctx context.Context, snapshotUrl, diskId, snapshotPath string) error {
  530. return fmt.Errorf("Not support")
  531. }
  532. func (s *SRbdStorage) DeleteSnapshots(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  533. return nil, fmt.Errorf("Not support delete snapshots")
  534. }
  535. func (s *SRbdStorage) DeleteSnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  536. return nil, fmt.Errorf("Not support delete snapshot")
  537. }
  538. func (s *SRbdStorage) CreateDiskFromSnapshot(ctx context.Context, disk IDisk, input *SDiskCreateByDiskinfo) (jsonutils.JSONObject, error) {
  539. info := input.DiskInfo
  540. err := disk.CreateFromRbdSnapshot(ctx, info.SnapshotUrl, info.SrcDiskId, info.SrcPool)
  541. if err != nil {
  542. return nil, err
  543. }
  544. return disk.GetDiskDesc(), nil
  545. }
  546. func (s *SRbdStorage) GetBackupDir() string {
  547. return ""
  548. }
  549. func (s *SRbdStorage) CreateDiskFromExistingPath(context.Context, IDisk, *SDiskCreateByDiskinfo) error {
  550. return fmt.Errorf("Not support")
  551. }
  552. func (s *SRbdStorage) CreateDiskFromBackup(ctx context.Context, disk IDisk, input *SDiskCreateByDiskinfo) error {
  553. pool, _ := s.StorageConf.GetString("pool")
  554. destPath := fmt.Sprintf("rbd:%s/%s%s", pool, disk.GetId(), s.getStorageConfString())
  555. err := doRestoreDisk(ctx, s, input, disk, destPath)
  556. if err != nil {
  557. return errors.Wrap(err, "doRestore")
  558. }
  559. /*backup := input.DiskInfo.Backup
  560. backupStorage, err := backupstorage.GetBackupStorage(backup.BackupStorageId, backup.BackupStorageAccessInfo)
  561. if err != nil {
  562. return errors.Wrap(err, "unable to GetBackupStorage")
  563. }
  564. err = backupStorage.ConvertTo(destPath, qemuimgfmt.RAW, backup.BackupId)
  565. if err != nil {
  566. return errors.Wrapf(err, "unable to Convert to with destPath %s and format %s", destPath, qemuimgfmt.RAW.String())
  567. }*/
  568. return nil
  569. }
  570. func (s *SRbdStorage) getDiskPath(diskId string) string {
  571. storageConf := s.GetStorageConf()
  572. pool, _ := storageConf.GetString("pool")
  573. return fmt.Sprintf("rbd:%s/%s", pool, diskId)
  574. }
  575. func (s *SRbdStorage) GetDiskPath(diskId string) string {
  576. return fmt.Sprintf("%s%s", s.getDiskPath(diskId), s.getStorageConfString())
  577. }
  578. func (s *SRbdStorage) GetCloneTargetDiskPath(ctx context.Context, targetDiskId string) string {
  579. return s.GetDiskPath(targetDiskId)
  580. }
  581. func (s *SRbdStorage) CloneDiskFromStorage(ctx context.Context, srcStorage IStorage, srcDisk IDisk, targetDiskId string, fullCopy bool, encInfo apis2.SEncryptInfo) (*hostapi.ServerCloneDiskFromStorageResponse, error) {
  582. srcDiskPath := srcDisk.GetPath()
  583. srcImg, err := qemuimg.NewQemuImage(srcDiskPath)
  584. if err != nil {
  585. return nil, errors.Wrapf(err, "Get source image %q info", srcDiskPath)
  586. }
  587. accessPath := s.GetCloneTargetDiskPath(ctx, targetDiskId)
  588. if fullCopy {
  589. _, err = srcImg.Clone(accessPath, qemuimgfmt.RAW, false)
  590. if err != nil {
  591. return nil, errors.Wrap(err, "Clone source disk to target rbd storage")
  592. }
  593. } else {
  594. err = s.createImage(targetDiskId, uint64(srcImg.GetSizeMB()))
  595. if err != nil {
  596. return nil, errors.Wrap(err, "Create rbd image")
  597. }
  598. }
  599. return &hostapi.ServerCloneDiskFromStorageResponse{
  600. TargetAccessPath: accessPath,
  601. TargetFormat: qemuimgfmt.RAW.String(),
  602. }, nil
  603. }
  604. func (s *SRbdStorage) SetStorageInfo(storageId, storageName string, conf jsonutils.JSONObject) error {
  605. s.StorageId = storageId
  606. s.StorageName = storageName
  607. if gotypes.IsNil(conf) {
  608. return fmt.Errorf("empty storage conf for storage %s(%s)", storageName, storageId)
  609. }
  610. if dconf, ok := conf.(*jsonutils.JSONDict); ok {
  611. s.StorageConf = dconf
  612. }
  613. conf.Unmarshal(&s.sStorageConf)
  614. if s.RadosMonOpTimeout == 0 {
  615. s.RadosMonOpTimeout = api.RBD_DEFAULT_MON_TIMEOUT
  616. }
  617. if s.RadosOsdOpTimeout == 0 {
  618. s.RadosOsdOpTimeout = api.RBD_DEFAULT_OSD_TIMEOUT
  619. }
  620. if s.ClientMountTimeout == 0 {
  621. s.ClientMountTimeout = api.RBD_DEFAULT_MOUNT_TIMEOUT
  622. }
  623. confDir := s.getStorageConfDir()
  624. if err := os.MkdirAll(confDir, os.ModePerm); err != nil {
  625. return errors.Wrapf(err, "mkdir all %s", confDir)
  626. }
  627. confPath := path.Join(confDir, "ceph.conf")
  628. keyringPath := path.Join(confDir, "ceph.keyring")
  629. cli, err := cephutils.NewClientAndPersistentConf(
  630. s.MonHost, s.Key, s.Pool,
  631. s.EnableMessengerV2, s.RadosMonOpTimeout,
  632. s.RadosOsdOpTimeout, s.ClientMountTimeout,
  633. confPath, keyringPath,
  634. )
  635. if err != nil {
  636. log.Errorf("failed get ceph client %s:", err)
  637. return errors.Wrap(err, "getClient")
  638. }
  639. defer cli.Close()
  640. return nil
  641. }
  642. func (s *SRbdStorage) CleanRecycleDiskfiles(ctx context.Context) {
  643. log.Infof("SRbdStorage CleanRecycleDiskfiles do nothing!")
  644. }