| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package storageman
- import (
- "context"
- "fmt"
- "yunion.io/x/cloudmux/pkg/cloudprovider"
- "yunion.io/x/jsonutils"
- "yunion.io/x/log"
- "yunion.io/x/pkg/appctx"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/utils"
- "yunion.io/x/onecloud/pkg/apis"
- api "yunion.io/x/onecloud/pkg/apis/compute"
- container_storage "yunion.io/x/onecloud/pkg/hostman/container/storage"
- deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
- "yunion.io/x/onecloud/pkg/hostman/hostutils"
- "yunion.io/x/onecloud/pkg/httperrors"
- "yunion.io/x/onecloud/pkg/util/qemuimg"
- "yunion.io/x/onecloud/pkg/util/seclib2"
- )
- var _ IDisk = (*SRBDDisk)(nil)
- type SRBDDisk struct {
- SBaseDisk
- }
- func NewRBDDisk(storage IStorage, id string) *SRBDDisk {
- var ret = new(SRBDDisk)
- ret.SBaseDisk = *NewBaseDisk(storage, id)
- return ret
- }
- func (d *SRBDDisk) GetType() string {
- return api.STORAGE_RBD
- }
- func (d *SRBDDisk) Probe() error {
- storage := d.Storage.(*SRbdStorage)
- exist, err := storage.IsImageExist(d.Id)
- if err != nil {
- return errors.Wrapf(err, "IsImageExist")
- }
- if !exist {
- return cloudprovider.ErrNotFound
- }
- return nil
- }
- func (d *SRBDDisk) getPath() string {
- return d.Storage.(*SRbdStorage).getDiskPath(d.Id)
- }
- func (d *SRBDDisk) GetPath() string {
- storage := d.Storage.(*SRbdStorage)
- return fmt.Sprintf("%s%s", d.getPath(), storage.getStorageConfString())
- }
- func (d *SRBDDisk) GetFormat() (string, error) {
- return "raw", nil
- }
- func (d *SRBDDisk) GetSnapshotDir() string {
- return ""
- }
- func (d *SRBDDisk) GetDiskDesc() jsonutils.JSONObject {
- storage := d.Storage.(*SRbdStorage)
- sizeMb, _ := storage.getImageSizeMb(d.Id)
- desc := map[string]interface{}{
- "disk_id": d.Id,
- "disk_format": "raw",
- "disk_path": d.getPath(),
- "disk_size": sizeMb,
- }
- return jsonutils.Marshal(desc)
- }
- func (d *SRBDDisk) GetDiskSetupScripts(idx int) string {
- return fmt.Sprintf("DISK_%d='%s'\n", idx, d.GetPath())
- }
- func (d *SRBDDisk) DeleteAllSnapshot(skipRecycle bool) error {
- return fmt.Errorf("Not Impl")
- }
- func (d *SRBDDisk) Delete(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
- p := params.(api.DiskDeleteInput)
- storage := d.Storage.(*SRbdStorage)
- return nil, storage.deleteImage(d.Id, p.SkipRecycle != nil && *p.SkipRecycle)
- }
- func (d *SRBDDisk) OnRebuildRoot(ctx context.Context, params api.DiskAllocateInput) error {
- if len(params.BackingDiskId) == 0 {
- _, err := d.Delete(ctx, api.DiskDeleteInput{})
- return err
- }
- storage := d.Storage.(*SRbdStorage)
- storageConf := d.Storage.GetStorageConf()
- pool, _ := storageConf.GetString("pool")
- return storage.renameImage(pool, d.Id, params.BackingDiskId)
- }
- func (d *SRBDDisk) Resize(ctx context.Context, params *SDiskResizeInput) (jsonutils.JSONObject, error) {
- diskInfo := params.DiskInfo
- storage := d.Storage.(*SRbdStorage)
- sizeMb, _ := diskInfo.Int("size")
- if err := storage.resizeImage(d.Id, uint64(sizeMb)); err != nil {
- return nil, err
- }
- resizeFsInfo := &deployapi.DiskInfo{
- Path: d.GetPath(),
- DiskId: d.GetId(),
- }
- if err := d.ResizeFs(resizeFsInfo, params.GuestDesc); err != nil {
- log.Errorf("Resize fs %s fail %s", d.GetPath(), err)
- return nil, errors.Wrapf(err, "resize fs %s", d.GetPath())
- }
- return d.GetDiskDesc(), nil
- }
- func (d *SRBDDisk) PrepareSaveToGlance(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
- if err := d.Probe(); err != nil {
- return nil, err
- }
- imageName := fmt.Sprintf("image_cache_%s_%s", d.Id, appctx.AppContextTaskId(ctx))
- imageCache := storageManager.GetStoragecacheById(d.Storage.GetStoragecacheId())
- if imageCache == nil {
- return nil, fmt.Errorf("failed to find image cache for prepare save to glance")
- }
- storage := d.Storage.(*SRbdStorage)
- pool, _ := storage.GetStorageConf().GetString("pool")
- if err := storage.cloneImage(ctx, pool, d.Id, imageCache.GetPath(), imageName); err != nil {
- log.Errorf("clone image %s from pool %s to %s/%s error: %v", d.Id, pool, imageCache.GetPath(), imageName, err)
- return nil, err
- }
- return jsonutils.Marshal(map[string]string{"backup": imageName}), nil
- }
- func (d *SRBDDisk) CleanupSnapshots(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
- storage := d.Storage.(*SRbdStorage)
- return nil, storage.deleteSnapshot(d.Id, "")
- }
- func (d *SRBDDisk) PrepareMigrate(liveMigrate bool) ([]string, string, bool, error) {
- return nil, "", false, fmt.Errorf("Not support")
- }
- func (d *SRBDDisk) CreateFromTemplate(ctx context.Context, imageId string, format string, size int64, encryptInfo *apis.SEncryptInfo) (jsonutils.JSONObject, error) {
- ret, err := d.createFromTemplate(ctx, imageId, format)
- if err != nil {
- return nil, err
- }
- retSize, _ := ret.Int("disk_size")
- log.Infof("REQSIZE: %d, RETSIZE: %d", size, retSize)
- if size > retSize {
- params := new(SDiskResizeInput)
- diskInfo := jsonutils.NewDict()
- diskInfo.Set("size", jsonutils.NewInt(size))
- params.DiskInfo = diskInfo
- return d.Resize(ctx, params)
- }
- return ret, nil
- }
- func (d *SRBDDisk) createFromTemplate(ctx context.Context, imageId, format string) (jsonutils.JSONObject, error) {
- var imageCacheManager = storageManager.GetStoragecacheById(d.Storage.GetStoragecacheId())
- if imageCacheManager == nil {
- return nil, fmt.Errorf("failed to find image cache manger for storage %s", d.Storage.GetStorageName())
- }
- input := api.CacheImageInput{
- ImageId: imageId,
- Zone: d.GetZoneId(),
- }
- imageCache, err := imageCacheManager.AcquireImage(ctx, input, nil)
- if err != nil {
- return nil, errors.Wrapf(err, "AcquireImage")
- }
- defer imageCacheManager.ReleaseImage(ctx, imageId)
- storage := d.Storage.(*SRbdStorage)
- storage.deleteImage(d.Id, false) //重装系统时,需要删除以前的系统盘
- err = storage.cloneImage(ctx, imageCacheManager.GetPath(), imageCache.GetName(), storage.Pool, d.Id)
- if err != nil {
- return nil, errors.Wrapf(err, "cloneImage(%s)", imageCache.GetName())
- }
- return d.GetDiskDesc(), nil
- }
- func (d *SRBDDisk) CreateFromRemoteHostImage(ctx context.Context, url string, size int64, encryptInfo *apis.SEncryptInfo) error {
- return fmt.Errorf("Not support")
- }
- 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) {
- if encryptInfo != nil {
- return nil, errors.Wrap(httperrors.ErrNotSupported, "rbd not support encryptInfo")
- }
- storage := d.Storage.(*SRbdStorage)
- if err := storage.createImage(diskId, uint64(sizeMb)); err != nil {
- return nil, err
- }
- diskInfo := &deployapi.DiskInfo{
- Path: d.GetPath(),
- }
- if utils.IsInStringArray(fsFormat, api.SUPPORTED_FS) {
- if err := d.FormatFs(fsFormat, nil, diskId, diskInfo); err != nil {
- return nil, errors.Wrap(err, "FormatFs")
- }
- }
- return d.GetDiskDesc(), nil
- }
- func (d *SRBDDisk) PostCreateFromRemoteHostImage(string) {
- log.Errorf("Not support PostCreateFromRemoteHostImage")
- }
- func (d *SRBDDisk) DiskBackup(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
- diskBackup := params.(*SDiskBackup)
- storage := d.Storage.(*SRbdStorage)
- sizeMb, err := storage.createBackup(ctx, d.Id, diskBackup)
- if err != nil {
- return nil, err
- }
- data := jsonutils.NewDict()
- data.Set("size_mb", jsonutils.NewInt(int64(sizeMb)))
- return data, nil
- }
- func (d *SRBDDisk) CreateSnapshot(snapshotId string, encryptKey string, encFormat qemuimg.TEncryptFormat, encAlg seclib2.TSymEncAlg) error {
- storage := d.Storage.(*SRbdStorage)
- return storage.createSnapshot(d.Id, snapshotId)
- }
- func (d *SRBDDisk) ConvertSnapshotRelyOnReloadDisk(convertSnapshotId string, encryptInfo apis.SEncryptInfo) (func() error, error) {
- return nil, nil
- }
- func (d *SRBDDisk) DeleteSnapshot(snapshotId, convertSnapshot string, blockStream bool, encryptInfo apis.SEncryptInfo) error {
- storage := d.Storage.(*SRbdStorage)
- return storage.deleteSnapshot(d.Id, snapshotId)
- }
- func (d *SRBDDisk) DiskSnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
- snapshotId, ok := params.(string)
- if !ok {
- return nil, hostutils.ParamsError
- }
- err := d.CreateSnapshot(snapshotId, "", "", "")
- if err != nil {
- return nil, err
- }
- ret := jsonutils.NewDict()
- storage := d.Storage.(*SRbdStorage)
- size, err := storage.getSnapshotSize(d.Id, snapshotId)
- if err != nil {
- log.Errorf("failed get snapshot %s size %s", snapshotId, err)
- } else {
- ret.Set("snapshot_size_mb", jsonutils.NewInt(size/1024/1024))
- }
- return ret, nil
- }
- func (d *SRBDDisk) DiskDeleteSnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
- snapshotId, ok := params.(string)
- if !ok {
- return nil, hostutils.ParamsError
- }
- err := d.DeleteSnapshot(snapshotId, "", false, apis.SEncryptInfo{})
- if err != nil {
- return nil, err
- } else {
- res := jsonutils.NewDict()
- res.Set("deleted", jsonutils.JSONTrue)
- return res, nil
- }
- }
- func (d *SRBDDisk) ResetFromSnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
- resetParams, ok := params.(*SDiskReset)
- if !ok {
- return nil, hostutils.ParamsError
- }
- diskId := resetParams.BackingDiskId
- if len(diskId) == 0 {
- diskId = d.GetId()
- }
- storage := d.Storage.(*SRbdStorage)
- return nil, storage.resetDisk(diskId, resetParams.SnapshotId)
- }
- func (d *SRBDDisk) CreateFromRbdSnapshot(ctx context.Context, snapshot, srcDiskId, srcPool string) error {
- storage := d.Storage.(*SRbdStorage)
- pool, _ := storage.StorageConf.GetString("pool")
- return storage.cloneFromSnapshot(srcDiskId, srcPool, snapshot, d.GetId(), pool)
- }
- func (d *SRBDDisk) IsFile() bool {
- return false
- }
- func (d *SRBDDisk) GetContainerStorageDriver() (container_storage.IContainerStorage, error) {
- drv := container_storage.GetDriver(container_storage.STORAGE_TYPE_RBD)
- if drv == nil {
- return nil, errors.Wrap(errors.ErrNotImplemented, "RBD container storage driver not registered")
- }
- return drv, nil
- }
|