Skip to content

Commit

Permalink
Merge pull request #21576 from jakecorrenti/usb-passthrough
Browse files Browse the repository at this point in the history
machine: USB passthrough
  • Loading branch information
openshift-merge-bot[bot] authored Feb 9, 2024
2 parents bc9f1f0 + 7be6cd4 commit a9ba80b
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 50 deletions.
19 changes: 8 additions & 11 deletions cmd/podman/machine/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand All @@ -28,7 +29,7 @@ var (

var (
setFlags = SetFlags{}
setOpts = machine.SetOptions{}
setOpts = define.SetOptions{}
)

type SetFlags struct {
Expand Down Expand Up @@ -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
Expand All @@ -111,36 +109,35 @@ 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 {
return fmt.Errorf("new disk size must be larger than %d GB", mc.Resources.DiskSize)
}
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
}

Expand Down
14 changes: 9 additions & 5 deletions pkg/machine/applehv/stubber.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
11 changes: 1 addition & 10 deletions pkg/machine/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
12 changes: 12 additions & 0 deletions pkg/machine/define/setopts.go
Original file line number Diff line number Diff line change
@@ -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
}
26 changes: 15 additions & 11 deletions pkg/machine/hyperv/stubber.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand All @@ -308,42 +308,46 @@ 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 {
return fmt.Errorf("setting CPU and Memory for VM: %w", err)
}
}

if opts.USBs != nil {
return fmt.Errorf("changing USBs not supported for hyperv machines")
}

return nil
}

Expand Down
21 changes: 14 additions & 7 deletions pkg/machine/qemu/stubber.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/machine/shim/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
3 changes: 1 addition & 2 deletions pkg/machine/vmconfigs/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand Down
14 changes: 12 additions & 2 deletions pkg/machine/vmconfigs/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand All @@ -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
Expand All @@ -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

Expand Down
2 changes: 1 addition & 1 deletion pkg/machine/wsl/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit a9ba80b

Please sign in to comment.