fix(host): lvm guest reload disk before delete snapshot (#23053)

This commit is contained in:
wanyaoqi
2025-08-08 20:57:24 +08:00
committed by GitHub
parent 9a3871014e
commit 35093fb7a7
6 changed files with 57 additions and 26 deletions
+11 -5
View File
@@ -2155,6 +2155,8 @@ type SGuestSnapshotDeleteTask struct {
encryptInfo apis.SEncryptInfo
tmpPath string
delSnapshotPathAfterReload func() error
}
func NewGuestSnapshotDeleteTask(
@@ -2176,10 +2178,12 @@ func (s *SGuestSnapshotDeleteTask) Start(totalDeleteSnapshotCount, deletedSnapsh
return
}
if err := s.doDiskConvert(); err != nil {
cb, err := s.disk.ConvertSnapshotRelyOnReloadDisk(s.convertSnapshot, s.encryptInfo)
if err != nil {
s.taskFailed(err.Error())
return
}
s.delSnapshotPathAfterReload = cb
s.fetchDisksInfo(s.doReloadDisk)
}
@@ -2205,15 +2209,17 @@ func (s *SGuestSnapshotDeleteTask) onStreamDiskComplete() {
hostutils.TaskComplete(s.ctx, body)
}
func (s *SGuestSnapshotDeleteTask) doDiskConvert() error {
return s.disk.ConvertSnapshot(s.convertSnapshot, s.encryptInfo)
}
func (s *SGuestSnapshotDeleteTask) doReloadDisk(device string) {
s.SGuestReloadDiskTask.doReloadDisk(device, s.onReloadBlkdevSucc)
}
func (s *SGuestSnapshotDeleteTask) onReloadBlkdevSucc(err string) {
if s.delSnapshotPathAfterReload != nil {
if e := s.delSnapshotPathAfterReload(); e != nil {
log.Errorf("failed do delSnapshotPathAfterReload: %s", e)
}
}
var callback = s.onResumeSucc
if len(err) > 0 {
callback = func(string) {
+3 -3
View File
@@ -77,7 +77,7 @@ type IDisk interface {
DeleteSnapshot(snapshotId, convertSnapshot string, blockStream bool, encryptInfo apis.SEncryptInfo) error
DeployGuestFs(diskInfo *deployapi.DiskInfo, guestDesc *desc.SGuestDesc,
deployInfo *deployapi.DeployInfo) (jsonutils.JSONObject, error)
ConvertSnapshot(convertSnapshotId string, encryptInfo apis.SEncryptInfo) error
ConvertSnapshotRelyOnReloadDisk(convertSnapshotId string, encryptInfo apis.SEncryptInfo) (func() error, error)
// GetBackupDir() string
DiskBackup(ctx context.Context, params interface{}) (jsonutils.JSONObject, error)
@@ -147,8 +147,8 @@ func (d *SBaseDisk) CreateSnapshot(snapshotId string, encryptKey string, encForm
return errors.Errorf("unsupported operation")
}
func (d *SBaseDisk) ConvertSnapshot(convertSnapshotId string, encryptInfo apis.SEncryptInfo) error {
return errors.Errorf("unsupported operation")
func (d *SBaseDisk) ConvertSnapshotRelyOnReloadDisk(convertSnapshotId string, encryptInfo apis.SEncryptInfo) (func() error, error) {
return nil, errors.Errorf("unsupported operation")
}
func (d *SBaseDisk) DeleteSnapshot(snapshotId, convertSnapshot string, blockStream bool, encryptInfo apis.SEncryptInfo) error {
+5 -5
View File
@@ -511,13 +511,13 @@ func (d *SLocalDisk) CreateSnapshot(snapshotId string, encryptKey string, encFor
return nil
}
func (d *SLocalDisk) ConvertSnapshot(convertSnapshotId string, encryptInfo apis.SEncryptInfo) error {
func (d *SLocalDisk) ConvertSnapshotRelyOnReloadDisk(convertSnapshotId string, encryptInfo apis.SEncryptInfo) (func() error, error) {
snapshotDir := d.GetSnapshotDir()
snapshotPath := path.Join(snapshotDir, convertSnapshotId)
img, err := qemuimg.NewQemuImage(snapshotPath)
if err != nil {
log.Errorln(err)
return err
return nil, err
}
convertedDisk := snapshotPath + ".tmp"
if err = img.Convert2Qcow2To(convertedDisk, false, "", "", ""); err != nil {
@@ -525,13 +525,13 @@ func (d *SLocalDisk) ConvertSnapshot(convertSnapshotId string, encryptInfo apis.
if fileutils2.Exists(convertedDisk) {
os.Remove(convertedDisk)
}
return err
return nil, err
}
if output, err := procutils.NewCommand("mv", "-f", convertedDisk, snapshotPath).Output(); err != nil {
log.Errorf("mv %s to %s failed: %s, %s", convertedDisk, snapshotPath, err, output)
return err
return nil, err
}
return nil
return nil, nil
}
func (d *SLocalDisk) DeleteSnapshot(snapshotId, convertSnapshot string, blockStream bool, encryptInfo apis.SEncryptInfo) error {
+5
View File
@@ -613,6 +613,11 @@ func (d *SLVMDisk) ConvertSnapshot(convertSnapshot string, encryptInfo apis.SEnc
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)
+2 -2
View File
@@ -256,8 +256,8 @@ func (d *SRBDDisk) CreateSnapshot(snapshotId string, encryptKey string, encForma
return storage.createSnapshot(d.Id, snapshotId)
}
func (d *SRBDDisk) ConvertSnapshot(convertSnapshotId string, encryptInfo apis.SEncryptInfo) error {
return nil
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 {
+31 -11
View File
@@ -653,23 +653,27 @@ func (d *SLVMStorage) GetDisksPath() ([]string, error) {
return disksPath, nil
}
func ConvertLVMDisk(vgName, lvName string, encryptInfo apis.SEncryptInfo) error {
func ConvertLVMDiskNeedReload(vgName, lvName string, encryptInfo apis.SEncryptInfo) (func() error, error) {
return convertLVMDisk(vgName, lvName, encryptInfo)
}
func convertLVMDisk(vgName, lvName string, encryptInfo apis.SEncryptInfo) (func() error, error) {
diskPath := path.Join("/dev", vgName, lvName)
qemuImg, err := qemuimg.NewQemuImage(diskPath)
if err != nil {
log.Errorln(err)
return err
return nil, err
}
lvSize, err := lvmutils.GetLvSize(diskPath)
if err != nil {
return err
return nil, err
}
tmpVolume := lvName + "-convert.tmp"
tmpVolumePath := path.Join("/dev", vgName, tmpVolume)
// create /dev/vg/disk-convert.tmp
if err := lvmutils.LvCreate(vgName, tmpVolume, lvSize); err != nil {
return errors.Wrap(err, "delete snapshot LvCreate")
return nil, errors.Wrap(err, "delete snapshot LvCreate")
}
srcInfo := qemuimg.SImageInfo{
Path: diskPath,
@@ -692,25 +696,41 @@ func ConvertLVMDisk(vgName, lvName string, encryptInfo apis.SEncryptInfo) error
}
// convert /dev/vg/disk to /dev/vg/disk-convert.tmp
if err = qemuimg.Convert(srcInfo, destInfo, false, nil); err != nil {
lvmutils.LvRemove(tmpVolumePath)
return errors.Wrap(err, "failed convert tmp disk")
if e := lvmutils.LvRemove(tmpVolumePath); e != nil {
log.Errorf("failed remote lvm convert tmp volume %s", tmpVolumePath)
}
return nil, errors.Wrap(err, "failed convert tmp disk")
}
tmpVolume2 := lvName + "-convert.tmp2"
tmpVolume2Path := path.Join("/dev", vgName, tmpVolume2)
// rename /dev/vg/disk to /dev/vg/disk-convert.tmp2
err = lvmutils.LvRename(vgName, diskPath, tmpVolume2)
if err != nil {
return errors.Wrap(err, "failed rename disk to tmp")
return nil, errors.Wrap(err, "failed rename disk to tmp")
}
// rename /dev/vg/disk-convert.tmp to /dev/vg/disk
err = lvmutils.LvRename(vgName, tmpVolume, diskPath)
if err != nil {
return errors.Wrap(err, "failed rename tmp to disk")
return nil, errors.Wrap(err, "failed rename tmp to disk")
}
// delete /dev/vg/disk-convert.tmp2
err = lvmutils.LvRemove(tmpVolume2Path)
return func() error {
// delete /dev/vg/disk-convert.tmp2
e1 := lvmutils.LvRemove(tmpVolume2Path)
if e1 != nil {
return errors.Wrap(err, "failed remove tmp disk")
}
return nil
}, nil
}
func ConvertLVMDisk(vgName, lvName string, encryptInfo apis.SEncryptInfo) error {
delTmpVolume2Disk, err := convertLVMDisk(vgName, lvName, encryptInfo)
if err != nil {
return errors.Wrap(err, "failed remove tmp disk")
return err
}
err = delTmpVolume2Disk()
if err != nil {
return err
}
return nil
}