Merge pull request #3891 from fredericdalleau/qemu-virtiofs

Add virtiofs command line option for qemu run
This commit is contained in:
Rolf Neugebauer 2023-02-28 21:32:44 +00:00 committed by GitHub
commit 7d9f1f03a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 157 additions and 83 deletions

View File

@ -23,28 +23,30 @@ const (
// QemuConfig contains the config for Qemu
type QemuConfig struct {
Path string
ISOBoot bool
UEFI bool
SquashFS bool
Kernel bool
GUI bool
Disks Disks
ISOImages []string
StatePath string
FWPath string
Arch string
CPUs string
Memory string
Accel string
Detached bool
QemuBinPath string
QemuImgPath string
PublishedPorts []string
NetdevConfig string
UUID uuid.UUID
USB bool
Devices []string
Path string
ISOBoot bool
UEFI bool
SquashFS bool
Kernel bool
GUI bool
Disks Disks
ISOImages []string
StatePath string
FWPath string
Arch string
CPUs string
Memory string
Accel string
Detached bool
QemuBinPath string
QemuImgPath string
PublishedPorts []string
NetdevConfig string
UUID uuid.UUID
USB bool
Devices []string
VirtiofsdBinPath string
VirtiofsShares []string
}
const (
@ -119,23 +121,25 @@ func generateMAC() net.HardwareAddr {
func runQEMUCmd() *cobra.Command {
var (
enableGUI bool
uefiBoot bool
isoBoot bool
squashFSBoot bool
kernelBoot bool
state string
data string
dataPath string
fw string
accel string
arch string
qemuCmd string
qemuDetached bool
networking string
usbEnabled bool
deviceFlags multipleFlag
publishFlags multipleFlag
enableGUI bool
uefiBoot bool
isoBoot bool
squashFSBoot bool
kernelBoot bool
state string
data string
dataPath string
fw string
accel string
arch string
qemuCmd string
qemuDetached bool
networking string
usbEnabled bool
deviceFlags multipleFlag
publishFlags multipleFlag
virtiofsdCmd string
virtiofsShares []string
)
cmd := &cobra.Command{
@ -279,34 +283,43 @@ func runQEMUCmd() *cobra.Command {
}
config := QemuConfig{
Path: path,
ISOBoot: isoBoot,
UEFI: uefiBoot,
SquashFS: squashFSBoot,
Kernel: kernelBoot,
GUI: enableGUI,
Disks: disks,
ISOImages: isoPaths,
StatePath: state,
FWPath: fw,
Arch: arch,
CPUs: fmt.Sprintf("%d", cpus),
Memory: fmt.Sprintf("%d", mem),
Accel: accel,
Detached: qemuDetached,
QemuBinPath: qemuCmd,
PublishedPorts: publishFlags,
NetdevConfig: netdevConfig,
UUID: vmUUID,
USB: usbEnabled,
Devices: deviceFlags,
Path: path,
ISOBoot: isoBoot,
UEFI: uefiBoot,
SquashFS: squashFSBoot,
Kernel: kernelBoot,
GUI: enableGUI,
Disks: disks,
ISOImages: isoPaths,
StatePath: state,
FWPath: fw,
Arch: arch,
CPUs: fmt.Sprintf("%d", cpus),
Memory: fmt.Sprintf("%d", mem),
Accel: accel,
Detached: qemuDetached,
QemuBinPath: qemuCmd,
PublishedPorts: publishFlags,
NetdevConfig: netdevConfig,
UUID: vmUUID,
USB: usbEnabled,
Devices: deviceFlags,
VirtiofsdBinPath: virtiofsdCmd,
VirtiofsShares: virtiofsShares,
}
config, err = discoverBinaries(config)
config, err = discoverQemu(config)
if err != nil {
return err
}
if len(config.VirtiofsShares) > 0 {
config, err = discoverVirtiofsd(config)
if err != nil {
return err
}
}
if err = runQemuLocal(config); err != nil {
return err
}
@ -351,6 +364,10 @@ func runQEMUCmd() *cobra.Command {
cmd.Flags().BoolVar(&usbEnabled, "usb", false, "Enable USB controller")
cmd.Flags().Var(&deviceFlags, "device", "Add USB host device(s). Format driver[,prop=value][,...] -- add device, like -device on the qemu command line.")
// Filesystems
cmd.Flags().StringVar(&virtiofsdCmd, "virtiofsd", "", "Path to virtiofsd binary (otherwise look in /usr/lib/qemu and /usr/local/lib/qemu)")
cmd.Flags().StringArrayVar(&virtiofsShares, "virtiofs", []string{}, "Directory shared on virtiofs")
return cmd
}
@ -398,6 +415,25 @@ func runQemuLocal(config QemuConfig) error {
return fmt.Errorf("Detached mode is only supported when running in a container, not locally")
}
if len(config.VirtiofsShares) > 0 {
args = append(args, "-object", "memory-backend-memfd,id=mem,size="+config.Memory+"M,share=on", "-numa", "node,memdev=mem")
}
for index, source := range config.VirtiofsShares {
socket := filepath.Join(config.StatePath, fmt.Sprintf("%s%d", "virtiofs", index))
cmd := exec.Command(config.VirtiofsdBinPath,
"--socket-path="+socket,
"-o", fmt.Sprintf("source=%s", source))
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Start(); err != nil {
return fmt.Errorf("virtiofs server cannot start: %v", err)
}
args = append(args, "-chardev", fmt.Sprintf("socket,id=char%d,path=%s", index, socket))
args = append(args, "-device",
fmt.Sprintf("vhost-user-fs-pci,chardev=char%d,tag=virtiofs%d", index, index))
}
qemuCmd := exec.Command(config.QemuBinPath, args...)
// If verbosity is enabled print out the full path/arguments
log.Debugf("%v\n", qemuCmd.Args)
@ -589,7 +625,7 @@ func buildQemuCmdline(config QemuConfig) (QemuConfig, []string) {
return config, qemuArgs
}
func discoverBinaries(config QemuConfig) (QemuConfig, error) {
func discoverQemu(config QemuConfig) (QemuConfig, error) {
if config.QemuImgPath != "" {
return config, nil
}
@ -611,6 +647,16 @@ func discoverBinaries(config QemuConfig) (QemuConfig, error) {
return config, nil
}
func discoverVirtiofsd(config QemuConfig) (QemuConfig, error) {
if config.VirtiofsdBinPath != "" {
return config, nil
}
virtiofsdPath := filepath.Dir(config.QemuBinPath)
config.VirtiofsdBinPath = filepath.Join(virtiofsdPath, "..", "lib", "qemu", "virtiofsd")
return config, nil
}
func buildQemuForwardings(publishFlags multipleFlag) (string, error) {
if len(publishFlags) == 0 {
return "", nil

View File

@ -14,23 +14,25 @@ const (
)
type virtualizationFramwworkConfig struct {
cpus uint
mem uint64
disks Disks
data string
dataPath string
state string
networking string
kernelBoot bool
cpus uint
mem uint64
disks Disks
data string
dataPath string
state string
networking string
kernelBoot bool
virtiofsShares []string
}
func runVirtualizationFrameworkCmd() *cobra.Command {
var (
data string
dataPath string
state string
networking string
kernelBoot bool
data string
dataPath string
state string
networking string
kernelBoot bool
virtiofsShares []string
)
cmd := &cobra.Command{
@ -43,14 +45,15 @@ func runVirtualizationFrameworkCmd() *cobra.Command {
Example: "linuxkit run virtualization [options] prefix",
RunE: func(cmd *cobra.Command, args []string) error {
cfg := virtualizationFramwworkConfig{
cpus: uint(cpus),
mem: uint64(mem) * 1024 * 1024,
disks: disks,
data: data,
dataPath: dataPath,
state: state,
networking: networking,
kernelBoot: kernelBoot,
cpus: uint(cpus),
mem: uint64(mem) * 1024 * 1024,
disks: disks,
data: data,
dataPath: dataPath,
state: state,
networking: networking,
kernelBoot: kernelBoot,
virtiofsShares: virtiofsShares,
}
return runVirtualizationFramework(cfg, args[0])
},
@ -63,6 +66,7 @@ func runVirtualizationFrameworkCmd() *cobra.Command {
cmd.Flags().StringVar(&networking, "networking", virtualizationNetworkingDefault, "Networking mode. Valid options are 'default', 'vmnet' and 'none'. 'vmnet' uses the Apple vmnet framework. 'none' disables networking.`")
cmd.Flags().BoolVar(&kernelBoot, "kernel", false, "Boot image is kernel+initrd+cmdline 'path'-kernel/-initrd/-cmdline")
cmd.Flags().StringArrayVar(&virtiofsShares, "virtiofs", []string{}, "Directory shared on virtiofs")
return cmd
}

View File

@ -239,6 +239,30 @@ func runVirtualizationFramework(cfg virtualizationFramwworkConfig, path string)
config.SetSocketDevicesVirtualMachineConfiguration([]vz.SocketDeviceConfiguration{
socketDeviceConfiguration,
})
if len(cfg.virtiofsShares) > 0 {
var cs []vz.DirectorySharingDeviceConfiguration
for idx, share := range cfg.virtiofsShares {
tag := fmt.Sprintf("virtiofs%d", idx)
device, err := vz.NewVirtioFileSystemDeviceConfiguration(tag)
if err != nil {
log.Fatal("virtiofs device configuration failed", err)
}
dir, err := vz.NewSharedDirectory(share, false)
if err != nil {
log.Fatal("virtiofs shared directory failed", err)
}
single, err := vz.NewSingleDirectoryShare(dir)
if err != nil {
log.Fatal("virtiofs single directory share failed", err)
}
device.SetDirectoryShare(single)
cs = append(cs, device)
}
config.SetDirectorySharingDevicesVirtualMachineConfiguration(cs)
}
validated, err := config.Validate()
if !validated || err != nil {
log.Fatal("validation failed", err)