From a5db53d988282e9c4240e52cc969a45793c0e17a Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Wed, 28 Jun 2023 12:49:04 +0200 Subject: [PATCH] vf: Add toVz() methods for all virtio devices This follows the same model as for virtio-fs or virtio-blk devices so that it's possible to add multiple devices of the same type to the VM. The only exception is virtio-vsock which is documented by Apple as only being allowed once. --- pkg/vf/virtio.go | 113 +++++++++++++++++++++++++---------------------- pkg/vf/vm.go | 24 ++++++++-- 2 files changed, 79 insertions(+), 58 deletions(-) diff --git a/pkg/vf/virtio.go b/pkg/vf/virtio.go index 8e2d5cb8..a30a6696 100644 --- a/pkg/vf/virtio.go +++ b/pkg/vf/virtio.go @@ -50,7 +50,7 @@ func (dev *VirtioBlk) AddToVirtualMachineConfig(vmConfig *vzVirtualMachineConfig return err } log.Infof("Adding virtio-blk device (imagePath: %s)", dev.ImagePath) - vmConfig.storageDeviceConfiguration = append(vmConfig.storageDeviceConfiguration, storageDeviceConfig) + vmConfig.storageDevicesConfiguration = append(vmConfig.storageDevicesConfiguration, storageDeviceConfig) return nil } @@ -80,17 +80,13 @@ func (dev *VirtioInput) AddToVirtualMachineConfig(vmConfig *vzVirtualMachineConf return err } - log.Infof("Adding virtio-input device") - switch conf := inputDeviceConfig.(type) { - case *vz.USBScreenCoordinatePointingDeviceConfiguration: - vmConfig.SetPointingDevicesVirtualMachineConfiguration([]vz.PointingDeviceConfiguration{ - conf, - }) - case *vz.USBKeyboardConfiguration: - vmConfig.SetKeyboardsVirtualMachineConfiguration([]vz.KeyboardConfiguration{ - conf, - }) + case vz.PointingDeviceConfiguration: + log.Info("Adding virtio-input pointing device") + vmConfig.pointingDevicesConfiguration = append(vmConfig.pointingDevicesConfiguration, conf) + case vz.KeyboardConfiguration: + log.Info("Adding virtio-input keyboard device") + vmConfig.keyboardConfiguration = append(vmConfig.keyboardConfiguration, conf) } return nil @@ -120,9 +116,7 @@ func (dev *VirtioGPU) AddToVirtualMachineConfig(vmConfig *vzVirtualMachineConfig log.Infof("Adding virtio-gpu device") - vmConfig.SetGraphicsDevicesVirtualMachineConfiguration([]vz.GraphicsDeviceConfiguration{ - gpuDeviceConfig, - }) + vmConfig.graphicsDevicesConfiguration = append(vmConfig.graphicsDevicesConfiguration, gpuDeviceConfig) return nil } @@ -161,7 +155,7 @@ func (dev *VirtioFs) AddToVirtualMachineConfig(vmConfig *vzVirtualMachineConfigu return err } log.Infof("Adding virtio-fs device") - vmConfig.directorySharingDeviceConfiguration = append(vmConfig.directorySharingDeviceConfiguration, fileSystemDeviceConfig) + vmConfig.directorySharingDevicesConfiguration = append(vmConfig.directorySharingDevicesConfiguration, fileSystemDeviceConfig) return nil } @@ -180,30 +174,19 @@ func (dev *VirtioNet) connectUnixPath() error { return nil } -func (dev *VirtioNet) AddToVirtualMachineConfig(vmConfig *vzVirtualMachineConfiguration) error { +func (dev *VirtioNet) toVz() (*vz.VirtioNetworkDeviceConfiguration, error) { var ( mac *vz.MACAddress err error ) - log.Infof("Adding virtio-net device (nat: %t macAddress: [%s])", dev.Nat, dev.MacAddress) - if dev.Socket != nil { - log.Infof("Using fd %d", dev.Socket.Fd()) - } - if dev.UnixSocketPath != "" { - log.Infof("Using unix socket %s", dev.UnixSocketPath) - if err := dev.connectUnixPath(); err != nil { - return err - } - } - if len(dev.MacAddress) == 0 { mac, err = vz.NewRandomLocallyAdministeredMACAddress() } else { mac, err = vz.NewMACAddress(dev.MacAddress) } if err != nil { - return err + return nil, err } var attachment vz.NetworkDeviceAttachment if dev.Socket != nil { @@ -212,29 +195,49 @@ func (dev *VirtioNet) AddToVirtualMachineConfig(vmConfig *vzVirtualMachineConfig attachment, err = vz.NewNATNetworkDeviceAttachment() } if err != nil { - return err + return nil, err } networkConfig, err := vz.NewVirtioNetworkDeviceConfiguration(attachment) if err != nil { - return err + return nil, err } networkConfig.SetMACAddress(mac) - vmConfig.SetNetworkDevicesVirtualMachineConfiguration([]*vz.VirtioNetworkDeviceConfiguration{ - networkConfig, - }) + + return networkConfig, nil +} + +func (dev *VirtioNet) AddToVirtualMachineConfig(vmConfig *vzVirtualMachineConfiguration) error { + log.Infof("Adding virtio-net device (nat: %t macAddress: [%s])", dev.Nat, dev.MacAddress) + if dev.Socket != nil { + log.Infof("Using fd %d", dev.Socket.Fd()) + } + if dev.UnixSocketPath != "" { + log.Infof("Using unix socket %s", dev.UnixSocketPath) + if err := dev.connectUnixPath(); err != nil { + return err + } + } + netConfig, err := dev.toVz() + if err != nil { + return err + } + + vmConfig.networkDevicesConfiguration = append(vmConfig.networkDevicesConfiguration, netConfig) return nil } +func (dev *VirtioRng) toVz() (*vz.VirtioEntropyDeviceConfiguration, error) { + return vz.NewVirtioEntropyDeviceConfiguration() +} + func (dev *VirtioRng) AddToVirtualMachineConfig(vmConfig *vzVirtualMachineConfiguration) error { log.Infof("Adding virtio-rng device") - entropyConfig, err := vz.NewVirtioEntropyDeviceConfiguration() + entropyConfig, err := dev.toVz() if err != nil { return err } - vmConfig.SetEntropyDevicesVirtualMachineConfiguration([]*vz.VirtioEntropyDeviceConfiguration{ - entropyConfig, - }) + vmConfig.entropyDevicesConfiguration = append(vmConfig.entropyDevicesConfiguration, entropyConfig) return nil } @@ -259,41 +262,43 @@ func setRawMode(f *os.File) error { return unix.IoctlSetTermios(int(f.Fd()), unix.TIOCSETA, attr) } -func (dev *VirtioSerial) AddToVirtualMachineConfig(vmConfig *vzVirtualMachineConfiguration) error { - if dev.LogFile != "" { - log.Infof("Adding virtio-serial device (logFile: %s)", dev.LogFile) - } - if dev.UsesStdio { - log.Infof("Adding stdio console") - } - +func (dev *VirtioSerial) toVz() (*vz.VirtioConsoleDeviceSerialPortConfiguration, error) { var serialPortAttachment vz.SerialPortAttachment var err error if dev.UsesStdio { if err := setRawMode(os.Stdin); err != nil { - return err + return nil, err } serialPortAttachment, err = vz.NewFileHandleSerialPortAttachment(os.Stdin, os.Stdout) } else { serialPortAttachment, err = vz.NewFileSerialPortAttachment(dev.LogFile, false) } if err != nil { - return err + return nil, err + } + + return vz.NewVirtioConsoleDeviceSerialPortConfiguration(serialPortAttachment) + +} +func (dev *VirtioSerial) AddToVirtualMachineConfig(vmConfig *vzVirtualMachineConfiguration) error { + if dev.LogFile != "" { + log.Infof("Adding virtio-serial device (logFile: %s)", dev.LogFile) + } + if dev.UsesStdio { + log.Infof("Adding stdio console") } - consoleConfig, err := vz.NewVirtioConsoleDeviceSerialPortConfiguration(serialPortAttachment) + consoleConfig, err := dev.toVz() if err != nil { return err } - vmConfig.SetSerialPortsVirtualMachineConfiguration([]*vz.VirtioConsoleDeviceSerialPortConfiguration{ - consoleConfig, - }) + vmConfig.serialPortsConfiguration = append(vmConfig.serialPortsConfiguration, consoleConfig) return nil } func (dev *VirtioVsock) AddToVirtualMachineConfig(vmConfig *vzVirtualMachineConfiguration) error { - if len(vmConfig.SocketDevices()) != 0 { + if len(vmConfig.socketDevicesConfiguration) != 0 { log.Debugf("virtio-vsock device already present, not adding a second one") return nil } @@ -302,7 +307,7 @@ func (dev *VirtioVsock) AddToVirtualMachineConfig(vmConfig *vzVirtualMachineConf if err != nil { return err } - vmConfig.SetSocketDevicesVirtualMachineConfiguration([]vz.SocketDeviceConfiguration{vzdev}) + vmConfig.socketDevicesConfiguration = append(vmConfig.socketDevicesConfiguration, vzdev) return nil } @@ -354,7 +359,7 @@ func (dev *USBMassStorage) AddToVirtualMachineConfig(vmConfig *vzVirtualMachineC return err } log.Infof("Adding USB mass storage device (imagePath: %s)", dev.ImagePath) - vmConfig.storageDeviceConfiguration = append(vmConfig.storageDeviceConfiguration, storageDeviceConfig) + vmConfig.storageDevicesConfiguration = append(vmConfig.storageDevicesConfiguration, storageDeviceConfig) return nil } diff --git a/pkg/vf/vm.go b/pkg/vf/vm.go index 010b5c6c..a34b38f1 100644 --- a/pkg/vf/vm.go +++ b/pkg/vf/vm.go @@ -9,8 +9,15 @@ import ( type vzVirtualMachineConfiguration struct { *vz.VirtualMachineConfiguration - storageDeviceConfiguration []vz.StorageDeviceConfiguration - directorySharingDeviceConfiguration []vz.DirectorySharingDeviceConfiguration + storageDevicesConfiguration []vz.StorageDeviceConfiguration + directorySharingDevicesConfiguration []vz.DirectorySharingDeviceConfiguration + keyboardConfiguration []vz.KeyboardConfiguration + pointingDevicesConfiguration []vz.PointingDeviceConfiguration + graphicsDevicesConfiguration []vz.GraphicsDeviceConfiguration + networkDevicesConfiguration []*vz.VirtioNetworkDeviceConfiguration + entropyDevicesConfiguration []*vz.VirtioEntropyDeviceConfiguration + serialPortsConfiguration []*vz.VirtioConsoleDeviceSerialPortConfiguration + socketDevicesConfiguration []vz.SocketDeviceConfiguration } func newVzVirtualMachineConfiguration(vm *config.VirtualMachine) (*vzVirtualMachineConfiguration, error) { @@ -40,8 +47,17 @@ func ToVzVirtualMachineConfig(vm *config.VirtualMachine) (*vz.VirtualMachineConf return nil, err } } - vzVMConfig.SetStorageDevicesVirtualMachineConfiguration(vzVMConfig.storageDeviceConfiguration) - vzVMConfig.SetDirectorySharingDevicesVirtualMachineConfiguration(vzVMConfig.directorySharingDeviceConfiguration) + vzVMConfig.SetStorageDevicesVirtualMachineConfiguration(vzVMConfig.storageDevicesConfiguration) + vzVMConfig.SetDirectorySharingDevicesVirtualMachineConfiguration(vzVMConfig.directorySharingDevicesConfiguration) + vzVMConfig.SetPointingDevicesVirtualMachineConfiguration(vzVMConfig.pointingDevicesConfiguration) + vzVMConfig.SetKeyboardsVirtualMachineConfiguration(vzVMConfig.keyboardConfiguration) + vzVMConfig.SetGraphicsDevicesVirtualMachineConfiguration(vzVMConfig.graphicsDevicesConfiguration) + vzVMConfig.SetNetworkDevicesVirtualMachineConfiguration(vzVMConfig.networkDevicesConfiguration) + vzVMConfig.SetEntropyDevicesVirtualMachineConfiguration(vzVMConfig.entropyDevicesConfiguration) + vzVMConfig.SetSerialPortsVirtualMachineConfiguration(vzVMConfig.serialPortsConfiguration) + // len(vzVMConfig.socketDevicesConfiguration should be 0 or 1 + // https://developer.apple.com/documentation/virtualization/vzvirtiosocketdeviceconfiguration?language=objc + vzVMConfig.SetSocketDevicesVirtualMachineConfiguration(vzVMConfig.socketDevicesConfiguration) if vm.Timesync != nil && vm.Timesync.VsockPort != 0 { // automatically add the vsock device we'll need for communication over VsockPort