Skip to content

Commit 61963c5

Browse files
authored
fix(host): slvm create from snapshot (#25265)
1 parent c2fbb42 commit 61963c5

10 files changed

Lines changed: 135 additions & 12 deletions

File tree

pkg/apis/compute/guest_disk.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ type GuestdiskJsonDesc struct {
9090
Index int8 `json:"index"`
9191
BootIndex *int8 `json:"boot_index"`
9292
MergeSnapshot bool `json:"merge_snapshot"`
93+
SnapshotId string `json:"snapshot_id"`
9394
Fs string `json:"fs"`
9495
Mountpoint string `json:"mountpoint"`
9596
Dev string `json:"dev"`

pkg/compute/models/guestdisks.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ func (self *SGuestdisk) GetDiskJsonDescAtHost(ctx context.Context, host *SHost,
237237
desc.Url = url
238238
}
239239
}
240+
desc.SnapshotId = disk.SnapshotId
240241
}
241242
if fpath := disk.GetMetadata(ctx, api.DISK_META_REMOTE_ACCESS_PATH, nil); len(fpath) > 0 {
242243
guest := self.getGuest()

pkg/hostman/guestman/qemu-kvm.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,7 @@ func (s *SKVMGuestInstance) eventBlockJobReady(event *monitor.Event) {
12141214
return
12151215
}
12161216
var diskId, diskPath, diskUrl string
1217+
var mergeSnapshotId string
12171218
var mergeSnapshots bool
12181219
for i := 0; i < len(disks); i++ {
12191220
index := disks[i].Index
@@ -1222,6 +1223,7 @@ func (s *SKVMGuestInstance) eventBlockJobReady(event *monitor.Event) {
12221223
diskPath = disks[i].Path
12231224
diskUrl = disks[i].Url
12241225
mergeSnapshots = disks[i].MergeSnapshot
1226+
mergeSnapshotId = disks[i].SnapshotId
12251227
}
12261228
}
12271229
if len(diskId) == 0 {
@@ -1235,7 +1237,7 @@ func (s *SKVMGuestInstance) eventBlockJobReady(event *monitor.Event) {
12351237
return
12361238
}
12371239
if mergeSnapshots {
1238-
disk.PostCreateFromRemoteHostImage(diskUrl)
1240+
disk.PostCreateFromRemoteHostImage(diskUrl, mergeSnapshotId)
12391241
}
12401242
blockJobCount := s.BlockJobsCount()
12411243
if blockJobCount == 0 {
@@ -2165,7 +2167,7 @@ func (s *SKVMGuestInstance) delTmpDisks(ctx context.Context, migrated bool) erro
21652167
}
21662168
}
21672169
if d != nil && disk.MergeSnapshot {
2168-
d.PostCreateFromRemoteHostImage(disk.Url)
2170+
d.PostCreateFromRemoteHostImage(disk.Url, disk.SnapshotId)
21692171
}
21702172
if migrated {
21712173
if d != nil && utils.IsInStringArray(d.GetType(), []string{api.STORAGE_SLVM, api.STORAGE_CLVM}) {
@@ -2931,7 +2933,7 @@ func (s *SKVMGuestInstance) streamDisksComplete(ctx context.Context) {
29312933
if disks[i].MergeSnapshot {
29322934
if d != nil {
29332935
log.Infof("Disk %s do post create from fuse", d.GetId())
2934-
d.PostCreateFromRemoteHostImage(disks[i].Url)
2936+
d.PostCreateFromRemoteHostImage(disks[i].Url, disks[i].SnapshotId)
29352937
}
29362938

29372939
disks[i].MergeSnapshot = false

pkg/hostman/storageman/disk_base.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ type IDisk interface {
7272
CreateFromRbdSnapshot(ctx context.Context, snapshotId, srcDiskId, srcPool string) error
7373
CreateFromRemoteHostImage(ctx context.Context, url string, size int64, encryptInfo *apis.SEncryptInfo) error
7474
CreateRaw(ctx context.Context, sizeMb int, diskFormat string, fsFormat string, fsFeatures *api.DiskFsFeatures, encryptInfo *apis.SEncryptInfo, diskId string, back string) (jsonutils.JSONObject, error)
75-
PostCreateFromRemoteHostImage(diskUrl string)
75+
PostCreateFromRemoteHostImage(diskUrl string, snapshotId string)
7676
CreateSnapshot(snapshotId string, encryptKey string, encFormat qemuimg.TEncryptFormat, encAlg seclib2.TSymEncAlg) error
7777
DeleteSnapshot(snapshotId, convertSnapshot string, blockStream bool, encryptInfo apis.SEncryptInfo) error
7878
DeployGuestFs(diskInfo *deployapi.DiskInfo, guestDesc *desc.SGuestDesc,
@@ -179,7 +179,7 @@ func (d *SBaseDisk) RebuildSlaveDisk(diskUri string) error {
179179
return nil
180180
}
181181

182-
func (d *SBaseDisk) PostCreateFromRemoteHostImage(string) {
182+
func (d *SBaseDisk) PostCreateFromRemoteHostImage(string, string) {
183183
}
184184

185185
func (d *SBaseDisk) GetZoneId() string {

pkg/hostman/storageman/disk_local.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ func (d *SLocalDisk) GetDiskSetupScripts(diskIndex int) string {
458458
return cmd
459459
}
460460

461-
func (d *SLocalDisk) PostCreateFromRemoteHostImage(diskUrl string) {
461+
func (d *SLocalDisk) PostCreateFromRemoteHostImage(diskUrl string, snapshotId string) {
462462
if diskUrl != "" {
463463
if err := d.RequestCloseNbdImage(context.Background(), diskUrl); err != nil {
464464
log.Errorf("failed request close nbd image %s: %s", diskUrl, err)

pkg/hostman/storageman/disk_lvm.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ func (d *SLVMDisk) Delete(ctx context.Context, params interface{}) (jsonutils.JS
176176
return nil, nil
177177
}
178178

179-
func (d *SLVMDisk) PostCreateFromRemoteHostImage(diskUrl string) {
179+
func (d *SLVMDisk) PostCreateFromRemoteHostImage(diskUrl string, snapshotId string) {
180180
if diskUrl != "" {
181181
if err := d.RequestCloseNbdImage(context.Background(), diskUrl); err != nil {
182182
log.Errorf("failed request close nbd image %s: %s", diskUrl, err)

pkg/hostman/storageman/disk_rbd.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ func (d *SRBDDisk) CreateRaw(ctx context.Context, sizeMb int, diskFormat string,
237237
return d.GetDiskDesc(), nil
238238
}
239239

240-
func (d *SRBDDisk) PostCreateFromRemoteHostImage(string) {
240+
func (d *SRBDDisk) PostCreateFromRemoteHostImage(string, string) {
241241
log.Errorf("Not support PostCreateFromRemoteHostImage")
242242
}
243243

pkg/hostman/storageman/disk_slvm.go

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,6 @@ func (d *SSLVMDisk) CreateSnapshot(snapshotId string, encryptKey string, encForm
225225
return nil
226226
}
227227

228-
func (d *SSLVMDisk) PostCreateFromRemoteHostImage(string) {
229-
log.Infof("slvm post create from fuse do nothing")
230-
}
231-
232228
func (d *SSLVMDisk) ResetFromSnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
233229
err := lvmutils.LVActive(d.GetPath(), false, d.Storage.Lvmlockd())
234230
if err != nil {
@@ -304,6 +300,43 @@ func (d *SSLVMDisk) CreateFromSnapshotLocation(ctx context.Context, snapshotLoca
304300
return ret, nil
305301
}
306302

303+
func (d *SSLVMDisk) PostCreateFromRemoteHostImage(diskUrl string, snapshotId string) {
304+
if len(snapshotId) == 0 {
305+
return
306+
}
307+
snapshotPath := d.GetSnapshotPath(snapshotId)
308+
309+
curPath := snapshotPath
310+
for {
311+
if !fileutils2.Exists(curPath) {
312+
break
313+
}
314+
if inUse, err := lvmutils.IsDeviceInUse(curPath); inUse {
315+
log.Errorf("slvm PostCreateFromRemoteHostImage %s inuse", curPath)
316+
break
317+
} else if err != nil {
318+
log.Errorf("slvm PostCreateFromRemoteHostImage failed check device %s is inuse: %s", curPath, err)
319+
break
320+
}
321+
322+
img, err := qemuimg.NewQemuImage(curPath)
323+
if err != nil {
324+
log.Errorf("failed open qemu image %s: %s", curPath, err)
325+
break
326+
}
327+
backPath := img.BackFilePath
328+
if err := lvmutils.LVDeactivate(curPath); err != nil {
329+
log.Errorf("failed deactivate lv %s: %s", curPath, err)
330+
break
331+
}
332+
if len(backPath) == 0 || strings.HasPrefix(path.Base(backPath), IMAGECACHE_PREFIX) {
333+
break
334+
} else {
335+
curPath = backPath
336+
}
337+
}
338+
}
339+
307340
func (d *SSLVMDisk) DeleteSnapshot(snapshotId, convertSnapshot string, blockStream bool, encryptInfo apis.SEncryptInfo) error {
308341
err := lvmutils.LVActive(d.GetPath(), false, d.Storage.Lvmlockd())
309342
if err != nil {

pkg/hostman/storageman/lvmutils/lvmutils.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@ package lvmutils
1717
import (
1818
"encoding/json"
1919
"fmt"
20+
"io/ioutil"
21+
"os"
22+
"path/filepath"
2023
"strconv"
2124
"strings"
25+
"syscall"
2226

2327
"yunion.io/x/log"
2428
"yunion.io/x/pkg/errors"
@@ -328,3 +332,53 @@ func GetLvSize(lvPath string) (int64, error) {
328332
}
329333
return size, nil
330334
}
335+
336+
func IsDeviceInUse(devPath string) (bool, error) {
337+
fi, err := os.Stat(devPath)
338+
if err != nil {
339+
return false, fmt.Errorf("stat %s: %w", devPath, err)
340+
}
341+
stat, ok := fi.Sys().(*syscall.Stat_t)
342+
if !ok {
343+
return false, fmt.Errorf("cannot get raw stat")
344+
}
345+
targetDev := uint64(stat.Rdev)
346+
347+
procEntries, err := ioutil.ReadDir("/proc")
348+
if err != nil {
349+
return false, fmt.Errorf("read /proc: %w", err)
350+
}
351+
352+
for _, entry := range procEntries {
353+
if !entry.IsDir() {
354+
continue
355+
}
356+
_, err := strconv.Atoi(entry.Name())
357+
if err != nil {
358+
continue
359+
}
360+
361+
fdDir := filepath.Join("/proc", entry.Name(), "fd")
362+
fds, err := ioutil.ReadDir(fdDir)
363+
if err != nil {
364+
continue
365+
}
366+
367+
for _, fd := range fds {
368+
fdPath := filepath.Join(fdDir, fd.Name())
369+
fdInfo, err := os.Stat(fdPath)
370+
if err != nil {
371+
continue
372+
}
373+
fdStat, ok := fdInfo.Sys().(*syscall.Stat_t)
374+
if !ok {
375+
continue
376+
}
377+
if uint64(fdStat.Rdev) == targetDev {
378+
return true, nil
379+
}
380+
}
381+
}
382+
383+
return false, nil
384+
}

pkg/hostman/storageman/storage_slvm.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import (
2525
api "yunion.io/x/onecloud/pkg/apis/compute"
2626
"yunion.io/x/onecloud/pkg/hostman/hostutils"
2727
"yunion.io/x/onecloud/pkg/hostman/storageman/lvmutils"
28+
"yunion.io/x/onecloud/pkg/util/fileutils2"
29+
"yunion.io/x/onecloud/pkg/util/qemuimg"
2830
)
2931

3032
func init() {
@@ -104,6 +106,36 @@ func (s *SSLVMStorage) GetDiskById(diskId string) (IDisk, error) {
104106

105107
func (s *SSLVMStorage) CreateDiskFromSnapshot(ctx context.Context, disk IDisk, input *SDiskCreateByDiskinfo) (jsonutils.JSONObject, error) {
106108
snapshotLocation := disk.GetSnapshotPath(input.DiskInfo.SnapshotId)
109+
var activedPath = []string{}
110+
var diskPath = snapshotLocation
111+
var err error
112+
var img *qemuimg.SQemuImage
113+
for {
114+
if !fileutils2.Exists(diskPath) {
115+
err = lvmutils.LVActive(diskPath, s.lvmlockd, false)
116+
if err != nil {
117+
log.Errorf("lvactive %s failed: %s", diskPath, err)
118+
break
119+
}
120+
activedPath = append(activedPath, diskPath)
121+
}
122+
img, err = qemuimg.NewQemuImage(diskPath)
123+
if err != nil {
124+
log.Errorf("failed open qemu image: %s, %s", diskPath, err)
125+
break
126+
}
127+
if len(img.BackFilePath) > 0 {
128+
diskPath = img.BackFilePath
129+
} else {
130+
break
131+
}
132+
}
133+
if err != nil {
134+
for _, apath := range activedPath {
135+
lvmutils.LVDeactivate(apath)
136+
}
137+
return nil, err
138+
}
107139

108140
return disk.CreateFromSnapshotLocation(ctx, snapshotLocation, int64(input.DiskInfo.DiskSizeMb), &input.DiskInfo.EncryptInfo)
109141
}

0 commit comments

Comments
 (0)