diff --git a/cmd/podman/compose_machine.go b/cmd/podman/compose_machine.go index 953b1eae0f..0b7ea0d0f1 100644 --- a/cmd/podman/compose_machine.go +++ b/cmd/podman/compose_machine.go @@ -7,8 +7,8 @@ import ( "net/url" "strconv" - "github.com/containers/podman/v5/pkg/machine" "github.com/containers/podman/v5/pkg/machine/define" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/containers/podman/v5/pkg/machine/provider" "github.com/containers/podman/v5/pkg/machine/vmconfigs" ) @@ -18,7 +18,7 @@ func getMachineConn(connectionURI string, parsedConnection *url.URL) (string, er if err != nil { return "", fmt.Errorf("getting machine provider: %w", err) } - dirs, err := machine.GetMachineDirs(machineProvider.VMType()) + dirs, err := env.GetMachineDirs(machineProvider.VMType()) if err != nil { return "", err } diff --git a/cmd/podman/machine/info.go b/cmd/podman/machine/info.go index 072c639fcb..793bc4efe8 100644 --- a/cmd/podman/machine/info.go +++ b/cmd/podman/machine/info.go @@ -14,8 +14,8 @@ import ( "github.com/containers/podman/v5/cmd/podman/validate" "github.com/containers/podman/v5/libpod/define" "github.com/containers/podman/v5/pkg/domain/entities" - "github.com/containers/podman/v5/pkg/machine" machineDefine "github.com/containers/podman/v5/pkg/machine/define" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/containers/podman/v5/pkg/machine/vmconfigs" "github.com/spf13/cobra" "gopkg.in/yaml.v3" @@ -100,7 +100,7 @@ func hostInfo() (*entities.MachineHostInfo, error) { host.Arch = runtime.GOARCH host.OS = runtime.GOOS - dirs, err := machine.GetMachineDirs(provider.VMType()) + dirs, err := env.GetMachineDirs(provider.VMType()) if err != nil { return nil, err } diff --git a/cmd/podman/machine/inspect.go b/cmd/podman/machine/inspect.go index 4e7c5941a0..92ed761ce1 100644 --- a/cmd/podman/machine/inspect.go +++ b/cmd/podman/machine/inspect.go @@ -10,6 +10,7 @@ import ( "github.com/containers/podman/v5/cmd/podman/registry" "github.com/containers/podman/v5/cmd/podman/utils" "github.com/containers/podman/v5/pkg/machine" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/containers/podman/v5/pkg/machine/vmconfigs" "github.com/spf13/cobra" ) @@ -47,7 +48,7 @@ func inspect(cmd *cobra.Command, args []string) error { var ( errs utils.OutputErrors ) - dirs, err := machine.GetMachineDirs(provider.VMType()) + dirs, err := env.GetMachineDirs(provider.VMType()) if err != nil { return err } diff --git a/cmd/podman/machine/machine.go b/cmd/podman/machine/machine.go index dc9b7b9f6b..1dd65c1ec8 100644 --- a/cmd/podman/machine/machine.go +++ b/cmd/podman/machine/machine.go @@ -15,7 +15,7 @@ import ( "github.com/containers/podman/v5/cmd/podman/registry" "github.com/containers/podman/v5/cmd/podman/validate" "github.com/containers/podman/v5/libpod/events" - "github.com/containers/podman/v5/pkg/machine" + "github.com/containers/podman/v5/pkg/machine/env" provider2 "github.com/containers/podman/v5/pkg/machine/provider" "github.com/containers/podman/v5/pkg/machine/vmconfigs" "github.com/containers/podman/v5/pkg/util" @@ -82,7 +82,7 @@ func getMachines(toComplete string) ([]string, cobra.ShellCompDirective) { if err != nil { return nil, cobra.ShellCompDirectiveNoFileComp } - dirs, err := machine.GetMachineDirs(provider.VMType()) + dirs, err := env.GetMachineDirs(provider.VMType()) if err != nil { return nil, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/podman/machine/os/manager.go b/cmd/podman/machine/os/manager.go index 0d402cd5c9..1e028be238 100644 --- a/cmd/podman/machine/os/manager.go +++ b/cmd/podman/machine/os/manager.go @@ -10,6 +10,7 @@ import ( machineconfig "github.com/containers/common/pkg/machine" pkgMachine "github.com/containers/podman/v5/pkg/machine" + "github.com/containers/podman/v5/pkg/machine/env" pkgOS "github.com/containers/podman/v5/pkg/machine/os" "github.com/containers/podman/v5/pkg/machine/provider" "github.com/containers/podman/v5/pkg/machine/vmconfigs" @@ -52,7 +53,7 @@ func machineOSManager(opts ManagerOpts, _ vmconfigs.VMProvider) (pkgOS.Manager, if err != nil { return nil, err } - dirs, err := pkgMachine.GetMachineDirs(p.VMType()) + dirs, err := env.GetMachineDirs(p.VMType()) if err != nil { return nil, err } diff --git a/cmd/podman/machine/reset.go b/cmd/podman/machine/reset.go index 920b553a1f..8c2f01e19a 100644 --- a/cmd/podman/machine/reset.go +++ b/cmd/podman/machine/reset.go @@ -12,6 +12,7 @@ import ( "github.com/containers/podman/v5/cmd/podman/registry" "github.com/containers/podman/v5/cmd/podman/validate" "github.com/containers/podman/v5/pkg/machine" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/containers/podman/v5/pkg/machine/shim" "github.com/containers/podman/v5/pkg/machine/vmconfigs" "github.com/spf13/cobra" @@ -50,7 +51,7 @@ func reset(_ *cobra.Command, _ []string) error { err error ) - dirs, err := machine.GetMachineDirs(provider.VMType()) + dirs, err := env.GetMachineDirs(provider.VMType()) if err != nil { return err } diff --git a/cmd/podman/machine/rm.go b/cmd/podman/machine/rm.go index 4a2130cbd8..5b76e1c19c 100644 --- a/cmd/podman/machine/rm.go +++ b/cmd/podman/machine/rm.go @@ -6,6 +6,7 @@ import ( "github.com/containers/podman/v5/cmd/podman/registry" "github.com/containers/podman/v5/libpod/events" "github.com/containers/podman/v5/pkg/machine" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/containers/podman/v5/pkg/machine/shim" "github.com/containers/podman/v5/pkg/machine/vmconfigs" "github.com/spf13/cobra" @@ -54,7 +55,7 @@ func rm(_ *cobra.Command, args []string) error { vmName = args[0] } - dirs, err := machine.GetMachineDirs(provider.VMType()) + dirs, err := env.GetMachineDirs(provider.VMType()) if err != nil { return err } diff --git a/cmd/podman/machine/set.go b/cmd/podman/machine/set.go index 431de52b5d..f6aad5e41d 100644 --- a/cmd/podman/machine/set.go +++ b/cmd/podman/machine/set.go @@ -8,8 +8,8 @@ import ( "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/strongunits" "github.com/containers/podman/v5/cmd/podman/registry" - "github.com/containers/podman/v5/pkg/machine" "github.com/containers/podman/v5/pkg/machine/define" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/containers/podman/v5/pkg/machine/shim" "github.com/containers/podman/v5/pkg/machine/vmconfigs" "github.com/spf13/cobra" @@ -99,7 +99,7 @@ func setMachine(cmd *cobra.Command, args []string) error { vmName = args[0] } - dirs, err := machine.GetMachineDirs(provider.VMType()) + dirs, err := env.GetMachineDirs(provider.VMType()) if err != nil { return err } diff --git a/cmd/podman/machine/ssh.go b/cmd/podman/machine/ssh.go index 73bed582c4..7c9346b47e 100644 --- a/cmd/podman/machine/ssh.go +++ b/cmd/podman/machine/ssh.go @@ -7,6 +7,7 @@ import ( "net/url" "github.com/containers/podman/v5/pkg/machine/define" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/containers/common/pkg/completion" "github.com/containers/podman/v5/cmd/podman/registry" @@ -54,7 +55,7 @@ func ssh(cmd *cobra.Command, args []string) error { validVM bool ) - dirs, err := machine.GetMachineDirs(provider.VMType()) + dirs, err := env.GetMachineDirs(provider.VMType()) if err != nil { return err } diff --git a/cmd/podman/machine/start.go b/cmd/podman/machine/start.go index fb6c822b73..84ae5a3094 100644 --- a/cmd/podman/machine/start.go +++ b/cmd/podman/machine/start.go @@ -9,6 +9,7 @@ import ( "github.com/containers/podman/v5/libpod/events" "github.com/containers/podman/v5/pkg/machine" "github.com/containers/podman/v5/pkg/machine/define" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/containers/podman/v5/pkg/machine/shim" "github.com/containers/podman/v5/pkg/machine/vmconfigs" "github.com/sirupsen/logrus" @@ -55,7 +56,7 @@ func start(_ *cobra.Command, args []string) error { vmName = args[0] } - dirs, err := machine.GetMachineDirs(provider.VMType()) + dirs, err := env.GetMachineDirs(provider.VMType()) if err != nil { return err } diff --git a/cmd/podman/machine/stop.go b/cmd/podman/machine/stop.go index 5a1877957a..ac9c4e5695 100644 --- a/cmd/podman/machine/stop.go +++ b/cmd/podman/machine/stop.go @@ -8,7 +8,7 @@ import ( "github.com/containers/podman/v5/cmd/podman/registry" "github.com/containers/podman/v5/libpod/events" - "github.com/containers/podman/v5/pkg/machine" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/containers/podman/v5/pkg/machine/shim" "github.com/containers/podman/v5/pkg/machine/vmconfigs" "github.com/sirupsen/logrus" @@ -46,7 +46,7 @@ func stop(cmd *cobra.Command, args []string) error { vmName = args[0] } - dirs, err := machine.GetMachineDirs(provider.VMType()) + dirs, err := env.GetMachineDirs(provider.VMType()) if err != nil { return err } diff --git a/cmd/podman/system/reset_machine.go b/cmd/podman/system/reset_machine.go index ad249a1a91..35430dfb7d 100644 --- a/cmd/podman/system/reset_machine.go +++ b/cmd/podman/system/reset_machine.go @@ -3,9 +3,9 @@ package system import ( - "github.com/containers/podman/v5/pkg/machine" "github.com/containers/podman/v5/pkg/machine/connection" "github.com/containers/podman/v5/pkg/machine/define" + "github.com/containers/podman/v5/pkg/machine/env" p "github.com/containers/podman/v5/pkg/machine/provider" "github.com/containers/podman/v5/pkg/machine/shim" "github.com/containers/podman/v5/pkg/machine/vmconfigs" @@ -18,7 +18,7 @@ func resetMachine() error { if err != nil { return err } - dirs, err := machine.GetMachineDirs(provider.VMType()) + dirs, err := env.GetMachineDirs(provider.VMType()) if err != nil { return err } diff --git a/go.mod b/go.mod index 18a87f9761..ee4b642b14 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/checkpoint-restore/go-criu/v7 v7.0.0 github.com/containernetworking/plugins v1.4.0 github.com/containers/buildah v1.34.1-0.20240229193131-f5d7689ef4cd - github.com/containers/common v0.57.1-0.20240229165734-cec09922602e + github.com/containers/common v0.57.1-0.20240304165751-a0d555c70d52 github.com/containers/conmon v2.0.20+incompatible github.com/containers/gvisor-tap-vsock v0.7.3 github.com/containers/image/v5 v5.29.3-0.20240229213915-cdc68020a24f diff --git a/go.sum b/go.sum index 531e7e6ede..d43c526b55 100644 --- a/go.sum +++ b/go.sum @@ -76,8 +76,8 @@ github.com/containernetworking/plugins v1.4.0 h1:+w22VPYgk7nQHw7KT92lsRmuToHvb7w github.com/containernetworking/plugins v1.4.0/go.mod h1:UYhcOyjefnrQvKvmmyEKsUA+M9Nfn7tqULPpH0Pkcj0= github.com/containers/buildah v1.34.1-0.20240229193131-f5d7689ef4cd h1:4cHNzaywyyJsCAtwUKMZm8r/wqm/WuNC70GfnI3kh18= github.com/containers/buildah v1.34.1-0.20240229193131-f5d7689ef4cd/go.mod h1:3fn5edBIPpIOPJYdnxBdTF7bjnBHhqZwYK5a6ApNdyk= -github.com/containers/common v0.57.1-0.20240229165734-cec09922602e h1:TPgCd6bWFyliJxCXEiCI1LnbB3kBUkpx1dw51ngDjWI= -github.com/containers/common v0.57.1-0.20240229165734-cec09922602e/go.mod h1:8irlyBcVooYx0F+YmoY7PQPAIgdJvCj17bvL7PqeaxI= +github.com/containers/common v0.57.1-0.20240304165751-a0d555c70d52 h1:+rq1qOOEv/2Sa1A9Tmv7yKuOzea8W2n6kFUH+bon61Y= +github.com/containers/common v0.57.1-0.20240304165751-a0d555c70d52/go.mod h1:h92alKzSekxVC+VDaX4gt7RJpXvJKF79a9TnULZ5ZDc= github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/gvisor-tap-vsock v0.7.3 h1:yORnf15sP+sLFhxLNLgmB5/lOhldn9dRMHx/tmYtSOQ= diff --git a/pkg/machine/applehv/stubber.go b/pkg/machine/applehv/stubber.go index d4915ba0bb..49caf3321a 100644 --- a/pkg/machine/applehv/stubber.go +++ b/pkg/machine/applehv/stubber.go @@ -313,6 +313,11 @@ func (a AppleHVStubber) StopHostNetworking(_ *vmconfigs.MachineConfig, _ define. return nil } +func (a AppleHVStubber) UpdateSSHPort(mc *vmconfigs.MachineConfig, port int) error { + // managed by gvproxy on this backend, so nothing to do + return nil +} + func (a AppleHVStubber) VMType() define.VMType { return define.AppleHvVirt } diff --git a/pkg/machine/config.go b/pkg/machine/config.go index 27834de7a9..ea43c5b6ec 100644 --- a/pkg/machine/config.go +++ b/pkg/machine/config.go @@ -9,14 +9,13 @@ import ( "net/http" "net/url" "os" - "path/filepath" "strings" "time" "github.com/containers/podman/v5/pkg/machine/compression" "github.com/containers/podman/v5/pkg/machine/define" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/containers/podman/v5/pkg/machine/vmconfigs" - "github.com/containers/storage/pkg/homedir" "github.com/sirupsen/logrus" ) @@ -119,147 +118,6 @@ type InspectInfo struct { Rootful bool } -// GetCacheDir returns the dir where VM images are downloaded into when pulled -func GetCacheDir(vmType define.VMType) (string, error) { - dataDir, err := GetDataDir(vmType) - if err != nil { - return "", err - } - cacheDir := filepath.Join(dataDir, "cache") - if _, err := os.Stat(cacheDir); !errors.Is(err, os.ErrNotExist) { - return cacheDir, nil - } - return cacheDir, os.MkdirAll(cacheDir, 0755) -} - -// GetDataDir returns the filepath where vm images should -// live for podman-machine. -func GetDataDir(vmType define.VMType) (string, error) { - dataDirPrefix, err := DataDirPrefix() - if err != nil { - return "", err - } - dataDir := filepath.Join(dataDirPrefix, vmType.String()) - if _, err := os.Stat(dataDir); !errors.Is(err, os.ErrNotExist) { - return dataDir, nil - } - mkdirErr := os.MkdirAll(dataDir, 0755) - return dataDir, mkdirErr -} - -// GetGlobalDataDir returns the root of all backends -// for shared machine data. -func GetGlobalDataDir() (string, error) { - dataDir, err := DataDirPrefix() - if err != nil { - return "", err - } - - return dataDir, os.MkdirAll(dataDir, 0755) -} - -func GetMachineDirs(vmType define.VMType) (*define.MachineDirs, error) { - rtDir, err := getRuntimeDir() - if err != nil { - return nil, err - } - - rtDir = filepath.Join(rtDir, "podman") - configDir, err := GetConfDir(vmType) - if err != nil { - return nil, err - } - - configDirFile, err := define.NewMachineFile(configDir, nil) - if err != nil { - return nil, err - } - dataDir, err := GetDataDir(vmType) - if err != nil { - return nil, err - } - - dataDirFile, err := define.NewMachineFile(dataDir, nil) - if err != nil { - return nil, err - } - - imageCacheDir, err := dataDirFile.AppendToNewVMFile("cache", nil) - if err != nil { - return nil, err - } - - rtDirFile, err := define.NewMachineFile(rtDir, nil) - if err != nil { - return nil, err - } - - dirs := define.MachineDirs{ - ConfigDir: configDirFile, - DataDir: dataDirFile, - ImageCacheDir: imageCacheDir, - RuntimeDir: rtDirFile, - } - - // make sure all machine dirs are present - if err := os.MkdirAll(rtDir, 0755); err != nil { - return nil, err - } - if err := os.MkdirAll(configDir, 0755); err != nil { - return nil, err - } - - // Because this is a mkdirall, we make the image cache dir - // which is a subdir of datadir (so the datadir is made anyway) - err = os.MkdirAll(imageCacheDir.GetPath(), 0755) - - return &dirs, err -} - -// DataDirPrefix returns the path prefix for all machine data files -func DataDirPrefix() (string, error) { - data, err := homedir.GetDataHome() - if err != nil { - return "", err - } - dataDir := filepath.Join(data, "containers", "podman", "machine") - return dataDir, nil -} - -// GetConfigDir returns the filepath to where configuration -// files for podman-machine should live -func GetConfDir(vmType define.VMType) (string, error) { - confDirPrefix, err := ConfDirPrefix() - if err != nil { - return "", err - } - confDir := filepath.Join(confDirPrefix, vmType.String()) - if _, err := os.Stat(confDir); !errors.Is(err, os.ErrNotExist) { - return confDir, nil - } - mkdirErr := os.MkdirAll(confDir, 0755) - return confDir, mkdirErr -} - -// ConfDirPrefix returns the path prefix for all machine config files -func ConfDirPrefix() (string, error) { - conf, err := homedir.GetConfigHome() - if err != nil { - return "", err - } - confDir := filepath.Join(conf, "containers", "podman", "machine") - return confDir, nil -} - -// GetSSHIdentityPath returns the path to the expected SSH private key -func GetSSHIdentityPath(name string) (string, error) { - datadir, err := GetGlobalDataDir() - if err != nil { - return "", err - } - return filepath.Join(datadir, name), nil -} - // ImageConfig describes the bootable image for the VM type ImageConfig struct { // IgnitionFile is the path to the filesystem where the @@ -314,12 +172,12 @@ func (p *Virtualization) VMType() define.VMType { } func (p *Virtualization) NewDownload(vmName string) (Download, error) { - cacheDir, err := GetCacheDir(p.VMType()) + cacheDir, err := env.GetCacheDir(p.VMType()) if err != nil { return Download{}, err } - dataDir, err := GetDataDir(p.VMType()) + dataDir, err := env.GetDataDir(p.VMType()) if err != nil { return Download{}, err } diff --git a/pkg/machine/config_test.go b/pkg/machine/config_test.go index 3450a111f1..f5cb14c314 100644 --- a/pkg/machine/config_test.go +++ b/pkg/machine/config_test.go @@ -6,14 +6,15 @@ import ( "path/filepath" "testing" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/stretchr/testify/assert" ) func TestGetSSHIdentityPath(t *testing.T) { name := "p-test" - datadir, err := GetGlobalDataDir() + datadir, err := env.GetGlobalDataDir() assert.Nil(t, err) - identityPath, err := GetSSHIdentityPath(name) + identityPath, err := env.GetSSHIdentityPath(name) assert.Nil(t, err) assert.Equal(t, identityPath, filepath.Join(datadir, name)) } diff --git a/pkg/machine/connection/add.go b/pkg/machine/connection/add.go index c87550065f..930c63f6ce 100644 --- a/pkg/machine/connection/add.go +++ b/pkg/machine/connection/add.go @@ -1,3 +1,5 @@ +//go:build amd64 || arm64 + package connection import ( @@ -14,10 +16,23 @@ func AddSSHConnectionsToPodmanSocket(uid, port int, identityPath, name, remoteUs fmt.Println("An ignition path was provided. No SSH connection was added to Podman") return nil } + + cons := createConnections(name, uid, port, remoteUsername) + + // The first connection defined when connections is empty will become the default + // regardless of IsDefault, so order according to rootful + if opts.Rootful { + cons[0], cons[1] = cons[1], cons[0] + } + + return addConnection(cons, identityPath, opts.IsDefault) +} + +func createConnections(name string, uid, port int, remoteUsername string) []connection { uri := makeSSHURL(LocalhostIP, fmt.Sprintf("/run/user/%d/podman/podman.sock", uid), strconv.Itoa(port), remoteUsername) uriRoot := makeSSHURL(LocalhostIP, "/run/podman/podman.sock", strconv.Itoa(port), "root") - cons := []connection{ + return []connection{ { name: name, uri: uri, @@ -27,12 +42,4 @@ func AddSSHConnectionsToPodmanSocket(uid, port int, identityPath, name, remoteUs uri: uriRoot, }, } - - // The first connection defined when connections is empty will become the default - // regardless of IsDefault, so order according to rootful - if opts.Rootful { - cons[0], cons[1] = cons[1], cons[0] - } - - return addConnection(cons, identityPath, opts.IsDefault) } diff --git a/pkg/machine/connection/connection.go b/pkg/machine/connection/connection.go index 4c3394a8d2..2dea2d93f9 100644 --- a/pkg/machine/connection/connection.go +++ b/pkg/machine/connection/connection.go @@ -55,14 +55,17 @@ func addConnection(cons []connection, identity string, isDefault bool) error { }) } -func ChangeConnectionURI(name string, uri fmt.Stringer) error { +func UpdateConnectionPairPort(name string, port, uid int, remoteUsername string, identityPath string) error { + cons := createConnections(name, uid, port, remoteUsername) return config.EditConnectionConfig(func(cfg *config.ConnectionsFile) error { - dst, ok := cfg.Connection.Connections[name] - if !ok { - return errors.New("connection not found") + for _, con := range cons { + dst := config.Destination{ + IsMachine: true, + URI: con.uri.String(), + Identity: identityPath, + } + cfg.Connection.Connections[name] = dst } - dst.URI = uri.String() - cfg.Connection.Connections[name] = dst return nil }) diff --git a/pkg/machine/env/dir.go b/pkg/machine/env/dir.go new file mode 100644 index 0000000000..5f0a664a64 --- /dev/null +++ b/pkg/machine/env/dir.go @@ -0,0 +1,151 @@ +package env + +import ( + "errors" + "os" + "path/filepath" + + "github.com/containers/podman/v5/pkg/machine/define" + "github.com/containers/storage/pkg/homedir" +) + +// GetCacheDir returns the dir where VM images are downloaded into when pulled +func GetCacheDir(vmType define.VMType) (string, error) { + dataDir, err := GetDataDir(vmType) + if err != nil { + return "", err + } + cacheDir := filepath.Join(dataDir, "cache") + if _, err := os.Stat(cacheDir); !errors.Is(err, os.ErrNotExist) { + return cacheDir, nil + } + return cacheDir, os.MkdirAll(cacheDir, 0755) +} + +// GetDataDir returns the filepath where vm images should +// live for podman-machine. +func GetDataDir(vmType define.VMType) (string, error) { + dataDirPrefix, err := DataDirPrefix() + if err != nil { + return "", err + } + dataDir := filepath.Join(dataDirPrefix, vmType.String()) + if _, err := os.Stat(dataDir); !errors.Is(err, os.ErrNotExist) { + return dataDir, nil + } + mkdirErr := os.MkdirAll(dataDir, 0755) + return dataDir, mkdirErr +} + +// GetGlobalDataDir returns the root of all backends +// for shared machine data. +func GetGlobalDataDir() (string, error) { + dataDir, err := DataDirPrefix() + if err != nil { + return "", err + } + + return dataDir, os.MkdirAll(dataDir, 0755) +} + +func GetMachineDirs(vmType define.VMType) (*define.MachineDirs, error) { + rtDir, err := getRuntimeDir() + if err != nil { + return nil, err + } + + rtDir = filepath.Join(rtDir, "podman") + configDir, err := GetConfDir(vmType) + if err != nil { + return nil, err + } + + configDirFile, err := define.NewMachineFile(configDir, nil) + if err != nil { + return nil, err + } + dataDir, err := GetDataDir(vmType) + if err != nil { + return nil, err + } + + dataDirFile, err := define.NewMachineFile(dataDir, nil) + if err != nil { + return nil, err + } + + imageCacheDir, err := dataDirFile.AppendToNewVMFile("cache", nil) + if err != nil { + return nil, err + } + + rtDirFile, err := define.NewMachineFile(rtDir, nil) + if err != nil { + return nil, err + } + + dirs := define.MachineDirs{ + ConfigDir: configDirFile, + DataDir: dataDirFile, + ImageCacheDir: imageCacheDir, + RuntimeDir: rtDirFile, + } + + // make sure all machine dirs are present + if err := os.MkdirAll(rtDir, 0755); err != nil { + return nil, err + } + if err := os.MkdirAll(configDir, 0755); err != nil { + return nil, err + } + + // Because this is a mkdirall, we make the image cache dir + // which is a subdir of datadir (so the datadir is made anyway) + err = os.MkdirAll(imageCacheDir.GetPath(), 0755) + + return &dirs, err +} + +// DataDirPrefix returns the path prefix for all machine data files +func DataDirPrefix() (string, error) { + data, err := homedir.GetDataHome() + if err != nil { + return "", err + } + dataDir := filepath.Join(data, "containers", "podman", "machine") + return dataDir, nil +} + +// GetConfigDir returns the filepath to where configuration +// files for podman-machine should live +func GetConfDir(vmType define.VMType) (string, error) { + confDirPrefix, err := ConfDirPrefix() + if err != nil { + return "", err + } + confDir := filepath.Join(confDirPrefix, vmType.String()) + if _, err := os.Stat(confDir); !errors.Is(err, os.ErrNotExist) { + return confDir, nil + } + mkdirErr := os.MkdirAll(confDir, 0755) + return confDir, mkdirErr +} + +// ConfDirPrefix returns the path prefix for all machine config files +func ConfDirPrefix() (string, error) { + conf, err := homedir.GetConfigHome() + if err != nil { + return "", err + } + confDir := filepath.Join(conf, "containers", "podman", "machine") + return confDir, nil +} + +// GetSSHIdentityPath returns the path to the expected SSH private key +func GetSSHIdentityPath(name string) (string, error) { + datadir, err := GetGlobalDataDir() + if err != nil { + return "", err + } + return filepath.Join(datadir, name), nil +} diff --git a/pkg/machine/options_darwin.go b/pkg/machine/env/dir_darwin.go similarity index 90% rename from pkg/machine/options_darwin.go rename to pkg/machine/env/dir_darwin.go index 3959175d2c..ed72aec8ab 100644 --- a/pkg/machine/options_darwin.go +++ b/pkg/machine/env/dir_darwin.go @@ -1,4 +1,4 @@ -package machine +package env import "os" diff --git a/pkg/machine/options_freebsd.go b/pkg/machine/env/dir_freebsd.go similarity index 90% rename from pkg/machine/options_freebsd.go rename to pkg/machine/env/dir_freebsd.go index 3959175d2c..ed72aec8ab 100644 --- a/pkg/machine/options_freebsd.go +++ b/pkg/machine/env/dir_freebsd.go @@ -1,4 +1,4 @@ -package machine +package env import "os" diff --git a/pkg/machine/options_linux.go b/pkg/machine/env/dir_linux.go similarity index 93% rename from pkg/machine/options_linux.go rename to pkg/machine/env/dir_linux.go index 5ba8280008..67f8142440 100644 --- a/pkg/machine/options_linux.go +++ b/pkg/machine/env/dir_linux.go @@ -1,4 +1,4 @@ -package machine +package env import ( "github.com/containers/podman/v5/pkg/rootless" diff --git a/pkg/machine/options_windows.go b/pkg/machine/env/dir_windows.go similarity index 91% rename from pkg/machine/options_windows.go rename to pkg/machine/env/dir_windows.go index 1a880069c6..9a272568ca 100644 --- a/pkg/machine/options_windows.go +++ b/pkg/machine/env/dir_windows.go @@ -1,4 +1,4 @@ -package machine +package env import "os" diff --git a/pkg/machine/hyperv/stubber.go b/pkg/machine/hyperv/stubber.go index d3070151e7..70029e9e35 100644 --- a/pkg/machine/hyperv/stubber.go +++ b/pkg/machine/hyperv/stubber.go @@ -10,6 +10,7 @@ import ( "os/exec" "path/filepath" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/containers/podman/v5/pkg/machine/shim/diskpull" "github.com/Microsoft/go-winio" @@ -387,7 +388,7 @@ func (h HyperVStubber) PostStartNetworking(mc *vmconfigs.MachineConfig, noInfo b dirs *define.MachineDirs gvproxyPID int ) - dirs, err = machine.GetMachineDirs(h.VMType()) + dirs, err = env.GetMachineDirs(h.VMType()) if err != nil { return err } @@ -445,6 +446,11 @@ func (h HyperVStubber) PostStartNetworking(mc *vmconfigs.MachineConfig, noInfo b return err } +func (h HyperVStubber) UpdateSSHPort(mc *vmconfigs.MachineConfig, port int) error { + // managed by gvproxy on this backend, so nothing to do + return nil +} + func (h HyperVStubber) GetDisk(userInputPath string, dirs *define.MachineDirs, mc *vmconfigs.MachineConfig) error { return diskpull.GetDisk(userInputPath, dirs, mc.ImagePath, h.VMType(), mc.Name) } @@ -503,7 +509,7 @@ func removeIgnitionFromRegistry(vm *hypervctl.VirtualMachine) error { } func logCommandToFile(c *exec.Cmd, filename string) error { - dir, err := machine.GetDataDir(define.HyperVVirt) + dir, err := env.GetDataDir(define.HyperVVirt) if err != nil { return fmt.Errorf("obtain machine dir: %w", err) } diff --git a/pkg/machine/ignition/ready.go b/pkg/machine/ignition/ready.go index 68bb57577b..47706b26eb 100644 --- a/pkg/machine/ignition/ready.go +++ b/pkg/machine/ignition/ready.go @@ -1,3 +1,5 @@ +//go:build amd64 || arm64 + package ignition import ( diff --git a/pkg/machine/machine_windows.go b/pkg/machine/machine_windows.go index 3743b0db05..602f142b33 100644 --- a/pkg/machine/machine_windows.go +++ b/pkg/machine/machine_windows.go @@ -17,6 +17,7 @@ import ( winio "github.com/Microsoft/go-winio" "github.com/containers/podman/v5/pkg/machine/define" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/sirupsen/logrus" ) @@ -250,7 +251,7 @@ func FindExecutablePeer(name string) (string, error) { } func GetWinProxyStateDir(name string, vmtype define.VMType) (string, error) { - dir, err := GetDataDir(vmtype) + dir, err := env.GetDataDir(vmtype) if err != nil { return "", err } diff --git a/pkg/machine/os/machine_os.go b/pkg/machine/os/machine_os.go index b77164fb98..6ff55fa92b 100644 --- a/pkg/machine/os/machine_os.go +++ b/pkg/machine/os/machine_os.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/containers/podman/v5/pkg/machine" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/containers/podman/v5/pkg/machine/shim" "github.com/containers/podman/v5/pkg/machine/vmconfigs" ) @@ -27,7 +28,7 @@ func (m *MachineOS) Apply(image string, opts ApplyOptions) error { return err } - dirs, err := machine.GetMachineDirs(m.Provider.VMType()) + dirs, err := env.GetMachineDirs(m.Provider.VMType()) if err != nil { return err } diff --git a/pkg/machine/ports.go b/pkg/machine/ports/ports.go similarity index 96% rename from pkg/machine/ports.go rename to pkg/machine/ports/ports.go index 2837d492f6..e9e9afa2b4 100644 --- a/pkg/machine/ports.go +++ b/pkg/machine/ports/ports.go @@ -1,4 +1,4 @@ -package machine +package ports import ( "context" @@ -11,6 +11,7 @@ import ( "path/filepath" "strconv" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/containers/storage/pkg/ioutils" "github.com/containers/storage/pkg/lockfile" "github.com/sirupsen/logrus" @@ -135,7 +136,7 @@ func getRandomPortHold() (io.Closer, int, error) { } func acquirePortLock() (*lockfile.LockFile, error) { - lockDir, err := GetGlobalDataDir() + lockDir, err := env.GetGlobalDataDir() if err != nil { return nil, err } @@ -150,7 +151,7 @@ func acquirePortLock() (*lockfile.LockFile, error) { } func loadPortAllocations() (map[int]struct{}, error) { - portDir, err := GetGlobalDataDir() + portDir, err := env.GetGlobalDataDir() if err != nil { return nil, err } @@ -186,7 +187,7 @@ func loadPortAllocations() (map[int]struct{}, error) { } func storePortAllocations(ports map[int]struct{}) error { - portDir, err := GetGlobalDataDir() + portDir, err := env.GetGlobalDataDir() if err != nil { return err } diff --git a/pkg/machine/ports_unix.go b/pkg/machine/ports/ports_unix.go similarity index 98% rename from pkg/machine/ports_unix.go rename to pkg/machine/ports/ports_unix.go index 38cad8948a..20188d3d78 100644 --- a/pkg/machine/ports_unix.go +++ b/pkg/machine/ports/ports_unix.go @@ -1,6 +1,6 @@ //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd -package machine +package ports import ( "net" diff --git a/pkg/machine/ports_windows.go b/pkg/machine/ports/ports_windows.go similarity index 98% rename from pkg/machine/ports_windows.go rename to pkg/machine/ports/ports_windows.go index 730d4be0b3..abfb4592e1 100644 --- a/pkg/machine/ports_windows.go +++ b/pkg/machine/ports/ports_windows.go @@ -1,4 +1,4 @@ -package machine +package ports import ( "net" diff --git a/pkg/machine/pull.go b/pkg/machine/pull.go index cba6466ee1..932c46a941 100644 --- a/pkg/machine/pull.go +++ b/pkg/machine/pull.go @@ -15,6 +15,7 @@ import ( "github.com/containers/podman/v5/pkg/machine/compression" "github.com/containers/podman/v5/pkg/machine/define" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/containers/podman/v5/pkg/machine/ocipull" "github.com/containers/podman/v5/utils" "github.com/sirupsen/logrus" @@ -31,11 +32,11 @@ func NewGenericDownloader(vmType define.VMType, vmName, pullPath string) (Distri var ( imageName string ) - dataDir, err := GetDataDir(vmType) + dataDir, err := env.GetDataDir(vmType) if err != nil { return nil, err } - cacheDir, err := GetCacheDir(vmType) + cacheDir, err := env.GetCacheDir(vmType) if err != nil { return nil, err } diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 1b62240127..2595eb54f0 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -1,4 +1,4 @@ -//go:build !darwin +//go:build linux || freebsd package qemu diff --git a/pkg/machine/qemu/options_windows_amd64.go b/pkg/machine/qemu/options_windows_amd64.go index 6e0ba0271a..1a929a5f32 100644 --- a/pkg/machine/qemu/options_windows_amd64.go +++ b/pkg/machine/qemu/options_windows_amd64.go @@ -1,4 +1,4 @@ -//go:build windows && amd64 +//go:build tempoff package qemu diff --git a/pkg/machine/qemu/stubber.go b/pkg/machine/qemu/stubber.go index df056ec803..9fd1580630 100644 --- a/pkg/machine/qemu/stubber.go +++ b/pkg/machine/qemu/stubber.go @@ -1,4 +1,4 @@ -//go:build !darwin +//go:build linux || freebsd package qemu @@ -352,6 +352,11 @@ func (q *QEMUStubber) PostStartNetworking(mc *vmconfigs.MachineConfig, noInfo bo return nil } +func (q *QEMUStubber) UpdateSSHPort(mc *vmconfigs.MachineConfig, port int) error { + // managed by gvproxy on this backend, so nothing to do + return nil +} + func (q *QEMUStubber) GetDisk(userInputPath string, dirs *define.MachineDirs, mc *vmconfigs.MachineConfig) error { return diskpull.GetDisk(userInputPath, dirs, mc.ImagePath, q.VMType(), mc.Name) } diff --git a/pkg/machine/shim/host.go b/pkg/machine/shim/host.go index f69bd8cbeb..787607943a 100644 --- a/pkg/machine/shim/host.go +++ b/pkg/machine/shim/host.go @@ -13,6 +13,7 @@ import ( "github.com/containers/podman/v5/pkg/machine" "github.com/containers/podman/v5/pkg/machine/connection" machineDefine "github.com/containers/podman/v5/pkg/machine/define" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/containers/podman/v5/pkg/machine/ignition" "github.com/containers/podman/v5/pkg/machine/proxyenv" "github.com/containers/podman/v5/pkg/machine/vmconfigs" @@ -29,7 +30,7 @@ func List(vmstubbers []vmconfigs.VMProvider, _ machine.ListOptions) ([]*machine. ) for _, s := range vmstubbers { - dirs, err := machine.GetMachineDirs(s.VMType()) + dirs, err := env.GetMachineDirs(s.VMType()) if err != nil { return nil, err } @@ -76,12 +77,12 @@ func Init(opts machineDefine.InitOptions, mp vmconfigs.VMProvider) (*vmconfigs.M defer callbackFuncs.CleanIfErr(&err) go callbackFuncs.CleanOnSignal() - dirs, err := machine.GetMachineDirs(mp.VMType()) + dirs, err := env.GetMachineDirs(mp.VMType()) if err != nil { return nil, err } - sshIdentityPath, err := machine.GetSSHIdentityPath(machineDefine.DefaultIdentityName) + sshIdentityPath, err := env.GetSSHIdentityPath(machineDefine.DefaultIdentityName) if err != nil { return nil, err } @@ -288,7 +289,7 @@ func CheckExclusiveActiveVM(provider vmconfigs.VMProvider, mc *vmconfigs.Machine func getMCsOverProviders(vmstubbers []vmconfigs.VMProvider) (map[string]*vmconfigs.MachineConfig, error) { mcs := make(map[string]*vmconfigs.MachineConfig) for _, stubber := range vmstubbers { - dirs, err := machine.GetMachineDirs(stubber.VMType()) + dirs, err := env.GetMachineDirs(stubber.VMType()) if err != nil { return nil, err } diff --git a/pkg/machine/shim/networking.go b/pkg/machine/shim/networking.go index 98c3bbe61d..5ad2aa2dea 100644 --- a/pkg/machine/shim/networking.go +++ b/pkg/machine/shim/networking.go @@ -11,7 +11,10 @@ import ( "github.com/containers/common/pkg/config" gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types" "github.com/containers/podman/v5/pkg/machine" + "github.com/containers/podman/v5/pkg/machine/connection" "github.com/containers/podman/v5/pkg/machine/define" + "github.com/containers/podman/v5/pkg/machine/env" + "github.com/containers/podman/v5/pkg/machine/ports" "github.com/containers/podman/v5/pkg/machine/vmconfigs" "github.com/sirupsen/logrus" ) @@ -90,12 +93,20 @@ func startHostForwarder(mc *vmconfigs.MachineConfig, provider vmconfigs.VMProvid } func startNetworking(mc *vmconfigs.MachineConfig, provider vmconfigs.VMProvider) (string, machine.APIForwardingState, error) { + // Check if SSH port is in use, and reassign if necessary + if !ports.IsLocalPortAvailable(mc.SSH.Port) { + logrus.Warnf("detected port conflict on machine ssh port [%d], reassigning", mc.SSH.Port) + if err := reassignSSHPort(mc, provider); err != nil { + return "", 0, err + } + } + // Provider has its own networking code path (e.g. WSL) if provider.UseProviderNetworkSetup() { return "", 0, provider.StartNetworking(mc, nil) } - dirs, err := machine.GetMachineDirs(provider.VMType()) + dirs, err := env.GetMachineDirs(provider.VMType()) if err != nil { return "", 0, err } @@ -152,6 +163,53 @@ func conductVMReadinessCheck(mc *vmconfigs.MachineConfig, maxBackoffs int, backo return } +func reassignSSHPort(mc *vmconfigs.MachineConfig, provider vmconfigs.VMProvider) error { + newPort, err := ports.AllocateMachinePort() + if err != nil { + return err + } + + success := false + defer func() { + if !success { + if err := ports.ReleaseMachinePort(newPort); err != nil { + logrus.Warnf("could not release port allocation as part of failure rollback (%d): %s", newPort, err.Error()) + } + } + }() + + // Write a transient invalid port, to force a retry on failure + oldPort := mc.SSH.Port + mc.SSH.Port = 0 + if err := mc.Write(); err != nil { + return err + } + + if err := ports.ReleaseMachinePort(oldPort); err != nil { + logrus.Warnf("could not release current ssh port allocation (%d): %s", oldPort, err.Error()) + } + + // Update the backend's settings if relevant (e.g. WSL) + if err := provider.UpdateSSHPort(mc, newPort); err != nil { + return err + } + + mc.SSH.Port = newPort + if err := connection.UpdateConnectionPairPort(mc.Name, newPort, mc.HostUser.UID, mc.SSH.RemoteUsername, mc.SSH.IdentityPath); err != nil { + return fmt.Errorf("could not update remote connection configuration: %w", err) + } + + // Write updated port back + if err := mc.Write(); err != nil { + return err + } + + // inform defer routine not to release the port + success = true + + return nil +} + func isListening(port int) bool { // Check if we can dial it conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", "127.0.0.1", port), 10*time.Millisecond) diff --git a/pkg/machine/vmconfigs/config.go b/pkg/machine/vmconfigs/config.go index 037681391f..2acd075952 100644 --- a/pkg/machine/vmconfigs/config.go +++ b/pkg/machine/vmconfigs/config.go @@ -96,6 +96,7 @@ type VMProvider interface { //nolint:interfacebloat UserModeNetworkEnabled(mc *MachineConfig) bool UseProviderNetworkSetup() bool RequireExclusiveActive() bool + UpdateSSHPort(mc *MachineConfig, port int) error } // HostUser describes the host user diff --git a/pkg/machine/vmconfigs/machine.go b/pkg/machine/vmconfigs/machine.go index b1877db0fa..dea667e315 100644 --- a/pkg/machine/vmconfigs/machine.go +++ b/pkg/machine/vmconfigs/machine.go @@ -15,7 +15,7 @@ import ( "github.com/containers/podman/v5/pkg/machine/connection" "github.com/containers/podman/v5/pkg/machine/define" "github.com/containers/podman/v5/pkg/machine/lock" - "github.com/containers/podman/v5/utils" + "github.com/containers/podman/v5/pkg/machine/ports" "github.com/containers/storage/pkg/ioutils" "github.com/sirupsen/logrus" ) @@ -78,8 +78,7 @@ func NewMachineConfig(opts define.InitOptions, dirs *define.MachineDirs, sshIden } mc.Resources = mrc - // TODO WSL had a locking port mechanism, we should consider this. - sshPort, err := utils.GetRandomPort() + sshPort, err := ports.AllocateMachinePort() if err != nil { return nil, err } @@ -204,6 +203,11 @@ func (mc *MachineConfig) Remove(saveIgnition, saveImage bool) ([]string, func() if err := mc.configPath.Delete(); err != nil { errs = append(errs, err) } + + if err := ports.ReleaseMachinePort(mc.SSH.Port); err != nil { + errs = append(errs, err) + } + return errorhandling.JoinErrors(errs) } diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go index 26f16a66ec..bc79614e3a 100644 --- a/pkg/machine/wsl/machine.go +++ b/pkg/machine/wsl/machine.go @@ -17,6 +17,7 @@ import ( "github.com/containers/common/pkg/config" "github.com/containers/podman/v5/pkg/machine" "github.com/containers/podman/v5/pkg/machine/define" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/containers/podman/v5/pkg/machine/ignition" "github.com/containers/podman/v5/pkg/machine/vmconfigs" "github.com/containers/podman/v5/pkg/machine/wsl/wutil" @@ -47,7 +48,7 @@ func getConfigPath(name string) (string, error) { //nolint:unused func getConfigPathExt(name string, extension string) (string, error) { - vmConfigDir, err := machine.GetConfDir(vmtype) + vmConfigDir, err := env.GetConfDir(vmtype) if err != nil { return "", err } @@ -66,7 +67,7 @@ func unprovisionWSL(mc *vmconfigs.MachineConfig) error { logrus.Error(err) } - vmDataDir, err := machine.GetDataDir(vmtype) + vmDataDir, err := env.GetDataDir(vmtype) if err != nil { return err } @@ -79,7 +80,7 @@ func unprovisionWSL(mc *vmconfigs.MachineConfig) error { // we should push this stuff be more common (dir names, etc) and also use // typed things where possible like vmfiles func provisionWSLDist(name string, imagePath string, prompt string) (string, error) { - vmDataDir, err := machine.GetDataDir(vmtype) + vmDataDir, err := env.GetDataDir(vmtype) if err != nil { return "", err } @@ -586,7 +587,7 @@ func setupWslProxyEnv() (hasProxy bool) { //nolint:unused func obtainGlobalConfigLock() (*fileLock, error) { - lockDir, err := machine.GetGlobalDataDir() + lockDir, err := env.GetGlobalDataDir() if err != nil { return nil, err } @@ -702,7 +703,7 @@ func isRunning(name string) (bool, error) { //nolint:unused func getDiskSize(name string) uint64 { - vmDataDir, err := machine.GetDataDir(vmtype) + vmDataDir, err := env.GetDataDir(vmtype) if err != nil { return 0 } diff --git a/pkg/machine/wsl/stubber.go b/pkg/machine/wsl/stubber.go index c28db07842..bb8f1d072d 100644 --- a/pkg/machine/wsl/stubber.go +++ b/pkg/machine/wsl/stubber.go @@ -110,7 +110,7 @@ func (w WSLStubber) Remove(mc *vmconfigs.MachineConfig) ([]string, func() error, if err := runCmdPassThrough(wutil.FindWSL(), "--unregister", machine.ToDist(mc.Name)); err != nil { logrus.Error(err) } - return machine.ReleaseMachinePort(mc.SSH.Port) + return nil } return []string{}, wslRemoveFunc, nil @@ -204,15 +204,6 @@ func (w WSLStubber) PostStartNetworking(mc *vmconfigs.MachineConfig, noInfo bool func (w WSLStubber) StartVM(mc *vmconfigs.MachineConfig) (func() error, func() error, error) { dist := machine.ToDist(mc.Name) - // TODO The original code checked to see if the SSH port was actually open and re-assigned if it was - // we could consider this but it should be higher up the stack - // if !machine.IsLocalPortAvailable(v.Port) { - // logrus.Warnf("SSH port conflict detected, reassigning a new port") - // if err := v.reassignSshPort(); err != nil { - // return err - // } - // } - err := wslInvoke(dist, "/root/bootstrap") if err != nil { err = fmt.Errorf("the WSL bootstrap script failed: %w", err) @@ -278,6 +269,16 @@ func (w WSLStubber) StopHostNetworking(mc *vmconfigs.MachineConfig, vmType defin return stopUserModeNetworking(mc) } +func (w WSLStubber) UpdateSSHPort(mc *vmconfigs.MachineConfig, port int) error { + dist := machine.ToDist(mc.Name) + + if err := wslInvoke(dist, "sh", "-c", fmt.Sprintf(changePort, port)); err != nil { + return fmt.Errorf("could not change SSH port for guest OS: %w", err) + } + + return nil +} + func (w WSLStubber) VMType() define.VMType { return define.WSLVirt } diff --git a/pkg/machine/wsl/usermodenet.go b/pkg/machine/wsl/usermodenet.go index 7d4b870cf8..b979941cb1 100644 --- a/pkg/machine/wsl/usermodenet.go +++ b/pkg/machine/wsl/usermodenet.go @@ -10,6 +10,7 @@ import ( "path/filepath" "github.com/containers/podman/v5/pkg/machine" + "github.com/containers/podman/v5/pkg/machine/env" "github.com/containers/podman/v5/pkg/machine/vmconfigs" "github.com/containers/podman/v5/pkg/machine/wsl/wutil" "github.com/containers/podman/v5/pkg/specgen" @@ -226,7 +227,7 @@ func createUserModeResolvConf(dist string) error { } func getUserModeNetDir() (string, error) { - vmDataDir, err := machine.GetDataDir(vmtype) + vmDataDir, err := env.GetDataDir(vmtype) if err != nil { return "", err } diff --git a/vendor/github.com/containers/common/pkg/cgroups/cgroups_linux.go b/vendor/github.com/containers/common/pkg/cgroups/cgroups_linux.go index 726324cfe7..bd87f14741 100644 --- a/vendor/github.com/containers/common/pkg/cgroups/cgroups_linux.go +++ b/vendor/github.com/containers/common/pkg/cgroups/cgroups_linux.go @@ -13,6 +13,9 @@ import ( "path/filepath" "strconv" "strings" + "sync" + "syscall" + "time" "github.com/containers/storage/pkg/unshare" systemdDbus "github.com/coreos/go-systemd/v22/dbus" @@ -22,6 +25,7 @@ import ( "github.com/opencontainers/runc/libcontainer/configs" "github.com/sirupsen/logrus" "golang.org/x/exp/maps" + "golang.org/x/sys/unix" ) var ( @@ -30,6 +34,10 @@ var ( // ErrCgroupV1Rootless means the cgroup v1 were attempted to be used in rootless environment ErrCgroupV1Rootless = errors.New("no support for CGroups V1 in rootless environments") ErrStatCgroup = errors.New("no cgroup available for gathering user statistics") + + isUnifiedOnce sync.Once + isUnified bool + isUnifiedErr error ) // CgroupControl controls a cgroup hierarchy @@ -731,3 +739,139 @@ func SystemCPUUsage() (uint64, error) { } return total, nil } + +// IsCgroup2UnifiedMode returns whether we are running in cgroup 2 cgroup2 mode. +func IsCgroup2UnifiedMode() (bool, error) { + isUnifiedOnce.Do(func() { + var st syscall.Statfs_t + if err := syscall.Statfs("/sys/fs/cgroup", &st); err != nil { + isUnified, isUnifiedErr = false, err + } else { + isUnified, isUnifiedErr = st.Type == unix.CGROUP2_SUPER_MAGIC, nil + } + }) + return isUnified, isUnifiedErr +} + +// UserConnection returns an user connection to D-BUS +func UserConnection(uid int) (*systemdDbus.Conn, error) { + return systemdDbus.NewConnection(func() (*dbus.Conn, error) { + return dbusAuthConnection(uid, dbus.SessionBusPrivateNoAutoStartup) + }) +} + +// UserOwnsCurrentSystemdCgroup checks whether the current EUID owns the +// current cgroup. +func UserOwnsCurrentSystemdCgroup() (bool, error) { + uid := os.Geteuid() + + cgroup2, err := IsCgroup2UnifiedMode() + if err != nil { + return false, err + } + + f, err := os.Open("/proc/self/cgroup") + if err != nil { + return false, err + } + defer f.Close() + + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := scanner.Text() + parts := strings.SplitN(line, ":", 3) + + if len(parts) < 3 { + continue + } + + var cgroupPath string + + if cgroup2 { + cgroupPath = filepath.Join(cgroupRoot, parts[2]) + } else { + if parts[1] != "name=systemd" { + continue + } + cgroupPath = filepath.Join(cgroupRoot, "systemd", parts[2]) + } + + st, err := os.Stat(cgroupPath) + if err != nil { + return false, err + } + s := st.Sys() + if s == nil { + return false, fmt.Errorf("stat cgroup path %s", cgroupPath) + } + + if int(s.(*syscall.Stat_t).Uid) != uid { + return false, nil + } + } + if err := scanner.Err(); err != nil { + return false, fmt.Errorf("parsing file /proc/self/cgroup: %w", err) + } + return true, nil +} + +// rmDirRecursively delete recursively a cgroup directory. +// It differs from os.RemoveAll as it doesn't attempt to unlink files. +// On cgroupfs we are allowed only to rmdir empty directories. +func rmDirRecursively(path string) error { + killProcesses := func(signal syscall.Signal) { + if signal == unix.SIGKILL { + if err := os.WriteFile(filepath.Join(path, "cgroup.kill"), []byte("1"), 0o600); err == nil { + return + } + } + // kill all the processes that are still part of the cgroup + if procs, err := os.ReadFile(filepath.Join(path, "cgroup.procs")); err == nil { + for _, pidS := range strings.Split(string(procs), "\n") { + if pid, err := strconv.Atoi(pidS); err == nil { + _ = unix.Kill(pid, signal) + } + } + } + } + + if err := os.Remove(path); err == nil || errors.Is(err, os.ErrNotExist) { + return nil + } + entries, err := os.ReadDir(path) + if err != nil { + return err + } + for _, i := range entries { + if i.IsDir() { + if err := rmDirRecursively(filepath.Join(path, i.Name())); err != nil { + return err + } + } + } + + attempts := 0 + for { + err := os.Remove(path) + if err == nil || errors.Is(err, os.ErrNotExist) { + return nil + } + if errors.Is(err, unix.EBUSY) { + // send a SIGTERM after 3 second + if attempts == 300 { + killProcesses(unix.SIGTERM) + } + // send SIGKILL after 8 seconds + if attempts == 800 { + killProcesses(unix.SIGKILL) + } + // give up after 10 seconds + if attempts < 1000 { + time.Sleep(time.Millisecond * 10) + attempts++ + continue + } + } + return fmt.Errorf("remove %s: %w", path, err) + } +} diff --git a/vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go b/vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go deleted file mode 100644 index 863a14a156..0000000000 --- a/vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go +++ /dev/null @@ -1,162 +0,0 @@ -//go:build linux - -package cgroups - -import ( - "bufio" - "errors" - "fmt" - "os" - "path/filepath" - "strconv" - "strings" - "sync" - "syscall" - "time" - - systemdDbus "github.com/coreos/go-systemd/v22/dbus" - "github.com/godbus/dbus/v5" - "golang.org/x/sys/unix" -) - -var ( - isUnifiedOnce sync.Once - isUnified bool - isUnifiedErr error -) - -// IsCgroup2UnifiedMode returns whether we are running in cgroup 2 cgroup2 mode. -func IsCgroup2UnifiedMode() (bool, error) { - isUnifiedOnce.Do(func() { - var st syscall.Statfs_t - if err := syscall.Statfs("/sys/fs/cgroup", &st); err != nil { - isUnified, isUnifiedErr = false, err - } else { - isUnified, isUnifiedErr = st.Type == unix.CGROUP2_SUPER_MAGIC, nil - } - }) - return isUnified, isUnifiedErr -} - -// UserConnection returns an user connection to D-BUS -func UserConnection(uid int) (*systemdDbus.Conn, error) { - return systemdDbus.NewConnection(func() (*dbus.Conn, error) { - return dbusAuthConnection(uid, dbus.SessionBusPrivateNoAutoStartup) - }) -} - -// UserOwnsCurrentSystemdCgroup checks whether the current EUID owns the -// current cgroup. -func UserOwnsCurrentSystemdCgroup() (bool, error) { - uid := os.Geteuid() - - cgroup2, err := IsCgroup2UnifiedMode() - if err != nil { - return false, err - } - - f, err := os.Open("/proc/self/cgroup") - if err != nil { - return false, err - } - defer f.Close() - - scanner := bufio.NewScanner(f) - for scanner.Scan() { - line := scanner.Text() - parts := strings.SplitN(line, ":", 3) - - if len(parts) < 3 { - continue - } - - var cgroupPath string - - if cgroup2 { - cgroupPath = filepath.Join(cgroupRoot, parts[2]) - } else { - if parts[1] != "name=systemd" { - continue - } - cgroupPath = filepath.Join(cgroupRoot, "systemd", parts[2]) - } - - st, err := os.Stat(cgroupPath) - if err != nil { - return false, err - } - s := st.Sys() - if s == nil { - return false, fmt.Errorf("stat cgroup path %s", cgroupPath) - } - - if int(s.(*syscall.Stat_t).Uid) != uid { - return false, nil - } - } - if err := scanner.Err(); err != nil { - return false, fmt.Errorf("parsing file /proc/self/cgroup: %w", err) - } - return true, nil -} - -// rmDirRecursively delete recursively a cgroup directory. -// It differs from os.RemoveAll as it doesn't attempt to unlink files. -// On cgroupfs we are allowed only to rmdir empty directories. -func rmDirRecursively(path string) error { - killProcesses := func(signal syscall.Signal) { - if signal == unix.SIGKILL { - if err := os.WriteFile(filepath.Join(path, "cgroup.kill"), []byte("1"), 0o600); err == nil { - return - } - } - // kill all the processes that are still part of the cgroup - if procs, err := os.ReadFile(filepath.Join(path, "cgroup.procs")); err == nil { - for _, pidS := range strings.Split(string(procs), "\n") { - if pid, err := strconv.Atoi(pidS); err == nil { - _ = unix.Kill(pid, signal) - } - } - } - } - - if err := os.Remove(path); err == nil || errors.Is(err, os.ErrNotExist) { - return nil - } - entries, err := os.ReadDir(path) - if err != nil { - return err - } - for _, i := range entries { - if i.IsDir() { - if err := rmDirRecursively(filepath.Join(path, i.Name())); err != nil { - return err - } - } - } - - attempts := 0 - for { - err := os.Remove(path) - if err == nil || errors.Is(err, os.ErrNotExist) { - return nil - } - if errors.Is(err, unix.EBUSY) { - // send a SIGTERM after 3 second - if attempts == 300 { - killProcesses(unix.SIGTERM) - } - // send SIGKILL after 8 seconds - if attempts == 800 { - killProcesses(unix.SIGKILL) - } - // give up after 10 seconds - if attempts < 1000 { - time.Sleep(time.Millisecond * 10) - attempts++ - continue - } - } - return fmt.Errorf("remove %s: %w", path, err) - } -} diff --git a/vendor/github.com/containers/common/pkg/cgroups/cgroups_unsupported.go b/vendor/github.com/containers/common/pkg/cgroups/cgroups_unsupported.go index 085031a59a..1602912122 100644 --- a/vendor/github.com/containers/common/pkg/cgroups/cgroups_unsupported.go +++ b/vendor/github.com/containers/common/pkg/cgroups/cgroups_unsupported.go @@ -3,10 +3,7 @@ package cgroups import ( - "fmt" "os" - - systemdDbus "github.com/coreos/go-systemd/v22/dbus" ) // IsCgroup2UnifiedMode returns whether we are running in cgroup 2 cgroup2 mode. @@ -23,8 +20,3 @@ func UserOwnsCurrentSystemdCgroup() (bool, error) { func rmDirRecursively(path string) error { return os.RemoveAll(path) } - -// UserConnection returns an user connection to D-BUS -func UserConnection(uid int) (*systemdDbus.Conn, error) { - return nil, fmt.Errorf("systemd d-bus is not supported on this platform") -} diff --git a/vendor/github.com/containers/common/pkg/cgroups/systemd.go b/vendor/github.com/containers/common/pkg/cgroups/systemd.go deleted file mode 100644 index b076ead6c1..0000000000 --- a/vendor/github.com/containers/common/pkg/cgroups/systemd.go +++ /dev/null @@ -1,80 +0,0 @@ -//go:build !linux - -package cgroups - -import ( - "context" - "fmt" - "path/filepath" - "strings" - - systemdDbus "github.com/coreos/go-systemd/v22/dbus" - "github.com/godbus/dbus/v5" -) - -func systemdCreate(path string, c *systemdDbus.Conn) error { - slice, name := filepath.Split(path) - slice = strings.TrimSuffix(slice, "/") - - var lastError error - for i := 0; i < 2; i++ { - properties := []systemdDbus.Property{ - systemdDbus.PropDescription(fmt.Sprintf("cgroup %s", name)), - systemdDbus.PropWants(slice), - } - pMap := map[string]bool{ - "DefaultDependencies": false, - "MemoryAccounting": true, - "CPUAccounting": true, - "BlockIOAccounting": true, - } - if i == 0 { - pMap["Delegate"] = true - } - for k, v := range pMap { - p := systemdDbus.Property{ - Name: k, - Value: dbus.MakeVariant(v), - } - properties = append(properties, p) - } - - ch := make(chan string) - _, err := c.StartTransientUnitContext(context.TODO(), name, "replace", properties, ch) - if err != nil { - lastError = err - continue - } - <-ch - return nil - } - return lastError -} - -/* -systemdDestroyConn is copied from containerd/cgroups/systemd.go file, that -has the following license: -Copyright The containerd Authors. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -func systemdDestroyConn(path string, c *systemdDbus.Conn) error { - name := filepath.Base(path) - - ch := make(chan string) - _, err := c.StopUnitContext(context.TODO(), name, "replace", ch) - if err != nil { - return err - } - <-ch - return nil -} diff --git a/vendor/github.com/containers/common/pkg/config/connections.go b/vendor/github.com/containers/common/pkg/config/connections.go index 00d110c380..d7c2c7d8a5 100644 --- a/vendor/github.com/containers/common/pkg/config/connections.go +++ b/vendor/github.com/containers/common/pkg/config/connections.go @@ -9,6 +9,7 @@ import ( "path/filepath" "github.com/containers/storage/pkg/ioutils" + "github.com/containers/storage/pkg/lockfile" ) const connectionsFile = "podman-connections.json" @@ -64,28 +65,24 @@ type Farm struct { ReadWrite bool } -func readConnectionConf() (*ConnectionsFile, string, error) { - path, err := connectionsConfigFile() - if err != nil { - return nil, "", err - } +func readConnectionConf(path string) (*ConnectionsFile, error) { conf := new(ConnectionsFile) f, err := os.Open(path) if err != nil { // return empty config if file does not exists if errors.Is(err, fs.ErrNotExist) { - return conf, path, nil + return conf, nil } - return nil, "", err + return nil, err } defer f.Close() err = json.NewDecoder(f).Decode(conf) if err != nil { - return nil, "", fmt.Errorf("parse %q: %w", path, err) + return nil, fmt.Errorf("parse %q: %w", path, err) } - return conf, path, nil + return conf, nil } func writeConnectionConf(path string, conf *ConnectionsFile) error { @@ -113,7 +110,20 @@ func writeConnectionConf(path string, conf *ConnectionsFile) error { // The function will read and write the file automatically and the // callback function just needs to modify the cfg as needed. func EditConnectionConfig(callback func(cfg *ConnectionsFile) error) error { - conf, path, err := readConnectionConf() + path, err := connectionsConfigFile() + if err != nil { + return err + } + + lockPath := path + ".lock" + lock, err := lockfile.GetLockFile(lockPath) + if err != nil { + return fmt.Errorf("obtain lock file: %w", err) + } + lock.Lock() + defer lock.Unlock() + + conf, err := readConnectionConf(path) if err != nil { return fmt.Errorf("read connections file: %w", err) } @@ -139,7 +149,11 @@ func makeConnection(name string, dst Destination, def, readWrite bool) *Connecti // GetConnection return the connection for the given name or if def is set to true then return the default connection. func (c *Config) GetConnection(name string, def bool) (*Connection, error) { - conConf, _, err := readConnectionConf() + path, err := connectionsConfigFile() + if err != nil { + return nil, err + } + conConf, err := readConnectionConf(path) if err != nil { return nil, err } @@ -167,7 +181,11 @@ func (c *Config) GetConnection(name string, def bool) (*Connection, error) { // GetAllConnections return all configured connections func (c *Config) GetAllConnections() ([]Connection, error) { - conConf, _, err := readConnectionConf() + path, err := connectionsConfigFile() + if err != nil { + return nil, err + } + conConf, err := readConnectionConf(path) if err != nil { return nil, err } @@ -222,7 +240,11 @@ func (c *Config) GetDefaultFarmConnections() (string, []Connection, error) { // if def is true it will use the default farm instead of the name. // Returns the name of the farm and the connections for it. func (c *Config) getFarmConnections(name string, def bool) (string, []Connection, error) { - conConf, _, err := readConnectionConf() + path, err := connectionsConfigFile() + if err != nil { + return "", nil, err + } + conConf, err := readConnectionConf(path) if err != nil { return "", nil, err } @@ -259,7 +281,11 @@ func makeFarm(name string, cons []string, def, readWrite bool) Farm { // GetAllFarms returns all configured farms func (c *Config) GetAllFarms() ([]Farm, error) { - conConf, _, err := readConnectionConf() + path, err := connectionsConfigFile() + if err != nil { + return nil, err + } + conConf, err := readConnectionConf(path) if err != nil { return nil, err } diff --git a/vendor/modules.txt b/vendor/modules.txt index 86007c41bb..d3012be406 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -171,7 +171,7 @@ github.com/containers/buildah/pkg/sshagent github.com/containers/buildah/pkg/util github.com/containers/buildah/pkg/volumes github.com/containers/buildah/util -# github.com/containers/common v0.57.1-0.20240229165734-cec09922602e +# github.com/containers/common v0.57.1-0.20240304165751-a0d555c70d52 ## explicit; go 1.20 github.com/containers/common/internal github.com/containers/common/internal/attributedstring