Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate VMs with direct LUNs from ovirt #371

Merged
merged 8 commits into from
Jul 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion pkg/controller/plan/adapter/base/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,14 @@ type Builder interface {
ResolvePersistentVolumeClaimIdentifier(pvc *core.PersistentVolumeClaim) string
// Conversion Pod environment
PodEnvironment(vmRef ref.Ref, sourceSecret *core.Secret) (env []core.EnvVar, err error)

// Create PersistentVolumeClaim with a DataSourceRef
PersistentVolumeClaimWithSourceRef(da interface{}, storageName *string, populatorName string, accessModes []core.PersistentVolumeAccessMode, volumeMode *core.PersistentVolumeMode) *core.PersistentVolumeClaim
// Add custom steps before creating PVC/DataVolume
PreTransferActions(c Client, vmRef ref.Ref) (ready bool, err error)
// Build LUN PVs.
LunPersistentVolumes(vmRef ref.Ref) (pvs []core.PersistentVolume, err error)
// Build LUN PVCs.
LunPersistentVolumeClaims(vmRef ref.Ref) (pvcs []core.PersistentVolumeClaim, err error)
}

// Client API.
Expand All @@ -83,6 +86,8 @@ type Client interface {
Close()
// Finalize migrations
Finalize(vms []*planapi.VMStatus, planName string)
// Detach disks that are attached to the target VM without being cloned (e.g., LUNs).
DetachDisks(vmRef ref.Ref) error
}

// Validator API.
Expand Down
12 changes: 12 additions & 0 deletions pkg/controller/plan/adapter/openstack/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -1153,3 +1153,15 @@ func (r *Builder) cleanup(c planbase.Client, imageName string) {
}
}
}

// Build LUN PVs.
func (r *Builder) LunPersistentVolumes(vmRef ref.Ref) (pvs []core.PersistentVolume, err error) {
// do nothing
return
}

// Build LUN PVCs.
func (r *Builder) LunPersistentVolumeClaims(vmRef ref.Ref) (pvcs []core.PersistentVolumeClaim, err error) {
// do nothing
return
}
5 changes: 5 additions & 0 deletions pkg/controller/plan/adapter/openstack/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,3 +395,8 @@ func (r *Client) Finalize(vms []*planapi.VMStatus, migrationName string) {
}
}
}

func (r *Client) DetachDisks(vmRef ref.Ref) (err error) {
// no-op
return
}
178 changes: 151 additions & 27 deletions pkg/controller/plan/adapter/ovirt/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ func (r *Builder) DataVolumes(vmRef ref.Ref, secret *core.Secret, configMap *cor
return
}
for _, da := range vm.DiskAttachments {
if da.Disk.StorageDomain == sd.ID {
if da.Disk.StorageType == "image" && da.Disk.StorageDomain == sd.ID {
storageClass := mapped.Destination.StorageClass
size := da.Disk.ProvisionedSize
if da.Disk.ActualSize > size {
Expand Down Expand Up @@ -427,16 +427,6 @@ func (r *Builder) mapDisks(vm *model.Workload, persistentVolumeClaims []core.Per
for _, da := range vm.DiskAttachments {
claimName := pvcMap[da.Disk.ID].Name
volumeName := da.Disk.ID
volume := cnv.Volume{
Name: volumeName,
VolumeSource: cnv.VolumeSource{
PersistentVolumeClaim: &cnv.PersistentVolumeClaimVolumeSource{
PersistentVolumeClaimVolumeSource: core.PersistentVolumeClaimVolumeSource{
ClaimName: claimName,
},
},
},
}
var bus string
switch da.Interface {
case VirtioScsi:
Expand All @@ -446,11 +436,34 @@ func (r *Builder) mapDisks(vm *model.Workload, persistentVolumeClaims []core.Per
default:
bus = Virtio
}
disk := cnv.Disk{
var disk cnv.Disk
if da.Disk.Disk.StorageType == "lun" {
claimName = volumeName
disk = cnv.Disk{
Name: volumeName,
DiskDevice: cnv.DiskDevice{
liranr23 marked this conversation as resolved.
Show resolved Hide resolved
LUN: &cnv.LunTarget{
Bus: cnv.DiskBus(bus),
},
},
}
} else {
disk = cnv.Disk{
Name: volumeName,
DiskDevice: cnv.DiskDevice{
Disk: &cnv.DiskTarget{
Bus: cnv.DiskBus(bus),
},
},
}
}
volume := cnv.Volume{
Name: volumeName,
DiskDevice: cnv.DiskDevice{
Disk: &cnv.DiskTarget{
Bus: cnv.DiskBus(bus),
VolumeSource: cnv.VolumeSource{
PersistentVolumeClaim: &cnv.PersistentVolumeClaimVolumeSource{
PersistentVolumeClaimVolumeSource: core.PersistentVolumeClaimVolumeSource{
ClaimName: claimName,
},
},
},
}
Expand Down Expand Up @@ -478,18 +491,22 @@ func (r *Builder) Tasks(vmRef ref.Ref) (list []*plan.Task, err error) {
vmRef.String())
}
for _, da := range vm.DiskAttachments {
mB := da.Disk.ProvisionedSize / 0x100000
list = append(
list,
&plan.Task{
Name: da.Disk.ID,
Progress: libitr.Progress{
Total: mB,
},
Annotations: map[string]string{
"unit": "MB",
},
})
// We don't add a task for LUNs because we don't copy their content but rather assume we can connect to
// the LUNs that are used in the source environment also from the target environment.
if da.Disk.StorageType != "lun" {
liranr23 marked this conversation as resolved.
Show resolved Hide resolved
mB := da.Disk.ProvisionedSize / 0x100000
list = append(
list,
&plan.Task{
Name: da.Disk.ID,
Progress: libitr.Progress{
Total: mB,
},
Annotations: map[string]string{
"unit": "MB",
},
})
}
}

return
Expand Down Expand Up @@ -578,3 +595,110 @@ func (r *Builder) PersistentVolumeClaimWithSourceRef(da interface{}, storageName
func (r *Builder) PreTransferActions(c planbase.Client, vmRef ref.Ref) (ready bool, err error) {
return true, nil
}

// Create PVs specs for the VM LUNs.
func (r *Builder) LunPersistentVolumes(vmRef ref.Ref) (pvs []core.PersistentVolume, err error) {
vm := &model.Workload{}
err = r.Source.Inventory.Find(vm, vmRef)
if err != nil {
err = liberr.Wrap(
err,
"VM lookup failed.",
"vm",
vmRef.String())
return
}
for _, da := range vm.DiskAttachments {
if da.Disk.StorageType == "lun" {
volMode := core.PersistentVolumeBlock
logicalUnit := da.Disk.Lun.LogicalUnits.LogicalUnit[0]

pvSpec := core.PersistentVolume{
ObjectMeta: meta.ObjectMeta{
Name: da.Disk.ID,
Namespace: r.Plan.Spec.TargetNamespace,
Annotations: map[string]string{
AnnImportDiskId: da.Disk.ID,
"vmID": vm.ID,
"plan": string(r.Plan.UID),
"lun": "true",
},
Labels: map[string]string{
"volume": fmt.Sprintf("%v-%v", vm.Name, da.ID),
},
},
Spec: core.PersistentVolumeSpec{
PersistentVolumeSource: core.PersistentVolumeSource{
ISCSI: &core.ISCSIPersistentVolumeSource{
TargetPortal: logicalUnit.Address + ":" + logicalUnit.Port,
IQN: logicalUnit.Target,
Lun: logicalUnit.LunMapping,
ReadOnly: false,
},
},
Capacity: core.ResourceList{
core.ResourceStorage: *resource.NewQuantity(logicalUnit.Size, resource.BinarySI),
},
AccessModes: []core.PersistentVolumeAccessMode{
core.ReadWriteMany,
},
VolumeMode: &volMode,
},
}
pvs = append(pvs, pvSpec)
}
}
return
}

// Create PVCs specs for the VM LUNs.
func (r *Builder) LunPersistentVolumeClaims(vmRef ref.Ref) (pvcs []core.PersistentVolumeClaim, err error) {
vm := &model.Workload{}
err = r.Source.Inventory.Find(vm, vmRef)
if err != nil {
err = liberr.Wrap(
err,
"VM lookup failed.",
"vm",
vmRef.String())
return
}
for _, da := range vm.DiskAttachments {
if da.Disk.StorageType == "lun" {
sc := ""
volMode := core.PersistentVolumeBlock
pvcSpec := core.PersistentVolumeClaim{
ObjectMeta: meta.ObjectMeta{
Name: da.Disk.ID,
Namespace: r.Plan.Spec.TargetNamespace,
Annotations: map[string]string{
AnnImportDiskId: da.Disk.ID,
"vmID": vm.ID,
"plan": string(r.Plan.UID),
"lun": "true",
},
Labels: map[string]string{"migration": r.Migration.Name},
},
Spec: core.PersistentVolumeClaimSpec{
AccessModes: []core.PersistentVolumeAccessMode{
core.ReadWriteMany,
},
Selector: &meta.LabelSelector{
MatchLabels: map[string]string{
"volume": fmt.Sprintf("%v-%v", vm.Name, da.ID),
},
},
StorageClassName: &sc,
VolumeMode: &volMode,
Resources: core.ResourceRequirements{
Requests: core.ResourceList{
core.ResourceStorage: *resource.NewQuantity(da.Disk.Lun.LogicalUnits.LogicalUnit[0].Size, resource.BinarySI),
},
},
},
}
pvcs = append(pvcs, pvcSpec)
}
}
return
}
34 changes: 34 additions & 0 deletions pkg/controller/plan/adapter/ovirt/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -544,3 +544,37 @@ func allJobsFinished(jobs []*ovirtsdk.Job) bool {

return true
}

func (r *Client) DetachDisks(vmRef ref.Ref) (err error) {
_, vmService, err := r.getVM(vmRef)
if err != nil {
return
}
vm := &model.Workload{}
err = r.Source.Inventory.Find(vm, vmRef)
if err != nil {
err = liberr.Wrap(
err,
"VM lookup failed.",
"vm",
vmRef.String())
return
}
diskAttachments := vm.DiskAttachments
for _, da := range diskAttachments {
if da.Disk.StorageType == "lun" {
_, err = vmService.DiskAttachmentsService().AttachmentService(da.ID).Remove().Send()
if err != nil {
err = liberr.Wrap(
err,
"failed to detach LUN disk.",
"vm",
vmRef.String(),
"disk",
da)
return
}
}
}
ahadas marked this conversation as resolved.
Show resolved Hide resolved
return
}
7 changes: 6 additions & 1 deletion pkg/controller/plan/adapter/ovirt/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,12 @@ func (r *Validator) StorageMapped(vmRef ref.Ref) (ok bool, err error) {
return
}
for _, da := range vm.DiskAttachments {
if !r.plan.Referenced.Map.Storage.Status.Refs.Find(ref.Ref{ID: da.Disk.StorageDomain}) {
if da.Disk.StorageType != "lun" {
if !r.plan.Referenced.Map.Storage.Status.Refs.Find(ref.Ref{ID: da.Disk.StorageDomain}) {
return
}
} else if len(da.Disk.Lun.LogicalUnits.LogicalUnit) > 0 && da.Disk.Lun.LogicalUnits.LogicalUnit[0].Address == "" {
// Have LUN disk but without the relevant data. This might happen with older oVirt versions.
return
}
}
Expand Down
12 changes: 12 additions & 0 deletions pkg/controller/plan/adapter/vsphere/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -823,3 +823,15 @@ func (r *Builder) PersistentVolumeClaimWithSourceRef(da interface{}, storageName
func (r *Builder) PreTransferActions(c planbase.Client, vmRef ref.Ref) (ready bool, err error) {
return true, nil
}

// Build LUN PVs.
func (r *Builder) LunPersistentVolumes(vmRef ref.Ref) (pvs []core.PersistentVolume, err error) {
// do nothing
return
}

// Build LUN PVCs.
func (r *Builder) LunPersistentVolumeClaims(vmRef ref.Ref) (pvcs []core.PersistentVolumeClaim, err error) {
// do nothing
return
}
5 changes: 5 additions & 0 deletions pkg/controller/plan/adapter/vsphere/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,3 +370,8 @@ func (r *Client) thumbprint() string {
}
return ""
}

func (r *Client) DetachDisks(vmRef ref.Ref) (err error) {
// no-op
return
}
Loading
Loading