Skip to content

Commit

Permalink
Introduce LUN import from ovirt
Browse files Browse the repository at this point in the history
This patch will allow importing direct LUNs from oVirt provider to
kubeVirt. The attached direct LUNs will be created in the destination
cluster. It will be connected to the VM as PVC and a PV which contains
the relevant direct LUN details.

Only on late oVirt version the API provides the relevant details.
Therefore, older version can not perform this flow.

The storage should be exposed to the destination environment.

Signed-off-by: Liran Rotenberg <lrotenbe@redhat.com>
  • Loading branch information
liranr23 committed May 31, 2023
1 parent 7fcedca commit f87c160
Show file tree
Hide file tree
Showing 10 changed files with 350 additions and 33 deletions.
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)
// Remove disk attachment from the VM.
DetachDisk(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 @@ -1130,3 +1130,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 @@ -332,3 +332,8 @@ func (r *Client) Finalize(vms []*planapi.VMStatus, migrationName string) {
}
}
}

func (r *Client) DetachDisk(vmRef ref.Ref) (err error) {
// no-op
return
}
185 changes: 158 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 != "lun" && da.Disk.StorageDomain == sd.ID {
storageClass := mapped.Destination.StorageClass
size := da.Disk.ProvisionedSize
if da.Disk.ActualSize > size {
Expand Down Expand Up @@ -427,14 +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: &core.PersistentVolumeClaimVolumeSource{
ClaimName: claimName,
},
},
}
var bus string
switch da.Interface {
case VirtioScsi:
Expand All @@ -444,13 +436,43 @@ func (r *Builder) mapDisks(vm *model.Workload, persistentVolumeClaims []core.Per
default:
bus = Virtio
}
disk := cnv.Disk{
Name: volumeName,
DiskDevice: cnv.DiskDevice{
Disk: &cnv.DiskTarget{
Bus: bus,
var disk cnv.Disk
var volume cnv.Volume
if da.Disk.Disk.StorageType == "lun" {
volume = cnv.Volume{
Name: volumeName,
VolumeSource: cnv.VolumeSource{
PersistentVolumeClaim: &core.PersistentVolumeClaimVolumeSource{
ClaimName: volumeName,
},
},
},
}
disk = cnv.Disk{
Name: volumeName,
DiskDevice: cnv.DiskDevice{
LUN: &cnv.LunTarget{
Bus: bus,
},
},
}
} else {
volume = cnv.Volume{
Name: volumeName,
VolumeSource: cnv.VolumeSource{
PersistentVolumeClaim: &core.PersistentVolumeClaimVolumeSource{
ClaimName: claimName,
},
},
}

disk = cnv.Disk{
Name: volumeName,
DiskDevice: cnv.DiskDevice{
Disk: &cnv.DiskTarget{
Bus: bus,
},
},
}
}
kVolumes = append(kVolumes, volume)
kDisks = append(kDisks, disk)
Expand All @@ -471,18 +493,20 @@ 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",
},
})
if da.Disk.StorageType != "lun" {
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 @@ -571,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),
},
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,
//TODO using creds to storage CHAPAuth:
},
},
Capacity: core.ResourceList{
core.ResourceStorage: *resource.NewQuantity(logicalUnit.Size, resource.BinarySI),
},
AccessModes: []core.PersistentVolumeAccessMode{
core.ReadWriteOnce,
},
VolumeMode: &volmode,
//TODO PersistentVolumeReclaimPolicy - currently it is retain, maybe need to switch into delete
},
}
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),
},
Labels: map[string]string{"migration": r.Migration.Name},
},
Spec: core.PersistentVolumeClaimSpec{
AccessModes: []core.PersistentVolumeAccessMode{
core.ReadWriteOnce,
},
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
}
17 changes: 17 additions & 0 deletions pkg/controller/plan/adapter/ovirt/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -533,3 +533,20 @@ func allJobsFinished(jobs []*ovirtsdk.Job) bool {

return true
}

// Remove disk attachment from the VM.
func (r *Client) DetachDisk(vmRef ref.Ref) (err error) {
vm, vmService, err := r.getVM(vmRef)
if err != nil {
return
}
diskAttachments, _ := vm.DiskAttachments()
for _, da := range diskAttachments.Slice() {
disk, _ := da.Disk()
stype, _ := disk.StorageType()
if stype == ovirtsdk.DISKSTORAGETYPE_LUN {
vmService.DiskAttachmentsService().AttachmentService(da.MustId()).Remove()
}
}
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 but without the relevant data
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 @@ -793,3 +793,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) DetachDisk(vmRef ref.Ref) (err error) {
// no-op
return
}
Loading

0 comments on commit f87c160

Please sign in to comment.