mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-19 10:46:58 +08:00
fix migrate with multi local storage
This commit is contained in:
@@ -212,15 +212,11 @@ func (self *SGuestdisk) GetJsonDescAtHost(host *SHost) jsonutils.JSONObject {
|
||||
desc.Add(jsonutils.NewString(storagecacheimg.Path), "image_path")
|
||||
}
|
||||
}
|
||||
storage := disk.GetStorage()
|
||||
// XXX ???
|
||||
if host.HostType == api.HOST_TYPE_HYPERVISOR {
|
||||
desc.Add(jsonutils.NewString(disk.StorageId), "storage_id")
|
||||
localpath := disk.GetPathAtHost(host)
|
||||
if len(localpath) == 0 {
|
||||
desc.Add(jsonutils.JSONTrue, "migrating")
|
||||
target := host.GetLeastUsedStorage(storage.StorageType)
|
||||
desc.Add(jsonutils.NewString(target.Id), "target_storage_id")
|
||||
disk.SetStatus(nil, api.DISK_START_MIGRATE, "migration")
|
||||
} else {
|
||||
desc.Add(jsonutils.NewString(localpath), "path")
|
||||
|
||||
@@ -105,6 +105,17 @@ func (self *GuestMigrateTask) SaveScheduleResult(ctx context.Context, obj ISched
|
||||
isLocalStorage := utils.IsInStringArray(disk.GetStorage().StorageType,
|
||||
api.STORAGE_LOCAL_TYPES)
|
||||
if isLocalStorage {
|
||||
targetStorages := jsonutils.NewArray()
|
||||
for i := 0; i < len(disks); i++ {
|
||||
var targetStroage string
|
||||
if len(target.Disks[i].StorageIds) == 0 {
|
||||
targetStroage = targetHost.GetLeastUsedStorage(disk.GetStorage().StorageType).Id
|
||||
} else {
|
||||
targetStroage = target.Disks[i].StorageIds[0]
|
||||
}
|
||||
targetStorages.Add(jsonutils.NewString(targetStroage))
|
||||
}
|
||||
body.Set("target_storages", targetStorages)
|
||||
body.Set("is_local_storage", jsonutils.JSONTrue)
|
||||
} else {
|
||||
body.Set("is_local_storage", jsonutils.JSONFalse)
|
||||
@@ -309,19 +320,14 @@ func (self *GuestMigrateTask) localStorageMigrateConf(ctx context.Context,
|
||||
self.TaskFailed(ctx, guest, "Get disksDesc error")
|
||||
return nil, true
|
||||
}
|
||||
targetStorageId, _ := disksDesc[0].GetString("target_storage_id")
|
||||
if len(targetStorageId) == 0 {
|
||||
self.TaskFailed(ctx, guest, "Get targetStorageId error")
|
||||
return nil, true
|
||||
targetStorages, _ := self.Params.GetArray("target_storages")
|
||||
for i := 0; i < len(disks); i++ {
|
||||
diskDesc := disksDesc[i].(*jsonutils.JSONDict)
|
||||
diskDesc.Set("target_storage_id", targetStorages[i])
|
||||
}
|
||||
|
||||
targetStorage := targetHost.GetHoststorageOfId(targetStorageId)
|
||||
sourceStorage := sourceHost.GetHoststorageOfId(disks[0].GetDisk().StorageId)
|
||||
if sourceStorage.MountPoint != targetStorage.MountPoint {
|
||||
// rebase disks backing file
|
||||
body.Set("rebase_disks", jsonutils.JSONTrue)
|
||||
}
|
||||
body.Set("desc", targetDesc)
|
||||
body.Set("rebase_disks", jsonutils.JSONTrue)
|
||||
body.Set("is_local_storage", jsonutils.JSONTrue)
|
||||
return body, false
|
||||
}
|
||||
@@ -363,20 +369,19 @@ func (self *GuestLiveMigrateTask) OnStartDestCompleteFailed(ctx context.Context,
|
||||
func (self *GuestMigrateTask) setGuest(ctx context.Context, guest *models.SGuest) error {
|
||||
targetHostId, _ := self.Params.GetString("target_host_id")
|
||||
if jsonutils.QueryBoolean(self.Params, "is_local_storage", false) {
|
||||
targetHost := models.HostManager.FetchHostById(targetHostId)
|
||||
targetStorage := targetHost.GetLeastUsedStorage(api.STORAGE_LOCAL)
|
||||
targetStorages, _ := self.Params.GetArray("target_storages")
|
||||
guestDisks := guest.GetDisks()
|
||||
for i := 0; i < len(guestDisks); i++ {
|
||||
disk := guestDisks[i].GetDisk()
|
||||
db.Update(disk, func() error {
|
||||
disk.Status = api.DISK_READY
|
||||
disk.StorageId = targetStorage.Id
|
||||
disk.StorageId, _ = targetStorages[i].GetString()
|
||||
return nil
|
||||
})
|
||||
snapshots := models.SnapshotManager.GetDiskSnapshots(disk.Id)
|
||||
for _, snapshot := range snapshots {
|
||||
db.Update(&snapshot, func() error {
|
||||
snapshot.StorageId = targetStorage.Id
|
||||
snapshot.StorageId, _ = targetStorages[i].GetString()
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -331,11 +331,17 @@ func guestDestPrepareMigrate(ctx context.Context, sid string, body jsonutils.JSO
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("Get desc disks error")
|
||||
} else {
|
||||
targetStorageId, _ := disks[0].GetString("target_storage_id")
|
||||
if len(targetStorageId) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("target_storage_id")
|
||||
targetStorageIds := []string{}
|
||||
for i := 0; i < len(disks); i++ {
|
||||
targetStorageId, _ := disks[i].GetString("target_storage_id")
|
||||
if len(targetStorageId) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("target_storage_id")
|
||||
}
|
||||
targetStorageIds = append(targetStorageIds, targetStorageId)
|
||||
// params.TargetStorageId = targetStorageId
|
||||
params.TargetStorageIds = targetStorageIds
|
||||
}
|
||||
params.TargetStorageId = targetStorageId
|
||||
|
||||
}
|
||||
params.RebaseDisks = jsonutils.QueryBoolean(body, "rebase_disks", false)
|
||||
}
|
||||
|
||||
@@ -38,14 +38,15 @@ type SSrcPrepareMigrate struct {
|
||||
}
|
||||
|
||||
type SDestPrepareMigrate struct {
|
||||
Sid string
|
||||
ServerUrl string
|
||||
QemuVersion string
|
||||
SnapshotsUri string
|
||||
DisksUri string
|
||||
TargetStorageId string
|
||||
LiveMigrate bool
|
||||
RebaseDisks bool
|
||||
Sid string
|
||||
ServerUrl string
|
||||
QemuVersion string
|
||||
SnapshotsUri string
|
||||
DisksUri string
|
||||
// TargetStorageId string
|
||||
TargetStorageIds []string
|
||||
LiveMigrate bool
|
||||
RebaseDisks bool
|
||||
|
||||
Desc jsonutils.JSONObject
|
||||
DisksBackingFile jsonutils.JSONObject
|
||||
|
||||
@@ -598,23 +598,27 @@ func (m *SGuestManager) DestPrepareMigrate(ctx context.Context, params interface
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(migParams.TargetStorageId) > 0 {
|
||||
iStorage := storageman.GetManager().GetStorage(migParams.TargetStorageId)
|
||||
if iStorage == nil {
|
||||
return nil, fmt.Errorf("Target storage %s not found", migParams.TargetStorageId)
|
||||
}
|
||||
disks, _ := migParams.Desc.GetArray("disks")
|
||||
if len(migParams.TargetStorageIds) > 0 {
|
||||
for i := 0; i < len(migParams.TargetStorageIds); i++ {
|
||||
iStorage := storageman.GetManager().GetStorage(migParams.TargetStorageIds[i])
|
||||
if iStorage == nil {
|
||||
return nil, fmt.Errorf("Target storage %s not found", migParams.TargetStorageIds[i])
|
||||
}
|
||||
|
||||
err := iStorage.DestinationPrepareMigrate(
|
||||
ctx, migParams.LiveMigrate, migParams.DisksUri, migParams.SnapshotsUri,
|
||||
migParams.Desc, migParams.DisksBackingFile, migParams.SrcSnapshots, migParams.RebaseDisks)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("dest prepare migrate failed %s", err)
|
||||
err := iStorage.DestinationPrepareMigrate(
|
||||
ctx, migParams.LiveMigrate, migParams.DisksUri, migParams.SnapshotsUri,
|
||||
migParams.DisksBackingFile, migParams.SrcSnapshots, migParams.RebaseDisks, disks[i],
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("dest prepare migrate failed %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err = guest.SaveDesc(migParams.Desc); err != nil {
|
||||
if err := guest.SaveDesc(migParams.Desc); err != nil {
|
||||
log.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if migParams.LiveMigrate {
|
||||
|
||||
@@ -120,7 +120,7 @@ type IStorage interface {
|
||||
GetImgsaveBackupPath() string
|
||||
|
||||
DestinationPrepareMigrate(ctx context.Context, liveMigrate bool, disksUri string, snapshotsUri string,
|
||||
desc, disksBackingFile, srcSnapshots jsonutils.JSONObject, rebaseDisks bool) error
|
||||
disksBackingFile, srcSnapshots jsonutils.JSONObject, rebaseDisks bool, diskDesc jsonutils.JSONObject) error
|
||||
|
||||
Accessible() error
|
||||
}
|
||||
@@ -312,7 +312,7 @@ func (s *SBaseStorage) CreateDiskFromSnpashot(ctx context.Context, disk IDisk, c
|
||||
|
||||
func (s *SBaseStorage) DestinationPrepareMigrate(
|
||||
ctx context.Context, liveMigrate bool, disksUri string, snapshotsUri string,
|
||||
desc, disksBackingFile, srcSnapshots jsonutils.JSONObject, rebaseDisks bool,
|
||||
disksBackingFile, srcSnapshots jsonutils.JSONObject, rebaseDisks bool, diskinfo jsonutils.JSONObject,
|
||||
) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -342,86 +342,83 @@ func (s *SLocalStorage) DeleteSnapshots(ctx context.Context, params interface{})
|
||||
|
||||
func (s *SLocalStorage) DestinationPrepareMigrate(
|
||||
ctx context.Context, liveMigrate bool, disksUri string, snapshotsUri string,
|
||||
desc, disksBackingFile, srcSnapshots jsonutils.JSONObject, rebaseDisks bool) error {
|
||||
disks, _ := desc.GetArray("disks")
|
||||
for i, diskinfo := range disks {
|
||||
var (
|
||||
diskId, _ = diskinfo.GetString("disk_id")
|
||||
snapshots, _ = srcSnapshots.GetArray(diskId)
|
||||
disk = s.CreateDisk(diskId)
|
||||
)
|
||||
disksBackingFile, srcSnapshots jsonutils.JSONObject, rebaseDisks bool, diskinfo jsonutils.JSONObject) error {
|
||||
var (
|
||||
diskId, _ = diskinfo.GetString("disk_id")
|
||||
snapshots, _ = srcSnapshots.GetArray(diskId)
|
||||
disk = s.CreateDisk(diskId)
|
||||
)
|
||||
|
||||
if disk == nil {
|
||||
return fmt.Errorf(
|
||||
"Storage %s create disk %s failed", s.GetId(), diskId)
|
||||
}
|
||||
if disk == nil {
|
||||
return fmt.Errorf(
|
||||
"Storage %s create disk %s failed", s.GetId(), diskId)
|
||||
}
|
||||
|
||||
templateId, _ := diskinfo.GetString("template_id")
|
||||
// prepare disk snapshot dir
|
||||
if len(snapshots) > 0 && !fileutils2.Exists(disk.GetSnapshotDir()) {
|
||||
_, err := procutils.NewCommand("mkdir", "-p", disk.GetSnapshotDir()).Output()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
templateId, _ := diskinfo.GetString("template_id")
|
||||
// prepare disk snapshot dir
|
||||
if len(snapshots) > 0 && !fileutils2.Exists(disk.GetSnapshotDir()) {
|
||||
_, err := procutils.NewCommand("mkdir", "-p", disk.GetSnapshotDir()).Output()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// create snapshots form remote url
|
||||
var (
|
||||
diskStorageId, _ = diskinfo.GetString("storage_id")
|
||||
baseImagePath string
|
||||
)
|
||||
for i, snapshotId := range snapshots {
|
||||
snapId, _ := snapshotId.GetString()
|
||||
snapshotUrl := fmt.Sprintf("%s/%s/%s/%s",
|
||||
snapshotsUri, diskStorageId, diskId, snapId)
|
||||
snapshotPath := path.Join(disk.GetSnapshotDir(), snapId)
|
||||
log.Infof("Disk %s snapshot %s url: %s", diskId, snapId, snapshotUrl)
|
||||
if err := s.CreateSnapshotFormUrl(ctx, snapshotUrl, diskId, snapshotPath); err != nil {
|
||||
return errors.Wrap(err, "create from snapshot url failed")
|
||||
}
|
||||
baseImagePath = snapshotPath
|
||||
if i == 0 && len(templateId) > 0 {
|
||||
templatePath := path.Join(storageManager.LocalStorageImagecacheManager.GetPath(), templateId)
|
||||
if err := doRebaseDisk(snapshotPath, templatePath); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if rebaseDisks {
|
||||
if err := doRebaseDisk(snapshotPath, baseImagePath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// create snapshots form remote url
|
||||
var (
|
||||
diskStorageId, _ = diskinfo.GetString("storage_id")
|
||||
baseImagePath string
|
||||
)
|
||||
for i, snapshotId := range snapshots {
|
||||
snapId, _ := snapshotId.GetString()
|
||||
snapshotUrl := fmt.Sprintf("%s/%s/%s/%s",
|
||||
snapshotsUri, diskStorageId, diskId, snapId)
|
||||
snapshotPath := path.Join(disk.GetSnapshotDir(), snapId)
|
||||
log.Infof("Disk %s snapshot %s url: %s", diskId, snapId, snapshotUrl)
|
||||
if err := s.CreateSnapshotFormUrl(ctx, snapshotUrl, diskId, snapshotPath); err != nil {
|
||||
return errors.Wrap(err, "create from snapshot url failed")
|
||||
}
|
||||
|
||||
if liveMigrate {
|
||||
// create local disk
|
||||
backingFile, _ := disksBackingFile.GetString(diskId)
|
||||
size, _ := diskinfo.Int("size")
|
||||
_, err := disk.CreateRaw(ctx, int(size), "qcow2", "", false, "", backingFile)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// download disk form remote url
|
||||
diskUrl := fmt.Sprintf("%s/%s/%s", disksUri, diskStorageId, diskId)
|
||||
if err := disk.CreateFromUrl(ctx, diskUrl, 0); err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
if rebaseDisks && len(templateId) > 0 && len(baseImagePath) == 0 {
|
||||
if i == 0 && len(templateId) > 0 {
|
||||
templatePath := path.Join(storageManager.LocalStorageImagecacheManager.GetPath(), templateId)
|
||||
if err := doRebaseDisk(disk.GetPath(), templatePath); err != nil {
|
||||
if err := doRebaseDisk(snapshotPath, templatePath); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if rebaseDisks && len(baseImagePath) > 0 {
|
||||
if err := doRebaseDisk(disk.GetPath(), baseImagePath); err != nil {
|
||||
if err := doRebaseDisk(snapshotPath, baseImagePath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
diskDesc, _ := disks[i].(*jsonutils.JSONDict)
|
||||
diskDesc.Set("path", jsonutils.NewString(disk.GetPath()))
|
||||
baseImagePath = snapshotPath
|
||||
}
|
||||
|
||||
if liveMigrate {
|
||||
// create local disk
|
||||
backingFile, _ := disksBackingFile.GetString(diskId)
|
||||
size, _ := diskinfo.Int("size")
|
||||
_, err := disk.CreateRaw(ctx, int(size), "qcow2", "", false, "", backingFile)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// download disk form remote url
|
||||
diskUrl := fmt.Sprintf("%s/%s/%s", disksUri, diskStorageId, diskId)
|
||||
if err := disk.CreateFromUrl(ctx, diskUrl, 0); err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
if rebaseDisks && len(templateId) > 0 && len(baseImagePath) == 0 {
|
||||
templatePath := path.Join(storageManager.LocalStorageImagecacheManager.GetPath(), templateId)
|
||||
if err := doRebaseDisk(disk.GetPath(), templatePath); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if rebaseDisks && len(baseImagePath) > 0 {
|
||||
if err := doRebaseDisk(disk.GetPath(), baseImagePath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
diskDesc, _ := diskinfo.(*jsonutils.JSONDict)
|
||||
diskDesc.Set("path", jsonutils.NewString(disk.GetPath()))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user