mirror of
https://github.com/containers/podman.git
synced 2025-07-01 00:01:02 +08:00
Merge pull request #22288 from ashley-cui/machmounttag
Fix machine volumes with long path
This commit is contained in:
@ -96,19 +96,19 @@ func GenerateSystemDFilesForVirtiofsMounts(mounts []machine.VirtIoFs) ([]ignitio
|
|||||||
|
|
||||||
virtiofsAutomount := ignition.Unit{
|
virtiofsAutomount := ignition.Unit{
|
||||||
Enabled: ignition.BoolToPtr(true),
|
Enabled: ignition.BoolToPtr(true),
|
||||||
Name: fmt.Sprintf("%s.automount", mnt.Tag),
|
Name: fmt.Sprintf("%s.automount", parser.PathEscape(mnt.Target)),
|
||||||
Contents: ignition.StrToPtr(fmt.Sprintf(autoMountUnitFile, mnt.Target, mnt.Target)),
|
Contents: ignition.StrToPtr(fmt.Sprintf(autoMountUnitFile, mnt.Tag, mnt.Target)),
|
||||||
}
|
}
|
||||||
virtiofsMount := ignition.Unit{
|
virtiofsMount := ignition.Unit{
|
||||||
Enabled: ignition.BoolToPtr(true),
|
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)),
|
Contents: ignition.StrToPtr(fmt.Sprintf(mountUnitFile, mnt.Tag, mnt.Target)),
|
||||||
}
|
}
|
||||||
|
|
||||||
// This "unit" simulates something like systemctl enable virtiofs-mount-prepare@
|
// This "unit" simulates something like systemctl enable virtiofs-mount-prepare@
|
||||||
enablePrep := ignition.Unit{
|
enablePrep := ignition.Unit{
|
||||||
Enabled: ignition.BoolToPtr(true),
|
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)
|
unitFiles = append(unitFiles, virtiofsAutomount, virtiofsMount, enablePrep)
|
||||||
|
@ -207,7 +207,8 @@ var _ = Describe("podman machine init", func() {
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
_, err = os.CreateTemp(tmpDir, "example")
|
_, err = os.CreateTemp(tmpDir, "example")
|
||||||
Expect(err).ToNot(HaveOccurred())
|
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) }()
|
defer func() { _ = utils.GuardedRemoveAll(tmpDir) }()
|
||||||
|
|
||||||
name := randomString()
|
name := randomString()
|
||||||
@ -217,7 +218,7 @@ var _ = Describe("podman machine init", func() {
|
|||||||
Expect(session).To(Exit(0))
|
Expect(session).To(Exit(0))
|
||||||
|
|
||||||
ssh := sshMachine{}
|
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(err).ToNot(HaveOccurred())
|
||||||
Expect(sshSession).To(Exit(0))
|
Expect(sshSession).To(Exit(0))
|
||||||
Expect(sshSession.outputToString()).To(ContainSubstring("example"))
|
Expect(sshSession.outputToString()).To(ContainSubstring("example"))
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
|
||||||
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
||||||
)
|
)
|
||||||
@ -29,14 +30,13 @@ func (v VirtIoFs) Kind() string {
|
|||||||
return string(VirtIOFsVk)
|
return string(VirtIOFsVk)
|
||||||
}
|
}
|
||||||
|
|
||||||
// unitName is the fq path where /'s are replaced with -'s
|
// generateTag generates a tag for VirtIOFs mounts.
|
||||||
func (v VirtIoFs) unitName() string {
|
// AppleHV requires tags to be 36 bytes or fewer.
|
||||||
// delete the leading -
|
// SHA256 the path, then truncate to 36 bytes
|
||||||
unit := strings.ReplaceAll(v.Target, "/", "-")
|
func (v VirtIoFs) generateTag() string {
|
||||||
if strings.HasPrefix(unit, "-") {
|
sum := sha256.Sum256([]byte(v.Target))
|
||||||
return unit[1:]
|
stringSum := hex.EncodeToString(sum[:])
|
||||||
}
|
return stringSum[:36]
|
||||||
return unit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v VirtIoFs) ToMount() vmconfigs.Mount {
|
func (v VirtIoFs) ToMount() vmconfigs.Mount {
|
||||||
@ -58,7 +58,7 @@ func NewVirtIoFsMount(src, target string, readOnly bool) VirtIoFs {
|
|||||||
Source: src,
|
Source: src,
|
||||||
Target: target,
|
Target: target,
|
||||||
}
|
}
|
||||||
vfs.Tag = vfs.unitName()
|
vfs.Tag = vfs.generateTag()
|
||||||
return vfs
|
return vfs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,13 +428,17 @@ func splitString(s string, separators string, flags SplitFlags) ([]string, error
|
|||||||
return splitStringAppend(make([]string, 0), s, separators, flags)
|
return splitStringAppend(make([]string, 0), s, separators, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
func charNeedEscape(c rune) bool {
|
func charNeedEscape(c rune, isPath bool) bool {
|
||||||
if c > 128 {
|
if c > 128 {
|
||||||
return false /* unicode is ok */
|
return false /* unicode is ok */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pathRune := (isPath && c == '-') ||
|
||||||
|
(isPath && c == '/')
|
||||||
|
|
||||||
return unicode.IsSpace(c) ||
|
return unicode.IsSpace(c) ||
|
||||||
unicode.IsControl(c) ||
|
unicode.IsControl(c) ||
|
||||||
|
pathRune ||
|
||||||
c == '"' ||
|
c == '"' ||
|
||||||
c == '\'' ||
|
c == '\'' ||
|
||||||
c == '\\'
|
c == '\\'
|
||||||
@ -442,18 +446,22 @@ func charNeedEscape(c rune) bool {
|
|||||||
|
|
||||||
func wordNeedEscape(word string) bool {
|
func wordNeedEscape(word string) bool {
|
||||||
for _, c := range word {
|
for _, c := range word {
|
||||||
if charNeedEscape(c) {
|
if charNeedEscape(c, false) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendEscapeWord(escaped *strings.Builder, word string) {
|
func appendEscapeWord(escaped *strings.Builder, word string) {
|
||||||
escaped.WriteRune('"')
|
escaped.WriteRune('"')
|
||||||
for _, c := range word {
|
escapeString(escaped, word, false)
|
||||||
if charNeedEscape(c) {
|
escaped.WriteRune('"')
|
||||||
|
}
|
||||||
|
|
||||||
|
func escapeString(escaped *strings.Builder, word string, isPath bool) {
|
||||||
|
for i, c := range word {
|
||||||
|
if charNeedEscape(c, isPath) {
|
||||||
switch c {
|
switch c {
|
||||||
case '\a':
|
case '\a':
|
||||||
escaped.WriteString("\\a")
|
escaped.WriteString("\\a")
|
||||||
@ -477,6 +485,10 @@ func appendEscapeWord(escaped *strings.Builder, word string) {
|
|||||||
escaped.WriteString("\\\"")
|
escaped.WriteString("\\\"")
|
||||||
case '\'':
|
case '\'':
|
||||||
escaped.WriteString("'")
|
escaped.WriteString("'")
|
||||||
|
case '/':
|
||||||
|
if isPath && i != 0 {
|
||||||
|
escaped.WriteString("-")
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
escaped.WriteString(fmt.Sprintf("\\x%.2x", c))
|
escaped.WriteString(fmt.Sprintf("\\x%.2x", c))
|
||||||
}
|
}
|
||||||
@ -484,7 +496,6 @@ func appendEscapeWord(escaped *strings.Builder, word string) {
|
|||||||
escaped.WriteRune(c)
|
escaped.WriteRune(c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
escaped.WriteRune('"')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func escapeWords(words []string) string {
|
func escapeWords(words []string) string {
|
||||||
@ -500,6 +511,5 @@ func escapeWords(words []string) string {
|
|||||||
escaped.WriteString(word)
|
escaped.WriteString(word)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return escaped.String()
|
return escaped.String()
|
||||||
}
|
}
|
||||||
|
@ -932,3 +932,9 @@ func (f *UnitFile) GetTemplateParts() (string, string) {
|
|||||||
}
|
}
|
||||||
return parts[0] + "@" + ext, parts[1]
|
return parts[0] + "@" + ext, parts[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PathEscape(path string) string {
|
||||||
|
var escaped strings.Builder
|
||||||
|
escapeString(&escaped, path, true)
|
||||||
|
return escaped.String()
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user