mirror of
https://github.com/containers/podman.git
synced 2025-08-06 19:44:14 +08:00
Introduce podman machine init --root=t|f and podman machine set --root=t|f
Switch default to rootless for mac and windows Signed-off-by: Jason T. Greene <jason.greene@redhat.com>
This commit is contained in:
@ -26,7 +26,7 @@ var (
|
||||
|
||||
var (
|
||||
initOpts = machine.InitOptions{}
|
||||
defaultMachineName = "podman-machine-default"
|
||||
defaultMachineName = machine.DefaultMachineName
|
||||
now bool
|
||||
)
|
||||
|
||||
@ -99,6 +99,9 @@ func init() {
|
||||
IgnitionPathFlagName := "ignition-path"
|
||||
flags.StringVar(&initOpts.IgnitionPath, IgnitionPathFlagName, "", "Path to ignition file")
|
||||
_ = initCmd.RegisterFlagCompletionFunc(IgnitionPathFlagName, completion.AutocompleteDefault)
|
||||
|
||||
rootfulFlagName := "rootful"
|
||||
flags.BoolVar(&initOpts.Rootful, rootfulFlagName, false, "Whether this machine should prefer rootful container exectution")
|
||||
}
|
||||
|
||||
// TODO should we allow for a users to append to the qemu cmdline?
|
||||
|
56
cmd/podman/machine/set.go
Normal file
56
cmd/podman/machine/set.go
Normal file
@ -0,0 +1,56 @@
|
||||
// +build amd64 arm64
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"github.com/containers/common/pkg/completion"
|
||||
"github.com/containers/podman/v4/cmd/podman/registry"
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
setCmd = &cobra.Command{
|
||||
Use: "set [options] [NAME]",
|
||||
Short: "Sets a virtual machine setting",
|
||||
Long: "Sets an updatable virtual machine setting",
|
||||
RunE: setMachine,
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
Example: `podman machine set --root=false`,
|
||||
ValidArgsFunction: completion.AutocompleteNone,
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
setOpts = machine.SetOptions{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.Commands = append(registry.Commands, registry.CliCommand{
|
||||
Command: setCmd,
|
||||
Parent: machineCmd,
|
||||
})
|
||||
flags := setCmd.Flags()
|
||||
|
||||
rootfulFlagName := "rootful"
|
||||
flags.BoolVar(&setOpts.Rootful, rootfulFlagName, false, "Whether this machine should prefer rootful container execution")
|
||||
}
|
||||
|
||||
func setMachine(cmd *cobra.Command, args []string) error {
|
||||
var (
|
||||
vm machine.VM
|
||||
err error
|
||||
)
|
||||
|
||||
vmName := defaultMachineName
|
||||
if len(args) > 0 && len(args[0]) > 0 {
|
||||
vmName = args[0]
|
||||
}
|
||||
provider := getSystemDefaultProvider()
|
||||
vm, err = provider.LoadVMByName(vmName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return vm.Set(vmName, setOpts)
|
||||
}
|
@ -55,6 +55,14 @@ Memory (in MB).
|
||||
|
||||
Start the virtual machine immediately after it has been initialized.
|
||||
|
||||
#### **--rootful**=*true|false*
|
||||
|
||||
Whether this machine should prefer rootful (`true`) or rootless (`false`)
|
||||
container execution. This option will also determine the remote connection default
|
||||
if there is no existing remote connection configurations.
|
||||
|
||||
API forwarding, if available, will follow this setting.
|
||||
|
||||
#### **--timezone**
|
||||
|
||||
Set the timezone for the machine and containers. Valid values are `local` or
|
||||
@ -84,6 +92,7 @@ Print usage statement.
|
||||
```
|
||||
$ podman machine init
|
||||
$ podman machine init myvm
|
||||
$ podman machine init --rootful
|
||||
$ podman machine init --disk-size 50
|
||||
$ podman machine init --memory=1024 myvm
|
||||
$ podman machine init -v /Users:/mnt/Users
|
||||
|
59
docs/source/markdown/podman-machine-set.1.md
Normal file
59
docs/source/markdown/podman-machine-set.1.md
Normal file
@ -0,0 +1,59 @@
|
||||
% podman-machine-set(1)
|
||||
|
||||
## NAME
|
||||
podman\-machine\-set - Sets a virtual machine setting
|
||||
|
||||
## SYNOPSIS
|
||||
**podman machine set** [*options*] [*name*]
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
Sets an updatable virtual machine setting.
|
||||
|
||||
Options mirror values passed to `podman machine init`. Only a limited
|
||||
subset can be changed after machine initialization.
|
||||
|
||||
## OPTIONS
|
||||
|
||||
#### **--rootful**=*true|false*
|
||||
|
||||
Whether this machine should prefer rootful (`true`) or rootless (`false`)
|
||||
container execution. This option will also update the current podman
|
||||
remote connection default if it is currently pointing at the specified
|
||||
machine name (or `podman-machine-default` if no name is specified).
|
||||
|
||||
API forwarding, if available, will follow this setting.
|
||||
|
||||
#### **--help**
|
||||
|
||||
Print usage statement.
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
To switch the default VM `podman-machine-default` from rootless to rootful:
|
||||
|
||||
```
|
||||
$ podman machine set --rootful
|
||||
```
|
||||
|
||||
or more explicitly:
|
||||
|
||||
```
|
||||
$ podman machine set --rootful=true
|
||||
```
|
||||
|
||||
To switch the default VM `podman-machine-default` from rootful to rootless:
|
||||
```
|
||||
$ podman machine set --rootful=false
|
||||
```
|
||||
|
||||
To switch the VM `myvm` from rootless to rootful:
|
||||
```
|
||||
$ podman machine set --rootful myvm
|
||||
```
|
||||
|
||||
## SEE ALSO
|
||||
**[podman(1)](podman.1.md)**, **[podman-machine(1)](podman-machine.1.md)**
|
||||
|
||||
## HISTORY
|
||||
February 2022, Originally compiled by Jason Greene <jason.greene@redhat.com>
|
@ -16,6 +16,7 @@ podman\-machine - Manage Podman's virtual machine
|
||||
| init | [podman-machine-init(1)](podman-machine-init.1.md) | Initialize a new virtual machine |
|
||||
| list | [podman-machine-list(1)](podman-machine-list.1.md) | List virtual machines |
|
||||
| rm | [podman-machine-rm(1)](podman-machine-rm.1.md) | Remove a virtual machine |
|
||||
| set | [podman-machine-set(1)](podman-machine-set.1.md) | Sets a virtual machine setting |
|
||||
| ssh | [podman-machine-ssh(1)](podman-machine-ssh.1.md) | SSH into a virtual machine |
|
||||
| start | [podman-machine-start(1)](podman-machine-start.1.md) | Start a virtual machine |
|
||||
| stop | [podman-machine-stop(1)](podman-machine-stop.1.md) | Stop a virtual machine |
|
||||
|
@ -27,6 +27,7 @@ type InitOptions struct {
|
||||
URI url.URL
|
||||
Username string
|
||||
ReExec bool
|
||||
Rootful bool
|
||||
}
|
||||
|
||||
type QemuMachineStatus = string
|
||||
@ -36,6 +37,7 @@ const (
|
||||
Running QemuMachineStatus = "running"
|
||||
// Stopped indicates the vm has stopped
|
||||
Stopped QemuMachineStatus = "stopped"
|
||||
DefaultMachineName string = "podman-machine-default"
|
||||
)
|
||||
|
||||
type Provider interface {
|
||||
@ -89,6 +91,10 @@ type ListResponse struct {
|
||||
IdentityPath string
|
||||
}
|
||||
|
||||
type SetOptions struct {
|
||||
Rootful bool
|
||||
}
|
||||
|
||||
type SSHOptions struct {
|
||||
Username string
|
||||
Args []string
|
||||
@ -107,6 +113,7 @@ type RemoveOptions struct {
|
||||
type VM interface {
|
||||
Init(opts InitOptions) (bool, error)
|
||||
Remove(name string, opts RemoveOptions) (string, func() error, error)
|
||||
Set(name string, opts SetOptions) error
|
||||
SSH(name string, opts SSHOptions) error
|
||||
Start(name string, opts StartOptions) error
|
||||
Stop(name string, opts StopOptions) error
|
||||
|
@ -39,6 +39,31 @@ func AddConnection(uri fmt.Stringer, name, identity string, isDefault bool) erro
|
||||
return cfg.Write()
|
||||
}
|
||||
|
||||
func AnyConnectionDefault(name ...string) (bool, error) {
|
||||
cfg, err := config.ReadCustomConfig()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, n := range name {
|
||||
if n == cfg.Engine.ActiveService {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func ChangeDefault(name string) error {
|
||||
cfg, err := config.ReadCustomConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg.Engine.ActiveService = name
|
||||
|
||||
return cfg.Write()
|
||||
}
|
||||
|
||||
func RemoveConnection(name string) error {
|
||||
cfg, err := config.ReadCustomConfig()
|
||||
if err != nil {
|
||||
|
@ -33,6 +33,8 @@ type MachineVM struct {
|
||||
QMPMonitor Monitor
|
||||
// RemoteUsername of the vm user
|
||||
RemoteUsername string
|
||||
// Whether this machine should run in a rootful or rootless manner
|
||||
Rootful bool
|
||||
}
|
||||
|
||||
type Mount struct {
|
||||
|
@ -5,14 +5,15 @@ package qemu
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/base64"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@ -166,14 +167,8 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
|
||||
key string
|
||||
)
|
||||
sshDir := filepath.Join(homedir.Get(), ".ssh")
|
||||
// GetConfDir creates the directory so no need to check for
|
||||
// its existence
|
||||
vmConfigDir, err := machine.GetConfDir(vmtype)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
jsonFile := filepath.Join(vmConfigDir, v.Name) + ".json"
|
||||
v.IdentityPath = filepath.Join(sshDir, v.Name)
|
||||
v.Rootful = opts.Rootful
|
||||
|
||||
switch opts.ImagePath {
|
||||
case "testing", "next", "stable", "":
|
||||
@ -256,29 +251,33 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
|
||||
// This kind of stinks but no other way around this r/n
|
||||
if len(opts.IgnitionPath) < 1 {
|
||||
uri := machine.SSHRemoteConnection.MakeSSHURL("localhost", "/run/user/1000/podman/podman.sock", strconv.Itoa(v.Port), v.RemoteUsername)
|
||||
if err := machine.AddConnection(&uri, v.Name, filepath.Join(sshDir, v.Name), opts.IsDefault); err != nil {
|
||||
return false, err
|
||||
uriRoot := machine.SSHRemoteConnection.MakeSSHURL("localhost", "/run/podman/podman.sock", strconv.Itoa(v.Port), "root")
|
||||
identity := filepath.Join(sshDir, v.Name)
|
||||
|
||||
uris := []url.URL{uri, uriRoot}
|
||||
names := []string{v.Name, v.Name + "-root"}
|
||||
|
||||
// The first connection defined when connections is empty will become the default
|
||||
// regardless of IsDefault, so order according to rootful
|
||||
if opts.Rootful {
|
||||
uris[0], names[0], uris[1], names[1] = uris[1], names[1], uris[0], names[0]
|
||||
}
|
||||
|
||||
uriRoot := machine.SSHRemoteConnection.MakeSSHURL("localhost", "/run/podman/podman.sock", strconv.Itoa(v.Port), "root")
|
||||
if err := machine.AddConnection(&uriRoot, v.Name+"-root", filepath.Join(sshDir, v.Name), opts.IsDefault); err != nil {
|
||||
for i := 0; i < 2; i++ {
|
||||
if err := machine.AddConnection(&uris[i], names[i], identity, opts.IsDefault && i == 0); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fmt.Println("An ignition path was provided. No SSH connection was added to Podman")
|
||||
}
|
||||
// Write the JSON file
|
||||
b, err := json.MarshalIndent(v, "", " ")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := ioutil.WriteFile(jsonFile, b, 0644); err != nil {
|
||||
return false, err
|
||||
}
|
||||
v.writeConfig()
|
||||
|
||||
// User has provided ignition file so keygen
|
||||
// will be skipped.
|
||||
if len(opts.IgnitionPath) < 1 {
|
||||
var err error
|
||||
key, err = machine.CreateSSHKeys(v.IdentityPath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@ -325,6 +324,30 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
|
||||
return err == nil, err
|
||||
}
|
||||
|
||||
func (v *MachineVM) Set(name string, opts machine.SetOptions) error {
|
||||
if v.Rootful == opts.Rootful {
|
||||
return nil
|
||||
}
|
||||
|
||||
changeCon, err := machine.AnyConnectionDefault(v.Name, v.Name+"-root")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if changeCon {
|
||||
newDefault := v.Name
|
||||
if opts.Rootful {
|
||||
newDefault += "-root"
|
||||
}
|
||||
if err := machine.ChangeDefault(newDefault); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
v.Rootful = opts.Rootful
|
||||
return v.writeConfig()
|
||||
}
|
||||
|
||||
// Start executes the qemu command line and forks it
|
||||
func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
|
||||
var (
|
||||
@ -457,7 +480,7 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
|
||||
}
|
||||
}
|
||||
|
||||
printAPIForwardInstructions(forwardState, forwardSock)
|
||||
waitAPIAndPrintInfo(forwardState, forwardSock, v.Rootful, v.Name)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -929,9 +952,17 @@ func (v *MachineVM) setupAPIForwarding(cmd []string) ([]string, string, apiForwa
|
||||
return cmd, "", noForwarding
|
||||
}
|
||||
|
||||
destSock := "/run/user/1000/podman/podman.sock"
|
||||
forwardUser := "core"
|
||||
|
||||
if v.Rootful {
|
||||
destSock = "/run/podman/podman.sock"
|
||||
forwardUser = "root"
|
||||
}
|
||||
|
||||
cmd = append(cmd, []string{"-forward-sock", socket}...)
|
||||
cmd = append(cmd, []string{"-forward-dest", "/run/podman/podman.sock"}...)
|
||||
cmd = append(cmd, []string{"-forward-user", "root"}...)
|
||||
cmd = append(cmd, []string{"-forward-dest", destSock}...)
|
||||
cmd = append(cmd, []string{"-forward-user", forwardUser}...)
|
||||
cmd = append(cmd, []string{"-forward-identity", v.IdentityPath}...)
|
||||
link := filepath.Join(filepath.Dir(filepath.Dir(socket)), "podman.sock")
|
||||
|
||||
@ -1031,19 +1062,32 @@ func waitAndPingAPI(sock string) {
|
||||
}
|
||||
}
|
||||
|
||||
func printAPIForwardInstructions(forwardState apiForwardingState, forwardSock string) {
|
||||
func waitAPIAndPrintInfo(forwardState apiForwardingState, forwardSock string, rootFul bool, name string) {
|
||||
if forwardState != noForwarding {
|
||||
waitAndPingAPI(forwardSock)
|
||||
if !rootFul {
|
||||
fmt.Printf("\nThis machine is currently configured in rootless mode. If your containers\n")
|
||||
fmt.Printf("require root permissions (e.g. ports < 1024), or if you run into compatibility\n")
|
||||
fmt.Printf("issues with non-podman clients, you can switch using the following command: \n")
|
||||
|
||||
suffix := ""
|
||||
if name != machine.DefaultMachineName {
|
||||
suffix = " " + name
|
||||
}
|
||||
fmt.Printf("\n\tpodman machine set --rootful%s\n\n", suffix)
|
||||
}
|
||||
|
||||
fmt.Printf("API forwarding listening on: %s\n", forwardSock)
|
||||
if forwardState == dockerGlobal {
|
||||
fmt.Printf("\nDocker API clients default to this address. You do not need to set DOCKER_HOST.\n\n")
|
||||
fmt.Printf("Docker API clients default to this address. You do not need to set DOCKER_HOST.\n\n")
|
||||
} else {
|
||||
stillString := "still "
|
||||
switch forwardState {
|
||||
case notInstalled:
|
||||
fmt.Printf("\nThe system helper service is not installed; the default Docker API socket address can't be used by podman.\n")
|
||||
fmt.Printf("\nThe system helper service is not installed; the default Docker API socket\n")
|
||||
fmt.Printf("address can't be used by podman. ")
|
||||
if helper := findClaimHelper(); len(helper) > 0 {
|
||||
fmt.Printf("If you would like to install it run the following command:\n")
|
||||
fmt.Printf("If you would like to install it run the\nfollowing command:\n")
|
||||
fmt.Printf("\n\tsudo %s install\n\n", helper)
|
||||
}
|
||||
case machineLocal:
|
||||
@ -1053,9 +1097,31 @@ func printAPIForwardInstructions(forwardState apiForwardingState, forwardSock st
|
||||
default:
|
||||
stillString = ""
|
||||
}
|
||||
fmt.Printf("You can %sconnect Docker API clients by setting DOCKER HOST using the\n", stillString)
|
||||
|
||||
fmt.Printf("You can %sconnect Docker API clients by setting DOCKER_HOST using the\n", stillString)
|
||||
fmt.Printf("following command in your terminal session:\n")
|
||||
fmt.Printf("\n\texport DOCKER_HOST='unix://%s'\n\n", forwardSock)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (v *MachineVM) writeConfig() error {
|
||||
// GetConfDir creates the directory so no need to check for
|
||||
// its existence
|
||||
vmConfigDir, err := machine.GetConfDir(vmtype)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jsonFile := filepath.Join(vmConfigDir, v.Name) + ".json"
|
||||
// Write the JSON file
|
||||
b, err := json.MarshalIndent(v, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ioutil.WriteFile(jsonFile, b, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package wsl
|
||||
@ -8,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@ -35,9 +37,6 @@ const (
|
||||
ErrorSuccessRebootRequired = 3010
|
||||
)
|
||||
|
||||
// Usermode networking avoids potential nftables compatibility issues between the distro
|
||||
// and the WSL Kernel. Additionally it avoids fw rule conflicts between distros, since
|
||||
// all instances run under the same Kernel at runtime
|
||||
const containersConf = `[containers]
|
||||
|
||||
[engine]
|
||||
@ -162,6 +161,8 @@ type MachineVM struct {
|
||||
Port int
|
||||
// RemoteUsername of the vm user
|
||||
RemoteUsername string
|
||||
// Whether this machine should run in a rootful or rootless manner
|
||||
Rootful bool
|
||||
}
|
||||
|
||||
type ExitCodeError struct {
|
||||
@ -227,12 +228,13 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
|
||||
homeDir := homedir.Get()
|
||||
sshDir := filepath.Join(homeDir, ".ssh")
|
||||
v.IdentityPath = filepath.Join(sshDir, v.Name)
|
||||
v.Rootful = opts.Rootful
|
||||
|
||||
if err := downloadDistro(v, opts); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if err := writeJSON(v); err != nil {
|
||||
if err := v.writeConfig(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
@ -282,7 +284,7 @@ func downloadDistro(v *MachineVM, opts machine.InitOptions) error {
|
||||
return machine.DownloadImage(dd)
|
||||
}
|
||||
|
||||
func writeJSON(v *MachineVM) error {
|
||||
func (v *MachineVM) writeConfig() error {
|
||||
vmConfigDir, err := machine.GetConfDir(vmtype)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -302,14 +304,26 @@ func writeJSON(v *MachineVM) error {
|
||||
}
|
||||
|
||||
func setupConnections(v *MachineVM, opts machine.InitOptions, sshDir string) error {
|
||||
uri := machine.SSHRemoteConnection.MakeSSHURL("localhost", "/run/user/1000/podman/podman.sock", strconv.Itoa(v.Port), v.RemoteUsername)
|
||||
uriRoot := machine.SSHRemoteConnection.MakeSSHURL("localhost", "/run/podman/podman.sock", strconv.Itoa(v.Port), "root")
|
||||
if err := machine.AddConnection(&uriRoot, v.Name+"-root", filepath.Join(sshDir, v.Name), opts.IsDefault); err != nil {
|
||||
return err
|
||||
identity := filepath.Join(sshDir, v.Name)
|
||||
|
||||
uris := []url.URL{uri, uriRoot}
|
||||
names := []string{v.Name, v.Name + "-root"}
|
||||
|
||||
// The first connection defined when connections is empty will become the default
|
||||
// regardless of IsDefault, so order according to rootful
|
||||
if opts.Rootful {
|
||||
uris[0], names[0], uris[1], names[1] = uris[1], names[1], uris[0], names[0]
|
||||
}
|
||||
|
||||
user := opts.Username
|
||||
uri := machine.SSHRemoteConnection.MakeSSHURL("localhost", withUser("/run/[USER]/1000/podman/podman.sock", user), strconv.Itoa(v.Port), v.RemoteUsername)
|
||||
return machine.AddConnection(&uri, v.Name, filepath.Join(sshDir, v.Name), opts.IsDefault)
|
||||
for i := 0; i < 2; i++ {
|
||||
if err := machine.AddConnection(&uris[i], names[i], identity, opts.IsDefault && i == 0); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func provisionWSLDist(v *MachineVM) (string, error) {
|
||||
@ -704,6 +718,30 @@ func pipeCmdPassThrough(name string, input string, arg ...string) error {
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
func (v *MachineVM) Set(name string, opts machine.SetOptions) error {
|
||||
if v.Rootful == opts.Rootful {
|
||||
return nil
|
||||
}
|
||||
|
||||
changeCon, err := machine.AnyConnectionDefault(v.Name, v.Name+"-root")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if changeCon {
|
||||
newDefault := v.Name
|
||||
if opts.Rootful {
|
||||
newDefault += "-root"
|
||||
}
|
||||
if err := machine.ChangeDefault(newDefault); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
v.Rootful = opts.Rootful
|
||||
return v.writeConfig()
|
||||
}
|
||||
|
||||
func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
|
||||
if v.isRunning() {
|
||||
return errors.Errorf("%q is already running", name)
|
||||
@ -716,6 +754,18 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
|
||||
return errors.Wrap(err, "WSL bootstrap script failed")
|
||||
}
|
||||
|
||||
if !v.Rootful {
|
||||
fmt.Printf("\nThis machine is currently configured in rootless mode. If your containers\n")
|
||||
fmt.Printf("require root permissions (e.g. ports < 1024), or if you run into compatibility\n")
|
||||
fmt.Printf("issues with non-podman clients, you can switch using the following command: \n")
|
||||
|
||||
suffix := ""
|
||||
if name != machine.DefaultMachineName {
|
||||
suffix = " " + name
|
||||
}
|
||||
fmt.Printf("\n\tpodman machine set --rootful%s\n\n", suffix)
|
||||
}
|
||||
|
||||
globalName, pipeName, err := launchWinProxy(v)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "API forwarding for Docker API clients is not available due to the following startup failures.")
|
||||
|
Reference in New Issue
Block a user