| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693 |
- // 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"
- "net"
- "path"
- "strconv"
- "strings"
- "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/util/qemuimgfmt"
- "yunion.io/x/pkg/utils"
- "yunion.io/x/onecloud/pkg/apis"
- api "yunion.io/x/onecloud/pkg/apis/compute"
- "yunion.io/x/onecloud/pkg/cloudcommon/consts"
- deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
- "yunion.io/x/onecloud/pkg/hostman/hostdeployer/deployclient"
- "yunion.io/x/onecloud/pkg/hostman/hostutils"
- "yunion.io/x/onecloud/pkg/hostman/storageman/lvmutils"
- "yunion.io/x/onecloud/pkg/hostman/storageman/storageutils"
- "yunion.io/x/onecloud/pkg/mcclient/auth"
- identity_modules "yunion.io/x/onecloud/pkg/mcclient/modules/identity"
- "yunion.io/x/onecloud/pkg/util/fileutils2"
- "yunion.io/x/onecloud/pkg/util/netutils2"
- "yunion.io/x/onecloud/pkg/util/procutils"
- "yunion.io/x/onecloud/pkg/util/qemuimg"
- "yunion.io/x/onecloud/pkg/util/seclib2"
- )
- var _ IDisk = (*SLVMDisk)(nil)
- type SLVMDisk struct {
- SBaseDisk
- }
- func (d *SLVMDisk) GetSnapshotDir() string {
- return d.GetSnapshotPrefix()
- }
- func (d *SLVMDisk) GetSnapshotPrefix() string {
- return path.Join("/dev", d.Storage.GetPath(), "snap_")
- }
- func (d *SLVMDisk) GetImageCachePrefix() string {
- return path.Join("/dev", d.Storage.GetPath(), "imagecache_")
- }
- func (d *SLVMDisk) GetType() string {
- return api.STORAGE_LVM
- }
- // /dev/<vg>/<lvm>
- func (d *SLVMDisk) GetLvPath() string {
- return path.Join("/dev", d.Storage.GetPath(), d.Id)
- }
- func (d *SLVMDisk) GetPath() string {
- return path.Join("/dev", d.Storage.GetPath(), d.Id)
- }
- // The LVM logical volume name is limited to 64 characters.
- func (d *SLVMDisk) GetSnapshotName(snapshotId string) string {
- return "snap_" + snapshotId
- }
- func (d *SLVMDisk) GetSnapshotPath(snapshotId string) string {
- return path.Join("/dev", d.Storage.GetPath(), d.GetSnapshotName(snapshotId))
- }
- func (d *SLVMDisk) GetDiskSetupScripts(idx int) string {
- return fmt.Sprintf("DISK_%d='%s'\n", idx, d.GetPath())
- }
- func (d *SLVMDisk) GetDiskDesc() jsonutils.JSONObject {
- qemuImg, err := qemuimg.NewQemuImage(d.GetPath())
- if err != nil {
- log.Errorf("qemuimg.NewQemuImage %s: %s", d.GetPath(), err)
- return nil
- }
- var desc = jsonutils.NewDict()
- desc.Set("disk_id", jsonutils.NewString(d.Id))
- desc.Set("disk_size", jsonutils.NewInt(qemuImg.SizeBytes/1024/1024))
- desc.Set("format", jsonutils.NewString(string(qemuImg.Format)))
- desc.Set("disk_path", jsonutils.NewString(d.GetPath()))
- return desc
- }
- func (d *SLVMDisk) CreateRaw(ctx context.Context, sizeMB int, diskFormat string, fsFormat string, fsFeatures *api.DiskFsFeatures, encryptInfo *apis.SEncryptInfo, diskId string, back string) (jsonutils.JSONObject, error) {
- if fileutils2.Exists(d.GetPath()) {
- if err := lvmutils.LvRemove(d.GetLvPath()); err != nil {
- return nil, errors.Wrap(err, "CreateRaw lvremove")
- }
- }
- img, err := qemuimg.NewQemuImage(d.GetPath())
- if err != nil {
- log.Errorf("NewQemuImage failed %s %s", d.GetPath(), err)
- return nil, err
- }
- qcow2Size := lvmutils.GetQcow2LvSize(int64(sizeMB))
- if sizeMB <= 0 && back != "" {
- backImg, err := qemuimg.NewQemuImage(back)
- if err != nil {
- log.Errorf("NewQemuImage failed %s %s", back, err)
- return nil, err
- }
- qcow2Size = lvmutils.GetQcow2LvSize(int64(backImg.GetSizeMB()))
- }
- err = lvmutils.LvCreate(d.Storage.GetPath(), d.Id, qcow2Size*1024*1024)
- if err != nil {
- return nil, errors.Wrap(err, "CreateRaw")
- }
- if encryptInfo != nil {
- err = img.CreateQcow2(sizeMB, false, back, encryptInfo.Key, qemuimg.EncryptFormatLuks, encryptInfo.Alg)
- } else {
- err = img.CreateQcow2(sizeMB, false, back, "", "", "")
- }
- if err != nil {
- return nil, fmt.Errorf("create_raw: Fail to create disk: %s", err)
- }
- diskInfo := &deployapi.DiskInfo{
- Path: d.GetPath(),
- }
- if encryptInfo != nil {
- diskInfo.EncryptPassword = encryptInfo.Key
- diskInfo.EncryptAlg = string(encryptInfo.Alg)
- }
- 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 *SLVMDisk) Delete(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
- p := params.(api.DiskDeleteInput)
- if p.EsxiFlatFilePath != "" {
- connections := &deployapi.EsxiDisksConnectionInfo{Disks: []*deployapi.EsxiDiskInfo{{DiskPath: p.EsxiFlatFilePath}}}
- _, err := deployclient.GetDeployClient().DisconnectEsxiDisks(ctx, connections)
- if err != nil {
- log.Errorf("Disconnect %s esxi disks failed %s", p.EsxiFlatFilePath, err)
- return nil, err
- }
- }
- if err := lvmutils.LvRemove(d.GetLvPath()); err != nil {
- return nil, errors.Wrap(err, "Delete lvremove")
- }
- d.Storage.RemoveDisk(d)
- return nil, nil
- }
- func (d *SLVMDisk) PostCreateFromRemoteHostImage(diskUrl string) {
- if diskUrl != "" {
- if err := d.RequestCloseNbdImage(context.Background(), diskUrl); err != nil {
- log.Errorf("failed request close nbd image %s: %s", diskUrl, err)
- }
- }
- }
- func (d *SLVMDisk) CreateFromRemoteHostImage(ctx context.Context, url string, size int64, encryptInfo *apis.SEncryptInfo) error {
- log.Infof("Create from remote host image %s", url)
- nbdPort, err := d.RequestExportNbdImage(ctx, url, encryptInfo)
- remoteHostIp := netutils2.ParseIpFromUrl(url)
- remoteHostAndPort := net.JoinHostPort(remoteHostIp, strconv.Itoa(int(nbdPort)))
- nbdImagePath := fmt.Sprintf("nbd://%s/%s", remoteHostAndPort, d.GetId())
- log.Infof("remote nbd image exported %s", nbdImagePath)
- newImg, err := qemuimg.NewQemuImage(d.GetPath())
- if err != nil {
- log.Errorf("qemuimg.NewQemuImage %s fail: %s", d.GetPath(), err)
- return err
- }
- if newImg.IsValid() && newImg.IsChained() && newImg.BackFilePath != nbdImagePath {
- if err := lvmutils.LvRemove(d.GetPath()); err != nil {
- return errors.Wrap(err, "remove disk")
- }
- }
- lvSize := lvmutils.GetQcow2LvSize(size)
- if err := lvmutils.LvCreate(d.Storage.GetPath(), d.Id, lvSize*1024*1024); err != nil {
- return errors.Wrap(err, "lvcreate")
- }
- if encryptInfo != nil {
- err = newImg.CreateQcow2(0, false, nbdImagePath, encryptInfo.Key, qemuimg.EncryptFormatLuks, encryptInfo.Alg)
- } else {
- err = newImg.CreateQcow2(0, false, nbdImagePath, "", "", "")
- }
- if err != nil {
- return errors.Wrapf(err, "create from remote host image")
- }
- return nil
- }
- func (d *SLVMDisk) IsFile() bool {
- return true
- }
- func (d *SLVMDisk) Probe() error {
- if !fileutils2.Exists(d.GetPath()) {
- return errors.Wrapf(cloudprovider.ErrNotFound, "%s", d.GetPath())
- }
- return nil
- }
- func (d *SLVMDisk) OnRebuildRoot(ctx context.Context, params api.DiskAllocateInput) error {
- _, err := d.Delete(ctx, api.DiskDeleteInput{})
- return err
- }
- func (d *SLVMDisk) PreResize(ctx context.Context, sizeMb int64) error {
- qemuImg, err := qemuimg.NewQemuImage(d.GetPath())
- if err != nil {
- return errors.Wrap(err, "lvm qemuimg.NewQemuImage")
- }
- lvsize := sizeMb
- if qemuImg.Format == qemuimgfmt.QCOW2 {
- lvsize = lvmutils.GetQcow2LvSize(sizeMb)
- }
- err = lvmutils.LvResize(d.Storage.GetPath(), d.GetPath(), lvsize*1024*1024)
- if err != nil {
- return errors.Wrap(err, "lv resize")
- }
- return nil
- }
- func (d *SLVMDisk) Resize(ctx context.Context, params *SDiskResizeInput) (jsonutils.JSONObject, error) {
- diskInfo := params.DiskInfo
- sizeMb, _ := diskInfo.Int("size")
- qemuImg, err := qemuimg.NewQemuImage(d.GetPath())
- if err != nil {
- return nil, errors.Wrap(err, "lvm qemuimg.NewQemuImage")
- }
- lvsize := sizeMb
- if qemuImg.Format == qemuimgfmt.QCOW2 {
- lvsize = lvmutils.GetQcow2LvSize(sizeMb)
- }
- err = lvmutils.LvResize(d.Storage.GetPath(), d.GetPath(), lvsize*1024*1024)
- if err != nil {
- return nil, errors.Wrap(err, "lv resize")
- }
- resizeFsInfo := &deployapi.DiskInfo{
- Path: d.GetPath(),
- DiskId: d.GetId(),
- }
- if diskInfo.Contains("encrypt_info") {
- var encryptInfo apis.SEncryptInfo
- err := diskInfo.Unmarshal(&encryptInfo, "encrypt_info")
- if err != nil {
- log.Errorf("fail to fetch encryptInfo %s", err)
- return nil, errors.Wrap(err, "Unmarshal encrpt_info")
- } else {
- qemuImg.SetPassword(encryptInfo.Key)
- resizeFsInfo.EncryptPassword = encryptInfo.Key
- resizeFsInfo.EncryptAlg = string(encryptInfo.Alg)
- }
- }
- err = qemuImg.Resize(int(sizeMb))
- if err != nil {
- return nil, errors.Wrap(err, "qemuImg resize")
- }
- 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 *SLVMDisk) CreateFromTemplate(
- ctx context.Context, imageId, format string, sizeMb int64, encryptInfo *apis.SEncryptInfo,
- ) (jsonutils.JSONObject, error) {
- if fileutils2.Exists(d.GetPath()) {
- if err := lvmutils.LvRemove(d.GetLvPath()); err != nil {
- return nil, errors.Wrap(err, "CreateRaw lvremove")
- }
- }
- var imageCacheManager = storageManager.GetStoragecacheById(d.Storage.GetStoragecacheId())
- ret, err := d.createFromTemplate(ctx, imageId, format, sizeMb, imageCacheManager, encryptInfo)
- if err != nil {
- return nil, err
- }
- retSize, _ := ret.Int("disk_size")
- log.Infof("REQSIZE: %d, RETSIZE: %d", sizeMb, retSize)
- if sizeMb > retSize {
- params := new(SDiskResizeInput)
- diskInfo := jsonutils.NewDict()
- diskInfo.Set("size", jsonutils.NewInt(sizeMb))
- if encryptInfo != nil {
- diskInfo.Set("encrypt_info", jsonutils.Marshal(encryptInfo))
- }
- params.DiskInfo = diskInfo
- return d.Resize(ctx, params)
- }
- return ret, nil
- }
- func (d *SLVMDisk) createFromTemplate(
- ctx context.Context, imageId, format string, sizeMb int64, imageCacheManager IImageCacheManger, encryptInfo *apis.SEncryptInfo,
- ) (jsonutils.JSONObject, error) {
- 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)
- cacheImagePath := imageCache.GetPath()
- lvSizeMb := lvmutils.GetQcow2LvSize(imageCache.GetDesc().SizeMb)
- if err := lvmutils.LvCreate(d.Storage.GetPath(), d.Id, lvSizeMb*1024*1024); err != nil {
- return nil, errors.Wrap(err, "CreateRaw")
- }
- newImg, err := qemuimg.NewQemuImage(d.GetPath())
- if err != nil {
- return nil, errors.Wrapf(err, "NewQemuImage(%s)", d.GetPath())
- }
- if encryptInfo != nil {
- err = newImg.CreateQcow2(0, false, cacheImagePath, encryptInfo.Key, qemuimg.EncryptFormatLuks, encryptInfo.Alg)
- } else {
- err = newImg.CreateQcow2(0, false, cacheImagePath, "", "", "")
- }
- if err != nil {
- return nil, errors.Wrapf(err, "CreateQcow2(%s)", cacheImagePath)
- }
- return d.GetDiskDesc(), nil
- }
- func (d *SLVMDisk) PrepareSaveToGlance(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
- if err := d.Probe(); err != nil {
- return nil, err
- }
- destDir := d.Storage.GetImgsaveBackupPath()
- if err := procutils.NewCommand("mkdir", "-p", destDir).Run(); err != nil {
- log.Errorln(err)
- return nil, err
- }
- freeSizeMb, err := storageutils.GetFreeSizeMb(destDir)
- if err != nil {
- return nil, errors.Wrap(err, "lvm storageutils.GetFreeSizeMb")
- }
- qemuImg, err := qemuimg.NewQemuImage(d.GetPath())
- if err != nil {
- return nil, errors.Wrap(err, "lvm qemuimg.NewQemuImage")
- }
- if int(qemuImg.SizeBytes/1024/1024) >= freeSizeMb*4/5 {
- return nil, errors.Errorf("image cache dir free size is not enough")
- }
- backupPath := path.Join(destDir, fmt.Sprintf("%s.%s", d.Id, appctx.AppContextTaskId(ctx)))
- if err := procutils.NewCommand("cp", "--sparse=always", "-f", d.GetPath(), backupPath).Run(); err != nil {
- log.Errorln(err)
- procutils.NewCommand("rm", "-f", backupPath).Run()
- return nil, err
- }
- res := jsonutils.NewDict()
- res.Set("backup", jsonutils.NewString(backupPath))
- return res, nil
- }
- func (d *SLVMDisk) GetBackupName(backupId string) string {
- return "backup_" + backupId
- }
- func (d *SLVMDisk) GetBackupPath(backupId string) string {
- return path.Join("/dev", d.Storage.GetPath(), d.GetBackupName(backupId))
- }
- func (d *SLVMDisk) DiskBackup(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
- diskBackup := params.(*SDiskBackup)
- var encKey = ""
- var encAlg seclib2.TSymEncAlg
- if len(diskBackup.EncryptKeyId) > 0 {
- session := auth.GetSession(ctx, diskBackup.UserCred, consts.GetRegion())
- secKey, err := identity_modules.Credentials.GetEncryptKey(session, diskBackup.EncryptKeyId)
- if err != nil {
- return nil, errors.Wrap(err, "GetEncryptKey")
- }
- encAlg = secKey.Alg
- encKey = secKey.Key
- }
- snapshotPath := d.GetSnapshotPath(diskBackup.SnapshotId)
- snapshotImg, err := qemuimg.NewQemuImage(snapshotPath)
- if err != nil {
- return nil, errors.Wrap(err, "lvm disk backup snapshotPath NewQemuImage")
- }
- // create backup lv
- lvSizeMb := lvmutils.GetQcow2LvSize(snapshotImg.SizeBytes / 1024 / 1024)
- err = lvmutils.LvCreate(d.Storage.GetPath(), d.GetBackupName(diskBackup.BackupId), lvSizeMb*1024*1024)
- if err != nil {
- return nil, errors.Wrap(err, "lvcreate backup")
- }
- backupPath := d.GetBackupPath(diskBackup.BackupId)
- srcInfo := qemuimg.SImageInfo{
- Path: snapshotPath,
- Format: snapshotImg.Format,
- IoLevel: qemuimg.IONiceNone,
- Password: encKey,
- EncryptAlg: encAlg,
- EncryptFormat: qemuimg.EncryptFormatLuks,
- ClusterSize: snapshotImg.ClusterSize,
- }
- destInfo := qemuimg.SImageInfo{
- Path: backupPath,
- Format: qemuimgfmt.QCOW2,
- IoLevel: qemuimg.IONiceNone,
- Password: encKey,
- EncryptAlg: encAlg,
- EncryptFormat: qemuimg.EncryptFormatLuks,
- }
- if err = qemuimg.Convert(srcInfo, destInfo, true, nil); err != nil {
- if errRm := lvmutils.LvRemove(backupPath); errRm != nil {
- log.Errorf("failed delete backup lv %s", errRm)
- }
- return nil, errors.Wrap(err, "failed convert snapshot to backup")
- }
- _, err = d.Storage.StorageBackup(ctx, &SStorageBackup{
- BackupId: diskBackup.BackupId,
- BackupLocalPath: backupPath,
- BackupStorageId: diskBackup.BackupStorageId,
- BackupStorageAccessInfo: diskBackup.BackupStorageAccessInfo,
- })
- if err != nil {
- return nil, errors.Wrap(err, "unable to SStorageBackup")
- }
- data := jsonutils.NewDict()
- data.Set("size_mb", jsonutils.NewInt(snapshotImg.SizeBytes/1024/1024))
- return data, nil
- }
- func (d *SLVMDisk) CreateSnapshot(snapshotId string, encryptKey string, encFormat qemuimg.TEncryptFormat, encAlg seclib2.TSymEncAlg) error {
- snapName := d.GetSnapshotName(snapshotId)
- log.Infof("Start create snapshot %s of lvm Disk %s", snapName, d.Id)
- lvSize, err := lvmutils.GetLvSize(d.GetPath())
- if err != nil {
- return err
- }
- err = lvmutils.LvRename(d.Storage.GetPath(), d.Id, snapName)
- if err != nil {
- return err
- }
- if err := lvmutils.LvCreate(d.Storage.GetPath(), d.Id, lvSize); err != nil {
- if e := lvmutils.LvRename(d.Storage.GetPath(), snapName, d.Id); e != nil {
- log.Errorf("failed rename lv %s to %s: %s", snapName, d.GetPath(), e)
- }
- return errors.Wrap(err, "snapshot LvCreate")
- }
- img, err := qemuimg.NewQemuImage(d.GetPath())
- if err != nil {
- if e := lvmutils.LvRemove(d.GetPath()); e != nil {
- log.Errorf("failed remove lv %s: %s", d.GetPath(), e)
- }
- if e := lvmutils.LvRename(d.Storage.GetPath(), snapName, d.Id); e != nil {
- log.Errorf("failed rename lv %s to %s: %s", snapName, d.GetPath(), e)
- }
- return errors.Wrapf(err, "failed qemuimg.NewQemuImage(%s))", d.GetPath())
- }
- snapPath := d.GetSnapshotPath(snapshotId)
- err = img.CreateQcow2(0, false, snapPath, encryptKey, encFormat, encAlg)
- if err != nil {
- if e := lvmutils.LvRemove(d.GetPath()); e != nil {
- log.Errorf("failed remove lv %s: %s", d.GetPath(), e)
- }
- if e := lvmutils.LvRename(d.Storage.GetPath(), snapName, d.Id); e != nil {
- log.Errorf("failed rename lv %s to %s: %s", snapName, d.GetPath(), e)
- }
- return errors.Wrapf(err, "CreateQcow2(%s)", snapPath)
- }
- return nil
- }
- func (d *SLVMDisk) ResetFromSnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
- resetParams, ok := params.(*SDiskReset)
- if !ok {
- return nil, hostutils.ParamsError
- }
- img, err := qemuimg.NewQemuImage(d.GetPath())
- if err != nil {
- return nil, err
- }
- diskSizeMB := int(img.SizeBytes / 1024 / 1024)
- lvSize, err := lvmutils.GetLvSize(d.GetPath())
- if err != nil {
- return nil, err
- }
- // rename disk to temp logical volume
- tmpVolume := d.Id + "-reset.tmp"
- err = lvmutils.LvRename(d.Storage.GetPath(), d.Id, tmpVolume)
- if err != nil {
- return nil, err
- }
- if err := lvmutils.LvCreate(d.Storage.GetPath(), d.Id, lvSize); err != nil {
- return nil, errors.Wrap(err, "reset snapshot LvCreate")
- }
- imgNew, err := qemuimg.NewQemuImage(d.GetPath())
- if err != nil {
- lvmutils.LvRemove(d.GetPath())
- lvmutils.LvRename(d.Storage.GetPath(), tmpVolume, d.Id)
- return nil, errors.Wrapf(err, "failed qemuimg.NewQemuImage(%s))", d.GetPath())
- }
- var encryptInfo *apis.SEncryptInfo
- if resetParams.Input.Contains("encrypt_info") {
- encInfo := apis.SEncryptInfo{}
- err := resetParams.Input.Unmarshal(&encInfo, "encrypt_info")
- if err != nil {
- log.Errorf("unmarshal encrypt_info fail %s", err)
- } else {
- encryptInfo = &encInfo
- }
- }
- var (
- encKey string
- encAlg seclib2.TSymEncAlg
- encFmt qemuimg.TEncryptFormat
- )
- if encryptInfo != nil {
- encKey = encryptInfo.Key
- encFmt = qemuimg.EncryptFormatLuks
- encAlg = encryptInfo.Alg
- }
- snapPath := d.GetSnapshotPath(resetParams.SnapshotId)
- err = imgNew.CreateQcow2(diskSizeMB, false, snapPath, encKey, encFmt, encAlg)
- if err != nil {
- lvmutils.LvRemove(d.GetPath())
- lvmutils.LvRename(d.Storage.GetPath(), tmpVolume, d.Id)
- return nil, errors.Wrapf(err, "CreateQcow2(%s)", snapPath)
- }
- tmpVolumePath := path.Join("/dev", d.Storage.GetPath(), tmpVolume)
- err = lvmutils.LvRemove(tmpVolumePath)
- if err != nil {
- return nil, errors.Wrap(err, "failed remove tmp volume")
- }
- return nil, nil
- }
- func (d *SLVMDisk) DeleteSnapshot(snapshotId, convertSnapshot string, blockStream bool, encryptInfo apis.SEncryptInfo) error {
- if blockStream {
- if err := ConvertLVMDisk(d.Storage.GetPath(), d.Id, encryptInfo); err != nil {
- return err
- }
- } else if len(convertSnapshot) > 0 {
- if err := d.ConvertSnapshot(convertSnapshot, encryptInfo); err != nil {
- return err
- }
- }
- return lvmutils.LvRemove(d.GetSnapshotPath(snapshotId))
- }
- func (d *SLVMDisk) DeleteAllSnapshot(skipRecycle bool) error {
- lvNames, err := lvmutils.GetLvNames(d.Storage.GetPath())
- if err != nil {
- log.Errorf("failed get lvm %s lvs %s", d.Storage.GetPath(), err)
- return nil
- }
- snapPrefix := "snap_" + d.Id
- for _, f := range lvNames {
- if strings.HasPrefix(f, snapPrefix) {
- if err := lvmutils.LvRemove(path.Join("/dev", d.Storage.GetPath(), f)); err != nil {
- return errors.Wrap(err, "delele lvm snapshots")
- }
- }
- }
- return nil
- }
- func (d *SLVMDisk) ConvertSnapshot(convertSnapshot string, encryptInfo apis.SEncryptInfo) error {
- convertSnapshotName := d.GetSnapshotName(convertSnapshot)
- return ConvertLVMDisk(d.Storage.GetPath(), convertSnapshotName, encryptInfo)
- }
- func (d *SLVMDisk) ConvertSnapshotRelyOnReloadDisk(convertSnapshot string, encryptInfo apis.SEncryptInfo) (func() error, error) {
- convertSnapshotName := d.GetSnapshotName(convertSnapshot)
- return ConvertLVMDiskNeedReload(d.Storage.GetPath(), convertSnapshotName, encryptInfo)
- }
- func (d *SLVMDisk) DoDeleteSnapshot(snapshotId string) error {
- snapshotPath := d.GetSnapshotPath(snapshotId)
- return lvmutils.LvRemove(snapshotPath)
- }
- func (d *SLVMDisk) RollbackDiskOnSnapshotFail(snapshotId string) error {
- diskPath := d.GetPath()
- if fileutils2.Exists(diskPath) {
- if err := lvmutils.LvRemove(diskPath); err != nil {
- return errors.Wrap(err, "rollback disk on snapshot fail delete disk")
- }
- }
- snapshotName := d.GetSnapshotName(snapshotId)
- if err := lvmutils.LvRename(d.Storage.GetPath(), snapshotName, d.Id); err != nil {
- return errors.Wrapf(err, "RollbackDiskOnSnapshotFail rename %s to %s failed: %s", snapshotName, d.Id, err)
- }
- return nil
- }
- func (d *SLVMDisk) PrepareMigrate(liveMigrate bool) ([]string, string, bool, error) {
- disk, err := qemuimg.NewQemuImage(d.GetPath())
- if err != nil {
- log.Errorln(err)
- return nil, "", false, err
- }
- ret, err := disk.WholeChainFormatIs("qcow2")
- if err != nil {
- log.Errorln(err)
- return nil, "", false, err
- }
- if liveMigrate && !ret {
- return nil, "", false, fmt.Errorf("Disk format doesn't support live migrate")
- }
- if disk.IsChained() {
- backingChain, err := disk.GetBackingChain()
- if err != nil {
- return nil, "", false, err
- }
- snapshots := []string{}
- for i := range backingChain {
- if strings.HasPrefix(backingChain[i], d.GetSnapshotDir()) {
- snapshots = append(snapshots, path.Base(backingChain[i]))
- } else if !strings.HasPrefix(backingChain[i], d.GetImageCachePrefix()) {
- return nil, "", false, errors.Errorf("backing file path %s unsupported", backingChain[i])
- }
- }
- hasTemplate := strings.HasPrefix(backingChain[len(backingChain)-1], d.GetImageCachePrefix())
- return snapshots, backingChain[0], hasTemplate, nil
- }
- return nil, "", false, nil
- }
- func (d *SLVMDisk) RebuildSlaveDisk(diskUri string) error {
- if err := lvmutils.LvRemove(d.GetPath()); err != nil {
- return errors.Wrap(err, "lvremove")
- }
- diskUrl := fmt.Sprintf("%s/%s", diskUri, d.Id)
- if err := d.CreateFromRemoteHostImage(context.Background(), diskUrl, 0, nil); err != nil {
- return errors.Wrap(err, "failed create slave disk")
- }
- return nil
- }
- func NewLVMDisk(storage IStorage, id string) *SLVMDisk {
- return &SLVMDisk{
- SBaseDisk: *NewBaseDisk(storage, id),
- }
- }
|