From 8ef1af0dbc766d6fddae4f9a3b19760dc1f8aa34 Mon Sep 17 00:00:00 2001 From: rainzm Date: Thu, 12 Nov 2020 21:02:13 +0800 Subject: [PATCH 1/3] fix: set isp's status as 'instance_snapshot_reset' when reseting guest from isp --- pkg/apis/compute/snapshot_const.go | 1 + pkg/compute/models/guest_actions.go | 1 + pkg/compute/models/instance_snapshots.go | 4 ++-- pkg/compute/tasks/instance_snapshot_reset_task.go | 3 +++ 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pkg/apis/compute/snapshot_const.go b/pkg/apis/compute/snapshot_const.go index 6fc25c2b8a..ea78cb8a0e 100644 --- a/pkg/apis/compute/snapshot_const.go +++ b/pkg/apis/compute/snapshot_const.go @@ -49,6 +49,7 @@ const ( INSTANCE_SNAPSHOT_FAILED = "instance_snapshot_create_failed" INSTANCE_SNAPSHOT_START_DELETE = "instance_snapshot_start_delete" INSTANCE_SNAPSHOT_DELETE_FAILED = "instance_snapshot_delete_failed" + INSTANCE_SNAPSHOT_RESET = "instance_snapshot_reset" SNAPSHOT_POLICY_CACHE_STATUS_READY = "ready" SNAPSHOT_POLICY_CACHE_STATUS_DELETING = "deleting" diff --git a/pkg/compute/models/guest_actions.go b/pkg/compute/models/guest_actions.go index 9a6a688647..11ea57f45e 100644 --- a/pkg/compute/models/guest_actions.go +++ b/pkg/compute/models/guest_actions.go @@ -4730,6 +4730,7 @@ func (self *SGuest) StartSnapshotResetTask(ctx context.Context, userCred mcclien data.Set("auto_start", jsonutils.JSONTrue) } self.SetStatus(userCred, api.VM_START_SNAPSHOT_RESET, "start snapshot reset task") + instanceSnapshot.SetStatus(userCred, api.INSTANCE_SNAPSHOT_RESET, "start snapshot reset task") if task, err := taskman.TaskManager.NewTask( ctx, "InstanceSnapshotResetTask", instanceSnapshot, userCred, data, "", "", nil, ); err != nil { diff --git a/pkg/compute/models/instance_snapshots.go b/pkg/compute/models/instance_snapshots.go index 16826cd23d..38cafcb122 100644 --- a/pkg/compute/models/instance_snapshots.go +++ b/pkg/compute/models/instance_snapshots.go @@ -422,8 +422,8 @@ func (self *SInstanceSnapshot) GetInstanceSnapshotJointAt(diskIndex int) (*SInst } func (self *SInstanceSnapshot) ValidateDeleteCondition(ctx context.Context) error { - if self.Status == api.INSTANCE_SNAPSHOT_START_DELETE { - return httperrors.NewBadRequestError("can't delete snapshot in deleting") + if self.Status == api.INSTANCE_SNAPSHOT_START_DELETE || self.Status == api.INSTANCE_SNAPSHOT_RESET { + return httperrors.NewForbiddenError("can't delete instance snapshot with wrong status") } return nil } diff --git a/pkg/compute/tasks/instance_snapshot_reset_task.go b/pkg/compute/tasks/instance_snapshot_reset_task.go index 6d7bcee359..a854cb94b6 100644 --- a/pkg/compute/tasks/instance_snapshot_reset_task.go +++ b/pkg/compute/tasks/instance_snapshot_reset_task.go @@ -42,6 +42,7 @@ func (self *InstanceSnapshotResetTask) taskFail( guest = models.GuestManager.FetchGuestById(isp.GuestId) } guest.SetStatus(self.UserCred, compute.VM_SNAPSHOT_RESET_FAILED, reason.String()) + isp.SetStatus(self.UserCred, compute.INSTANCE_SNAPSHOT_READY, "") db.OpsLog.LogEvent(guest, db.ACT_VM_RESET_SNAPSHOT_FAILED, reason, self.UserCred) logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_RESET, reason, self.UserCred, false) @@ -52,6 +53,7 @@ func (self *InstanceSnapshotResetTask) taskFail( func (self *InstanceSnapshotResetTask) taskComplete( ctx context.Context, isp *models.SInstanceSnapshot, guest *models.SGuest, data jsonutils.JSONObject) { + isp.SetStatus(self.UserCred, compute.INSTANCE_SNAPSHOT_READY, "") if guest == nil { guest = models.GuestManager.FetchGuestById(isp.GuestId) } @@ -104,6 +106,7 @@ func (self *InstanceSnapshotResetTask) OnInstanceSnapshotReset(ctx context.Conte guest, _ := isp.GetGuest() if guest.Status == compute.VM_READY && jsonutils.QueryBoolean(self.Params, "auto_start", false) { self.SetStage("OnGuestStartComplete", nil) + isp.SetStatus(self.UserCred, compute.INSTANCE_SNAPSHOT_READY, "") guest.StartGueststartTask(ctx, self.UserCred, nil, self.GetTaskId()) } else { self.taskComplete(ctx, isp, guest, data) From a14b556f27885fd93ce46064779e0fe5d850440f Mon Sep 17 00:00:00 2001 From: rainzm Date: Thu, 12 Nov 2020 21:00:31 +0800 Subject: [PATCH 2/3] fix(region): start vm when 'auto_start' is true --- pkg/compute/tasks/instance_snapshot_reset_task.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/compute/tasks/instance_snapshot_reset_task.go b/pkg/compute/tasks/instance_snapshot_reset_task.go index a854cb94b6..197031032a 100644 --- a/pkg/compute/tasks/instance_snapshot_reset_task.go +++ b/pkg/compute/tasks/instance_snapshot_reset_task.go @@ -104,7 +104,7 @@ func (self *InstanceSnapshotResetTask) OnKvmDiskResetFailed( func (self *InstanceSnapshotResetTask) OnInstanceSnapshotReset(ctx context.Context, isp *models.SInstanceSnapshot, data jsonutils.JSONObject) { guest, _ := isp.GetGuest() - if guest.Status == compute.VM_READY && jsonutils.QueryBoolean(self.Params, "auto_start", false) { + if jsonutils.QueryBoolean(self.Params, "auto_start", false) { self.SetStage("OnGuestStartComplete", nil) isp.SetStatus(self.UserCred, compute.INSTANCE_SNAPSHOT_READY, "") guest.StartGueststartTask(ctx, self.UserCred, nil, self.GetTaskId()) From 781870953957e5926a325a7a8b3e42e9a72d7c00 Mon Sep 17 00:00:00 2001 From: rainzm Date: Thu, 12 Nov 2020 21:01:35 +0800 Subject: [PATCH 3/3] fix: creating esxi guest from instance snapshot --- pkg/compute/models/instance_snapshots.go | 18 +++++++++++++++--- pkg/multicloud/esxi/host.go | 4 ++-- pkg/multicloud/esxi/manager.go | 20 ++++++++++++++++++++ 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/pkg/compute/models/instance_snapshots.go b/pkg/compute/models/instance_snapshots.go index 38cafcb122..a6348da928 100644 --- a/pkg/compute/models/instance_snapshots.go +++ b/pkg/compute/models/instance_snapshots.go @@ -17,6 +17,7 @@ package models import ( "context" "database/sql" + "fmt" "yunion.io/x/jsonutils" "yunion.io/x/log" @@ -361,16 +362,25 @@ func (self *SInstanceSnapshot) ToInstanceCreateInput( return nil, errors.Wrap(err, "unmarshal sched input") } - if len(self.ExternalId) > 0 { + cp := self.GetCloudprovider() + if cp == nil { + return nil, fmt.Errorf("unable to get cloudprovider of isp %q", self.GetId()) + } + if cp.Provider != api.CLOUD_PROVIDER_VMWARE { isjs := make([]SInstanceSnapshotJoint, 0) err := InstanceSnapshotJointManager.Query().Equals("instance_snapshot_id", self.Id).Asc("disk_index").All(&isjs) if err != nil { return nil, errors.Wrap(err, "fetch instance snapshots") } + for i := 0; i < len(serverConfig.Disks); i++ { - serverConfig.Disks[i].SnapshotId = isjs[serverConfig.Disks[i].Index].SnapshotId + index := serverConfig.Disks[i].Index + if index < len(isjs) { + serverConfig.Disks[i].SnapshotId = isjs[index].SnapshotId + } } } + sourceInput.Disks = serverConfig.Disks if sourceInput.VmemSize == 0 { sourceInput.VmemSize = serverConfig.Memory @@ -394,7 +404,9 @@ func (self *SInstanceSnapshot) ToInstanceCreateInput( } sourceInput.OsType = self.OsType sourceInput.InstanceType = self.InstanceType - sourceInput.Networks = serverConfig.Networks + if len(sourceInput.Networks) == 0 { + sourceInput.Networks = serverConfig.Networks + } return sourceInput, nil } diff --git a/pkg/multicloud/esxi/host.go b/pkg/multicloud/esxi/host.go index f5a19ce1ec..1c080c92ef 100644 --- a/pkg/multicloud/esxi/host.go +++ b/pkg/multicloud/esxi/host.go @@ -727,9 +727,9 @@ type SEsxiImageInfo struct { func (self *SHost) CreateVM2(ctx context.Context, ds *SDatastore, params SCreateVMParam) (*SVirtualMachine, error) { if len(params.InstanceSnapshotInfo.InstanceSnapshotId) > 0 { - temvm, err := self.manager.SearchTemplateVM(params.InstanceSnapshotInfo.InstanceId) + temvm, err := self.manager.SearchVM(params.InstanceSnapshotInfo.InstanceId) if err != nil { - return nil, errors.Wrapf(err, "SEsxiClient.SearchTemplateVM for image %q", params.InstanceSnapshotInfo.InstanceId) + return nil, errors.Wrapf(err, "SEsxiClient.SearchVM for image %q", params.InstanceSnapshotInfo.InstanceId) } isp, err := temvm.GetInstanceSnapshot(params.InstanceSnapshotInfo.InstanceSnapshotId) if err != nil { diff --git a/pkg/multicloud/esxi/manager.go b/pkg/multicloud/esxi/manager.go index e2fe25adef..b2177dc7be 100644 --- a/pkg/multicloud/esxi/manager.go +++ b/pkg/multicloud/esxi/manager.go @@ -349,6 +349,26 @@ func (cli *SESXiClient) scanAllMObjects(props []string, dst interface{}) error { return cli.scanMObjects(cli.client.ServiceContent.RootFolder, props, dst) } +func (cli *SESXiClient) SearchVM(id string) (*SVirtualMachine, error) { + filter := property.Filter{} + filter["summary.config.uuid"] = id + var movms []mo.VirtualMachine + err := cli.scanMObjectsWithFilter(cli.client.ServiceContent.RootFolder, VIRTUAL_MACHINE_PROPS, &movms, filter) + if err != nil { + return nil, err + } + if len(movms) == 0 { + return nil, errors.ErrNotFound + } + vm := NewVirtualMachine(cli, &movms[0], nil) + dc, err := vm.fetchDatacenter() + if err != nil { + return nil, errors.Wrap(err, "fetchDatacenter") + } + vm.datacenter = dc + return vm, nil +} + func (cli *SESXiClient) SearchTemplateVM(id string) (*SVirtualMachine, error) { filter := property.Filter{} uuid := toTemplateUuid(id)