From 9ad7b469773bba697350aee75ce32c8ff4398e1d Mon Sep 17 00:00:00 2001 From: wanyaoqi Date: Tue, 23 Apr 2019 16:03:59 +0800 Subject: [PATCH] rbd disk add auto migrate on start, if mem not enough --- pkg/compute/models/guest_actions.go | 34 ++++++++++++++++++- pkg/compute/models/hosts.go | 8 +++++ pkg/compute/tasks/guest_start_task.go | 49 +++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) diff --git a/pkg/compute/models/guest_actions.go b/pkg/compute/models/guest_actions.go index 3b0079979f..05ed23e17b 100644 --- a/pkg/compute/models/guest_actions.go +++ b/pkg/compute/models/guest_actions.go @@ -798,7 +798,39 @@ func (self *SGuest) StartInsertIsoTask(ctx context.Context, imageId string, host return nil } -func (self *SGuest) StartGueststartTask(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, parentTaskId string) error { +func (self *SGuest) IsDisksShared() bool { + return self.getDefaultStorageType() == api.STORAGE_RBD +} + +func (self *SGuest) StartGueststartTask( + ctx context.Context, userCred mcclient.TokenCredential, + data *jsonutils.JSONDict, parentTaskId string, +) error { + if self.Hypervisor == api.HYPERVISOR_KVM && self.IsDisksShared() { + return self.GuestSchedStartTask(ctx, userCred, data, parentTaskId) + } else { + return self.GuestNonSchedStartTask(ctx, userCred, data, parentTaskId) + } +} + +func (self *SGuest) GuestSchedStartTask( + ctx context.Context, userCred mcclient.TokenCredential, + data *jsonutils.JSONDict, parentTaskId string, +) error { + self.SetStatus(userCred, api.VM_SCHEDULE, "") + task, err := taskman.TaskManager.NewTask(ctx, "GuestSchedStartTask", self, userCred, data, + parentTaskId, "", nil) + if err != nil { + return err + } + task.ScheduleRun(nil) + return nil +} + +func (self *SGuest) GuestNonSchedStartTask( + ctx context.Context, userCred mcclient.TokenCredential, + data *jsonutils.JSONDict, parentTaskId string, +) error { self.SetStatus(userCred, api.VM_START_START, "") task, err := taskman.TaskManager.NewTask(ctx, "GuestStartTask", self, userCred, data, parentTaskId, "", nil) if err != nil { diff --git a/pkg/compute/models/hosts.go b/pkg/compute/models/hosts.go index 5a8c53e1b7..1c9b0bbfbd 100644 --- a/pkg/compute/models/hosts.go +++ b/pkg/compute/models/hosts.go @@ -1215,6 +1215,14 @@ func (self *SHost) GetRunningGuestCount() (int, error) { return q.CountWithError() } +func (self *SHost) GetRunningGuestMemorySize() int { + res := self.getGuestsResource(api.VM_RUNNING) + if res != nil { + return res.GuestVmemSize + } + return -1 +} + func (self *SHost) GetBaremetalnetworksQuery() *sqlchemy.SQuery { return HostnetworkManager.Query().Equals("baremetal_id", self.Id) } diff --git a/pkg/compute/tasks/guest_start_task.go b/pkg/compute/tasks/guest_start_task.go index 00f0e6402e..f3bfffe050 100644 --- a/pkg/compute/tasks/guest_start_task.go +++ b/pkg/compute/tasks/guest_start_task.go @@ -154,3 +154,52 @@ func (self *GuestStartTask) taskComplete(ctx context.Context, guest *models.SGue models.HostManager.ClearSchedDescCache(guest.HostId) self.SetStageComplete(ctx, nil) } + +type GuestSchedStartTask struct { + SGuestBaseTask +} + +func (self *GuestSchedStartTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) { + guest := obj.(*models.SGuest) + self.StartScheduler(ctx, guest) +} + +func (self *GuestSchedStartTask) StartScheduler(ctx context.Context, guest *models.SGuest) { + host := guest.GetHost() + if guestsMem := host.GetRunningGuestMemorySize(); guestsMem < 0 { + self.TaskFailed(ctx, guest, "Guest Start Failed: Can't Get Host Guests Memory") + } else { + if float32(guestsMem+guest.VmemSize) > host.GetVirtualMemorySize() { + self.ScheduleFailed(ctx, guest) + } else { + self.ScheduleSucc(ctx, guest) + } + } +} + +func (self *GuestSchedStartTask) ScheduleFailed(ctx context.Context, guest *models.SGuest) { + self.SetStage("OnGuestMigrate", nil) + guest.StartMigrateTask(ctx, self.UserCred, false, false, guest.Status, "", self.GetId()) +} + +func (self *GuestSchedStartTask) OnGuestMigrate(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) { + self.SetStageComplete(ctx, nil) + guest.GuestNonSchedStartTask(ctx, self.UserCred, nil, "") +} + +func (self *GuestSchedStartTask) OnGuestMigrateFailed(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) { + self.TaskFailed(ctx, guest, fmt.Sprintf("OnGuestMigrateFailed %s", data)) +} + +func (self *GuestSchedStartTask) ScheduleSucc(ctx context.Context, guest *models.SGuest) { + self.SetStageComplete(ctx, nil) + guest.GuestNonSchedStartTask(ctx, self.UserCred, nil, "") +} + +func (self *GuestSchedStartTask) TaskFailed(ctx context.Context, guest *models.SGuest, reason string) { + self.SetStageFailed(ctx, reason) + guest.SetStatus(self.UserCred, api.VM_START_FAILED, reason) + db.OpsLog.LogEvent(guest, db.ACT_START_FAIL, reason, self.UserCred) + logclient.AddActionLogWithStartable( + self, guest, logclient.ACT_VM_START, reason, self.UserCred, false) +}