Merge pull request #22288 from ashley-cui/machmounttag

Fix machine volumes with long path
This commit is contained in:
openshift-merge-bot[bot]
2024-04-30 16:36:53 +00:00
committed by GitHub
5 changed files with 40 additions and 23 deletions

View File

@ -96,19 +96,19 @@ func GenerateSystemDFilesForVirtiofsMounts(mounts []machine.VirtIoFs) ([]ignitio
virtiofsAutomount := ignition.Unit{
Enabled: ignition.BoolToPtr(true),
Name: fmt.Sprintf("%s.automount", mnt.Tag),
Contents: ignition.StrToPtr(fmt.Sprintf(autoMountUnitFile, mnt.Target, mnt.Target)),
Name: fmt.Sprintf("%s.automount", parser.PathEscape(mnt.Target)),
Contents: ignition.StrToPtr(fmt.Sprintf(autoMountUnitFile, mnt.Tag, mnt.Target)),
}
virtiofsMount := ignition.Unit{
Enabled: ignition.BoolToPtr(true),
Name: fmt.Sprintf("%s.mount", mnt.Tag),
Name: fmt.Sprintf("%s.mount", parser.PathEscape(mnt.Target)),
Contents: ignition.StrToPtr(fmt.Sprintf(mountUnitFile, mnt.Tag, mnt.Target)),
}
// This "unit" simulates something like systemctl enable virtiofs-mount-prepare@
enablePrep := ignition.Unit{
Enabled: ignition.BoolToPtr(true),
Name: fmt.Sprintf("virtiofs-mount-prepare@%s.service", mnt.Tag),
Name: fmt.Sprintf("virtiofs-mount-prepare@%s.service", parser.PathEscape(mnt.Target)),
}
unitFiles = append(unitFiles, virtiofsAutomount, virtiofsMount, enablePrep)

View File

@ -207,7 +207,8 @@ var _ = Describe("podman machine init", func() {
Expect(err).ToNot(HaveOccurred())
_, err = os.CreateTemp(tmpDir, "example")
Expect(err).ToNot(HaveOccurred())
mount := tmpDir + ":/testmountdir"
// Test long target path, see https://github.com/containers/podman/issues/22226
mount := tmpDir + ":/very-long-test-mount-dir-path-more-than-thirty-six-bytes"
defer func() { _ = utils.GuardedRemoveAll(tmpDir) }()
name := randomString()
@ -217,7 +218,7 @@ var _ = Describe("podman machine init", func() {
Expect(session).To(Exit(0))
ssh := sshMachine{}
sshSession, err := mb.setName(name).setCmd(ssh.withSSHCommand([]string{"ls /testmountdir"})).run()
sshSession, err := mb.setName(name).setCmd(ssh.withSSHCommand([]string{"ls /very-long-test-mount-dir-path-more-than-thirty-six-bytes"})).run()
Expect(err).ToNot(HaveOccurred())
Expect(sshSession).To(Exit(0))
Expect(sshSession.outputToString()).To(ContainSubstring("example"))

View File

@ -1,7 +1,8 @@
package machine
import (
"strings"
"crypto/sha256"
"encoding/hex"
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
)
@ -29,14 +30,13 @@ func (v VirtIoFs) Kind() string {
return string(VirtIOFsVk)
}
// unitName is the fq path where /'s are replaced with -'s
func (v VirtIoFs) unitName() string {
// delete the leading -
unit := strings.ReplaceAll(v.Target, "/", "-")
if strings.HasPrefix(unit, "-") {
return unit[1:]
}
return unit
// generateTag generates a tag for VirtIOFs mounts.
// AppleHV requires tags to be 36 bytes or fewer.
// SHA256 the path, then truncate to 36 bytes
func (v VirtIoFs) generateTag() string {
sum := sha256.Sum256([]byte(v.Target))
stringSum := hex.EncodeToString(sum[:])
return stringSum[:36]
}
func (v VirtIoFs) ToMount() vmconfigs.Mount {
@ -58,7 +58,7 @@ func NewVirtIoFsMount(src, target string, readOnly bool) VirtIoFs {
Source: src,
Target: target,
}
vfs.Tag = vfs.unitName()
vfs.Tag = vfs.generateTag()
return vfs
}

View File

@ -428,13 +428,17 @@ func splitString(s string, separators string, flags SplitFlags) ([]string, error
return splitStringAppend(make([]string, 0), s, separators, flags)
}
func charNeedEscape(c rune) bool {
func charNeedEscape(c rune, isPath bool) bool {
if c > 128 {
return false /* unicode is ok */
}
pathRune := (isPath && c == '-') ||
(isPath && c == '/')
return unicode.IsSpace(c) ||
unicode.IsControl(c) ||
pathRune ||
c == '"' ||
c == '\'' ||
c == '\\'
@ -442,18 +446,22 @@ func charNeedEscape(c rune) bool {
func wordNeedEscape(word string) bool {
for _, c := range word {
if charNeedEscape(c) {
if charNeedEscape(c, false) {
return true
}
}
return false
}
func appendEscapeWord(escaped *strings.Builder, word string) {
escaped.WriteRune('"')
for _, c := range word {
if charNeedEscape(c) {
escapeString(escaped, word, false)
escaped.WriteRune('"')
}
func escapeString(escaped *strings.Builder, word string, isPath bool) {
for i, c := range word {
if charNeedEscape(c, isPath) {
switch c {
case '\a':
escaped.WriteString("\\a")
@ -477,6 +485,10 @@ func appendEscapeWord(escaped *strings.Builder, word string) {
escaped.WriteString("\\\"")
case '\'':
escaped.WriteString("'")
case '/':
if isPath && i != 0 {
escaped.WriteString("-")
}
default:
escaped.WriteString(fmt.Sprintf("\\x%.2x", c))
}
@ -484,7 +496,6 @@ func appendEscapeWord(escaped *strings.Builder, word string) {
escaped.WriteRune(c)
}
}
escaped.WriteRune('"')
}
func escapeWords(words []string) string {
@ -500,6 +511,5 @@ func escapeWords(words []string) string {
escaped.WriteString(word)
}
}
return escaped.String()
}

View File

@ -932,3 +932,9 @@ func (f *UnitFile) GetTemplateParts() (string, string) {
}
return parts[0] + "@" + ext, parts[1]
}
func PathEscape(path string) string {
var escaped strings.Builder
escapeString(&escaped, path, true)
return escaped.String()
}