@@ -27,6 +27,7 @@ import (
2727 "yunion.io/x/log"
2828 "yunion.io/x/pkg/appctx"
2929 "yunion.io/x/pkg/errors"
30+ "yunion.io/x/pkg/util/qemuimgfmt"
3031 "yunion.io/x/pkg/utils"
3132
3233 "yunion.io/x/onecloud/pkg/apis"
@@ -40,6 +41,7 @@ import (
4041 "yunion.io/x/onecloud/pkg/httperrors"
4142 "yunion.io/x/onecloud/pkg/util/fileutils2"
4243 "yunion.io/x/onecloud/pkg/util/losetup"
44+ "yunion.io/x/onecloud/pkg/util/mountutils"
4345 "yunion.io/x/onecloud/pkg/util/netutils2"
4446 "yunion.io/x/onecloud/pkg/util/procutils"
4547 "yunion.io/x/onecloud/pkg/util/qemuimg"
@@ -127,6 +129,9 @@ func (d *SLocalDisk) UmountFuseImage() {
127129func (d * SLocalDisk ) Delete (ctx context.Context , params interface {}) (jsonutils.JSONObject , error ) {
128130 p := params .(api.DiskDeleteInput )
129131 dpath := d .GetPath ()
132+ if err := d .cleanLoopDevice (dpath ); err != nil {
133+ return nil , errors .Wrapf (err , "clean loop device" )
134+ }
130135 log .Infof ("Delete guest disk %s" , dpath )
131136 if err := d .Storage .DeleteDiskfile (dpath , p .SkipRecycle != nil && * p .SkipRecycle ); err != nil {
132137 return nil , err
@@ -333,6 +338,47 @@ func (d *SLocalDisk) CreateFromUrl(ctx context.Context, url string, size int64,
333338 return nil
334339}
335340
341+ func (d * SLocalDisk ) cleanLoopDevice (diskPath string ) error {
342+ diskFmt , _ := d .GetFormat ()
343+ if diskFmt != string (qemuimgfmt .RAW ) {
344+ return nil
345+ }
346+ devs , err := losetup .ListDevices ()
347+ if err != nil {
348+ return errors .Wrap (err , "list devices fail" )
349+ }
350+ dev := devs .GetDeviceByFile (diskPath )
351+ if dev == nil {
352+ return nil
353+ }
354+ drv , _ := d .GetContainerStorageDriver ()
355+ if drv == nil {
356+ return nil
357+ }
358+ devPart := fmt .Sprintf ("%sp1" , dev .Name )
359+ cmd := fmt .Sprintf ("mount | grep %s | awk '{print $3}'" , devPart )
360+ out , err := procutils .NewRemoteCommandAsFarAsPossible ("sh" , "-c" , cmd ).Output ()
361+ if err != nil {
362+ return errors .Wrapf (err , "exec cmd %s: %s" , cmd , out )
363+ }
364+ mntPoints := strings .Split (string (out ), "\n " )
365+ lastMntPoint := ""
366+ for _ , mntPoint := range mntPoints {
367+ if mntPoint == "" {
368+ continue
369+ }
370+ lastMntPoint = mntPoint
371+ if err := mountutils .Unmount (mntPoint , false ); err != nil {
372+ return errors .Wrapf (err , "umount %s" , mntPoint )
373+ }
374+ }
375+
376+ if err := drv .DisconnectDisk (diskPath , lastMntPoint ); err != nil {
377+ return errors .Wrapf (err , "DisconnectDisk(%s)" , diskPath )
378+ }
379+ return nil
380+ }
381+
336382func (d * SLocalDisk ) CreateRaw (ctx context.Context , sizeMB int , diskFormat string , fsFormat string , fsFeatures * api.DiskFsFeatures , encryptInfo * apis.SEncryptInfo , diskId string , back string ) (jsonutils.JSONObject , error ) {
337383 if fileutils2 .Exists (d .GetPath ()) {
338384 if err := os .Remove (d .GetPath ()); err != nil {
0 commit comments