diff --git a/cmd/climc/shell/compute/servers.go b/cmd/climc/shell/compute/servers.go index 77a90f6d12..b37e392f1d 100644 --- a/cmd/climc/shell/compute/servers.go +++ b/cmd/climc/shell/compute/servers.go @@ -728,6 +728,7 @@ func init() { type ServerRollBackSnapshot struct { ID string `help:"ID or name of VM" json:"-"` InstanceSnapshot string `help:"Instance snapshot id or name" json:"instance_snapshot"` + AutoStart bool `help:"Auto start VM"` } R(&ServerRollBackSnapshot{}, "instance-snapshot-reset", "reset instance snapshot", func(s *mcclient.ClientSession, opts *ServerRollBackSnapshot) error { params := jsonutils.Marshal(opts) diff --git a/pkg/apis/compute/guests.go b/pkg/apis/compute/guests.go index e791a7d6d5..8f1d0ec590 100644 --- a/pkg/apis/compute/guests.go +++ b/pkg/apis/compute/guests.go @@ -432,3 +432,9 @@ type ServerDissociateEipInput struct { // 是否自动释放 AudoDelete *bool `json:"auto_delete"` } + +type ServerResetInput struct { + InstanceSnapshot string `json:"instance_snapshot"` + // 自动启动 + AutoStart *bool `json:"auto_start"` +} diff --git a/pkg/compute/models/guest_actions.go b/pkg/compute/models/guest_actions.go index 156720a7c4..9a6a688647 100644 --- a/pkg/compute/models/guest_actions.go +++ b/pkg/compute/models/guest_actions.go @@ -50,7 +50,6 @@ import ( "yunion.io/x/onecloud/pkg/cloudcommon/notifyclient" "yunion.io/x/onecloud/pkg/cloudcommon/policy" "yunion.io/x/onecloud/pkg/cloudcommon/userdata" - "yunion.io/x/onecloud/pkg/cloudcommon/validators" "yunion.io/x/onecloud/pkg/compute/options" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" @@ -4699,28 +4698,24 @@ func (self *SGuest) AllowPerformInstanceSnapshotReset(ctx context.Context, return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "instance-snapshot") } -func (self *SGuest) PerformInstanceSnapshotReset( - ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject, -) (jsonutils.JSONObject, error) { +func (self *SGuest) PerformInstanceSnapshotReset(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.ServerResetInput) (jsonutils.JSONObject, error) { if self.Status != api.VM_READY { return nil, httperrors.NewInvalidStatusError("guest can't do snapshot in status %s", self.Status) } - dataDict := data.(*jsonutils.JSONDict) - instanceSnapshotV := validators.NewModelIdOrNameValidator( - "instance_snapshot", "instance_snapshot", self.GetOwnerId(), - ) - err := instanceSnapshotV.Validate(dataDict) + obj, err := InstanceSnapshotManager.FetchByIdOrName(userCred, input.InstanceSnapshot) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "unable to fetch instance snapshot %q", input.InstanceSnapshot) } - instanceSnapshot := instanceSnapshotV.Model.(*SInstanceSnapshot) + + instanceSnapshot := obj.(*SInstanceSnapshot) + if instanceSnapshot.Status != api.INSTANCE_SNAPSHOT_READY { return nil, httperrors.NewBadRequestError("Instance sanpshot not ready") } - err = self.StartSnapshotResetTask(ctx, userCred, instanceSnapshot) + err = self.StartSnapshotResetTask(ctx, userCred, instanceSnapshot, input.AutoStart) if err != nil { return nil, httperrors.NewInternalServerError("start snapshot reset failed %s", err) } @@ -4728,12 +4723,15 @@ func (self *SGuest) PerformInstanceSnapshotReset( return nil, nil } -func (self *SGuest) StartSnapshotResetTask( - ctx context.Context, userCred mcclient.TokenCredential, instanceSnapshot *SInstanceSnapshot) error { +func (self *SGuest) StartSnapshotResetTask(ctx context.Context, userCred mcclient.TokenCredential, instanceSnapshot *SInstanceSnapshot, autoStart *bool) error { + data := jsonutils.NewDict() + if autoStart != nil && *autoStart { + data.Set("auto_start", jsonutils.JSONTrue) + } self.SetStatus(userCred, api.VM_START_SNAPSHOT_RESET, "start snapshot reset task") if task, err := taskman.TaskManager.NewTask( - ctx, "InstanceSnapshotResetTask", instanceSnapshot, userCred, nil, "", "", nil, + ctx, "InstanceSnapshotResetTask", instanceSnapshot, userCred, data, "", "", nil, ); err != nil { return err } else { diff --git a/pkg/compute/tasks/instance_snapshot_reset_task.go b/pkg/compute/tasks/instance_snapshot_reset_task.go index 83d5dcd480..6d7bcee359 100644 --- a/pkg/compute/tasks/instance_snapshot_reset_task.go +++ b/pkg/compute/tasks/instance_snapshot_reset_task.go @@ -102,9 +102,19 @@ func (self *InstanceSnapshotResetTask) OnKvmDiskResetFailed( func (self *InstanceSnapshotResetTask) OnInstanceSnapshotReset(ctx context.Context, isp *models.SInstanceSnapshot, data jsonutils.JSONObject) { guest, _ := isp.GetGuest() - self.taskComplete(ctx, isp, guest, data) + if guest.Status == compute.VM_READY && jsonutils.QueryBoolean(self.Params, "auto_start", false) { + self.SetStage("OnGuestStartComplete", nil) + guest.StartGueststartTask(ctx, self.UserCred, nil, self.GetTaskId()) + } else { + self.taskComplete(ctx, isp, guest, data) + } } func (self *InstanceSnapshotResetTask) OnInstanceSnapshotResetFailed(ctx context.Context, isp *models.SInstanceSnapshot, data jsonutils.JSONObject) { self.taskFail(ctx, isp, nil, data) } + +func (self *InstanceSnapshotResetTask) OnGuestStartComplete(ctx context.Context, isp *models.SInstanceSnapshot, data jsonutils.JSONObject) { + guest, _ := isp.GetGuest() + self.taskComplete(ctx, isp, guest, data) +}