mirror of
https://github.com/containers/podman.git
synced 2025-05-17 15:18:43 +08:00
Fix running machines with volumes containing spaces
Machines configured to mount local paths containing spaces failed to start on Hyper-V and silently failed to mount the folder on macOS/Linux. On Windows/hyperv, where local paths are mounted running a 9p client inside the VM, the local host path needs to be surrounding with quotation marks before using in a `podman machine ssh ...` command. A similar behavior happened on Linux/QEMU where the path was used in a SSH command to mount the folder using virtiofs. Quoting the path when buidling the command arguments fixed the problem. On macOS/libkit,applehv the path was written as is in a systemd unit name to instruct how to mount it. Escaping space chars so that they are are parsed successfully fixed this: ```diff -- enable path with spaces.mount ++ enable path\x20with\x20spaces.mount ``` Fixes https://github.com/containers/podman/issues/25500 Signed-off-by: Mario Loriedo <mario.loriedo@gmail.com>
This commit is contained in:

committed by
openshift-cherrypick-robot

parent
4cb4d121a6
commit
d358e91817
@ -283,9 +283,6 @@ var _ = Describe("podman machine init", func() {
|
||||
})
|
||||
|
||||
It("machine init with volume", func() {
|
||||
if testProvider.VMType() == define.HyperVVirt {
|
||||
Skip("volumes are not supported on hyperv yet")
|
||||
}
|
||||
skipIfWSL("WSL volumes are much different. This test will not pass as is")
|
||||
|
||||
tmpDir, err := os.MkdirTemp("", "")
|
||||
@ -296,9 +293,16 @@ var _ = Describe("podman machine init", func() {
|
||||
mount := tmpDir + ":/very-long-test-mount-dir-path-more-than-thirty-six-bytes"
|
||||
defer func() { _ = utils.GuardedRemoveAll(tmpDir) }()
|
||||
|
||||
tmpDirWithSpaces, err := os.MkdirTemp("", "with spaces")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
_, err = os.CreateTemp(tmpDirWithSpaces, "example")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
mountWithSpaces := tmpDirWithSpaces + ":/host folder"
|
||||
defer func() { _ = utils.GuardedRemoveAll(tmpDirWithSpaces) }()
|
||||
|
||||
name := randomString()
|
||||
i := new(initMachine)
|
||||
session, err := mb.setName(name).setCmd(i.withImage(mb.imagePath).withVolume(mount).withNow()).run()
|
||||
session, err := mb.setName(name).setCmd(i.withImage(mb.imagePath).withVolume(mount).withVolume(mountWithSpaces).withNow()).run()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(session).To(Exit(0))
|
||||
|
||||
@ -307,6 +311,11 @@ var _ = Describe("podman machine init", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(sshSession).To(Exit(0))
|
||||
Expect(sshSession.outputToString()).To(ContainSubstring("example"))
|
||||
|
||||
sshSession, err = mb.setName(name).setCmd(ssh.withSSHCommand([]string{"ls \"/host folder\""})).run()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(sshSession).To(Exit(0))
|
||||
Expect(sshSession.outputToString()).To(ContainSubstring("example"))
|
||||
})
|
||||
|
||||
It("machine init with ignition path", func() {
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/podman/v5/pkg/machine"
|
||||
@ -48,7 +49,7 @@ func startShares(mc *vmconfigs.MachineConfig) error {
|
||||
if requiresChattr {
|
||||
args = append(args, "sudo", "chattr", "-i", "/", "; ")
|
||||
}
|
||||
args = append(args, "sudo", "mkdir", "-p", cleanTarget, "; ")
|
||||
args = append(args, "sudo", "mkdir", "-p", strconv.Quote(cleanTarget), "; ")
|
||||
if requiresChattr {
|
||||
args = append(args, "sudo", "chattr", "+i", "/", "; ")
|
||||
}
|
||||
@ -61,7 +62,7 @@ func startShares(mc *vmconfigs.MachineConfig) error {
|
||||
if mount.VSockNumber == nil {
|
||||
return errors.New("cannot start 9p shares with undefined vsock number")
|
||||
}
|
||||
args = append(args, "machine", "client9p", fmt.Sprintf("%d", *mount.VSockNumber), mount.Target)
|
||||
args = append(args, "machine", "client9p", fmt.Sprintf("%d", *mount.VSockNumber), strconv.Quote(mount.Target))
|
||||
|
||||
if err := machine.CommonSSH(mc.SSH.RemoteUsername, mc.SSH.IdentityPath, mc.Name, mc.SSH.Port, args); err != nil {
|
||||
return err
|
||||
|
@ -349,7 +349,7 @@ func (q *QEMUStubber) MountVolumesToVM(mc *vmconfigs.MachineConfig, quiet bool)
|
||||
if !strings.HasPrefix(mount.Target, "/home") && !strings.HasPrefix(mount.Target, "/mnt") {
|
||||
args = append(args, "sudo", "chattr", "-i", "/", ";")
|
||||
}
|
||||
args = append(args, "sudo", "mkdir", "-p", mount.Target)
|
||||
args = append(args, "sudo", "mkdir", "-p", strconv.Quote(mount.Target))
|
||||
if !strings.HasPrefix(mount.Target, "/home") && !strings.HasPrefix(mount.Target, "/mnt") {
|
||||
args = append(args, ";", "sudo", "chattr", "+i", "/", ";")
|
||||
}
|
||||
@ -362,7 +362,7 @@ func (q *QEMUStubber) MountVolumesToVM(mc *vmconfigs.MachineConfig, quiet bool)
|
||||
// in other words we don't want to make people unnecessarily reprovision their machines
|
||||
// to upgrade from 9p to virtiofs.
|
||||
mountOptions := []string{"-t", "virtiofs"}
|
||||
mountOptions = append(mountOptions, []string{mount.Tag, mount.Target}...)
|
||||
mountOptions = append(mountOptions, []string{mount.Tag, strconv.Quote(mount.Target)}...)
|
||||
mountFlags := fmt.Sprintf("context=\"%s\"", machine.NFSSELinuxContext)
|
||||
if mount.ReadOnly {
|
||||
mountFlags += ",ro"
|
||||
|
@ -473,7 +473,7 @@ func escapeString(escaped *strings.Builder, word string, isPath bool) {
|
||||
case '\\':
|
||||
escaped.WriteString("\\\\")
|
||||
case ' ':
|
||||
escaped.WriteString(" ")
|
||||
escaped.WriteString("\\x20")
|
||||
case '"':
|
||||
escaped.WriteString("\\\"")
|
||||
case '\'':
|
||||
|
Reference in New Issue
Block a user