machine: USB passthrough
Sets up USB passthrough for machine. Additionally moves `SetOptions` out from `pkg/machine/config.go` to its own file in `pkg/machine/define/setopts.go`. [NO NEW TESTS NEEDED] Signed-off-by: Jake Correnti <jakecorrenti+github@proton.me>
This commit is contained in:
		
							parent
							
								
									5311233f86
								
							
						
					
					
						commit
						7be6cd4b09
					
				| 
						 | 
				
			
			@ -9,6 +9,7 @@ import (
 | 
			
		|||
	"github.com/containers/common/pkg/strongunits"
 | 
			
		||||
	"github.com/containers/podman/v5/cmd/podman/registry"
 | 
			
		||||
	"github.com/containers/podman/v5/pkg/machine"
 | 
			
		||||
	"github.com/containers/podman/v5/pkg/machine/define"
 | 
			
		||||
	"github.com/containers/podman/v5/pkg/machine/vmconfigs"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +29,7 @@ var (
 | 
			
		|||
 | 
			
		||||
var (
 | 
			
		||||
	setFlags = SetFlags{}
 | 
			
		||||
	setOpts  = machine.SetOptions{}
 | 
			
		||||
	setOpts  = define.SetOptions{}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type SetFlags struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -89,10 +90,7 @@ func init() {
 | 
			
		|||
 | 
			
		||||
func setMachine(cmd *cobra.Command, args []string) error {
 | 
			
		||||
	var (
 | 
			
		||||
		err                error
 | 
			
		||||
		newCPUs, newMemory *uint64
 | 
			
		||||
		newDiskSize        *strongunits.GiB
 | 
			
		||||
		newRootful         *bool
 | 
			
		||||
		err error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	vmName := defaultMachineName
 | 
			
		||||
| 
						 | 
				
			
			@ -111,15 +109,15 @@ func setMachine(cmd *cobra.Command, args []string) error {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	if cmd.Flags().Changed("rootful") {
 | 
			
		||||
		newRootful = &setFlags.Rootful
 | 
			
		||||
		setOpts.Rootful = &setFlags.Rootful
 | 
			
		||||
	}
 | 
			
		||||
	if cmd.Flags().Changed("cpus") {
 | 
			
		||||
		mc.Resources.CPUs = setFlags.CPUs
 | 
			
		||||
		newCPUs = &mc.Resources.CPUs
 | 
			
		||||
		setOpts.CPUs = &mc.Resources.CPUs
 | 
			
		||||
	}
 | 
			
		||||
	if cmd.Flags().Changed("memory") {
 | 
			
		||||
		mc.Resources.Memory = setFlags.Memory
 | 
			
		||||
		newMemory = &mc.Resources.Memory
 | 
			
		||||
		setOpts.Memory = &mc.Resources.Memory
 | 
			
		||||
	}
 | 
			
		||||
	if cmd.Flags().Changed("disk-size") {
 | 
			
		||||
		if setFlags.DiskSize <= mc.Resources.DiskSize {
 | 
			
		||||
| 
						 | 
				
			
			@ -127,20 +125,19 @@ func setMachine(cmd *cobra.Command, args []string) error {
 | 
			
		|||
		}
 | 
			
		||||
		mc.Resources.DiskSize = setFlags.DiskSize
 | 
			
		||||
		newDiskSizeGB := strongunits.GiB(setFlags.DiskSize)
 | 
			
		||||
		newDiskSize = &newDiskSizeGB
 | 
			
		||||
		setOpts.DiskSize = &newDiskSizeGB
 | 
			
		||||
	}
 | 
			
		||||
	if cmd.Flags().Changed("user-mode-networking") {
 | 
			
		||||
		// TODO This needs help
 | 
			
		||||
		setOpts.UserModeNetworking = &setFlags.UserModeNetworking
 | 
			
		||||
	}
 | 
			
		||||
	if cmd.Flags().Changed("usb") {
 | 
			
		||||
		// TODO This needs help
 | 
			
		||||
		setOpts.USBs = &setFlags.USBs
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// At this point, we have the known changed information, etc
 | 
			
		||||
	// Walk through changes to the providers if they need them
 | 
			
		||||
	if err := provider.SetProviderAttrs(mc, newCPUs, newMemory, newDiskSize, newRootful); err != nil {
 | 
			
		||||
	if err := provider.SetProviderAttrs(mc, setOpts); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -79,19 +79,23 @@ func (a AppleHVStubber) RemoveAndCleanMachines(_ *define.MachineDirs) error {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a AppleHVStubber) SetProviderAttrs(mc *vmconfigs.MachineConfig, cpus, memory *uint64, newDiskSize *strongunits.GiB, newRootful *bool) error {
 | 
			
		||||
	if newDiskSize != nil {
 | 
			
		||||
		if err := resizeDisk(mc, *newDiskSize); err != nil {
 | 
			
		||||
func (a AppleHVStubber) SetProviderAttrs(mc *vmconfigs.MachineConfig, opts define.SetOptions) error {
 | 
			
		||||
	if opts.DiskSize != nil {
 | 
			
		||||
		if err := resizeDisk(mc, *opts.DiskSize); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if newRootful != nil && mc.HostUser.Rootful != *newRootful {
 | 
			
		||||
		if err := mc.SetRootful(*newRootful); err != nil {
 | 
			
		||||
	if opts.Rootful != nil && mc.HostUser.Rootful != *opts.Rootful {
 | 
			
		||||
		if err := mc.SetRootful(*opts.Rootful); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.USBs != nil {
 | 
			
		||||
		return fmt.Errorf("changing USBs not supported for applehv machines")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// VFKit does not require saving memory, disk, or cpu
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,15 +68,6 @@ type ListResponse struct {
 | 
			
		|||
	UserModeNetworking bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type SetOptions struct {
 | 
			
		||||
	CPUs               *uint64
 | 
			
		||||
	DiskSize           *uint64
 | 
			
		||||
	Memory             *uint64
 | 
			
		||||
	Rootful            *bool
 | 
			
		||||
	UserModeNetworking *bool
 | 
			
		||||
	USBs               *[]string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type SSHOptions struct {
 | 
			
		||||
	Username string
 | 
			
		||||
	Args     []string
 | 
			
		||||
| 
						 | 
				
			
			@ -101,7 +92,7 @@ type VM interface {
 | 
			
		|||
	Init(opts define.InitOptions) (bool, error)
 | 
			
		||||
	Inspect() (*InspectInfo, error)
 | 
			
		||||
	Remove(name string, opts RemoveOptions) (string, func() error, error)
 | 
			
		||||
	Set(name string, opts SetOptions) ([]error, error)
 | 
			
		||||
	Set(name string, opts define.SetOptions) ([]error, error)
 | 
			
		||||
	SSH(name string, opts SSHOptions) error
 | 
			
		||||
	Start(name string, opts StartOptions) error
 | 
			
		||||
	State(bypass bool) (define.Status, error)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
package define
 | 
			
		||||
 | 
			
		||||
import "github.com/containers/common/pkg/strongunits"
 | 
			
		||||
 | 
			
		||||
type SetOptions struct {
 | 
			
		||||
	CPUs               *uint64
 | 
			
		||||
	DiskSize           *strongunits.GiB
 | 
			
		||||
	Memory             *uint64
 | 
			
		||||
	Rootful            *bool
 | 
			
		||||
	UserModeNetworking *bool
 | 
			
		||||
	USBs               *[]string
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -290,7 +290,7 @@ func stateConversion(s hypervctl.EnabledState) (define.Status, error) {
 | 
			
		|||
	return define.Unknown, fmt.Errorf("unknown state: %q", s.String())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h HyperVStubber) SetProviderAttrs(mc *vmconfigs.MachineConfig, cpus, memory *uint64, newDiskSize *strongunits.GiB, newRootful *bool) error {
 | 
			
		||||
func (h HyperVStubber) SetProviderAttrs(mc *vmconfigs.MachineConfig, opts define.SetOptions) error {
 | 
			
		||||
	var (
 | 
			
		||||
		cpuChanged, memoryChanged bool
 | 
			
		||||
	)
 | 
			
		||||
| 
						 | 
				
			
			@ -308,35 +308,35 @@ func (h HyperVStubber) SetProviderAttrs(mc *vmconfigs.MachineConfig, cpus, memor
 | 
			
		|||
		return errors.New("unable to change settings unless vm is stopped")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if newRootful != nil && mc.HostUser.Rootful != *newRootful {
 | 
			
		||||
		if err := mc.SetRootful(*newRootful); err != nil {
 | 
			
		||||
	if opts.Rootful != nil && mc.HostUser.Rootful != *opts.Rootful {
 | 
			
		||||
		if err := mc.SetRootful(*opts.Rootful); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if newDiskSize != nil {
 | 
			
		||||
		if err := resizeDisk(*newDiskSize, mc.ImagePath); err != nil {
 | 
			
		||||
	if opts.DiskSize != nil {
 | 
			
		||||
		if err := resizeDisk(*opts.DiskSize, mc.ImagePath); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if cpus != nil {
 | 
			
		||||
	if opts.CPUs != nil {
 | 
			
		||||
		cpuChanged = true
 | 
			
		||||
	}
 | 
			
		||||
	if memory != nil {
 | 
			
		||||
	if opts.Memory != nil {
 | 
			
		||||
		memoryChanged = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if cpuChanged || memoryChanged {
 | 
			
		||||
		err := vm.UpdateProcessorMemSettings(func(ps *hypervctl.ProcessorSettings) {
 | 
			
		||||
			if cpuChanged {
 | 
			
		||||
				ps.VirtualQuantity = *cpus
 | 
			
		||||
				ps.VirtualQuantity = *opts.CPUs
 | 
			
		||||
			}
 | 
			
		||||
		}, func(ms *hypervctl.MemorySettings) {
 | 
			
		||||
			if memoryChanged {
 | 
			
		||||
				ms.DynamicMemoryEnabled = false
 | 
			
		||||
				ms.VirtualQuantity = *memory
 | 
			
		||||
				ms.Limit = *memory
 | 
			
		||||
				ms.Reservation = *memory
 | 
			
		||||
				ms.VirtualQuantity = *opts.Memory
 | 
			
		||||
				ms.Limit = *opts.Memory
 | 
			
		||||
				ms.Reservation = *opts.Memory
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -344,6 +344,10 @@ func (h HyperVStubber) SetProviderAttrs(mc *vmconfigs.MachineConfig, cpus, memor
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.USBs != nil {
 | 
			
		||||
		return fmt.Errorf("changing USBs not supported for hyperv machines")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -64,8 +64,7 @@ func (q *QEMUStubber) setQEMUCommandLine(mc *vmconfigs.MachineConfig) error {
 | 
			
		|||
		q.Command.SetVirtfsMount(mount.Source, mount.Tag, securityModel, mount.ReadOnly)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TODO
 | 
			
		||||
	// v.QEMUConfig.Command.SetUSBHostPassthrough(v.USBs)
 | 
			
		||||
	q.Command.SetUSBHostPassthrough(mc.Resources.USBs)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -243,19 +242,27 @@ func (q *QEMUStubber) resizeDisk(newSize strongunits.GiB, diskPath *define.VMFil
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (q *QEMUStubber) SetProviderAttrs(mc *vmconfigs.MachineConfig, cpus, memory *uint64, newDiskSize *strongunits.GiB, newRootful *bool) error {
 | 
			
		||||
	if newDiskSize != nil {
 | 
			
		||||
		if err := q.resizeDisk(*newDiskSize, mc.ImagePath); err != nil {
 | 
			
		||||
func (q *QEMUStubber) SetProviderAttrs(mc *vmconfigs.MachineConfig, opts define.SetOptions) error {
 | 
			
		||||
	if opts.DiskSize != nil {
 | 
			
		||||
		if err := q.resizeDisk(*opts.DiskSize, mc.ImagePath); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if newRootful != nil && mc.HostUser.Rootful != *newRootful {
 | 
			
		||||
		if err := mc.SetRootful(*newRootful); err != nil {
 | 
			
		||||
	if opts.Rootful != nil && mc.HostUser.Rootful != *opts.Rootful {
 | 
			
		||||
		if err := mc.SetRootful(*opts.Rootful); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.USBs != nil {
 | 
			
		||||
		usbs, err := command.ParseUSBs(*opts.USBs)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		mc.Resources.USBs = usbs
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Because QEMU does nothing with these hardware attributes, we can simply return
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -104,7 +104,7 @@ func Init(opts machineDefine.InitOptions, mp vmconfigs.VMProvider) (*vmconfigs.M
 | 
			
		|||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mc, err := vmconfigs.NewMachineConfig(opts, dirs, sshIdentityPath)
 | 
			
		||||
	mc, err := vmconfigs.NewMachineConfig(opts, dirs, sshIdentityPath, mp.VMType())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,6 @@ import (
 | 
			
		|||
	"net/url"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/containers/common/pkg/strongunits"
 | 
			
		||||
	gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types"
 | 
			
		||||
	"github.com/containers/podman/v5/pkg/machine/define"
 | 
			
		||||
	"github.com/containers/podman/v5/pkg/machine/ignition"
 | 
			
		||||
| 
						 | 
				
			
			@ -114,7 +113,7 @@ type VMProvider interface { //nolint:interfacebloat
 | 
			
		|||
	MountVolumesToVM(mc *MachineConfig, quiet bool) error
 | 
			
		||||
	Remove(mc *MachineConfig) ([]string, func() error, error)
 | 
			
		||||
	RemoveAndCleanMachines(dirs *define.MachineDirs) error
 | 
			
		||||
	SetProviderAttrs(mc *MachineConfig, cpus, memory *uint64, newDiskSize *strongunits.GiB, newRootful *bool) error
 | 
			
		||||
	SetProviderAttrs(mc *MachineConfig, opts define.SetOptions) error
 | 
			
		||||
	StartNetworking(mc *MachineConfig, cmd *gvproxy.GvproxyCommand) error
 | 
			
		||||
	PostStartNetworking(mc *MachineConfig) error
 | 
			
		||||
	StartVM(mc *MachineConfig) (func() error, func() error, error)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,7 @@ import (
 | 
			
		|||
	"github.com/containers/podman/v5/pkg/machine/connection"
 | 
			
		||||
	"github.com/containers/podman/v5/pkg/machine/define"
 | 
			
		||||
	"github.com/containers/podman/v5/pkg/machine/lock"
 | 
			
		||||
	"github.com/containers/podman/v5/pkg/machine/qemu/command"
 | 
			
		||||
	"github.com/containers/podman/v5/utils"
 | 
			
		||||
	"github.com/sirupsen/logrus"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +41,7 @@ var (
 | 
			
		|||
type RemoteConnectionType string
 | 
			
		||||
 | 
			
		||||
// NewMachineConfig creates the initial machine configuration file from cli options
 | 
			
		||||
func NewMachineConfig(opts define.InitOptions, dirs *define.MachineDirs, sshIdentityPath string) (*MachineConfig, error) {
 | 
			
		||||
func NewMachineConfig(opts define.InitOptions, dirs *define.MachineDirs, sshIdentityPath string, vmtype define.VMType) (*MachineConfig, error) {
 | 
			
		||||
	mc := new(MachineConfig)
 | 
			
		||||
	mc.Name = opts.Name
 | 
			
		||||
	mc.dirs = dirs
 | 
			
		||||
| 
						 | 
				
			
			@ -58,12 +59,21 @@ func NewMachineConfig(opts define.InitOptions, dirs *define.MachineDirs, sshIden
 | 
			
		|||
	}
 | 
			
		||||
	mc.configPath = cf
 | 
			
		||||
 | 
			
		||||
	if vmtype != define.QemuVirt && len(opts.USBs) > 0 {
 | 
			
		||||
		return nil, fmt.Errorf("USB host passthrough not supported for %s machines", vmtype)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	usbs, err := command.ParseUSBs(opts.USBs)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// System Resources
 | 
			
		||||
	mrc := ResourceConfig{
 | 
			
		||||
		CPUs:     opts.CPUS,
 | 
			
		||||
		DiskSize: opts.DiskSize,
 | 
			
		||||
		Memory:   opts.Memory,
 | 
			
		||||
		USBs:     nil, // Needs to be filled in by providers?
 | 
			
		||||
		USBs:     usbs,
 | 
			
		||||
	}
 | 
			
		||||
	mc.Resources = mrc
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1105,7 +1105,7 @@ func setupWslProxyEnv() (hasProxy bool) {
 | 
			
		|||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v *MachineVM) Set(_ string, opts machine.SetOptions) ([]error, error) {
 | 
			
		||||
func (v *MachineVM) Set(_ string, opts define.SetOptions) ([]error, error) {
 | 
			
		||||
	// If one setting fails to be applied, the others settings will not fail and still be applied.
 | 
			
		||||
	// The setting(s) that failed to be applied will have its errors returned in setErrors
 | 
			
		||||
	var setErrors []error
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue