mirror of
https://github.com/containers/podman.git
synced 2025-06-21 01:19:15 +08:00
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:
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/containers/common/pkg/strongunits"
|
"github.com/containers/common/pkg/strongunits"
|
||||||
"github.com/containers/podman/v5/cmd/podman/registry"
|
"github.com/containers/podman/v5/cmd/podman/registry"
|
||||||
"github.com/containers/podman/v5/pkg/machine"
|
"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/containers/podman/v5/pkg/machine/vmconfigs"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
@ -28,7 +29,7 @@ var (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
setFlags = SetFlags{}
|
setFlags = SetFlags{}
|
||||||
setOpts = machine.SetOptions{}
|
setOpts = define.SetOptions{}
|
||||||
)
|
)
|
||||||
|
|
||||||
type SetFlags struct {
|
type SetFlags struct {
|
||||||
@ -90,9 +91,6 @@ func init() {
|
|||||||
func setMachine(cmd *cobra.Command, args []string) error {
|
func setMachine(cmd *cobra.Command, args []string) error {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
newCPUs, newMemory *uint64
|
|
||||||
newDiskSize *strongunits.GiB
|
|
||||||
newRootful *bool
|
|
||||||
)
|
)
|
||||||
|
|
||||||
vmName := defaultMachineName
|
vmName := defaultMachineName
|
||||||
@ -111,15 +109,15 @@ func setMachine(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cmd.Flags().Changed("rootful") {
|
if cmd.Flags().Changed("rootful") {
|
||||||
newRootful = &setFlags.Rootful
|
setOpts.Rootful = &setFlags.Rootful
|
||||||
}
|
}
|
||||||
if cmd.Flags().Changed("cpus") {
|
if cmd.Flags().Changed("cpus") {
|
||||||
mc.Resources.CPUs = setFlags.CPUs
|
mc.Resources.CPUs = setFlags.CPUs
|
||||||
newCPUs = &mc.Resources.CPUs
|
setOpts.CPUs = &mc.Resources.CPUs
|
||||||
}
|
}
|
||||||
if cmd.Flags().Changed("memory") {
|
if cmd.Flags().Changed("memory") {
|
||||||
mc.Resources.Memory = setFlags.Memory
|
mc.Resources.Memory = setFlags.Memory
|
||||||
newMemory = &mc.Resources.Memory
|
setOpts.Memory = &mc.Resources.Memory
|
||||||
}
|
}
|
||||||
if cmd.Flags().Changed("disk-size") {
|
if cmd.Flags().Changed("disk-size") {
|
||||||
if setFlags.DiskSize <= mc.Resources.DiskSize {
|
if setFlags.DiskSize <= mc.Resources.DiskSize {
|
||||||
@ -127,20 +125,19 @@ func setMachine(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
mc.Resources.DiskSize = setFlags.DiskSize
|
mc.Resources.DiskSize = setFlags.DiskSize
|
||||||
newDiskSizeGB := strongunits.GiB(setFlags.DiskSize)
|
newDiskSizeGB := strongunits.GiB(setFlags.DiskSize)
|
||||||
newDiskSize = &newDiskSizeGB
|
setOpts.DiskSize = &newDiskSizeGB
|
||||||
}
|
}
|
||||||
if cmd.Flags().Changed("user-mode-networking") {
|
if cmd.Flags().Changed("user-mode-networking") {
|
||||||
// TODO This needs help
|
// TODO This needs help
|
||||||
setOpts.UserModeNetworking = &setFlags.UserModeNetworking
|
setOpts.UserModeNetworking = &setFlags.UserModeNetworking
|
||||||
}
|
}
|
||||||
if cmd.Flags().Changed("usb") {
|
if cmd.Flags().Changed("usb") {
|
||||||
// TODO This needs help
|
|
||||||
setOpts.USBs = &setFlags.USBs
|
setOpts.USBs = &setFlags.USBs
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point, we have the known changed information, etc
|
// At this point, we have the known changed information, etc
|
||||||
// Walk through changes to the providers if they need them
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,19 +79,23 @@ func (a AppleHVStubber) RemoveAndCleanMachines(_ *define.MachineDirs) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AppleHVStubber) SetProviderAttrs(mc *vmconfigs.MachineConfig, cpus, memory *uint64, newDiskSize *strongunits.GiB, newRootful *bool) error {
|
func (a AppleHVStubber) SetProviderAttrs(mc *vmconfigs.MachineConfig, opts define.SetOptions) error {
|
||||||
if newDiskSize != nil {
|
if opts.DiskSize != nil {
|
||||||
if err := resizeDisk(mc, *newDiskSize); err != nil {
|
if err := resizeDisk(mc, *opts.DiskSize); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if newRootful != nil && mc.HostUser.Rootful != *newRootful {
|
if opts.Rootful != nil && mc.HostUser.Rootful != *opts.Rootful {
|
||||||
if err := mc.SetRootful(*newRootful); err != nil {
|
if err := mc.SetRootful(*opts.Rootful); err != nil {
|
||||||
return err
|
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
|
// VFKit does not require saving memory, disk, or cpu
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -68,15 +68,6 @@ type ListResponse struct {
|
|||||||
UserModeNetworking bool
|
UserModeNetworking bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type SetOptions struct {
|
|
||||||
CPUs *uint64
|
|
||||||
DiskSize *uint64
|
|
||||||
Memory *uint64
|
|
||||||
Rootful *bool
|
|
||||||
UserModeNetworking *bool
|
|
||||||
USBs *[]string
|
|
||||||
}
|
|
||||||
|
|
||||||
type SSHOptions struct {
|
type SSHOptions struct {
|
||||||
Username string
|
Username string
|
||||||
Args []string
|
Args []string
|
||||||
@ -101,7 +92,7 @@ type VM interface {
|
|||||||
Init(opts define.InitOptions) (bool, error)
|
Init(opts define.InitOptions) (bool, error)
|
||||||
Inspect() (*InspectInfo, error)
|
Inspect() (*InspectInfo, error)
|
||||||
Remove(name string, opts RemoveOptions) (string, func() error, 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
|
SSH(name string, opts SSHOptions) error
|
||||||
Start(name string, opts StartOptions) error
|
Start(name string, opts StartOptions) error
|
||||||
State(bypass bool) (define.Status, error)
|
State(bypass bool) (define.Status, error)
|
||||||
|
12
pkg/machine/define/setopts.go
Normal file
12
pkg/machine/define/setopts.go
Normal file
@ -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())
|
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 (
|
var (
|
||||||
cpuChanged, memoryChanged bool
|
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")
|
return errors.New("unable to change settings unless vm is stopped")
|
||||||
}
|
}
|
||||||
|
|
||||||
if newRootful != nil && mc.HostUser.Rootful != *newRootful {
|
if opts.Rootful != nil && mc.HostUser.Rootful != *opts.Rootful {
|
||||||
if err := mc.SetRootful(*newRootful); err != nil {
|
if err := mc.SetRootful(*opts.Rootful); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if newDiskSize != nil {
|
if opts.DiskSize != nil {
|
||||||
if err := resizeDisk(*newDiskSize, mc.ImagePath); err != nil {
|
if err := resizeDisk(*opts.DiskSize, mc.ImagePath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if cpus != nil {
|
if opts.CPUs != nil {
|
||||||
cpuChanged = true
|
cpuChanged = true
|
||||||
}
|
}
|
||||||
if memory != nil {
|
if opts.Memory != nil {
|
||||||
memoryChanged = true
|
memoryChanged = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if cpuChanged || memoryChanged {
|
if cpuChanged || memoryChanged {
|
||||||
err := vm.UpdateProcessorMemSettings(func(ps *hypervctl.ProcessorSettings) {
|
err := vm.UpdateProcessorMemSettings(func(ps *hypervctl.ProcessorSettings) {
|
||||||
if cpuChanged {
|
if cpuChanged {
|
||||||
ps.VirtualQuantity = *cpus
|
ps.VirtualQuantity = *opts.CPUs
|
||||||
}
|
}
|
||||||
}, func(ms *hypervctl.MemorySettings) {
|
}, func(ms *hypervctl.MemorySettings) {
|
||||||
if memoryChanged {
|
if memoryChanged {
|
||||||
ms.DynamicMemoryEnabled = false
|
ms.DynamicMemoryEnabled = false
|
||||||
ms.VirtualQuantity = *memory
|
ms.VirtualQuantity = *opts.Memory
|
||||||
ms.Limit = *memory
|
ms.Limit = *opts.Memory
|
||||||
ms.Reservation = *memory
|
ms.Reservation = *opts.Memory
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if err != nil {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,8 +64,7 @@ func (q *QEMUStubber) setQEMUCommandLine(mc *vmconfigs.MachineConfig) error {
|
|||||||
q.Command.SetVirtfsMount(mount.Source, mount.Tag, securityModel, mount.ReadOnly)
|
q.Command.SetVirtfsMount(mount.Source, mount.Tag, securityModel, mount.ReadOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
q.Command.SetUSBHostPassthrough(mc.Resources.USBs)
|
||||||
// v.QEMUConfig.Command.SetUSBHostPassthrough(v.USBs)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -243,19 +242,27 @@ func (q *QEMUStubber) resizeDisk(newSize strongunits.GiB, diskPath *define.VMFil
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *QEMUStubber) SetProviderAttrs(mc *vmconfigs.MachineConfig, cpus, memory *uint64, newDiskSize *strongunits.GiB, newRootful *bool) error {
|
func (q *QEMUStubber) SetProviderAttrs(mc *vmconfigs.MachineConfig, opts define.SetOptions) error {
|
||||||
if newDiskSize != nil {
|
if opts.DiskSize != nil {
|
||||||
if err := q.resizeDisk(*newDiskSize, mc.ImagePath); err != nil {
|
if err := q.resizeDisk(*opts.DiskSize, mc.ImagePath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if newRootful != nil && mc.HostUser.Rootful != *newRootful {
|
if opts.Rootful != nil && mc.HostUser.Rootful != *opts.Rootful {
|
||||||
if err := mc.SetRootful(*newRootful); err != nil {
|
if err := mc.SetRootful(*opts.Rootful); err != nil {
|
||||||
return err
|
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
|
// Because QEMU does nothing with these hardware attributes, we can simply return
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ func Init(opts machineDefine.InitOptions, mp vmconfigs.VMProvider) (*vmconfigs.M
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
mc, err := vmconfigs.NewMachineConfig(opts, dirs, sshIdentityPath)
|
mc, err := vmconfigs.NewMachineConfig(opts, dirs, sshIdentityPath, mp.VMType())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containers/common/pkg/strongunits"
|
|
||||||
gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types"
|
gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types"
|
||||||
"github.com/containers/podman/v5/pkg/machine/define"
|
"github.com/containers/podman/v5/pkg/machine/define"
|
||||||
"github.com/containers/podman/v5/pkg/machine/ignition"
|
"github.com/containers/podman/v5/pkg/machine/ignition"
|
||||||
@ -114,7 +113,7 @@ type VMProvider interface { //nolint:interfacebloat
|
|||||||
MountVolumesToVM(mc *MachineConfig, quiet bool) error
|
MountVolumesToVM(mc *MachineConfig, quiet bool) error
|
||||||
Remove(mc *MachineConfig) ([]string, func() error, error)
|
Remove(mc *MachineConfig) ([]string, func() error, error)
|
||||||
RemoveAndCleanMachines(dirs *define.MachineDirs) 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
|
StartNetworking(mc *MachineConfig, cmd *gvproxy.GvproxyCommand) error
|
||||||
PostStartNetworking(mc *MachineConfig) error
|
PostStartNetworking(mc *MachineConfig) error
|
||||||
StartVM(mc *MachineConfig) (func() error, func() error, 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/connection"
|
||||||
"github.com/containers/podman/v5/pkg/machine/define"
|
"github.com/containers/podman/v5/pkg/machine/define"
|
||||||
"github.com/containers/podman/v5/pkg/machine/lock"
|
"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/containers/podman/v5/utils"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@ -40,7 +41,7 @@ var (
|
|||||||
type RemoteConnectionType string
|
type RemoteConnectionType string
|
||||||
|
|
||||||
// NewMachineConfig creates the initial machine configuration file from cli options
|
// 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 := new(MachineConfig)
|
||||||
mc.Name = opts.Name
|
mc.Name = opts.Name
|
||||||
mc.dirs = dirs
|
mc.dirs = dirs
|
||||||
@ -58,12 +59,21 @@ func NewMachineConfig(opts define.InitOptions, dirs *define.MachineDirs, sshIden
|
|||||||
}
|
}
|
||||||
mc.configPath = cf
|
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
|
// System Resources
|
||||||
mrc := ResourceConfig{
|
mrc := ResourceConfig{
|
||||||
CPUs: opts.CPUS,
|
CPUs: opts.CPUS,
|
||||||
DiskSize: opts.DiskSize,
|
DiskSize: opts.DiskSize,
|
||||||
Memory: opts.Memory,
|
Memory: opts.Memory,
|
||||||
USBs: nil, // Needs to be filled in by providers?
|
USBs: usbs,
|
||||||
}
|
}
|
||||||
mc.Resources = mrc
|
mc.Resources = mrc
|
||||||
|
|
||||||
|
@ -1105,7 +1105,7 @@ func setupWslProxyEnv() (hasProxy bool) {
|
|||||||
return
|
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.
|
// 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
|
// The setting(s) that failed to be applied will have its errors returned in setErrors
|
||||||
var setErrors []error
|
var setErrors []error
|
||||||
|
Reference in New Issue
Block a user