diff --git a/pkg/compute/models/guests.go b/pkg/compute/models/guests.go index 09940bd3bc..7c0f3f7327 100644 --- a/pkg/compute/models/guests.go +++ b/pkg/compute/models/guests.go @@ -1669,6 +1669,10 @@ func (self *SGuest) getMaxDiskIndex() int8 { return int8(len(guestdisks)) } +func (self *SGuest) AttachDisk(disk *SDisk, userCred mcclient.TokenCredential, driver string, cache string, mountpoint string) error { + return self.attach2Disk(disk, userCred, driver, cache, mountpoint) +} + func (self *SGuest) attach2Disk(disk *SDisk, userCred mcclient.TokenCredential, driver string, cache string, mountpoint string) error { if self.isAttach2Disk(disk) { return fmt.Errorf("Guest has been attached to disk") diff --git a/pkg/compute/tasks/guest_detach_disk_task.go b/pkg/compute/tasks/guest_detach_disk_task.go index 0a6653750f..abbe01ea0e 100644 --- a/pkg/compute/tasks/guest_detach_disk_task.go +++ b/pkg/compute/tasks/guest_detach_disk_task.go @@ -26,20 +26,30 @@ func (self *GuestDetachDiskTask) OnInit(ctx context.Context, obj db.IStandaloneM diskId, _ := self.Params.GetString("disk_id") objDisk, err := models.DiskManager.FetchById(diskId) if err != nil { - self.OnTaskFail(ctx, guest, err) + self.OnTaskFail(ctx, guest, nil, err) return } disk := objDisk.(*models.SDisk) if disk == nil { - self.OnTaskFail(ctx, guest, fmt.Errorf("Connot find disk %s", diskId)) + self.OnTaskFail(ctx, guest, nil, fmt.Errorf("Connot find disk %s", diskId)) return } + guestdisks := disk.GetGuestdisks() + if len(guestdisks) > 0 { + guestdisk := guestdisks[0] + self.Params.Add(jsonutils.NewString(guestdisk.Driver), "driver") + self.Params.Add(jsonutils.NewString(guestdisk.CacheMode), "cache") + self.Params.Add(jsonutils.NewString(guestdisk.Mountpoint), "mountpoint") + } + guest.DetachDisk(ctx, disk, self.UserCred) if disk.Status == models.DISK_INIT { self.OnSyncConfigComplete(ctx, guest, nil) return } + disk.SetStatus(self.UserCred, models.DISK_DETACHING, "Disk detach") + host := guest.GetHost() purge := false if host != nil && host.Status == models.HOST_DISABLED && jsonutils.QueryBoolean(self.Params, "purge", false) { @@ -47,13 +57,12 @@ func (self *GuestDetachDiskTask) OnInit(ctx context.Context, obj db.IStandaloneM } detachStatus, err := guest.GetDriver().GetDetachDiskStatus() if err != nil { - self.OnTaskFail(ctx, guest, err) + self.OnTaskFail(ctx, guest, disk, err) return } if utils.IsInStringArray(guest.Status, detachStatus) && !purge { self.SetStage("on_sync_config_complete", nil) guest.GetDriver().RequestDetachDisk(ctx, guest, self) - disk.SetStatus(self.UserCred, models.DISK_READY, "Disk detach") } else { self.OnSyncConfigComplete(ctx, guest, nil) } @@ -63,14 +72,15 @@ func (self *GuestDetachDiskTask) OnSyncConfigComplete(ctx context.Context, guest diskId, _ := self.Params.GetString("disk_id") objDisk, err := models.DiskManager.FetchById(diskId) if err != nil { - self.OnTaskFail(ctx, guest, err) + self.OnTaskFail(ctx, guest, nil, err) return } disk := objDisk.(*models.SDisk) if disk == nil { - self.OnTaskFail(ctx, guest, fmt.Errorf("Connot find disk %s", diskId)) + self.OnTaskFail(ctx, guest, nil, fmt.Errorf("Connot find disk %s", diskId)) return } + disk.SetDiskReady(ctx, self.UserCred, "") keepDisk := jsonutils.QueryBoolean(self.Params, "keep_disk", true) host := guest.GetHost() purge := false @@ -81,12 +91,14 @@ func (self *GuestDetachDiskTask) OnSyncConfigComplete(ctx context.Context, guest db.OpsLog.LogEvent(disk, db.ACT_DELETE, "", self.UserCred) disk.RealDelete(ctx, self.UserCred) self.SetStageComplete(ctx, nil) - } else if (disk.Status == models.DISK_READY || !keepDisk) && disk.GetGuestDiskCount() == 0 && disk.AutoDelete { + return + } + if !keepDisk && disk.GetGuestDiskCount() == 0 && disk.AutoDelete { self.SetStage("on_disk_delete_complete", nil) db.OpsLog.LogEvent(disk, db.ACT_DELETE, "", self.UserCred) err := guest.GetDriver().RequestDeleteDetachedDisk(ctx, disk, self, purge) if err != nil { - self.OnTaskFail(ctx, guest, err) + self.OnTaskFail(ctx, guest, disk, err) return } } else { @@ -94,7 +106,31 @@ func (self *GuestDetachDiskTask) OnSyncConfigComplete(ctx context.Context, guest } } -func (self *GuestDetachDiskTask) OnTaskFail(ctx context.Context, guest *models.SGuest, err error) { +func (self *GuestDetachDiskTask) OnSyncConfigCompleteFailed(ctx context.Context, obj db.IStandaloneModel, resion jsonutils.JSONObject) { + guest := obj.(*models.SGuest) + driver, _ := self.Params.GetString("driver") + cache, _ := self.Params.GetString("cache") + mountpoint, _ := self.Params.GetString("mountpoint") + diskId, _ := self.Params.GetString("disk_id") + objDisk, err := models.DiskManager.FetchById(diskId) + if err != nil { + self.OnTaskFail(ctx, guest, nil, err) + return + } + disk := objDisk.(*models.SDisk) + db.OpsLog.LogEvent(disk, db.ACT_DETACH, resion.String(), self.UserCred) + disk.SetDiskReady(ctx, self.UserCred, "") + err = guest.AttachDisk(disk, self.UserCred, driver, cache, mountpoint) + if err != nil { + self.OnTaskFail(ctx, guest, disk, err) + return + } +} + +func (self *GuestDetachDiskTask) OnTaskFail(ctx context.Context, guest *models.SGuest, disk *models.SDisk, err error) { + if disk != nil { + disk.SetDiskReady(ctx, self.UserCred, "") + } self.SetStageFailed(ctx, err.Error()) log.Errorf("Guest %s GuestDetachDiskTask failed %s", guest.Id, err.Error()) }