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

MTV-2093 | Sort the disks by bus #1374

Merged
merged 1 commit into from
Feb 28, 2025
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
34 changes: 30 additions & 4 deletions pkg/controller/plan/adapter/vsphere/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -730,15 +730,41 @@ func (r *Builder) mapFirmware(vm *model.VM, object *cnv.VirtualMachineSpec) {
object.Template.Spec.Domain.Firmware = firmware
}

func (r *Builder) filterDisksWithBus(disks []vsphere.Disk, bus string) []vsphere.Disk {
var resp []vsphere.Disk
for _, disk := range disks {
if disk.Bus == bus {
resp = append(resp, disk)
}
}
return resp
}

// The disks are first sorted by the buses going in order SCSI, SATA and IDE and within the controller the
// disks are sorted by the key. This needs to be done because the virt-v2v outputs the files in an order,
// which it gets from libvirt. The libvirt orders the devices starting with SCSI, SATA and IDE.
// When we were sorting by the keys the order was IDE, SATA and SCSI. This cause that some PVs were populated by
// incorrect disks.
// https://github.com/libvirt/libvirt/blob/master/src/vmx/vmx.c#L1713
func (r *Builder) sortedDisks(disks []vsphere.Disk) []vsphere.Disk {
var buses = []string{container.SCSI, container.SATA, container.IDE}
var resp []vsphere.Disk
for _, bus := range buses {
disksWithBus := r.filterDisksWithBus(disks, bus)
sort.Slice(disksWithBus, func(i, j int) bool {
return disksWithBus[i].Key < disksWithBus[j].Key
})
resp = append(resp, disksWithBus...)
}
return resp
}

func (r *Builder) mapDisks(vm *model.VM, vmRef ref.Ref, persistentVolumeClaims []*core.PersistentVolumeClaim, object *cnv.VirtualMachineSpec) {
var kVolumes []cnv.Volume
var kDisks []cnv.Disk
var templateErr error

disks := vm.Disks
sort.Slice(disks, func(i, j int) bool {
return disks[i].Key < disks[j].Key
})
disks := r.sortedDisks(vm.Disks)
pvcMap := make(map[string]*core.PersistentVolumeClaim)
for i := range persistentVolumeClaims {
pvc := persistentVolumeClaims[i]
Expand Down
84 changes: 84 additions & 0 deletions pkg/controller/plan/adapter/vsphere/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package vsphere
import (
v1beta1 "github.com/konveyor/forklift-controller/pkg/apis/forklift/v1beta1"
plancontext "github.com/konveyor/forklift-controller/pkg/controller/plan/context"
container "github.com/konveyor/forklift-controller/pkg/controller/provider/container/vsphere"
"github.com/konveyor/forklift-controller/pkg/controller/provider/model/vsphere"
model "github.com/konveyor/forklift-controller/pkg/controller/provider/web/vsphere"
"github.com/konveyor/forklift-controller/pkg/lib/logging"
Expand Down Expand Up @@ -131,6 +132,89 @@ var _ = Describe("vSphere builder", func() {
}},
}, "00:50:56:83:25:47:ip:172.29.3.193,172.29.3.1,16"),
)

DescribeTable("should", func(disks []vsphere.Disk, output []vsphere.Disk) {
Expect(builder.sortedDisks(disks)).Should(Equal(output))
},
Entry("sort all disks by buses",
[]vsphere.Disk{
{Key: 1, Bus: container.IDE},
{Key: 1, Bus: container.SATA},
{Key: 1, Bus: container.SCSI},
{Key: 2, Bus: container.SCSI},
},
[]vsphere.Disk{
{Key: 1, Bus: container.SCSI},
{Key: 2, Bus: container.SCSI},
{Key: 1, Bus: container.SATA},
{Key: 1, Bus: container.IDE},
},
),
Entry("sort IDE and SATA disks by buses",
[]vsphere.Disk{
{Key: 1, Bus: container.IDE},
{Key: 1, Bus: container.SATA},
},
[]vsphere.Disk{
{Key: 1, Bus: container.SATA},
{Key: 1, Bus: container.IDE},
},
),
Entry("sort multiple SATA disks by buses",
[]vsphere.Disk{
{Key: 3, Bus: container.SATA},
{Key: 1, Bus: container.SATA},
{Key: 2, Bus: container.SATA},
},
[]vsphere.Disk{
{Key: 1, Bus: container.SATA},
{Key: 2, Bus: container.SATA},
{Key: 3, Bus: container.SATA},
},
),
Entry("sort multiple SATA and multiple SCSI disks by buses",
[]vsphere.Disk{
{Key: 3, Bus: container.SATA},
{Key: 3, Bus: container.SCSI},
{Key: 2, Bus: container.SCSI},
{Key: 1, Bus: container.SATA},
{Key: 2, Bus: container.SATA},
{Key: 1, Bus: container.SCSI},
},
[]vsphere.Disk{
{Key: 1, Bus: container.SCSI},
{Key: 2, Bus: container.SCSI},
{Key: 3, Bus: container.SCSI},
{Key: 1, Bus: container.SATA},
{Key: 2, Bus: container.SATA},
{Key: 3, Bus: container.SATA},
},
),
Entry("sort multiple all disks by buses",
[]vsphere.Disk{
{Key: 2, Bus: container.IDE},
{Key: 3, Bus: container.SATA},
{Key: 3, Bus: container.SCSI},
{Key: 2, Bus: container.SCSI},
{Key: 3, Bus: container.IDE},
{Key: 1, Bus: container.SATA},
{Key: 2, Bus: container.SATA},
{Key: 1, Bus: container.SCSI},
{Key: 1, Bus: container.IDE},
},
[]vsphere.Disk{
{Key: 1, Bus: container.SCSI},
{Key: 2, Bus: container.SCSI},
{Key: 3, Bus: container.SCSI},
{Key: 1, Bus: container.SATA},
{Key: 2, Bus: container.SATA},
{Key: 3, Bus: container.SATA},
{Key: 1, Bus: container.IDE},
{Key: 2, Bus: container.IDE},
{Key: 3, Bus: container.IDE},
},
),
)
})

//nolint:errcheck
Expand Down
84 changes: 84 additions & 0 deletions pkg/controller/provider/container/vsphere/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ import (
"github.com/vmware/govmomi/vim25/types"
)

// Bus types
const (
NVME = "nvme"
USB = "usb"
SATA = "sata"
SCSI = "scsi"
IDE = "ide"
)

// Model adapter.
// Each adapter provides provider-specific management of a model.
type Adapter interface {
Expand Down Expand Up @@ -762,27 +771,99 @@ func (v *VmAdapter) Apply(u types.ObjectUpdate) {
}
v.model.Devices = devList
v.model.NICs = nicList
v.updateControllers(&devArray)
v.updateDisks(&devArray)
}
}
}
}
}

// Update virtual disk devices.
func (v *VmAdapter) updateControllers(devArray *types.ArrayOfVirtualDevice) {
controllers := []model.Controller{}
for _, dev := range devArray.VirtualDevice {
var md model.Controller
switch controller := dev.(type) {
case *types.VirtualIDEController:
md = model.Controller{
Bus: IDE,
Disks: controller.Device,
Key: controller.Key,
}
case *types.VirtualBusLogicController:
md = model.Controller{
Bus: SCSI,
Disks: controller.Device,
Key: controller.Key,
}
case *types.VirtualLsiLogicController:
md = model.Controller{
Bus: SCSI,
Disks: controller.Device,
Key: controller.Key,
}
case *types.VirtualLsiLogicSASController:
md = model.Controller{
Bus: SCSI,
Disks: controller.Device,
Key: controller.Key,
}
case *types.ParaVirtualSCSIController:
md = model.Controller{
Bus: SCSI,
Disks: controller.Device,
Key: controller.Key,
}
case *types.VirtualAHCIController:
md = model.Controller{
Bus: SATA,
Disks: controller.Device,
Key: controller.Key,
}
case *types.VirtualUSBController:
md = model.Controller{
Bus: USB,
Disks: controller.Device,
Key: controller.Key,
}
case *types.VirtualNVMEController:
md = model.Controller{
Bus: NVME,
Disks: controller.Device,
Key: controller.Key,
}
}
controllers = append(controllers, md)
}
v.model.Controllers = controllers
}

func (v *VmAdapter) getDiskController(key int32) *model.Controller {
for _, controller := range v.model.Controllers {
if controller.Key == key {
return &controller
}
}
return nil
}

// Update virtual disk devices.
func (v *VmAdapter) updateDisks(devArray *types.ArrayOfVirtualDevice) {
disks := []model.Disk{}
for _, dev := range devArray.VirtualDevice {
switch dev.(type) {
case *types.VirtualDisk:
disk := dev.(*types.VirtualDisk)
controller := v.getDiskController(disk.ControllerKey)
switch backing := disk.Backing.(type) {
case *types.VirtualDiskFlatVer1BackingInfo:
md := model.Disk{
Key: disk.Key,
File: backing.FileName,
Capacity: disk.CapacityInBytes,
Mode: backing.DiskMode,
Bus: controller.Bus,
}
if backing.Datastore != nil {
datastoreId, _ := sanitize(backing.Datastore.Value)
Expand All @@ -799,6 +880,7 @@ func (v *VmAdapter) updateDisks(devArray *types.ArrayOfVirtualDevice) {
Capacity: disk.CapacityInBytes,
Shared: backing.Sharing != "sharingNone",
Mode: backing.DiskMode,
Bus: controller.Bus,
}
if backing.Datastore != nil {
datastoreId, _ := sanitize(backing.Datastore.Value)
Expand All @@ -816,6 +898,7 @@ func (v *VmAdapter) updateDisks(devArray *types.ArrayOfVirtualDevice) {
Shared: backing.Sharing != "sharingNone",
Mode: backing.DiskMode,
RDM: true,
Bus: controller.Bus,
}
if backing.Datastore != nil {
datastoreId, _ := sanitize(backing.Datastore.Value)
Expand All @@ -832,6 +915,7 @@ func (v *VmAdapter) updateDisks(devArray *types.ArrayOfVirtualDevice) {
Capacity: disk.CapacityInBytes,
Shared: backing.Sharing != "sharingNone",
RDM: true,
Bus: controller.Bus,
}
disks = append(disks, md)
}
Expand Down
9 changes: 9 additions & 0 deletions pkg/controller/provider/model/vsphere/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ type VM struct {
Devices []Device `sql:""`
NICs []NIC `sql:""`
Disks []Disk `sql:""`
Controllers []Controller `sql:""`
Networks []Ref `sql:""`
Concerns []Concern `sql:""`
GuestNetworks []GuestNetwork `sql:""`
Expand All @@ -276,6 +277,13 @@ func (m *VM) Validated() bool {
return m.RevisionValidated == m.Revision
}

// Virtual Controller.
type Controller struct {
Key int32 `json:"key"`
Bus string `json:"bus"`
Disks []int32 `sql:""`
}

// Virtual Disk.
type Disk struct {
Key int32 `json:"key"`
Expand All @@ -284,6 +292,7 @@ type Disk struct {
Capacity int64 `json:"capacity"`
Shared bool `json:"shared"`
RDM bool `json:"rdm"`
Bus string `json:"bus"`
Mode string `json:"mode,omitempty"`
}

Expand Down
Loading