fix(region): managed vm migrate (#21747)

This commit is contained in:
屈轩
2024-12-05 16:11:47 +08:00
committed by GitHub
parent fc74470066
commit 460e1e58d8
7 changed files with 85 additions and 244 deletions
@@ -30,7 +30,6 @@ import (
"yunion.io/x/pkg/util/httputils"
"yunion.io/x/pkg/util/rbacscope"
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
@@ -592,80 +591,6 @@ func (self *SCloudpodsESXiGuestDriver) IsSupportLiveMigrate() bool {
return true
}
func (self *SCloudpodsESXiGuestDriver) RequestMigrate(ctx context.Context, guest *models.SGuest, userCred mcclient.TokenCredential, input api.GuestMigrateInput, task taskman.ITask) error {
return self.RequestLiveMigrate(ctx, guest, userCred, api.GuestLiveMigrateInput{PreferHostId: input.PreferHostId}, task)
}
func (self *SCloudpodsESXiGuestDriver) RequestLiveMigrate(ctx context.Context, guest *models.SGuest, userCred mcclient.TokenCredential, input api.GuestLiveMigrateInput, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
iVM, err := guest.GetIVM(ctx)
if err != nil {
return nil, errors.Wrap(err, "guest.GetIVM")
}
iHost, err := models.HostManager.FetchById(input.PreferHostId)
if err != nil {
return nil, errors.Wrapf(err, "models.HostManager.FetchById(%s)", input.PreferHostId)
}
host := iHost.(*models.SHost)
hostExternalId := host.ExternalId
if err = iVM.LiveMigrateVM(hostExternalId); err != nil {
return nil, errors.Wrapf(err, "iVM.LiveMigrateVM(%s)", hostExternalId)
}
hostExternalId = iVM.GetIHostId()
if hostExternalId == "" {
return nil, errors.Wrap(fmt.Errorf("empty hostExternalId"), "iVM.GetIHostId()")
}
iHost, err = db.FetchByExternalIdAndManagerId(models.HostManager, hostExternalId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
if host, _ := guest.GetHost(); host != nil {
return q.Equals("manager_id", host.ManagerId)
}
return q
})
if err != nil {
return nil, errors.Wrapf(err, "db.FetchByExternalId(models.HostManager,%s)", hostExternalId)
}
host = iHost.(*models.SHost)
_, err = db.Update(guest, func() error {
guest.HostId = host.GetId()
return nil
})
if err != nil {
return nil, errors.Wrap(err, "db.Update guest.hostId")
}
disks, err := guest.GetDisks()
if err != nil {
return nil, errors.Wrapf(err, "GetDisks")
}
iRegion, err := host.GetIRegion(ctx)
if err != nil {
return nil, errors.Wrapf(err, "GetIRegion")
}
for i := range disks {
iDisk, err := iRegion.GetIDiskById(disks[i].ExternalId)
if err != nil {
return nil, errors.Wrapf(err, "GetIDisk(%s)", disks[i].ExternalId)
}
iStorage, err := db.FetchByExternalIdAndManagerId(models.StorageManager, iDisk.GetIStorageId(), func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
hcs := models.HoststorageManager.Query().SubQuery()
return q.Join(hcs, sqlchemy.Equals(hcs.Field("storage_id"), q.Field("id"))).Filter(sqlchemy.Equals(hcs.Field("host_id"), host.GetId()))
})
if err != nil {
return nil, errors.Wrapf(err, "FetchStorageByExternalId(%s)", iDisk.GetIStorageId())
}
storage := iStorage.(*models.SStorage)
_, err = db.Update(&disks[i], func() error {
disks[i].StorageId = storage.Id
return nil
})
if err != nil {
return nil, errors.Wrapf(err, "db.Update disk %s storageid", disks[i].Name)
}
}
return nil, nil
})
return nil
}
func (self *SCloudpodsESXiGuestDriver) RequestStartOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, userCred mcclient.TokenCredential, task taskman.ITask) error {
ivm, err := guest.GetIVM(ctx)
if err != nil {
-75
View File
@@ -30,7 +30,6 @@ import (
"yunion.io/x/pkg/util/httputils"
"yunion.io/x/pkg/util/rbacscope"
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
@@ -622,80 +621,6 @@ func (self *SESXiGuestDriver) CheckLiveMigrate(ctx context.Context, guest *model
return nil
}
func (self *SESXiGuestDriver) RequestMigrate(ctx context.Context, guest *models.SGuest, userCred mcclient.TokenCredential, input api.GuestMigrateInput, task taskman.ITask) error {
return self.RequestLiveMigrate(ctx, guest, userCred, api.GuestLiveMigrateInput{PreferHostId: input.PreferHostId}, task)
}
func (self *SESXiGuestDriver) RequestLiveMigrate(ctx context.Context, guest *models.SGuest, userCred mcclient.TokenCredential, input api.GuestLiveMigrateInput, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
iVM, err := guest.GetIVM(ctx)
if err != nil {
return nil, errors.Wrap(err, "guest.GetIVM")
}
iHost, err := models.HostManager.FetchById(input.PreferHostId)
if err != nil {
return nil, errors.Wrapf(err, "models.HostManager.FetchById(%s)", input.PreferHostId)
}
host := iHost.(*models.SHost)
hostExternalId := host.ExternalId
if err = iVM.LiveMigrateVM(hostExternalId); err != nil {
return nil, errors.Wrapf(err, "iVM.LiveMigrateVM(%s)", hostExternalId)
}
hostExternalId = iVM.GetIHostId()
if hostExternalId == "" {
return nil, errors.Wrap(fmt.Errorf("empty hostExternalId"), "iVM.GetIHostId()")
}
iHost, err = db.FetchByExternalIdAndManagerId(models.HostManager, hostExternalId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
if host, _ := guest.GetHost(); host != nil {
return q.Equals("manager_id", host.ManagerId)
}
return q
})
if err != nil {
return nil, errors.Wrapf(err, "db.FetchByExternalId(models.HostManager,%s)", hostExternalId)
}
host = iHost.(*models.SHost)
_, err = db.Update(guest, func() error {
guest.HostId = host.GetId()
return nil
})
if err != nil {
return nil, errors.Wrap(err, "db.Update guest.hostId")
}
disks, err := guest.GetDisks()
if err != nil {
return nil, errors.Wrapf(err, "GetDisks")
}
iRegion, err := host.GetIRegion(ctx)
if err != nil {
return nil, errors.Wrapf(err, "GetIRegion")
}
for i := range disks {
iDisk, err := iRegion.GetIDiskById(disks[i].ExternalId)
if err != nil {
return nil, errors.Wrapf(err, "GetIDisk(%s)", disks[i].ExternalId)
}
iStorage, err := db.FetchByExternalIdAndManagerId(models.StorageManager, iDisk.GetIStorageId(), func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
hcs := models.HoststorageManager.Query().SubQuery()
return q.Join(hcs, sqlchemy.Equals(hcs.Field("storage_id"), q.Field("id"))).Filter(sqlchemy.Equals(hcs.Field("host_id"), host.GetId()))
})
if err != nil {
return nil, errors.Wrapf(err, "FetchStorageByExternalId(%s)", iDisk.GetIStorageId())
}
storage := iStorage.(*models.SStorage)
_, err = db.Update(&disks[i], func() error {
disks[i].StorageId = storage.Id
return nil
})
if err != nil {
return nil, errors.Wrapf(err, "db.Update disk %s storageid", disks[i].Name)
}
}
return nil, nil
})
return nil
}
func (self *SESXiGuestDriver) RequestStartOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, userCred mcclient.TokenCredential, task taskman.ITask) error {
ivm, err := guest.GetIVM(ctx)
if err != nil {
@@ -18,6 +18,7 @@ import (
"context"
"fmt"
"math"
"strings"
"sync"
"time"
@@ -1366,6 +1367,7 @@ func GetCloudVMStatus(vm cloudprovider.ICloudVM) string {
status = cloudprovider.CloudVMStatusDeploying
case api.VM_SUSPEND:
status = cloudprovider.CloudVMStatusSuspend
case api.VM_MIGRATING, api.VM_START_MIGRATE:
default:
status = cloudprovider.CloudVMStatusOther
}
@@ -1373,6 +1375,84 @@ func GetCloudVMStatus(vm cloudprovider.ICloudVM) string {
return status
}
func (self *SManagedVirtualizedGuestDriver) RequestMigrate(ctx context.Context, guest *models.SGuest, userCred mcclient.TokenCredential, input api.GuestMigrateInput, task taskman.ITask) error {
return self.requestMigrate(ctx, guest, userCred, api.GuestLiveMigrateInput{PreferHostId: input.PreferHostId}, task, false)
}
func (self *SManagedVirtualizedGuestDriver) RequestLiveMigrate(ctx context.Context, guest *models.SGuest, userCred mcclient.TokenCredential, input api.GuestLiveMigrateInput, task taskman.ITask) error {
return self.requestMigrate(ctx, guest, userCred, input, task, true)
}
func (self *SManagedVirtualizedGuestDriver) requestMigrate(ctx context.Context, guest *models.SGuest, userCred mcclient.TokenCredential, input api.GuestLiveMigrateInput, task taskman.ITask, isLive bool) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
iVM, err := guest.GetIVM(ctx)
if err != nil {
return nil, errors.Wrap(err, "guest.GetIVM")
}
iHost, err := models.HostManager.FetchById(input.PreferHostId)
if err != nil {
return nil, errors.Wrapf(err, "FetchById(%s)", input.PreferHostId)
}
host := iHost.(*models.SHost)
hostExternalId := host.ExternalId
if isLive {
err = iVM.LiveMigrateVM(hostExternalId)
} else {
err = iVM.MigrateVM(hostExternalId)
}
if err != nil {
return nil, errors.Wrapf(err, "Migrate (%s)", hostExternalId)
}
err = cloudprovider.Wait(time.Second*10, time.Hour*1, func() (bool, error) {
err = iVM.Refresh()
if err != nil {
return false, err
}
vmStatus := iVM.GetStatus()
if vmStatus == api.VM_UNKNOWN || strings.Contains(vmStatus, "fail") {
return false, errors.Wrapf(cloudprovider.ErrInvalidStatus, vmStatus)
}
if !utils.IsInStringArray(vmStatus, []string{api.VM_RUNNING, api.VM_READY}) {
return false, nil
}
hostId := iVM.GetIHostId()
if len(hostId) > 0 && hostId != hostExternalId {
hostExternalId = hostId
return true, nil
}
return false, nil
})
if err != nil {
return nil, errors.Wrapf(err, "wait host change")
}
iHost, err = db.FetchByExternalIdAndManagerId(models.HostManager, hostExternalId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
if host, _ := guest.GetHost(); host != nil {
return q.Equals("manager_id", host.ManagerId)
}
return q
})
if err != nil {
return nil, errors.Wrapf(err, "fetch host %s", hostExternalId)
}
host = iHost.(*models.SHost)
_, err = db.Update(guest, func() error {
guest.HostId = host.GetId()
return nil
})
if err != nil {
return nil, errors.Wrap(err, "update hostId")
}
provider := host.GetCloudprovider()
driver, err := provider.GetProvider(ctx)
if err != nil {
return nil, err
}
models.SyncVMPeripherals(ctx, userCred, guest, iVM, host, provider, driver)
return nil, nil
})
return nil
}
func (drv *SManagedVirtualizedGuestDriver) RequestConvertPublicipToEip(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
iVM, err := guest.GetIVM(ctx)
-89
View File
@@ -26,7 +26,6 @@ import (
"yunion.io/x/pkg/util/billing"
"yunion.io/x/pkg/util/rbacscope"
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
@@ -392,91 +391,3 @@ func (self *SOpenStackGuestDriver) IsSupportMigrate() bool {
func (self *SOpenStackGuestDriver) IsSupportLiveMigrate() bool {
return true
}
func (self *SOpenStackGuestDriver) RequestMigrate(ctx context.Context, guest *models.SGuest, userCred mcclient.TokenCredential, input api.GuestMigrateInput, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
iVM, err := guest.GetIVM(ctx)
if err != nil {
return nil, errors.Wrap(err, "guest.GetIVM")
}
hostExternalId := ""
if input.PreferHostId != "" {
iHost, err := models.HostManager.FetchById(input.PreferHostId)
if err != nil {
return nil, errors.Wrapf(err, "models.HostManager.FetchById(%s)", input.PreferHostId)
}
host := iHost.(*models.SHost)
hostExternalId = host.ExternalId
}
if err = iVM.MigrateVM(hostExternalId); err != nil {
return nil, errors.Wrapf(err, "iVM.MigrateVM(%s)", hostExternalId)
}
hostExternalId = iVM.GetIHostId()
if hostExternalId == "" {
return nil, errors.Wrap(fmt.Errorf("empty hostExternalId"), "iVM.GetIHostId()")
}
iHost, err := db.FetchByExternalIdAndManagerId(models.HostManager, hostExternalId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
if host, _ := guest.GetHost(); host != nil {
return q.Equals("manager_id", host.ManagerId)
}
return q
})
if err != nil {
return nil, errors.Wrapf(err, "db.FetchByExternalId(models.HostManager,%s)", hostExternalId)
}
host := iHost.(*models.SHost)
_, err = db.Update(guest, func() error {
guest.HostId = host.GetId()
return nil
})
if err != nil {
return nil, errors.Wrap(err, "db.Update guest.hostId")
}
return nil, nil
})
return nil
}
func (self *SOpenStackGuestDriver) RequestLiveMigrate(ctx context.Context, guest *models.SGuest, userCred mcclient.TokenCredential, input api.GuestLiveMigrateInput, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
iVM, err := guest.GetIVM(ctx)
if err != nil {
return nil, errors.Wrap(err, "guest.GetIVM")
}
hostExternalId := ""
if input.PreferHostId != "" {
iHost, err := models.HostManager.FetchById(input.PreferHostId)
if err != nil {
return nil, errors.Wrapf(err, "models.HostManager.FetchById(%s)", input.PreferHostId)
}
host := iHost.(*models.SHost)
hostExternalId = host.ExternalId
}
if err = iVM.LiveMigrateVM(hostExternalId); err != nil {
return nil, errors.Wrapf(err, "iVM.LiveMigrateVM(%s)", hostExternalId)
}
hostExternalId = iVM.GetIHostId()
if hostExternalId == "" {
return nil, errors.Wrap(fmt.Errorf("empty hostExternalId"), "iVM.GetIHostId()")
}
iHost, err := db.FetchByExternalIdAndManagerId(models.HostManager, hostExternalId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
if host, _ := guest.GetHost(); host != nil {
return q.Equals("manager_id", host.ManagerId)
}
return q
})
if err != nil {
return nil, errors.Wrapf(err, "db.FetchByExternalId(models.HostManager,%s)", hostExternalId)
}
host := iHost.(*models.SHost)
_, err = db.Update(guest, func() error {
guest.HostId = host.GetId()
return nil
})
if err != nil {
return nil, errors.Wrap(err, "db.Update guest.hostId")
}
return nil, nil
})
return nil
}
+2 -2
View File
@@ -1109,7 +1109,7 @@ func syncHostVMs(ctx context.Context, userCred mcclient.TokenCredential, syncRes
return
}
syncVMPeripherals(ctx, userCred, syncVMPairs[i].Local, syncVMPairs[i].Remote, localHost, provider, driver)
SyncVMPeripherals(ctx, userCred, syncVMPairs[i].Local, syncVMPairs[i].Remote, localHost, provider, driver)
}()
}
@@ -1142,7 +1142,7 @@ func syncHostIsolateDevices(ctx context.Context, userCred mcclient.TokenCredenti
provider.SyncError(result, notes, userCred)
}
func syncVMPeripherals(
func SyncVMPeripherals(
ctx context.Context,
userCred mcclient.TokenCredential,
local *SGuest,
+2 -2
View File
@@ -590,7 +590,7 @@ func (self *SGuest) StartMigrateTask(
data.Set("guest_status", jsonutils.NewString(guestStatus))
dedicateMigrateTask := "GuestMigrateTask"
if !utils.IsInStringArray(self.GetHypervisor(), []string{api.HYPERVISOR_KVM, api.HYPERVISOR_POD}) {
if len(self.ExternalId) > 0 {
dedicateMigrateTask = "ManagedGuestMigrateTask" //托管私有云
}
self.SetStatus(ctx, userCred, vmStatus, "")
@@ -649,7 +649,7 @@ func (self *SGuest) StartGuestLiveMigrateTask(
data.Set("guest_status", jsonutils.NewString(guestStatus))
dedicateMigrateTask := "GuestLiveMigrateTask"
if self.GetHypervisor() != api.HYPERVISOR_KVM {
if len(self.ExternalId) > 0 {
dedicateMigrateTask = "ManagedGuestLiveMigrateTask" //托管私有云
}
if task, err := taskman.TaskManager.NewTask(ctx, dedicateMigrateTask, self, userCred, data, parentTaskId, "", nil); err != nil {
+1 -1
View File
@@ -3154,7 +3154,7 @@ func (guest *SGuest) SyncAllWithCloudVM(ctx context.Context, userCred mcclient.T
return errors.Wrap(err, "guest.syncWithCloudVM")
}
syncVMPeripherals(ctx, userCred, guest, extVM, host, provider, driver)
SyncVMPeripherals(ctx, userCred, guest, extVM, host, provider, driver)
return nil
}