Skip to content

Commit 33577a5

Browse files
committed
Implement virtfs volumes for podman machine
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 <[email protected]>
1 parent 0f3d3bd commit 33577a5

File tree

5 files changed

+65
-1
lines changed

5 files changed

+65
-1
lines changed

Diff for: cmd/podman/machine/init.go

+4
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ func init() {
6565
flags.StringVar(&initOpts.ImagePath, ImagePathFlagName, cfg.Engine.MachineImage, "Path to qcow image")
6666
_ = initCmd.RegisterFlagCompletionFunc(ImagePathFlagName, completion.AutocompleteDefault)
6767

68+
VolumeFlagName := "volume"
69+
flags.StringArrayVarP(&initOpts.Volumes, VolumeFlagName, "v", []string{}, "Volumes to mount, source:target")
70+
_ = initCmd.RegisterFlagCompletionFunc(VolumeFlagName, completion.AutocompleteDefault)
71+
6872
IgnitionPathFlagName := "ignition-path"
6973
flags.StringVar(&initOpts.IgnitionPath, IgnitionPathFlagName, "", "Path to ignition file")
7074
_ = initCmd.RegisterFlagCompletionFunc(IgnitionPathFlagName, completion.AutocompleteDefault)

Diff for: docs/source/markdown/podman-machine-init.1.md

+4
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ Defaults to `testing`.
4747

4848
Memory (in MB).
4949

50+
#### **--volume**, **-v**=*source:target*
51+
52+
Mounts a volume from source to target.
53+
5054
#### **--help**
5155

5256
Print usage statement.

Diff for: pkg/machine/config.go

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type InitOptions struct {
1818
DiskSize uint64
1919
IgnitionPath string
2020
ImagePath string
21+
Volumes []string
2122
IsDefault bool
2223
Memory uint64
2324
Name string

Diff for: pkg/machine/qemu/config.go

+9
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ type MachineVM struct {
99
CPUs uint64
1010
// The command line representation of the qemu command
1111
CmdLine []string
12+
// Mounts is the list of remote filesystems to mount
13+
Mounts []Mount
1214
// IdentityPath is the fq path to the ssh priv key
1315
IdentityPath string
1416
// IgnitionFilePath is the fq path to the .ign file
@@ -27,6 +29,13 @@ type MachineVM struct {
2729
RemoteUsername string
2830
}
2931

32+
type Mount struct {
33+
Type string
34+
Tag string
35+
Source string
36+
Target string
37+
}
38+
3039
type Monitor struct {
3140
// Address portion of the qmp monitor (/tmp/tmp.sock)
3241
Address string

Diff for: pkg/machine/qemu/machine.go

+47-1
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,21 @@ func (v *MachineVM) Init(opts machine.InitOptions) error {
164164
// Add arch specific options including image location
165165
v.CmdLine = append(v.CmdLine, v.addArchOptions()...)
166166

167+
mounts := []Mount{}
168+
for i, volume := range opts.Volumes {
169+
tag := fmt.Sprintf("vol%d", i)
170+
paths := strings.SplitN(volume, ":", 2)
171+
source := paths[0]
172+
target := source
173+
if len(paths) > 1 {
174+
target = paths[1]
175+
}
176+
addVirtfsOptions := []string{"-virtfs", fmt.Sprintf("local,path=%s,mount_tag=%s,security_model=mapped-xattr", source, tag)}
177+
v.CmdLine = append(v.CmdLine, addVirtfsOptions...)
178+
mounts = append(mounts, Mount{Type: "9p", Tag: tag, Source: source, Target: target})
179+
}
180+
v.Mounts = mounts
181+
167182
// Add location of bootable image
168183
v.CmdLine = append(v.CmdLine, "-drive", "if=virtio,file="+v.ImagePath)
169184
// 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 {
324339
return err
325340
}
326341
_, err = bufio.NewReader(conn).ReadString('\n')
327-
return err
342+
if err != nil {
343+
return err
344+
}
345+
346+
if len(v.Mounts) > 0 {
347+
for !v.isRunning() || !v.isListening() {
348+
time.Sleep(100 * time.Millisecond)
349+
}
350+
}
351+
for _, mount := range v.Mounts {
352+
fmt.Printf("Mounting volume... %s:%s\n", mount.Source, mount.Target)
353+
// create mountpoint directory if it doesn't exist
354+
err = v.SSH(name, machine.SSHOptions{Args: []string{"-q", "--", "sudo", "mkdir", "-p", mount.Target}})
355+
if err != nil {
356+
return err
357+
}
358+
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"}})
359+
if err != nil {
360+
return err
361+
}
362+
}
363+
return nil
328364
}
329365

330366
// Stop uses the qmp monitor to call a system_powerdown
@@ -481,6 +517,16 @@ func (v *MachineVM) isRunning() bool {
481517
return true
482518
}
483519

520+
func (v *MachineVM) isListening() bool {
521+
// Check if we can dial it
522+
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", "localhost", v.Port), 10*time.Millisecond)
523+
if err != nil {
524+
return false
525+
}
526+
conn.Close()
527+
return true
528+
}
529+
484530
// SSH opens an interactive SSH session to the vm specified.
485531
// Added ssh function to VM interface: pkg/machine/config/go : line 58
486532
func (v *MachineVM) SSH(name string, opts machine.SSHOptions) error {

0 commit comments

Comments
 (0)