mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-01 15:07:17 +08:00
delete snapshots on delete disk or guest, instance snapshot fix
This commit is contained in:
@@ -81,6 +81,7 @@ func init() {
|
||||
type DiskDeleteOptions struct {
|
||||
ID []string `help:"ID of disks to delete" metavar:"DISK"`
|
||||
OverridePendingDelete bool `help:"Delete disk directly instead of pending delete" short-token:"f"`
|
||||
DeleteSnapshots bool `help:"Delete disk snapshots before delete disk"`
|
||||
}
|
||||
|
||||
R(&DiskDeleteOptions{}, "disk-delete", "Delete a disk", func(s *mcclient.ClientSession, args *DiskDeleteOptions) error {
|
||||
@@ -88,6 +89,9 @@ func init() {
|
||||
if args.OverridePendingDelete {
|
||||
params.Add(jsonutils.JSONTrue, "override_pending_delete")
|
||||
}
|
||||
if args.DeleteSnapshots {
|
||||
params.Add(jsonutils.JSONTrue, "delete_snapshots")
|
||||
}
|
||||
ret := modules.Disks.BatchDeleteWithParam(s, args.ID, params, nil)
|
||||
printBatchResults(ret, modules.Disks.GetColumns(s))
|
||||
return nil
|
||||
|
||||
@@ -190,7 +190,7 @@ func (self *SVirtualizedGuestDriver) StartGuestResetTask(guest *models.SGuest, c
|
||||
|
||||
func (self *SVirtualizedGuestDriver) RequestDeleteDetachedDisk(ctx context.Context, disk *models.SDisk, task taskman.ITask, isPurge bool) error {
|
||||
return disk.StartDiskDeleteTask(ctx, task.GetUserCred(), task.GetTaskId(), isPurge,
|
||||
jsonutils.QueryBoolean(task.GetParams(), "override_pending_delete", false))
|
||||
jsonutils.QueryBoolean(task.GetParams(), "override_pending_delete", false), false)
|
||||
}
|
||||
|
||||
func (self *SVirtualizedGuestDriver) StartGuestSyncstatusTask(guest *models.SGuest, ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
|
||||
@@ -1604,7 +1604,7 @@ func (self *SDisk) PerformPurge(ctx context.Context, userCred mcclient.TokenCred
|
||||
}
|
||||
}
|
||||
|
||||
return nil, self.StartDiskDeleteTask(ctx, userCred, "", true, false)
|
||||
return nil, self.StartDiskDeleteTask(ctx, userCred, "", true, false, false)
|
||||
}
|
||||
|
||||
func (self *SDisk) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
@@ -1620,7 +1620,8 @@ func (self *SDisk) CustomizeDelete(ctx context.Context, userCred mcclient.TokenC
|
||||
}
|
||||
|
||||
return self.StartDiskDeleteTask(ctx, userCred, "", false,
|
||||
jsonutils.QueryBoolean(query, "override_pending_delete", false))
|
||||
jsonutils.QueryBoolean(query, "override_pending_delete", false),
|
||||
jsonutils.QueryBoolean(query, "delete_snapshots", false))
|
||||
}
|
||||
|
||||
func (self *SDisk) getMoreDetails(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
@@ -1722,7 +1723,10 @@ func (self *SDisk) StartDiskResizeTask(ctx context.Context, userCred mcclient.To
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SDisk) StartDiskDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string, isPurge, overridePendingDelete bool) error {
|
||||
func (self *SDisk) StartDiskDeleteTask(
|
||||
ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string,
|
||||
isPurge, overridePendingDelete, deleteSnapshots bool,
|
||||
) error {
|
||||
params := jsonutils.NewDict()
|
||||
if isPurge {
|
||||
params.Add(jsonutils.JSONTrue, "purge")
|
||||
@@ -1730,6 +1734,9 @@ func (self *SDisk) StartDiskDeleteTask(ctx context.Context, userCred mcclient.To
|
||||
if overridePendingDelete {
|
||||
params.Add(jsonutils.JSONTrue, "override_pending_delete")
|
||||
}
|
||||
if deleteSnapshots {
|
||||
params.Add(jsonutils.JSONTrue, "delete_snapshots")
|
||||
}
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "DiskDeleteTask", self, userCred, params, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
log.Errorf("%s", err)
|
||||
@@ -1887,7 +1894,7 @@ func (manager *SDiskManager) CleanPendingDeleteDisks(ctx context.Context, userCr
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(disks); i += 1 {
|
||||
disks[i].StartDiskDeleteTask(ctx, userCred, "", false, false)
|
||||
disks[i].StartDiskDeleteTask(ctx, userCred, "", false, false, false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2205,3 +2212,17 @@ func (self *SDisk) syncSnapshots(ctx context.Context, userCred mcclient.TokenCre
|
||||
}
|
||||
return syncResult
|
||||
}
|
||||
|
||||
func (self *SDisk) GetSnapshotsNotInInstanceSnapshot() ([]SSnapshot, error) {
|
||||
snapshots := make([]SSnapshot, 0)
|
||||
sq := InstanceSnapshotJointManager.Query("snapshot_id").SubQuery()
|
||||
q := SnapshotManager.Query().IsFalse("fake_deleted")
|
||||
q = q.LeftJoin(sq, sqlchemy.Equals(q.Field("id"), sq.Field("snapshot_id"))).
|
||||
Filter(sqlchemy.IsNull(sq.Field("snapshot_id")))
|
||||
err := db.FetchModelObjects(SnapshotManager, q, &snapshots)
|
||||
if err != nil {
|
||||
log.Errorf("Fetch db snapshots failed %s", err)
|
||||
return nil, err
|
||||
}
|
||||
return snapshots, nil
|
||||
}
|
||||
|
||||
@@ -905,10 +905,13 @@ func (self *SGuest) StartSyncstatus(ctx context.Context, userCred mcclient.Token
|
||||
|
||||
func (self *SGuest) StartAutoDeleteGuestTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
db.OpsLog.LogEvent(self, db.ACT_DELETE, "auto-delete after stop", userCred)
|
||||
return self.StartDeleteGuestTask(ctx, userCred, parentTaskId, false, false)
|
||||
return self.StartDeleteGuestTask(ctx, userCred, parentTaskId, false, false, false)
|
||||
}
|
||||
|
||||
func (self *SGuest) StartDeleteGuestTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string, isPurge bool, overridePendingDelete bool) error {
|
||||
func (self *SGuest) StartDeleteGuestTask(
|
||||
ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string,
|
||||
isPurge, overridePendingDelete, deleteSnapshots bool,
|
||||
) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(self.Status), "guest_status")
|
||||
if isPurge {
|
||||
@@ -917,6 +920,9 @@ func (self *SGuest) StartDeleteGuestTask(ctx context.Context, userCred mcclient.
|
||||
if overridePendingDelete {
|
||||
params.Add(jsonutils.JSONTrue, "override_pending_delete")
|
||||
}
|
||||
if deleteSnapshots {
|
||||
params.Add(jsonutils.JSONTrue, "delete_snapshots")
|
||||
}
|
||||
self.SetStatus(userCred, api.VM_START_DELETE, "")
|
||||
return self.GetDriver().StartDeleteGuestTask(ctx, userCred, self, params, parentTaskId)
|
||||
}
|
||||
@@ -1170,7 +1176,7 @@ func (self *SGuest) PerformPurge(ctx context.Context, userCred mcclient.TokenCre
|
||||
if host != nil && host.Enabled {
|
||||
return nil, httperrors.NewInvalidStatusError("Cannot purge server on enabled host")
|
||||
}
|
||||
err = self.StartDeleteGuestTask(ctx, userCred, "", true, false)
|
||||
err = self.StartDeleteGuestTask(ctx, userCred, "", true, false, false)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1465,7 +1471,9 @@ func (self *SGuest) PerformDetachdisk(ctx context.Context, userCred mcclient.Tok
|
||||
return nil, httperrors.NewResourceNotFoundError("Disk %s not found", diskId)
|
||||
}
|
||||
|
||||
func (self *SGuest) StartGuestDetachdiskTask(ctx context.Context, userCred mcclient.TokenCredential, disk *SDisk, keepDisk bool, parentTaskId string, purge bool) error {
|
||||
func (self *SGuest) StartGuestDetachdiskTask(
|
||||
ctx context.Context, userCred mcclient.TokenCredential, disk *SDisk, keepDisk bool, parentTaskId string, purge bool,
|
||||
) error {
|
||||
taskData := jsonutils.NewDict()
|
||||
taskData.Add(jsonutils.NewString(disk.Id), "disk_id")
|
||||
taskData.Add(jsonutils.NewBool(keepDisk), "keep_disk")
|
||||
@@ -4063,3 +4071,12 @@ func (self *SGuest) GetDetailsJnlp(ctx context.Context, userCred mcclient.TokenC
|
||||
}
|
||||
return host.GetDetailsJnlp(ctx, userCred, query)
|
||||
}
|
||||
|
||||
func (guest *SGuest) StartDeleteGuestSnapshots(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "GuestDeleteSnapshotsTask", guest, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3208,13 +3208,17 @@ func (self *SGuest) AllowDeleteItem(ctx context.Context, userCred mcclient.Token
|
||||
}
|
||||
|
||||
func (self *SGuest) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
overridePendingDelete := false
|
||||
purge := false
|
||||
var (
|
||||
overridePendingDelete = false
|
||||
purge = false
|
||||
deleteSnapshots = false
|
||||
)
|
||||
if query != nil {
|
||||
overridePendingDelete = jsonutils.QueryBoolean(query, "override_pending_delete", false)
|
||||
purge = jsonutils.QueryBoolean(query, "purge", false)
|
||||
deleteSnapshots = jsonutils.QueryBoolean(query, "delete_snapshots", false)
|
||||
}
|
||||
return self.StartDeleteGuestTask(ctx, userCred, "", purge, overridePendingDelete)
|
||||
return self.StartDeleteGuestTask(ctx, userCred, "", purge, overridePendingDelete, deleteSnapshots)
|
||||
}
|
||||
|
||||
func (self *SGuest) DeleteAllDisksInDB(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
@@ -4023,7 +4027,7 @@ func (manager *SGuestManager) CleanPendingDeleteServers(ctx context.Context, use
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(guests); i += 1 {
|
||||
guests[i].StartDeleteGuestTask(ctx, userCred, "", false, true)
|
||||
guests[i].StartDeleteGuestTask(ctx, userCred, "", false, true, false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4087,7 +4091,7 @@ func (manager *SGuestManager) DeleteExpiredPrepaidServers(ctx context.Context, u
|
||||
}
|
||||
}
|
||||
guests[i].SetDisableDelete(userCred, false)
|
||||
guests[i].StartDeleteGuestTask(ctx, userCred, "", false, false)
|
||||
guests[i].StartDeleteGuestTask(ctx, userCred, "", false, false, false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4105,7 +4109,7 @@ func (manager *SGuestManager) DeleteExpiredPostpaidServers(ctx context.Context,
|
||||
}
|
||||
}
|
||||
guests[i].SetDisableDelete(userCred, false)
|
||||
guests[i].StartDeleteGuestTask(ctx, userCred, "", false, false)
|
||||
guests[i].StartDeleteGuestTask(ctx, userCred, "", false, false, false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4721,3 +4725,32 @@ func (guest *SGuest) GetDetailsRemoteNics(ctx context.Context, userCred mcclient
|
||||
// ret.Set("vnics", jsonutils.Marshal(nics))
|
||||
return jsonutils.Marshal(nics), nil
|
||||
}
|
||||
|
||||
func (self *SGuest) GetInstanceSnapshots() ([]SInstanceSnapshot, error) {
|
||||
instanceSnapshots := make([]SInstanceSnapshot, 0)
|
||||
q := InstanceSnapshotManager.Query().Equals("guest_id", self.Id)
|
||||
err := db.FetchModelObjects(InstanceSnapshotManager, q, &instanceSnapshots)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return instanceSnapshots, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) GetDiskSnapshotsNotInInstanceSnapshots() ([]SSnapshot, error) {
|
||||
guestDisks := self.GetDisks()
|
||||
diskIds := make([]string, len(guestDisks))
|
||||
for i := 0; i < len(guestDisks); i++ {
|
||||
diskIds[i] = guestDisks[i].DiskId
|
||||
}
|
||||
snapshots := make([]SSnapshot, 0)
|
||||
q := SnapshotManager.Query().IsFalse("fake_deleted").In("disk_id", diskIds)
|
||||
sq := InstanceSnapshotJointManager.Query("snapshot_id").SubQuery()
|
||||
q = q.LeftJoin(sq, sqlchemy.Equals(q.Field("id"), sq.Field("snapshot_id"))).
|
||||
Filter(sqlchemy.IsNull(sq.Field("snapshot_id")))
|
||||
err := db.FetchModelObjects(SnapshotManager, q, &snapshots)
|
||||
if err != nil {
|
||||
log.Errorf("fetch db snapshots failed %s", err)
|
||||
return nil, err
|
||||
}
|
||||
return snapshots, nil
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ func (self *SGuest) DoPerformPrepaidRecycle(ctx context.Context, userCred mcclie
|
||||
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_RECYCLE_PREPAID, self.GetShortDesc(ctx), userCred, true)
|
||||
|
||||
if autoDelete {
|
||||
self.StartDeleteGuestTask(ctx, userCred, "", false, true)
|
||||
self.StartDeleteGuestTask(ctx, userCred, "", false, true, false)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
|
||||
@@ -35,7 +35,7 @@ func (manager *SInstanceSnapshotJointManager) GetMasterFieldName() string {
|
||||
}
|
||||
|
||||
func (manager *SInstanceSnapshotJointManager) GetSlaveFieldName() string {
|
||||
return "disk_id"
|
||||
return "snapshot_id"
|
||||
}
|
||||
|
||||
var InstanceSnapshotJointManager *SInstanceSnapshotJointManager
|
||||
|
||||
@@ -67,24 +67,30 @@ func (self *SInstanceSnapshot) AllowUpdateItem(ctx context.Context, userCred mcc
|
||||
|
||||
func (self *SInstanceSnapshot) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
|
||||
extra := self.SVirtualResourceBase.GetCustomizeColumns(ctx, userCred, query)
|
||||
extra = self.getMoreDetails(extra)
|
||||
return extra
|
||||
}
|
||||
|
||||
func (self *SInstanceSnapshot) getMoreDetails(extra *jsonutils.JSONDict) *jsonutils.JSONDict {
|
||||
if guest := GuestManager.FetchGuestById(self.GuestId); guest != nil {
|
||||
extra.Set("guest_status", jsonutils.NewString(guest.Status))
|
||||
extra.Set("guest_name", jsonutils.NewString(guest.Name))
|
||||
}
|
||||
snapshots, _ := self.GetSnapshots()
|
||||
snapshotsDesc := jsonutils.NewDict()
|
||||
for i := 0; i < len(snapshots); i++ {
|
||||
snapshotsDesc.Set(snapshots[i].Id, jsonutils.NewString(snapshots[i].Name))
|
||||
}
|
||||
extra.Set("snapshots", snapshotsDesc)
|
||||
return extra
|
||||
}
|
||||
|
||||
// func (self *SInstanceSnapshot) getMoreDetails()
|
||||
|
||||
func (self *SInstanceSnapshot) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*jsonutils.JSONDict, error) {
|
||||
extra, err := self.SVirtualResourceBase.GetExtraDetails(ctx, userCred, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if guest := GuestManager.FetchGuestById(self.GuestId); guest != nil {
|
||||
extra.Set("guest_status", jsonutils.NewString(guest.Status))
|
||||
extra.Set("guest_name", jsonutils.NewString(guest.Name))
|
||||
}
|
||||
extra = self.getMoreDetails(extra)
|
||||
return extra, nil
|
||||
}
|
||||
func (self *SInstanceSnapshot) StartCreateInstanceSnapshotTask(
|
||||
@@ -209,3 +215,7 @@ func (self *SInstanceSnapshot) StartInstanceSnapshotDeleteTask(
|
||||
func (self *SInstanceSnapshot) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return db.DeleteModel(ctx, userCred, self)
|
||||
}
|
||||
|
||||
func (self *SInstanceSnapshot) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -581,7 +581,7 @@ func (self *SSnapshot) RealDelete(ctx context.Context, userCred mcclient.TokenCr
|
||||
if err == nil {
|
||||
val := disk.GetMetadata("disk_delete_after_snapshots", userCred)
|
||||
if cnt == 0 && val == "true" {
|
||||
disk.StartDiskDeleteTask(ctx, userCred, "", false, true)
|
||||
disk.StartDiskDeleteTask(ctx, userCred, "", false, true, false)
|
||||
}
|
||||
} else {
|
||||
// very unlikely
|
||||
|
||||
@@ -90,7 +90,7 @@ func (self *BaremetalConvertHypervisorTask) OnGuestDeployCompleteFailed(ctx cont
|
||||
guest := self.getGuest()
|
||||
guest.SetDisableDelete(self.UserCred, false)
|
||||
self.SetStage("OnGuestDeleteComplete", nil)
|
||||
guest.StartDeleteGuestTask(ctx, self.UserCred, self.GetTaskId(), false, true)
|
||||
guest.StartDeleteGuestTask(ctx, self.UserCred, self.GetTaskId(), false, true, false)
|
||||
logclient.AddActionLogWithStartable(self, baremetal, logclient.ACT_BM_CONVERT_HYPER, fmt.Sprintf("convert deploy failed: %s", body.String()), self.UserCred, false)
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ func (self *BaremetalUnconvertHypervisorTask) OnInit(ctx context.Context, obj db
|
||||
if len(guests) == 1 {
|
||||
guest := guests[0]
|
||||
self.SetStage("OnGuestDeleteComplete", nil)
|
||||
guest.StartDeleteGuestTask(ctx, self.UserCred, self.GetTaskId(), false, true)
|
||||
guest.StartDeleteGuestTask(ctx, self.UserCred, self.GetTaskId(), false, true, false)
|
||||
} else {
|
||||
self.OnGuestDeleteComplete(ctx, baremetal, nil)
|
||||
}
|
||||
|
||||
@@ -53,7 +53,14 @@ func (self *DiskDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel,
|
||||
db.OpsLog.LogEvent(disk, db.ACT_DELOCATE_FAIL, reason, self.UserCred)
|
||||
return
|
||||
}
|
||||
if jsonutils.QueryBoolean(self.Params, "delete_snapshots", false) {
|
||||
|
||||
} else {
|
||||
self.OnDeleteSnapshots(ctx, disk)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *DiskDeleteTask) OnDeleteSnapshots(ctx context.Context, disk *models.SDisk) {
|
||||
isPurge := jsonutils.QueryBoolean(self.Params, "purge", false)
|
||||
overridePendingDelete := jsonutils.QueryBoolean(self.Params, "override_pending_delete", false)
|
||||
if options.Options.EnablePendingDelete && !isPurge && !overridePendingDelete {
|
||||
@@ -61,6 +68,9 @@ func (self *DiskDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel,
|
||||
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)
|
||||
@@ -143,6 +153,7 @@ func (self *DiskDeleteTask) OnGuestDiskDeleteComplete(ctx context.Context, obj d
|
||||
self.SetStageComplete(ctx, nil)
|
||||
return
|
||||
}
|
||||
|
||||
disk := obj.(*models.SDisk)
|
||||
self.CleanHostSchedCache(disk)
|
||||
db.OpsLog.LogEvent(disk, db.ACT_DELOCATE, disk.GetShortDesc(ctx), self.UserCred)
|
||||
|
||||
@@ -45,7 +45,7 @@ func (self *GuestDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel
|
||||
host := guest.GetHost()
|
||||
if guest.Hypervisor == api.HYPERVISOR_BAREMETAL && host != nil && host.HostType != api.HOST_TYPE_BAREMETAL {
|
||||
// if a fake server for converted hypervisor, then just skip stop
|
||||
self.OnGuestStopComplete(ctx, obj, data)
|
||||
self.OnGuestStopComplete(ctx, guest, data)
|
||||
return
|
||||
}
|
||||
if len(guest.BackupHostId) > 0 {
|
||||
@@ -77,9 +77,29 @@ func (self *GuestDeleteTask) OnMasterHostStopGuestCompleteFailed(ctx context.Con
|
||||
self.OnGuestStopComplete(ctx, guest, nil) // ignore stop error
|
||||
}
|
||||
|
||||
func (self *GuestDeleteTask) OnGuestStopComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
func (self *GuestDeleteTask) StartDeleteGuestSnapshots(ctx context.Context, guest *models.SGuest) {
|
||||
guest.StartDeleteGuestSnapshots(ctx, self.UserCred, self.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *GuestDeleteTask) OnGuestStopComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
if jsonutils.QueryBoolean(self.Params, "delete_snapshots", false) {
|
||||
self.SetStage("OnStartEipDissociate", nil)
|
||||
guest.StartDeleteGuestSnapshots(ctx, self.UserCred, self.Id)
|
||||
return
|
||||
}
|
||||
self.OnStartEipDissociate(ctx, guest, data)
|
||||
}
|
||||
|
||||
func (self *GuestDeleteTask) OnGuestStopCompleteFailed(ctx context.Context, guest *models.SGuest, err jsonutils.JSONObject) {
|
||||
self.OnGuestStopComplete(ctx, guest, err) // ignore stop error
|
||||
}
|
||||
|
||||
func (self *GuestDeleteTask) OnStartEipDissociateFailed(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
log.Errorf("Delete guest snapshots faield: %s", data)
|
||||
self.OnStartEipDissociate(ctx, guest, nil)
|
||||
}
|
||||
|
||||
func (self *GuestDeleteTask) OnStartEipDissociate(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
eip, _ := guest.GetEip()
|
||||
if eip != nil && eip.Mode != api.EIP_MODE_INSTANCE_PUBLICIP {
|
||||
// detach floating EIP only
|
||||
@@ -92,14 +112,10 @@ func (self *GuestDeleteTask) OnGuestStopComplete(ctx context.Context, obj db.ISt
|
||||
eip.StartEipDissociateTask(ctx, self.UserCred, false, self.GetTaskId())
|
||||
}
|
||||
} else {
|
||||
self.OnEipDissociateComplete(ctx, obj, nil)
|
||||
self.OnEipDissociateComplete(ctx, guest, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *GuestDeleteTask) OnGuestStopCompleteFailed(ctx context.Context, obj db.IStandaloneModel, err jsonutils.JSONObject) {
|
||||
self.OnGuestStopComplete(ctx, obj, err) // ignore stop error
|
||||
}
|
||||
|
||||
func (self *GuestDeleteTask) OnEipDissociateCompleteFailed(ctx context.Context, obj db.IStandaloneModel, err jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
self.OnFailed(ctx, guest, err)
|
||||
@@ -117,12 +133,15 @@ func (self *GuestDeleteTask) OnDiskDetachComplete(ctx context.Context, obj db.IS
|
||||
|
||||
guestdisks := guest.GetDisks()
|
||||
if len(guestdisks) == 0 {
|
||||
// on guest disks detached
|
||||
self.doClearSecurityGroupComplete(ctx, guest)
|
||||
return
|
||||
}
|
||||
lastDisk := guestdisks[len(guestdisks)-1].GetDisk() // remove last detachable disk
|
||||
// detach last detachable disk
|
||||
lastDisk := guestdisks[len(guestdisks)-1].GetDisk()
|
||||
log.Debugf("lastDisk IsDetachable?? %v", lastDisk.IsDetachable())
|
||||
if !lastDisk.IsDetachable() {
|
||||
// no more disk need detach
|
||||
self.doClearSecurityGroupComplete(ctx, guest)
|
||||
return
|
||||
}
|
||||
@@ -238,7 +257,7 @@ func (self *GuestDeleteTask) DoDeleteGuest(ctx context.Context, guest *models.SG
|
||||
} else if (host == nil || !host.Enabled) && jsonutils.QueryBoolean(self.Params, "purge", false) {
|
||||
self.OnGuestDeleteComplete(ctx, guest, nil)
|
||||
} else {
|
||||
self.SetStage("on_guest_delete_complete", nil)
|
||||
self.SetStage("OnGuestDeleteComplete", nil)
|
||||
guest.StartUndeployGuestTask(ctx, self.UserCred, self.GetTaskId(), "")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ type GuestDiskSnapshotTask struct {
|
||||
|
||||
func (self *GuestDiskSnapshotTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
guest.SetStatus(self.UserCred, api.VM_START_SNAPSHOT, "StartDiskSnapshot")
|
||||
self.DoDiskSnapshot(ctx, guest)
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@ import (
|
||||
func init() {
|
||||
taskman.RegisterTask(SnapshotDeleteTask{})
|
||||
taskman.RegisterTask(BatchSnapshotsDeleteTask{})
|
||||
taskman.RegisterTask(GuestDeleteSnapshotsTask{})
|
||||
taskman.RegisterTask(DiskDeleteSnapshotsTask{})
|
||||
}
|
||||
|
||||
/***************************** Snapshot Delete Task *****************************/
|
||||
@@ -189,3 +191,105 @@ func (self *BatchSnapshotsDeleteTask) OnStorageDeleteSnapshot(ctx context.Contex
|
||||
}
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
type GuestDeleteSnapshotsTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func (self *GuestDeleteSnapshotsTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
instanceSnapshots, _ := guest.GetInstanceSnapshots()
|
||||
self.StartDeleteInstanceSnapshots(ctx, guest, instanceSnapshots)
|
||||
}
|
||||
|
||||
func (self *GuestDeleteSnapshotsTask) StartDeleteInstanceSnapshots(
|
||||
ctx context.Context, guest *models.SGuest, instanceSnapshots []models.SInstanceSnapshot) {
|
||||
if len(instanceSnapshots) > 0 {
|
||||
instanceSnapshot := instanceSnapshots[0]
|
||||
instanceSnapshots := instanceSnapshots[1:]
|
||||
self.Params.Set("instance_snapshots", jsonutils.Marshal(instanceSnapshots))
|
||||
self.SetStage("OnInstanceSnapshotDelete", nil)
|
||||
instanceSnapshot.SetModelManager(models.InstanceSnapshotManager, &instanceSnapshot)
|
||||
instanceSnapshot.StartInstanceSnapshotDeleteTask(ctx, self.UserCred, self.Id)
|
||||
return
|
||||
}
|
||||
snapshots, _ := guest.GetDiskSnapshotsNotInInstanceSnapshots()
|
||||
self.StartDeleteDiskSnapshots(ctx, guest, snapshots)
|
||||
}
|
||||
|
||||
func (self *GuestDeleteSnapshotsTask) OnInstanceSnapshotDelete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
instanceSnapshots := make([]models.SInstanceSnapshot, 0)
|
||||
self.Params.Unmarshal(&instanceSnapshots, "instance_snapshots")
|
||||
self.StartDeleteInstanceSnapshots(ctx, guest, instanceSnapshots)
|
||||
}
|
||||
|
||||
func (self *GuestDeleteSnapshotsTask) OnInstanceSnapshotDeleteFailed(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
log.Errorln(data.String())
|
||||
instanceSnapshots := make([]models.SInstanceSnapshot, 0)
|
||||
self.Params.Unmarshal(&instanceSnapshots, "instance_snapshots")
|
||||
self.StartDeleteInstanceSnapshots(ctx, guest, instanceSnapshots)
|
||||
}
|
||||
|
||||
func (self *GuestDeleteSnapshotsTask) StartDeleteDiskSnapshots(
|
||||
ctx context.Context, guest *models.SGuest, snapshots []models.SSnapshot) {
|
||||
if len(snapshots) > 0 {
|
||||
snapshot := snapshots[0]
|
||||
snapshots := snapshots[1:]
|
||||
self.Params.Set("snapshots", jsonutils.Marshal(snapshots))
|
||||
self.SetStage("OnSnapshotDelete", nil)
|
||||
snapshot.SetModelManager(models.SnapshotManager, &snapshot)
|
||||
snapshot.StartSnapshotDeleteTask(ctx, self.UserCred, false, self.Id)
|
||||
return
|
||||
}
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (self *GuestDeleteSnapshotsTask) OnSnapshotDelete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
snapshots := make([]models.SSnapshot, 0)
|
||||
self.Params.Unmarshal(&snapshots, "snapshots")
|
||||
self.StartDeleteDiskSnapshots(ctx, guest, snapshots)
|
||||
}
|
||||
|
||||
func (self *GuestDeleteSnapshotsTask) OnSnapshotDeleteFailed(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
log.Errorln(data.String())
|
||||
snapshots := make([]models.SSnapshot, 0)
|
||||
self.Params.Unmarshal(&snapshots, "snapshots")
|
||||
self.StartDeleteDiskSnapshots(ctx, guest, snapshots)
|
||||
}
|
||||
|
||||
type DiskDeleteSnapshotsTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func (self *DiskDeleteSnapshotsTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
disk := obj.(*models.SDisk)
|
||||
snapshots, _ := disk.GetSnapshotsNotInInstanceSnapshot()
|
||||
self.StartDeleteDiskSnapshots(ctx, disk, snapshots)
|
||||
}
|
||||
|
||||
func (self *DiskDeleteSnapshotsTask) StartDeleteDiskSnapshots(
|
||||
ctx context.Context, disk *models.SDisk, snapshots []models.SSnapshot) {
|
||||
if len(snapshots) > 0 {
|
||||
snapshot := snapshots[0]
|
||||
snapshots := snapshots[1:]
|
||||
self.Params.Set("snapshots", jsonutils.Marshal(snapshots))
|
||||
self.SetStage("OnSnapshotDelete", nil)
|
||||
snapshot.SetModelManager(models.SnapshotManager, &snapshot)
|
||||
snapshot.StartSnapshotDeleteTask(ctx, self.UserCred, false, self.Id)
|
||||
return
|
||||
}
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (self *DiskDeleteSnapshotsTask) OnSnapshotDelete(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
|
||||
snapshots := make([]models.SSnapshot, 0)
|
||||
self.Params.Unmarshal(&snapshots, "snapshots")
|
||||
self.StartDeleteDiskSnapshots(ctx, disk, snapshots)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -9,10 +9,9 @@ var (
|
||||
func init() {
|
||||
InstanceSnapshots = NewComputeManager("instance_snapshot", "instance_snapshots",
|
||||
[]string{"ID", "Name",
|
||||
"Status", "GuestId",
|
||||
"ServerConfig",
|
||||
"Status", "Guest_Id",
|
||||
},
|
||||
[]string{},
|
||||
[]string{"Guest_Name", "Snapshots"},
|
||||
)
|
||||
|
||||
registerCompute(&InstanceSnapshots)
|
||||
|
||||
@@ -468,6 +468,7 @@ func (opts *ServerUpdateOptions) Params() (*jsonutils.JSONDict, error) {
|
||||
type ServerDeleteOptions struct {
|
||||
ID []string `help:"ID of servers to operate" metavar:"SERVER" json:"-"`
|
||||
OverridePendingDelete *bool `help:"Delete server directly instead of pending delete" short-token:"f"`
|
||||
DeleteSnapshots *bool `help:"Delete server snapshots"`
|
||||
}
|
||||
|
||||
type ServerDeployOptions struct {
|
||||
|
||||
Reference in New Issue
Block a user