From 75cc892bf7d0900bbafee3644267d034b6e959b1 Mon Sep 17 00:00:00 2001 From: wanyaoqi <18528551+wanyaoqi@users.noreply.github.com> Date: Fri, 26 Jun 2026 10:20:37 +0800 Subject: [PATCH] fix(region,host): kvm guest change disk driver reset uefi vars (#25069) --- cmd/climc/shell/compute/serverdisks.go | 4 --- cmd/climc/shell/compute/servers.go | 1 + pkg/apis/compute/guests.go | 5 +++ pkg/compute/guestdrivers/base.go | 4 +++ pkg/compute/guestdrivers/kvm.go | 12 +++++++ pkg/compute/models/guest_actions.go | 34 +++++++++++++++++++ pkg/compute/models/guestdisks.go | 2 +- pkg/compute/models/guestdrivers.go | 2 ++ .../guestman/guesthandlers/guesthandler.go | 6 ++++ pkg/hostman/guestman/guestman.go | 21 ++++++++++++ pkg/mcclient/options/compute/servers.go | 10 ++++++ 11 files changed, 96 insertions(+), 5 deletions(-) diff --git a/cmd/climc/shell/compute/serverdisks.go b/cmd/climc/shell/compute/serverdisks.go index 0c587bf674..41152b84e6 100644 --- a/cmd/climc/shell/compute/serverdisks.go +++ b/cmd/climc/shell/compute/serverdisks.go @@ -77,16 +77,12 @@ func init() { type ServerDiskUpdateOptions struct { SERVER string `help:"ID or Name of server"` DISK string `help:"ID or Name of Disk"` - Driver string `help:"Driver of vDisk" choices:"virtio|ide|sata|scsi|pvscsi"` Cache string `help:"Cache mode of vDisk" choices:"writethrough|none|writeback|directsync"` Aio string `help:"Asynchronous IO mode of vDisk" choices:"native|threads"` Index int64 `help:"Index of vDisk" default:"-1"` } R(&ServerDiskUpdateOptions{}, "server-disk-update", "Update details of a virtual disk of a virtual server", func(s *mcclient.ClientSession, args *ServerDiskUpdateOptions) error { params := jsonutils.NewDict() - if len(args.Driver) > 0 { - params.Add(jsonutils.NewString(args.Driver), "driver") - } if len(args.Cache) > 0 { params.Add(jsonutils.NewString(args.Cache), "cache_mode") } diff --git a/cmd/climc/shell/compute/servers.go b/cmd/climc/shell/compute/servers.go index fd1496e30a..130c400968 100644 --- a/cmd/climc/shell/compute/servers.go +++ b/cmd/climc/shell/compute/servers.go @@ -158,6 +158,7 @@ func init() { cmd.Perform("set-network-secgroup", new(options.ServerNetworkSecGroupsOptions)) cmd.Perform("add-network-secgroup", new(options.ServerNetworkSecGroupsOptions)) cmd.Perform("revoke-network-secgroup", new(options.ServerNetworkSecGroupsOptions)) + cmd.Perform("change-disk-driver", new(options.ServerChangeDiskDriverOptions)) cmd.GetProperty(&options.ServerStatusStatisticsOptions{}) cmd.GetProperty(&options.ServerProjectStatisticsOptions{}) diff --git a/pkg/apis/compute/guests.go b/pkg/apis/compute/guests.go index 43fa2b43f9..78d71b8266 100644 --- a/pkg/apis/compute/guests.go +++ b/pkg/apis/compute/guests.go @@ -1065,6 +1065,11 @@ type ServerChangeDiskStorageInput struct { KeepOriginDisk bool `json:"keep_origin_disk"` } +type ServerChangeDiskDriverInput struct { + DiskId string `json:"disk_id"` + Driver string `json:"driver"` +} + type ServerChangeDiskStorageInternalInput struct { ServerChangeDiskStorageInput StorageId string `json:"storage_id"` diff --git a/pkg/compute/guestdrivers/base.go b/pkg/compute/guestdrivers/base.go index f679aec67d..6e34a43d5a 100644 --- a/pkg/compute/guestdrivers/base.go +++ b/pkg/compute/guestdrivers/base.go @@ -478,6 +478,10 @@ func (drv *SBaseGuestDriver) RequestChangeDiskStorage(ctx context.Context, userC return cloudprovider.ErrNotImplemented } +func (drv *SBaseGuestDriver) RequestResetUefiFirmwareVars(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest) error { + return nil +} + func (drv *SBaseGuestDriver) RequestSwitchToTargetStorageDisk(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, input *api.ServerChangeDiskStorageInternalInput, task taskman.ITask) error { return cloudprovider.ErrNotImplemented } diff --git a/pkg/compute/guestdrivers/kvm.go b/pkg/compute/guestdrivers/kvm.go index fe1cbe6a70..6be55cd571 100644 --- a/pkg/compute/guestdrivers/kvm.go +++ b/pkg/compute/guestdrivers/kvm.go @@ -958,6 +958,18 @@ func (self *SKVMGuestDriver) RequestChangeDiskStorage(ctx context.Context, userC return err } +func (self *SKVMGuestDriver) RequestResetUefiFirmwareVars(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest) error { + host, err := guest.GetHost() + if err != nil { + return err + } + body := jsonutils.NewDict() + header := mcclient.GetTokenHeaders(userCred) + url := fmt.Sprintf("%s/servers/%s/reset-uefi-vars", host.ManagerUri, guest.GetId()) + _, _, err = httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, body, false) + return err +} + func (self *SKVMGuestDriver) RequestSwitchToTargetStorageDisk(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, input *api.ServerChangeDiskStorageInternalInput, task taskman.ITask) error { host, err := guest.GetHost() if err != nil { diff --git a/pkg/compute/models/guest_actions.go b/pkg/compute/models/guest_actions.go index 99102eb771..81779842f2 100644 --- a/pkg/compute/models/guest_actions.go +++ b/pkg/compute/models/guest_actions.go @@ -6648,6 +6648,40 @@ func (self *SGuest) StartGuestChangeStorageTask(ctx context.Context, userCred mc return nil } +func (self *SGuest) PerformChangeDiskDriver(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input *api.ServerChangeDiskDriverInput) (jsonutils.JSONObject, error) { + if self.Status != api.VM_READY { + return nil, httperrors.NewInvalidStatusError("can't change disk driver in guest status %s", self.Status) + } + gd := self.GetGuestDisk(input.DiskId) + if gd == nil { + return nil, httperrors.NewBadRequestError("failed get guest disk by disk id %s", input.DiskId) + } + if input.Driver == gd.Driver { + return nil, nil + } + if !utils.IsInStringArray(input.Driver, []string{api.DISK_DRIVER_VIRTIO, api.DISK_DRIVER_PVSCSI, api.DISK_DRIVER_IDE, api.DISK_DRIVER_SCSI}) { + return nil, httperrors.NewInputParameterError("unknown driver %s", input.Driver) + } + _, err := db.Update(gd, func() error { + gd.Driver = input.Driver + return nil + }) + if err != nil { + return nil, errors.Wrap(err, "failed update disk driver") + } + if self.Bios == api.VM_BOOT_MODE_UEFI { + drv, err := self.GetDriver() + if err != nil { + return nil, err + } + err = drv.RequestResetUefiFirmwareVars(ctx, userCred, self) + if err != nil { + return nil, errors.Wrap(err, "failed reset uefi fw vars") + } + } + return nil, nil +} + func (self *SGuest) PerformChangeDiskStorage(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input *api.ServerChangeDiskStorageInput) (*api.ServerChangeDiskStorageInput, error) { // validate input if input.DiskId == "" { diff --git a/pkg/compute/models/guestdisks.go b/pkg/compute/models/guestdisks.go index 55c9592d22..9f3d98755a 100644 --- a/pkg/compute/models/guestdisks.go +++ b/pkg/compute/models/guestdisks.go @@ -65,7 +65,7 @@ type SGuestdisk struct { ImagePath string `width:"256" charset:"ascii" nullable:"false" get:"user" create:"required"` // Column(VARCHAR(256, charset='ascii'), nullable=False) - Driver string `width:"32" charset:"ascii" nullable:"true" list:"user" update:"user"` // Column(VARCHAR(32, charset='ascii'), nullable=True) + Driver string `width:"32" charset:"ascii" nullable:"true" list:"user"` // Column(VARCHAR(32, charset='ascii'), nullable=True) CacheMode string `width:"32" charset:"ascii" nullable:"true" list:"user" update:"user"` // Column(VARCHAR(32, charset='ascii'), nullable=True) AioMode string `width:"32" charset:"ascii" nullable:"true" get:"user" update:"user"` // Column(VARCHAR(32, charset='ascii'), nullable=True) Iops int `nullable:"true" default:"0" list:"user" update:"user"` diff --git a/pkg/compute/models/guestdrivers.go b/pkg/compute/models/guestdrivers.go index 7422f4cc2c..3a0cb1ea38 100644 --- a/pkg/compute/models/guestdrivers.go +++ b/pkg/compute/models/guestdrivers.go @@ -233,6 +233,8 @@ type IGuestDriver interface { RequestChangeDiskStorage(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, input *api.ServerChangeDiskStorageInternalInput, task taskman.ITask) error RequestSwitchToTargetStorageDisk(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, input *api.ServerChangeDiskStorageInternalInput, task taskman.ITask) error + RequestResetUefiFirmwareVars(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest) error + RequestSyncIsolatedDevice(ctx context.Context, guest *SGuest, task taskman.ITask) error RequestCPUSet(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, guest *SGuest, input *api.ServerCPUSetInput) (*api.ServerCPUSetResp, error) diff --git a/pkg/hostman/guestman/guesthandlers/guesthandler.go b/pkg/hostman/guestman/guesthandlers/guesthandler.go index 416c391735..a4d2dc56d1 100644 --- a/pkg/hostman/guestman/guesthandlers/guesthandler.go +++ b/pkg/hostman/guestman/guesthandlers/guesthandler.go @@ -115,6 +115,7 @@ func AddGuestTaskHandler(prefix string, app *appsrv.Application) { "start-rescue": guestStartRescue, "guest-screen-dump": guestScreenDump, "upload-status": guestUploadStatus, + "reset-uefi-vars": guestResetUefiVars, } { app.AddHandler("POST", fmt.Sprintf("%s/%s//%s", prefix, keyWord, action), @@ -1027,6 +1028,11 @@ func guestScreenDump(ctx context.Context, userCred mcclient.TokenCredential, sid return gm.RequestGuestScreenDump(sid) } +func guestResetUefiVars(ctx context.Context, userCred mcclient.TokenCredential, sid string, body jsonutils.JSONObject) (interface{}, error) { + gm := guestman.GetGuestManager() + return gm.ResetGuestUefiVars(sid) +} + // prepare rescue files func guestStartRescue(ctx context.Context, userCred mcclient.TokenCredential, sid string, body jsonutils.JSONObject) (interface{}, error) { return guestman.GetGuestManager().GuestStartRescue(ctx, userCred, sid, body) diff --git a/pkg/hostman/guestman/guestman.go b/pkg/hostman/guestman/guestman.go index f2a594dfa7..33aa6763b6 100644 --- a/pkg/hostman/guestman/guestman.go +++ b/pkg/hostman/guestman/guestman.go @@ -2044,6 +2044,27 @@ func SyncGuestNicsTraffics(guestNicsTraffics *compute.GuestNicTrafficSyncInput) } } +func (m *SGuestManager) ResetGuestUefiVars(sid string) (*jsonutils.JSONDict, error) { + guest, _ := m.GetServer(sid) + if guest == nil { + return nil, httperrors.NewNotFoundError("guest %s not found", sid) + } + kvmGuest, ok := guest.(*SKVMGuestInstance) + if !ok { + return nil, httperrors.NewBadRequestError("guest %s not kvm instance", sid) + } + if kvmGuest.IsRunning() { + return nil, httperrors.NewBadRequestError("Can't reset ovmf vars in guest %s running", sid) + } + varsPath := kvmGuest.getOvmfVarsPath() + if fileutils2.Exists(varsPath) { + if err := os.Remove(varsPath); err != nil { + return nil, errors.Wrapf(err, "remove ovmf vars file %s", varsPath) + } + } + return nil, nil +} + var guestManager *SGuestManager func Stop() { diff --git a/pkg/mcclient/options/compute/servers.go b/pkg/mcclient/options/compute/servers.go index 643d7a6437..30a4b1b9b1 100644 --- a/pkg/mcclient/options/compute/servers.go +++ b/pkg/mcclient/options/compute/servers.go @@ -1651,6 +1651,16 @@ func (o *ServerScreenDumpOptions) Params() (jsonutils.JSONObject, error) { return jsonutils.Marshal(o), nil } +type ServerChangeDiskDriverOptions struct { + ServerIdOptions + DISK_ID string + DRIVER string `help:"Driver of vDisk" choices:"virtio|ide|sata|scsi|pvscsi"` +} + +func (o *ServerChangeDiskDriverOptions) Params() (jsonutils.JSONObject, error) { + return jsonutils.Marshal(o), nil +} + type ServerSetNetworkNumQueues struct { ServerIdOptions MacAddr string `help:"server network mac addr"`