From fa077dbe9b0939353f60055e450a8e6e113ef3b5 Mon Sep 17 00:00:00 2001 From: wanyaoqi Date: Tue, 5 Jan 2021 15:13:56 +0800 Subject: [PATCH] feat(region): stop guest before freeze --- pkg/cloudcommon/db/opslog_const.go | 5 ++-- pkg/compute/models/guest_actions.go | 21 +++++++++++++++ pkg/compute/tasks/guest_stop_task.go | 39 ++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/pkg/cloudcommon/db/opslog_const.go b/pkg/cloudcommon/db/opslog_const.go index 4bde5e7169..61a707152d 100644 --- a/pkg/cloudcommon/db/opslog_const.go +++ b/pkg/cloudcommon/db/opslog_const.go @@ -47,8 +47,9 @@ const ( ACT_BACKUP_START = "backup_start" ACT_BACKUP_START_FAILED = "backup_start_fail" - ACT_FREEZE = "freeze" - ACT_UNFREEZE = "unfreeze" + ACT_FREEZE = "freeze" + ACT_FREEZE_FAIL = "freeze_fail" + ACT_UNFREEZE = "unfreeze" ACT_RESTARING = "restarting" ACT_RESTART_FAIL = "restart_fail" diff --git a/pkg/compute/models/guest_actions.go b/pkg/compute/models/guest_actions.go index 226c3e2e68..da137ee79e 100644 --- a/pkg/compute/models/guest_actions.go +++ b/pkg/compute/models/guest_actions.go @@ -2770,6 +2770,27 @@ func (self *SGuest) PerformStop(ctx context.Context, userCred mcclient.TokenCred return nil, httperrors.NewInvalidStatusError("Cannot stop server in status %s", self.Status) } +func (self *SGuest) PerformFreeze(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformFreezeInput) (jsonutils.JSONObject, error) { + if self.Freezed { + return nil, httperrors.NewBadRequestError("virtual resource already freezed") + } + if utils.IsInStringArray(self.Status, []string{api.VM_RUNNING, api.VM_STOP_FAILED}) { + return nil, self.StartGuestStopAndFreezeTask(ctx, userCred) + } else { + return self.SVirtualResourceBase.PerformFreeze(ctx, userCred, query, input) + } +} + +func (self *SGuest) StartGuestStopAndFreezeTask(ctx context.Context, userCred mcclient.TokenCredential) error { + self.SetStatus(userCred, api.VM_START_STOP, "") + task, err := taskman.TaskManager.NewTask(ctx, "GuestStopAndFreezeTask", self, userCred, nil, "", "", nil) + if err != nil { + return err + } + task.ScheduleRun(nil) + return nil +} + func (self *SGuest) AllowPerformRestart(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, diff --git a/pkg/compute/tasks/guest_stop_task.go b/pkg/compute/tasks/guest_stop_task.go index 36afb479a2..7093129250 100644 --- a/pkg/compute/tasks/guest_stop_task.go +++ b/pkg/compute/tasks/guest_stop_task.go @@ -20,6 +20,7 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/log" + "yunion.io/x/onecloud/pkg/apis" api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" @@ -33,6 +34,7 @@ type GuestStopTask struct { func init() { taskman.RegisterTask(GuestStopTask{}) + taskman.RegisterTask(GuestStopAndFreezeTask{}) } func (self *GuestStopTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) { @@ -80,3 +82,40 @@ func (self *GuestStopTask) OnGuestStopTaskCompleteFailed(ctx context.Context, gu self.SetStageFailed(ctx, reason) logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_STOP, reason.String(), self.UserCred, false) } + +type GuestStopAndFreezeTask struct { + SGuestBaseTask +} + +func (self *GuestStopAndFreezeTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) { + guest := obj.(*models.SGuest) + self.SetStage("OnStopGuest", nil) + err := guest.StartGuestStopTask(ctx, self.UserCred, false, false, self.GetTaskId()) + if err != nil { + self.OnStopGuestFailed(ctx, guest, jsonutils.NewString(err.Error())) + } +} + +func (self *GuestStopAndFreezeTask) OnStopGuestFailed(ctx context.Context, guest *models.SGuest, reason jsonutils.JSONObject) { + db.OpsLog.LogEvent(guest, db.ACT_FREEZE_FAIL, reason.String(), self.UserCred) + self.SetStageFailed(ctx, reason) +} + +func (self *GuestStopAndFreezeTask) OnStopGuest(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) { + self.SetStage("OnSyncStatus", nil) + guest.StartSyncstatus(ctx, self.UserCred, self.GetTaskId()) +} + +func (self *GuestStopAndFreezeTask) OnSyncStatus(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) { + _, err := guest.SVirtualResourceBase.PerformFreeze(ctx, self.UserCred, nil, apis.PerformFreezeInput{}) + if err != nil { + self.OnStopGuestFailed(ctx, guest, jsonutils.NewString(err.Error())) + return + } + self.SetStageComplete(ctx, nil) +} + +func (self *GuestStopAndFreezeTask) OnSyncStatusFailed(ctx context.Context, guest *models.SGuest, reason jsonutils.JSONObject) { + db.OpsLog.LogEvent(guest, db.ACT_FREEZE_FAIL, reason.String(), self.UserCred) + self.SetStageFailed(ctx, reason) +}