mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-19 17:26:28 +00:00
Merge pull request #3891 from fredericdalleau/qemu-virtiofs
Add virtiofs command line option for qemu run
This commit is contained in:
commit
7d9f1f03a8
@ -23,28 +23,30 @@ const (
|
|||||||
|
|
||||||
// QemuConfig contains the config for Qemu
|
// QemuConfig contains the config for Qemu
|
||||||
type QemuConfig struct {
|
type QemuConfig struct {
|
||||||
Path string
|
Path string
|
||||||
ISOBoot bool
|
ISOBoot bool
|
||||||
UEFI bool
|
UEFI bool
|
||||||
SquashFS bool
|
SquashFS bool
|
||||||
Kernel bool
|
Kernel bool
|
||||||
GUI bool
|
GUI bool
|
||||||
Disks Disks
|
Disks Disks
|
||||||
ISOImages []string
|
ISOImages []string
|
||||||
StatePath string
|
StatePath string
|
||||||
FWPath string
|
FWPath string
|
||||||
Arch string
|
Arch string
|
||||||
CPUs string
|
CPUs string
|
||||||
Memory string
|
Memory string
|
||||||
Accel string
|
Accel string
|
||||||
Detached bool
|
Detached bool
|
||||||
QemuBinPath string
|
QemuBinPath string
|
||||||
QemuImgPath string
|
QemuImgPath string
|
||||||
PublishedPorts []string
|
PublishedPorts []string
|
||||||
NetdevConfig string
|
NetdevConfig string
|
||||||
UUID uuid.UUID
|
UUID uuid.UUID
|
||||||
USB bool
|
USB bool
|
||||||
Devices []string
|
Devices []string
|
||||||
|
VirtiofsdBinPath string
|
||||||
|
VirtiofsShares []string
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -119,23 +121,25 @@ func generateMAC() net.HardwareAddr {
|
|||||||
|
|
||||||
func runQEMUCmd() *cobra.Command {
|
func runQEMUCmd() *cobra.Command {
|
||||||
var (
|
var (
|
||||||
enableGUI bool
|
enableGUI bool
|
||||||
uefiBoot bool
|
uefiBoot bool
|
||||||
isoBoot bool
|
isoBoot bool
|
||||||
squashFSBoot bool
|
squashFSBoot bool
|
||||||
kernelBoot bool
|
kernelBoot bool
|
||||||
state string
|
state string
|
||||||
data string
|
data string
|
||||||
dataPath string
|
dataPath string
|
||||||
fw string
|
fw string
|
||||||
accel string
|
accel string
|
||||||
arch string
|
arch string
|
||||||
qemuCmd string
|
qemuCmd string
|
||||||
qemuDetached bool
|
qemuDetached bool
|
||||||
networking string
|
networking string
|
||||||
usbEnabled bool
|
usbEnabled bool
|
||||||
deviceFlags multipleFlag
|
deviceFlags multipleFlag
|
||||||
publishFlags multipleFlag
|
publishFlags multipleFlag
|
||||||
|
virtiofsdCmd string
|
||||||
|
virtiofsShares []string
|
||||||
)
|
)
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
@ -279,34 +283,43 @@ func runQEMUCmd() *cobra.Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
config := QemuConfig{
|
config := QemuConfig{
|
||||||
Path: path,
|
Path: path,
|
||||||
ISOBoot: isoBoot,
|
ISOBoot: isoBoot,
|
||||||
UEFI: uefiBoot,
|
UEFI: uefiBoot,
|
||||||
SquashFS: squashFSBoot,
|
SquashFS: squashFSBoot,
|
||||||
Kernel: kernelBoot,
|
Kernel: kernelBoot,
|
||||||
GUI: enableGUI,
|
GUI: enableGUI,
|
||||||
Disks: disks,
|
Disks: disks,
|
||||||
ISOImages: isoPaths,
|
ISOImages: isoPaths,
|
||||||
StatePath: state,
|
StatePath: state,
|
||||||
FWPath: fw,
|
FWPath: fw,
|
||||||
Arch: arch,
|
Arch: arch,
|
||||||
CPUs: fmt.Sprintf("%d", cpus),
|
CPUs: fmt.Sprintf("%d", cpus),
|
||||||
Memory: fmt.Sprintf("%d", mem),
|
Memory: fmt.Sprintf("%d", mem),
|
||||||
Accel: accel,
|
Accel: accel,
|
||||||
Detached: qemuDetached,
|
Detached: qemuDetached,
|
||||||
QemuBinPath: qemuCmd,
|
QemuBinPath: qemuCmd,
|
||||||
PublishedPorts: publishFlags,
|
PublishedPorts: publishFlags,
|
||||||
NetdevConfig: netdevConfig,
|
NetdevConfig: netdevConfig,
|
||||||
UUID: vmUUID,
|
UUID: vmUUID,
|
||||||
USB: usbEnabled,
|
USB: usbEnabled,
|
||||||
Devices: deviceFlags,
|
Devices: deviceFlags,
|
||||||
|
VirtiofsdBinPath: virtiofsdCmd,
|
||||||
|
VirtiofsShares: virtiofsShares,
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err = discoverBinaries(config)
|
config, err = discoverQemu(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(config.VirtiofsShares) > 0 {
|
||||||
|
config, err = discoverVirtiofsd(config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err = runQemuLocal(config); err != nil {
|
if err = runQemuLocal(config); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -351,6 +364,10 @@ func runQEMUCmd() *cobra.Command {
|
|||||||
cmd.Flags().BoolVar(&usbEnabled, "usb", false, "Enable USB controller")
|
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.")
|
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
|
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")
|
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...)
|
qemuCmd := exec.Command(config.QemuBinPath, args...)
|
||||||
// If verbosity is enabled print out the full path/arguments
|
// If verbosity is enabled print out the full path/arguments
|
||||||
log.Debugf("%v\n", qemuCmd.Args)
|
log.Debugf("%v\n", qemuCmd.Args)
|
||||||
@ -589,7 +625,7 @@ func buildQemuCmdline(config QemuConfig) (QemuConfig, []string) {
|
|||||||
return config, qemuArgs
|
return config, qemuArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
func discoverBinaries(config QemuConfig) (QemuConfig, error) {
|
func discoverQemu(config QemuConfig) (QemuConfig, error) {
|
||||||
if config.QemuImgPath != "" {
|
if config.QemuImgPath != "" {
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
@ -611,6 +647,16 @@ func discoverBinaries(config QemuConfig) (QemuConfig, error) {
|
|||||||
return config, nil
|
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) {
|
func buildQemuForwardings(publishFlags multipleFlag) (string, error) {
|
||||||
if len(publishFlags) == 0 {
|
if len(publishFlags) == 0 {
|
||||||
return "", nil
|
return "", nil
|
||||||
|
@ -14,23 +14,25 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type virtualizationFramwworkConfig struct {
|
type virtualizationFramwworkConfig struct {
|
||||||
cpus uint
|
cpus uint
|
||||||
mem uint64
|
mem uint64
|
||||||
disks Disks
|
disks Disks
|
||||||
data string
|
data string
|
||||||
dataPath string
|
dataPath string
|
||||||
state string
|
state string
|
||||||
networking string
|
networking string
|
||||||
kernelBoot bool
|
kernelBoot bool
|
||||||
|
virtiofsShares []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func runVirtualizationFrameworkCmd() *cobra.Command {
|
func runVirtualizationFrameworkCmd() *cobra.Command {
|
||||||
var (
|
var (
|
||||||
data string
|
data string
|
||||||
dataPath string
|
dataPath string
|
||||||
state string
|
state string
|
||||||
networking string
|
networking string
|
||||||
kernelBoot bool
|
kernelBoot bool
|
||||||
|
virtiofsShares []string
|
||||||
)
|
)
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
@ -43,14 +45,15 @@ func runVirtualizationFrameworkCmd() *cobra.Command {
|
|||||||
Example: "linuxkit run virtualization [options] prefix",
|
Example: "linuxkit run virtualization [options] prefix",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
cfg := virtualizationFramwworkConfig{
|
cfg := virtualizationFramwworkConfig{
|
||||||
cpus: uint(cpus),
|
cpus: uint(cpus),
|
||||||
mem: uint64(mem) * 1024 * 1024,
|
mem: uint64(mem) * 1024 * 1024,
|
||||||
disks: disks,
|
disks: disks,
|
||||||
data: data,
|
data: data,
|
||||||
dataPath: dataPath,
|
dataPath: dataPath,
|
||||||
state: state,
|
state: state,
|
||||||
networking: networking,
|
networking: networking,
|
||||||
kernelBoot: kernelBoot,
|
kernelBoot: kernelBoot,
|
||||||
|
virtiofsShares: virtiofsShares,
|
||||||
}
|
}
|
||||||
return runVirtualizationFramework(cfg, args[0])
|
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().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().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
|
return cmd
|
||||||
}
|
}
|
||||||
|
@ -239,6 +239,30 @@ func runVirtualizationFramework(cfg virtualizationFramwworkConfig, path string)
|
|||||||
config.SetSocketDevicesVirtualMachineConfiguration([]vz.SocketDeviceConfiguration{
|
config.SetSocketDevicesVirtualMachineConfiguration([]vz.SocketDeviceConfiguration{
|
||||||
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()
|
validated, err := config.Validate()
|
||||||
if !validated || err != nil {
|
if !validated || err != nil {
|
||||||
log.Fatal("validation failed", err)
|
log.Fatal("validation failed", err)
|
||||||
|
Loading…
Reference in New Issue
Block a user