Skip to content

Commit

Permalink
Automatically find shared PVC and attach it to VM
Browse files Browse the repository at this point in the history
Signed-off-by: Martin Necas <[email protected]>
  • Loading branch information
mnecas committed Feb 5, 2025
1 parent 41dfcac commit a7ba4f9
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 1 deletion.
91 changes: 90 additions & 1 deletion pkg/controller/plan/adapter/vsphere/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/vmware/govmomi/vim25/types"
core "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
k8slabels "k8s.io/apimachinery/pkg/labels"
"k8s.io/utils/ptr"
cnv "kubevirt.io/api/core/v1"
cdi "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1"
Expand Down Expand Up @@ -82,6 +83,10 @@ const (
AnnImportBackingFile = "cdi.kubevirt.io/storage.import.backingFile"
)

const (
Shareable = "shareable"
)

// Map of vmware guest ids to osinfo ids.
var osMap = map[string]string{
"centos64Guest": "centos5.11",
Expand Down Expand Up @@ -490,6 +495,9 @@ func (r *Builder) DataVolumes(vmRef ref.Ref, secret *core.Secret, _ *core.Config
dv.ObjectMeta.Annotations = make(map[string]string)
}
dv.ObjectMeta.Annotations[planbase.AnnDiskSource] = r.baseVolume(disk.File)
if disk.Shared {
dv.ObjectMeta.Labels[Shareable] = "true"
}
dvs = append(dvs, *dv)
}
}
Expand All @@ -498,6 +506,64 @@ func (r *Builder) DataVolumes(vmRef ref.Ref, secret *core.Secret, _ *core.Config
return
}

// Return all shareable PVCs
func (r *Builder) ShareablePVCs() (pvcs []*core.PersistentVolumeClaim, err error) {
pvcsList := &core.PersistentVolumeClaimList{}
err = r.Destination.Client.List(
context.TODO(),
pvcsList,
&client.ListOptions{
LabelSelector: k8slabels.SelectorFromSet(map[string]string{
Shareable: "true",
}),
},
)
if err != nil {
err = liberr.Wrap(err)
return
}
pvcs = make([]*core.PersistentVolumeClaim, len(pvcsList.Items))
for i, pvc := range pvcsList.Items {
// loopvar
copyPvc := pvc
pvcs[i] = &copyPvc
}

return
}

// Return PersistentVolumeClaims associated with a VM.
func (r *Builder) getSharedPVCs(vm *model.VM) (pvcs []*core.PersistentVolumeClaim, err error) {
allPvcs, err := r.ShareablePVCs()
if err != nil {
return pvcs, err
}
for _, disk := range vm.Disks {
if !disk.Shared {
continue
}
pvc := r.getDisksPvc(disk, allPvcs)
if pvc != nil {
pvcs = append(pvcs, pvc)
r.Log.Info("Found shared PVC disk", "disk", disk.File)
} else {
// No PVC found skipping disk
r.Log.Info("No PVC found to the shared disk, the disk will not be created", "disk", disk.File)
}
}
return pvcs, nil
}

// Return PersistentVolumeClaims associated with a VM.
func (r *Builder) getDisksPvc(disk vsphere.Disk, pvcs []*core.PersistentVolumeClaim) *core.PersistentVolumeClaim {
for _, pvc := range pvcs {
if pvc.Annotations[planbase.AnnDiskSource] == r.baseVolume(disk.File) {
return pvc
}
}
return nil
}

// Create the destination Kubevirt VM.
func (r *Builder) VirtualMachine(vmRef ref.Ref, object *cnv.VirtualMachineSpec, persistentVolumeClaims []*core.PersistentVolumeClaim, usesInstanceType bool) (err error) {
vm := &model.VM{}
Expand Down Expand Up @@ -529,7 +595,27 @@ func (r *Builder) VirtualMachine(vmRef ref.Ref, object *cnv.VirtualMachineSpec,
return
}
if !r.Context.Plan.Spec.MigrateSharedDisks {
r.removeSharedDisks(vm)
sharedPVCs, err := r.getSharedPVCs(vm)
if err != nil {
return err
}
var temp []vsphere.Disk
for _, disk := range vm.Disks {
if !disk.Shared {
temp = append(temp, disk)
continue
}
pvc := r.getDisksPvc(disk, sharedPVCs)
if pvc != nil {
temp = append(temp, disk)
persistentVolumeClaims = append(persistentVolumeClaims, pvc)
r.Log.Info("Found shared PVC disk", "disk", disk.File)
} else {
// No PVC found skipping disk
r.Log.Info("No PVC found to the shared disk, the disk will not be created", "disk", disk.File)
}
}
vm.Disks = temp
}

var conflicts []string
Expand Down Expand Up @@ -748,6 +834,9 @@ func (r *Builder) mapDisks(vm *model.VM, vmRef ref.Ref, persistentVolumeClaims [
},
},
}
if disk.Shared {
kubevirtDisk.Cache = cnv.CacheNone
}
// For multiboot VMs, if the selected boot device is the current disk,
// set it as the first in the boot order.
if bootDisk == i+1 {
Expand Down
18 changes: 18 additions & 0 deletions pkg/controller/plan/kubevirt.go
Original file line number Diff line number Diff line change
Expand Up @@ -1900,6 +1900,15 @@ func (r *KubeVirt) podVolumeMounts(vmVolumes []cnv.Volume, configMap *core.Confi

for i, v := range vmVolumes {
pvc := pvcsByName[v.PersistentVolumeClaim.ClaimName]
if pvc == nil {
r.Log.V(1).Info(
"Failed to find the PVC to the Volume for the pod volume mount",
"volume",
v.Name,
"pvc",
v.PersistentVolumeClaim.ClaimName)
continue
}
vol := core.Volume{
Name: pvc.Name,
VolumeSource: core.VolumeSource{
Expand Down Expand Up @@ -2081,6 +2090,15 @@ func (r *KubeVirt) libvirtDomain(vmCr *VirtualMachine, pvcs []*core.PersistentVo
diskSource := libvirtxml.DomainDiskSource{}

pvc := pvcsByName[vol.PersistentVolumeClaim.ClaimName]
if pvc == nil {
r.Log.V(1).Info(
"Failed to find the PVC to the Volume for the libvirt domain",
"volume",
vol.Name,
"pvc",
vol.PersistentVolumeClaim.ClaimName)
continue
}
if pvc.Spec.VolumeMode != nil && *pvc.Spec.VolumeMode == core.PersistentVolumeBlock {
diskSource.Block = &libvirtxml.DomainDiskSourceBlock{
Dev: fmt.Sprintf("/dev/block%v", i),
Expand Down

0 comments on commit a7ba4f9

Please sign in to comment.