mirror of
https://github.com/containers/podman
synced 2024-10-21 17:53:44 +00:00
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 NEW TESTS NEEDED] Signed-off-by: Anders F Björklund <anders.f.bjorklund@gmail.com>
This commit is contained in:
parent
807f7cfed3
commit
8e7eeaa4dd
|
@ -88,6 +88,10 @@ func init() {
|
|||
flags.StringVar(&initOpts.ImagePath, ImagePathFlagName, cfg.Machine.Image, "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)
|
||||
|
|
|
@ -61,6 +61,16 @@ Set the timezone for the machine and containers. Valid values are `local` or
|
|||
a `timezone` such as `America/Chicago`. A value of `local`, which is the default,
|
||||
means to use the timezone of the machine host.
|
||||
|
||||
#### **--volume**, **-v**=*source:target*
|
||||
|
||||
Mounts a volume from source to target.
|
||||
|
||||
Create a mount. If /host-dir:/machine-dir is specified as the `*source:target*`,
|
||||
Podman mounts _host-dir_ in the host to _machine-dir_ in the Podman machine.
|
||||
|
||||
The root filesystem is mounted read-only in the default operating system,
|
||||
so mounts must be created under the /mnt directory.
|
||||
|
||||
#### **--help**
|
||||
|
||||
Print usage statement.
|
||||
|
@ -72,6 +82,7 @@ $ podman machine init
|
|||
$ podman machine init myvm
|
||||
$ podman machine init --disk-size 50
|
||||
$ podman machine init --memory=1024 myvm
|
||||
$ podman machine init -v /Users:/mnt/Users
|
||||
```
|
||||
|
||||
## SEE ALSO
|
||||
|
|
|
@ -18,6 +18,7 @@ type InitOptions struct {
|
|||
DiskSize uint64
|
||||
IgnitionPath string
|
||||
ImagePath string
|
||||
Volumes []string
|
||||
IsDefault bool
|
||||
Memory uint64
|
||||
Name string
|
||||
|
|
|
@ -11,6 +11,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
|
||||
|
@ -33,6 +35,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
|
||||
|
|
|
@ -167,6 +167,21 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, 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
|
||||
|
@ -329,7 +344,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
|
||||
|
@ -506,6 +542,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 {
|
||||
|
|
Loading…
Reference in a new issue