From 6979430f8c8c841fecec68f1a928ed2174a7e587 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Fri, 15 Nov 2019 02:32:37 +0800 Subject: [PATCH] fix: baremetal server rebuild root fail to cache image --- pkg/apis/compute/guests.go | 38 +++++++ pkg/compute/guestdrivers/baremetals.go | 11 ++- pkg/compute/models/guest_actions.go | 51 ++++++---- .../baremetal_server_rebuild_root_task.go | 99 ------------------- pkg/compute/tasks/guest_rebuild_root_task.go | 8 +- 5 files changed, 82 insertions(+), 125 deletions(-) create mode 100644 pkg/apis/compute/guests.go delete mode 100644 pkg/compute/tasks/baremetal_server_rebuild_root_task.go diff --git a/pkg/apis/compute/guests.go b/pkg/apis/compute/guests.go new file mode 100644 index 0000000000..c655827e03 --- /dev/null +++ b/pkg/apis/compute/guests.go @@ -0,0 +1,38 @@ +package compute + +import ( + "yunion.io/x/onecloud/pkg/apis" +) + +type ServerRebuildRootInput struct { + apis.Meta + + Image string `json:"image"` + ImageId string `json:"image_id"` + Keypair string `json:"keypair"` + KeypairId string `json:"keypair_id"` + ResetPassword *bool `json:"reset_password"` + Password string `json:"password"` + AutoStart *bool `json:"auto_start"` + AllDisks *bool `json:"all_disks"` +} + +func (i ServerRebuildRootInput) GetImageName() string { + if len(i.Image) > 0 { + return i.Image + } + if len(i.ImageId) > 0 { + return i.ImageId + } + return "" +} + +func (i ServerRebuildRootInput) GetKeypairName() string { + if len(i.Keypair) > 0 { + return i.Keypair + } + if len(i.KeypairId) > 0 { + return i.KeypairId + } + return "" +} diff --git a/pkg/compute/guestdrivers/baremetals.go b/pkg/compute/guestdrivers/baremetals.go index 9128295ed1..0f27a330c5 100644 --- a/pkg/compute/guestdrivers/baremetals.go +++ b/pkg/compute/guestdrivers/baremetals.go @@ -258,7 +258,7 @@ func (self *SBaremetalGuestDriver) RequestGuestCreateAllDisks(ctx context.Contex if storageCache == nil { return fmt.Errorf("no valid storage cache") } - return storageCache.StartImageCacheTask(ctx, task.GetUserCred(), imageId, diskCat.Root.DiskFormat, false, task.GetTaskId()) + return storageCache.StartImageCacheTask(ctx, task.GetUserCred(), imageId, "qcow2", false, task.GetTaskId()) } func (self *SBaremetalGuestDriver) NeedRequestGuestHotAddIso(ctx context.Context, guest *models.SGuest) bool { @@ -401,6 +401,15 @@ func (self *SBaremetalGuestDriver) GetGuestVncInfo(ctx context.Context, userCred return data, nil } +func (self *SBaremetalGuestDriver) RequestRebuildRootDisk(ctx context.Context, guest *models.SGuest, task taskman.ITask) error { + subtask, err := taskman.TaskManager.NewTask(ctx, "ManagedGuestRebuildRootTask", guest, task.GetUserCred(), task.GetParams(), task.GetTaskId(), "", nil) + if err != nil { + return err + } + subtask.ScheduleRun(nil) + return nil +} + func (self *SBaremetalGuestDriver) PerformStart(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, data *jsonutils.JSONDict) error { return guest.StartGueststartTask(ctx, userCred, data, "") } diff --git a/pkg/compute/models/guest_actions.go b/pkg/compute/models/guest_actions.go index 30c62eb5fa..c44635f80d 100644 --- a/pkg/compute/models/guest_actions.go +++ b/pkg/compute/models/guest_actions.go @@ -36,6 +36,7 @@ import ( billing_api "yunion.io/x/onecloud/pkg/apis/billing" api "yunion.io/x/onecloud/pkg/apis/compute" + imageapi "yunion.io/x/onecloud/pkg/apis/image" schedapi "yunion.io/x/onecloud/pkg/apis/scheduler" "yunion.io/x/onecloud/pkg/cloudcommon/cmdline" "yunion.io/x/onecloud/pkg/cloudcommon/db" @@ -1279,13 +1280,26 @@ func (self *SGuest) AllowPerformRebuildRoot(ctx context.Context, userCred mcclie } func (self *SGuest) PerformRebuildRoot(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { - imageId, _ := data.GetString("image_id") + input := api.ServerRebuildRootInput{} + err := data.Unmarshal(&input) + if err != nil { + return nil, httperrors.NewInputParameterError("invalid input: %s", err) + } + + imageId := input.GetImageName() if len(imageId) > 0 { img, err := CachedimageManager.getImageInfo(ctx, userCred, imageId, false) if err != nil { return nil, httperrors.NewNotFoundError("failed to find %s", imageId) } + diskCat := self.CategorizeDisks() + if img.MinDiskMB == 0 || img.Status != imageapi.IMAGE_STATUS_ACTIVE { + return nil, httperrors.NewInputParameterError("invlid image") + } + if img.MinDiskMB > diskCat.Root.DiskSize { + return nil, httperrors.NewInputParameterError("image size exceeds root disk size") + } osType, _ := img.Properties["os_type"] osName := self.GetMetadata("os_name", userCred) if len(osName) == 0 && len(osType) == 0 && strings.ToLower(osType) != strings.ToLower(osName) { @@ -1313,20 +1327,26 @@ func (self *SGuest) PerformRebuildRoot(ctx context.Context, userCred mcclient.To return nil, httperrors.NewInvalidStatusError("Cannot reset root in status %s", self.Status) } - autoStart := jsonutils.QueryBoolean(data, "auto_start", false) + autoStart := false + if input.AutoStart != nil { + autoStart = *input.AutoStart + } var needStop = false if self.Status == api.VM_RUNNING { needStop = true } - resetPasswd := jsonutils.QueryBoolean(data, "reset_password", true) - passwd, _ := data.GetString("password") + resetPasswd := true + if input.ResetPassword != nil { + resetPasswd = *input.ResetPassword + } + passwd := input.Password if len(passwd) > 0 { if !seclib2.MeetComplxity(passwd) { return nil, httperrors.NewWeakPasswordError() } } - keypairStr := jsonutils.GetAnyString(data, []string{"keypair", "keypair_id"}) + keypairStr := input.GetKeypairName() if len(keypairStr) > 0 { keypairObj, err := KeypairManager.FetchByIdOrName(userCred, keypairStr) if err != nil { @@ -1350,7 +1370,10 @@ func (self *SGuest) PerformRebuildRoot(ctx context.Context, userCred mcclient.To } } - allDisks := jsonutils.QueryBoolean(data, "all_disks", false) + allDisks := false + if input.AllDisks != nil { + allDisks = *input.AllDisks + } return nil, self.StartRebuildRootTask(ctx, userCred, imageId, needStop, autoStart, passwd, resetPasswd, allDisks) } @@ -1393,19 +1416,11 @@ func (self *SGuest) StartRebuildRootTask(ctx context.Context, userCred mcclient. data.Set("all_disks", jsonutils.JSONFalse) } self.SetStatus(userCred, api.VM_REBUILD_ROOT, "request start rebuild root") - if self.GetHypervisor() == api.HYPERVISOR_BAREMETAL { - task, err := taskman.TaskManager.NewTask(ctx, "BaremetalServerRebuildRootTask", self, userCred, data, "", "", nil) - if err != nil { - return err - } - task.ScheduleRun(nil) - } else { - task, err := taskman.TaskManager.NewTask(ctx, "GuestRebuildRootTask", self, userCred, data, "", "", nil) - if err != nil { - return err - } - task.ScheduleRun(nil) + task, err := taskman.TaskManager.NewTask(ctx, "GuestRebuildRootTask", self, userCred, data, "", "", nil) + if err != nil { + return err } + task.ScheduleRun(nil) return nil } diff --git a/pkg/compute/tasks/baremetal_server_rebuild_root_task.go b/pkg/compute/tasks/baremetal_server_rebuild_root_task.go deleted file mode 100644 index 5bcc0bae2e..0000000000 --- a/pkg/compute/tasks/baremetal_server_rebuild_root_task.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2019 Yunion -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tasks - -import ( - "context" - "fmt" - - "yunion.io/x/jsonutils" - - api "yunion.io/x/onecloud/pkg/apis/compute" - "yunion.io/x/onecloud/pkg/cloudcommon/db" - "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" - "yunion.io/x/onecloud/pkg/compute/models" - "yunion.io/x/onecloud/pkg/util/logclient" -) - -type BaremetalServerRebuildRootTask struct { - SGuestBaseTask -} - -func init() { - taskman.RegisterTask(BaremetalServerRebuildRootTask{}) -} - -func (self *BaremetalServerRebuildRootTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) { - guest := obj.(*models.SGuest) - if jsonutils.QueryBoolean(self.Params, "need_stop", false) { - self.SetStage("OnStopServerComplete", nil) - guest.StartGuestStopTask(ctx, self.UserCred, false, self.GetTaskId()) - return - } - self.StartRebuildRootDisk(ctx, guest) -} - -func (self *BaremetalServerRebuildRootTask) OnStopServerComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) { - self.StartRebuildRootDisk(ctx, guest) -} - -func (self *BaremetalServerRebuildRootTask) StartRebuildRootDisk(ctx context.Context, guest *models.SGuest) { - if guest.Status != api.VM_ADMIN { - guest.SetStatus(self.UserCred, api.VM_REBUILD_ROOT, "") - } - imageId, _ := self.Params.GetString("image_id") - db.OpsLog.LogEvent(guest, db.ACT_REBUILDING_ROOT, imageId, self.UserCred) - gds := guest.CategorizeDisks() - oldStatus := gds.Root.Status - _, err := db.Update(gds.Root, func() error { - gds.Root.TemplateId = imageId - gds.Root.Status = api.DISK_REBUILD - return nil - }) - if err != nil { - self.SetStageFailed(ctx, err.Error()) - logclient.AddActionLogWithStartable(self, guest, logclient.ACT_VM_REBUILD, err, self.UserCred, false) - return - } else { - db.OpsLog.LogEvent(gds.Root, db.ACT_UPDATE_STATUS, - fmt.Sprintf("%s=>%s", oldStatus, api.DISK_REBUILD), self.UserCred) - } - self.SetStage("OnRebuildRootDiskComplete", nil) - - // clear logininfo - loginParams := make(map[string]interface{}) - loginParams["login_account"] = "none" - loginParams["login_key"] = "none" - loginParams["login_key_timestamp"] = "none" - guest.SetAllMetadata(ctx, loginParams, self.UserCred) - guest.StartGuestDeployTask(ctx, self.UserCred, self.Params, "rebuild", self.GetTaskId()) -} - -func (self *BaremetalServerRebuildRootTask) OnRebuildRootDiskComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) { - db.OpsLog.LogEvent(guest, db.ACT_REBUILD_ROOT, "", self.UserCred) - self.SetStage("OnSyncStatusComplete", nil) - guest.StartSyncstatus(ctx, self.UserCred, self.GetTaskId()) -} - -func (self *BaremetalServerRebuildRootTask) OnRebuildRootDiskCompleteFailed(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) { - db.OpsLog.LogEvent(guest, db.ACT_REBUILD_ROOT_FAIL, data, self.UserCred) - if guest.Status != api.VM_ADMIN { - guest.SetStatus(self.UserCred, api.VM_REBUILD_ROOT_FAIL, "") - } -} - -func (self *BaremetalServerRebuildRootTask) OnSyncStatusComplete(ctx context.Context, _ *models.SGuest, _ jsonutils.JSONObject) { - self.SetStageComplete(ctx, nil) -} diff --git a/pkg/compute/tasks/guest_rebuild_root_task.go b/pkg/compute/tasks/guest_rebuild_root_task.go index f3346a00fc..642cb0cffd 100644 --- a/pkg/compute/tasks/guest_rebuild_root_task.go +++ b/pkg/compute/tasks/guest_rebuild_root_task.go @@ -236,14 +236,8 @@ type ManagedGuestRebuildRootTask struct { func (self *ManagedGuestRebuildRootTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) { guest := obj.(*models.SGuest) - diskCat := guest.CategorizeDisks() - imageId := diskCat.Root.GetTemplateId() - format := diskCat.Root.DiskFormat - storage := diskCat.Root.GetStorage() - cache := storage.GetStoragecache() - self.SetStage("OnHostCacheImageComplete", nil) - cache.StartImageCacheTask(ctx, self.UserCred, imageId, format, false, self.GetTaskId()) + guest.GetDriver().RequestGuestCreateAllDisks(ctx, guest, self) } func (self *ManagedGuestRebuildRootTask) OnHostCacheImageComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {