diff --git a/pkg/compute/models/disks.go b/pkg/compute/models/disks.go index 01dc34c9c4..bf7e921869 100644 --- a/pkg/compute/models/disks.go +++ b/pkg/compute/models/disks.go @@ -1782,14 +1782,23 @@ func (self *SDisk) PerformPurge(ctx context.Context, userCred mcclient.TokenCred } func (self *SDisk) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error { - provider := self.GetCloudprovider() - if provider != nil && provider.Provider == api.CLOUD_PROVIDER_HUAWEI { - cnt, err := self.GetSnapshotCount() - if err != nil { - return httperrors.NewInternalServerError("GetSnapshotCount fail %s", err) - } - if cnt > 0 { - return httperrors.NewForbiddenError("not allow to delete. Virtual disk must not have snapshots") + if !jsonutils.QueryBoolean(query, "delete_snapshots", false) { + if provider := self.GetCloudprovider(); provider != nil && provider.Provider == api.CLOUD_PROVIDER_HUAWEI { + cnt, err := self.GetSnapshotCount() + if err != nil { + return httperrors.NewInternalServerError("GetSnapshotCount fail %s", err) + } + if cnt > 0 { + return httperrors.NewForbiddenError("not allow to delete. Virtual disk must not have snapshots") + } + } else if storage := self.GetStorage(); storage != nil && storage.StorageType == api.STORAGE_RBD { + scnt, err := self.GetSnapshotCount() + if err != nil { + return err + } + if scnt > 0 { + return httperrors.NewBadRequestError("not allow to delete %s disk with snapshots", storage.StorageType) + } } } @@ -2230,6 +2239,16 @@ func (self *SDisk) StartCreateBackupTask(ctx context.Context, userCred mcclient. return nil } +func (self *SDisk) DeleteSnapshots(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error { + if task, err := taskman.TaskManager.NewTask(ctx, "DiskDeleteSnapshotsTask", self, userCred, nil, parentTaskId, "", nil); err != nil { + log.Errorln(err) + return err + } else { + task.ScheduleRun(nil) + } + return nil +} + func (self *SDisk) SaveRenewInfo(ctx context.Context, userCred mcclient.TokenCredential, bc *billing.SBillingCycle, expireAt *time.Time) error { _, err := db.Update(self, func() error { if self.BillingType != billing_api.BILLING_TYPE_PREPAID { diff --git a/pkg/compute/tasks/disk_delete_task.go b/pkg/compute/tasks/disk_delete_task.go index 291312e09c..da88f34ecd 100644 --- a/pkg/compute/tasks/disk_delete_task.go +++ b/pkg/compute/tasks/disk_delete_task.go @@ -26,6 +26,7 @@ import ( "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" "yunion.io/x/onecloud/pkg/compute/models" "yunion.io/x/onecloud/pkg/compute/options" + "yunion.io/x/onecloud/pkg/util/logclient" ) type DiskDeleteTask struct { @@ -54,7 +55,8 @@ func (self *DiskDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, return } if jsonutils.QueryBoolean(self.Params, "delete_snapshots", false) { - + self.SetStage("OnDiskSnapshotDelete", nil) + self.StartDeleteDiskSnapshots(ctx, disk) } else { self.OnDeleteSnapshots(ctx, disk) } @@ -68,15 +70,25 @@ func (self *DiskDeleteTask) OnDeleteSnapshots(ctx context.Context, disk *models. self.SetStageComplete(ctx, nil) return } - if jsonutils.QueryBoolean(self.Params, "delete_sanpshots", false) { - disk.SetMetadata(ctx, "__delete_snapshots_on_delete", "true", self.UserCred) - } self.startPendingDeleteDisk(ctx, disk) } else { self.startDeleteDisk(ctx, disk) } } +func (self *DiskDeleteTask) StartDeleteDiskSnapshots(ctx context.Context, disk *models.SDisk) { + disk.DeleteSnapshots(ctx, self.UserCred, self.GetId()) +} + +func (self *DiskDeleteTask) OnDiskSnapshotDelete(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) { + self.OnDeleteSnapshots(ctx, disk) +} + +func (self *DiskDeleteTask) OnDiskSnapshotDeleteFailed(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) { + log.Errorf("Delete disk snapshots failed %s", data.String()) + self.OnGuestDiskDeleteCompleteFailed(ctx, disk, data) +} + func (self *DiskDeleteTask) startDeleteDisk(ctx context.Context, disk *models.SDisk) { db.OpsLog.LogEvent(disk, db.ACT_DELOCATING, disk.GetShortDesc(ctx), self.UserCred) if disk.Status == api.DISK_INIT { @@ -169,6 +181,7 @@ func (self *DiskDeleteTask) OnGuestDiskDeleteCompleteFailed(ctx context.Context, disk.SetStatus(self.GetUserCred(), api.DISK_DEALLOC_FAILED, reason.String()) self.SetStageFailed(ctx, reason.String()) db.OpsLog.LogEvent(disk, db.ACT_DELOCATE_FAIL, disk.GetShortDesc(ctx), self.GetUserCred()) + logclient.AddActionLogWithContext(ctx, disk, logclient.ACT_DELOCATE, reason, self.UserCred, false) } type StorageDeleteRbdDiskTask struct { diff --git a/pkg/compute/tasks/snapshot_delete_task.go b/pkg/compute/tasks/snapshot_delete_task.go index 6688c5ed18..c6ada5d351 100644 --- a/pkg/compute/tasks/snapshot_delete_task.go +++ b/pkg/compute/tasks/snapshot_delete_task.go @@ -288,8 +288,6 @@ func (self *DiskDeleteSnapshotsTask) OnSnapshotDelete(ctx context.Context, disk } func (self *DiskDeleteSnapshotsTask) OnSnapshotDeleteFailed(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) { - log.Errorln(data.String()) - snapshots := make([]models.SSnapshot, 0) - self.Params.Unmarshal(&snapshots, "snapshots") - self.StartDeleteDiskSnapshots(ctx, disk, snapshots) + log.Errorf("Delete disk snapshots failed %s", data.String()) + self.SetStageFailed(ctx, data.String()) }