From 33577a55dc498c43de23745bd18f67881630bf5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20F=20Bj=C3=B6rklund?= Date: Sun, 5 Sep 2021 22:16:59 +0200 Subject: [PATCH 1/3] Implement virtfs volumes for podman machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow using the built-in 9pfs feature of qemu, mounting host directories into vm mountpoints. The volumes are generic, the mounts are specific. Wait for the machine to be "running", otherwise the SSH function might throw an error instead. Increase the default msize from 8 KiB to 128 KiB [NO TESTS NEEDED] Signed-off-by: Anders F Björklund --- cmd/podman/machine/init.go | 4 ++ docs/source/markdown/podman-machine-init.1.md | 4 ++ pkg/machine/config.go | 1 + pkg/machine/qemu/config.go | 9 ++++ pkg/machine/qemu/machine.go | 48 ++++++++++++++++++- 5 files changed, 65 insertions(+), 1 deletion(-) diff --git a/cmd/podman/machine/init.go b/cmd/podman/machine/init.go index ec44a707d3..6096c3ea1d 100644 --- a/cmd/podman/machine/init.go +++ b/cmd/podman/machine/init.go @@ -65,6 +65,10 @@ func init() { flags.StringVar(&initOpts.ImagePath, ImagePathFlagName, cfg.Engine.MachineImage, "Path to qcow image") _ = initCmd.RegisterFlagCompletionFunc(ImagePathFlagName, completion.AutocompleteDefault) + VolumeFlagName := "volume" + flags.StringArrayVarP(&initOpts.Volumes, VolumeFlagName, "v", []string{}, "Volumes to mount, source:target") + _ = initCmd.RegisterFlagCompletionFunc(VolumeFlagName, completion.AutocompleteDefault) + IgnitionPathFlagName := "ignition-path" flags.StringVar(&initOpts.IgnitionPath, IgnitionPathFlagName, "", "Path to ignition file") _ = initCmd.RegisterFlagCompletionFunc(IgnitionPathFlagName, completion.AutocompleteDefault) diff --git a/docs/source/markdown/podman-machine-init.1.md b/docs/source/markdown/podman-machine-init.1.md index 740897666a..152f0e3cb7 100644 --- a/docs/source/markdown/podman-machine-init.1.md +++ b/docs/source/markdown/podman-machine-init.1.md @@ -47,6 +47,10 @@ Defaults to `testing`. Memory (in MB). +#### **--volume**, **-v**=*source:target* + +Mounts a volume from source to target. + #### **--help** Print usage statement. diff --git a/pkg/machine/config.go b/pkg/machine/config.go index cad71ba490..3565a3a990 100644 --- a/pkg/machine/config.go +++ b/pkg/machine/config.go @@ -18,6 +18,7 @@ type InitOptions struct { DiskSize uint64 IgnitionPath string ImagePath string + Volumes []string IsDefault bool Memory uint64 Name string diff --git a/pkg/machine/qemu/config.go b/pkg/machine/qemu/config.go index 3d0fa4094f..78a489c87a 100644 --- a/pkg/machine/qemu/config.go +++ b/pkg/machine/qemu/config.go @@ -9,6 +9,8 @@ type MachineVM struct { CPUs uint64 // The command line representation of the qemu command CmdLine []string + // Mounts is the list of remote filesystems to mount + Mounts []Mount // IdentityPath is the fq path to the ssh priv key IdentityPath string // IgnitionFilePath is the fq path to the .ign file @@ -27,6 +29,13 @@ type MachineVM struct { RemoteUsername string } +type Mount struct { + Type string + Tag string + Source string + Target string +} + type Monitor struct { // Address portion of the qmp monitor (/tmp/tmp.sock) Address string diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 855a39c56c..254fb20960 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -164,6 +164,21 @@ func (v *MachineVM) Init(opts machine.InitOptions) error { // Add arch specific options including image location v.CmdLine = append(v.CmdLine, v.addArchOptions()...) + mounts := []Mount{} + for i, volume := range opts.Volumes { + tag := fmt.Sprintf("vol%d", i) + paths := strings.SplitN(volume, ":", 2) + source := paths[0] + target := source + if len(paths) > 1 { + target = paths[1] + } + addVirtfsOptions := []string{"-virtfs", fmt.Sprintf("local,path=%s,mount_tag=%s,security_model=mapped-xattr", source, tag)} + v.CmdLine = append(v.CmdLine, addVirtfsOptions...) + mounts = append(mounts, Mount{Type: "9p", Tag: tag, Source: source, Target: target}) + } + v.Mounts = mounts + // Add location of bootable image v.CmdLine = append(v.CmdLine, "-drive", "if=virtio,file="+v.ImagePath) // This kind of stinks but no other way around this r/n @@ -324,7 +339,28 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { return err } _, err = bufio.NewReader(conn).ReadString('\n') - return err + if err != nil { + return err + } + + if len(v.Mounts) > 0 { + for !v.isRunning() || !v.isListening() { + time.Sleep(100 * time.Millisecond) + } + } + for _, mount := range v.Mounts { + fmt.Printf("Mounting volume... %s:%s\n", mount.Source, mount.Target) + // create mountpoint directory if it doesn't exist + err = v.SSH(name, machine.SSHOptions{Args: []string{"-q", "--", "sudo", "mkdir", "-p", mount.Target}}) + if err != nil { + return err + } + err = v.SSH(name, machine.SSHOptions{Args: []string{"-q", "--", "sudo", "mount", "-t", mount.Type, "-o", "trans=virtio", mount.Tag, mount.Target, "-o", "version=9p2000.L,msize=131072"}}) + if err != nil { + return err + } + } + return nil } // Stop uses the qmp monitor to call a system_powerdown @@ -481,6 +517,16 @@ func (v *MachineVM) isRunning() bool { return true } +func (v *MachineVM) isListening() bool { + // Check if we can dial it + conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", "localhost", v.Port), 10*time.Millisecond) + if err != nil { + return false + } + conn.Close() + return true +} + // SSH opens an interactive SSH session to the vm specified. // Added ssh function to VM interface: pkg/machine/config/go : line 58 func (v *MachineVM) SSH(name string, opts machine.SSHOptions) error { From bee9ad7189511159beb7d40cf6081784961c12b2 Mon Sep 17 00:00:00 2001 From: Josh Giron Date: Wed, 22 Sep 2021 13:14:43 -0400 Subject: [PATCH 2/3] add section for '--volume' into podman machine init docs --- docs/source/markdown/podman-machine-init.1.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/source/markdown/podman-machine-init.1.md b/docs/source/markdown/podman-machine-init.1.md index 1236db6020..27dc127593 100644 --- a/docs/source/markdown/podman-machine-init.1.md +++ b/docs/source/markdown/podman-machine-init.1.md @@ -47,6 +47,10 @@ Defaults to `testing`. Memory (in MB). +#### **--volume**, **-v**=*source:target* + +Mounts a volume from source to target. + #### **--now** Start the virtual machine immediately after it has been initialized. From fd1fe196f6bc3552a87e6bc215767f7860aab6bc Mon Sep 17 00:00:00 2001 From: Josh Giron Date: Wed, 22 Sep 2021 15:16:18 -0400 Subject: [PATCH 3/3] Small update to docs to sign commit Signed-off-by: Josh Giron --- docs/source/markdown/podman-machine-init.1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/markdown/podman-machine-init.1.md b/docs/source/markdown/podman-machine-init.1.md index 27dc127593..de5d8e685b 100644 --- a/docs/source/markdown/podman-machine-init.1.md +++ b/docs/source/markdown/podman-machine-init.1.md @@ -49,7 +49,7 @@ Memory (in MB). #### **--volume**, **-v**=*source:target* -Mounts a volume from source to target. +Mounts a volume from `source` to `target`. #### **--now**