mirror of
https://github.com/containers/podman.git
synced 2025-06-02 02:26:52 +08:00
Ensure HyperV 9p mounts work when a dir doesn't exist
Before, we required that the mount target exist and be a directory for the 9p mount to successfully complete, which is not how things are supposed to work - the user should be able to mount anywhere. This should just be a simple mkdir, but with FCOS the root directory is immutable so we need to undo that before we can mkdir, and unfortunately we don't have a library that can do chattr (and I didn't want to drag in a new dependency just for that), so let's be gross and add it to the SSH command. I aggressively dislike this but it does work. [NO NEW TESTS NEEDED] Can worry about getting a more generic mount test together for Machine later. Signed-off-by: Matt Heon <mheon@redhat.com>
This commit is contained in:
@ -8,6 +8,7 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/containers/common/pkg/completion"
|
||||
"github.com/containers/podman/v5/cmd/podman/registry"
|
||||
@ -69,8 +70,22 @@ func client9p(portNum uint32, mountPath string) error {
|
||||
|
||||
logrus.Infof("Going to mount 9p on vsock port %d to directory %s", portNum, mountPath)
|
||||
|
||||
// Host connects to non-hypervisor processes on the host running the VM.
|
||||
conn, err := vsock.Dial(vsock.Host, portNum, nil)
|
||||
// The server is starting at the same time.
|
||||
// Perform up to 5 retries with a backoff.
|
||||
var (
|
||||
conn *vsock.Conn
|
||||
retries = 20
|
||||
)
|
||||
for i := 0; i < retries; i++ {
|
||||
// Host connects to non-hypervisor processes on the host running the VM.
|
||||
conn, err = vsock.Dial(vsock.Host, portNum, nil)
|
||||
// If errors.Is worked on this error, we could detect non-timeout errors.
|
||||
// But it doesn't. So retry 5 times regardless.
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("dialing vsock port %d: %w", portNum, err)
|
||||
}
|
||||
|
@ -1,10 +1,14 @@
|
||||
package e2e_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
@ -93,6 +97,31 @@ var _ = Describe("run basic podman commands", func() {
|
||||
Expect(out).ToNot(ContainSubstring("gvproxy"))
|
||||
})
|
||||
|
||||
It("podman volume on non-standard path", func() {
|
||||
skipIfWSL("Requires standard volume handling")
|
||||
dir, err := os.MkdirTemp("", "machine-volume")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
testString := "abcdefg1234567"
|
||||
testFile := "testfile"
|
||||
err = os.WriteFile(filepath.Join(dir, testFile), []byte(testString), 0644)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
name := randomString()
|
||||
machinePath := "/does/not/exist"
|
||||
init := new(initMachine).withVolume(fmt.Sprintf("%s:%s", dir, machinePath)).withImagePath(mb.imagePath).withNow()
|
||||
session, err := mb.setName(name).setCmd(init).run()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(session).To(Exit(0))
|
||||
|
||||
// Must use path.Join to ensure forward slashes are used, even on Windows.
|
||||
ssh := new(sshMachine).withSSHCommand([]string{"cat", path.Join(machinePath, testFile)})
|
||||
ls, err := mb.setName(name).setCmd(ssh).run()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(ls).To(Exit(0))
|
||||
Expect(ls.outputToString()).To(ContainSubstring(testString))
|
||||
})
|
||||
})
|
||||
|
||||
func testHTTPServer(port string, shouldErr bool, expectedResponse string) {
|
||||
|
@ -423,7 +423,7 @@ func (h HyperVStubber) PostStartNetworking(mc *vmconfigs.MachineConfig, noInfo b
|
||||
|
||||
for _, mount := range mc.Mounts {
|
||||
if mount.VSockNumber == nil {
|
||||
return fmt.Errorf("mount %s has not vsock port defined", mount.Source)
|
||||
return fmt.Errorf("mount %s has no vsock port defined", mount.Source)
|
||||
}
|
||||
p9ServerArgs = append(p9ServerArgs, "--serve", fmt.Sprintf("%s:%s", mount.Source, winio.VsockServiceID(uint32(*mount.VSockNumber)).String()))
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ package hyperv
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/podman/v5/pkg/machine"
|
||||
"github.com/containers/podman/v5/pkg/machine/hyperv/vsock"
|
||||
@ -40,7 +42,19 @@ func removeShares(mc *vmconfigs.MachineConfig) error {
|
||||
|
||||
func startShares(mc *vmconfigs.MachineConfig) error {
|
||||
for _, mount := range mc.Mounts {
|
||||
args := []string{"-q", "--", "sudo", "podman"}
|
||||
args := []string{"-q", "--"}
|
||||
|
||||
cleanTarget := path.Clean(mount.Target)
|
||||
requiresChattr := !strings.HasPrefix(cleanTarget, "/home") && !strings.HasPrefix(cleanTarget, "/mnt")
|
||||
if requiresChattr {
|
||||
args = append(args, "sudo", "chattr", "-i", "/", "; ")
|
||||
}
|
||||
args = append(args, "sudo", "mkdir", "-p", cleanTarget, "; ")
|
||||
if requiresChattr {
|
||||
args = append(args, "sudo", "chattr", "+i", "/", "; ")
|
||||
}
|
||||
|
||||
args = append(args, "sudo", "podman")
|
||||
if logrus.IsLevelEnabled(logrus.DebugLevel) {
|
||||
args = append(args, "--log-level=debug")
|
||||
}
|
||||
@ -48,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), mount.Target)
|
||||
|
||||
if err := machine.CommonSSH(mc.SSH.RemoteUsername, mc.SSH.IdentityPath, mc.Name, mc.SSH.Port, args); err != nil {
|
||||
return err
|
||||
|
Reference in New Issue
Block a user