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 (
|
var (
|
||||||
initOpts = machine.InitOptions{}
|
initOpts = machine.InitOptions{}
|
||||||
defaultMachineName = "podman-machine-default"
|
defaultMachineName = machine.DefaultMachineName
|
||||||
now bool
|
now bool
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -99,6 +99,9 @@ func init() {
|
|||||||
IgnitionPathFlagName := "ignition-path"
|
IgnitionPathFlagName := "ignition-path"
|
||||||
flags.StringVar(&initOpts.IgnitionPath, IgnitionPathFlagName, "", "Path to ignition file")
|
flags.StringVar(&initOpts.IgnitionPath, IgnitionPathFlagName, "", "Path to ignition file")
|
||||||
_ = initCmd.RegisterFlagCompletionFunc(IgnitionPathFlagName, completion.AutocompleteDefault)
|
_ = 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?
|
// 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.
|
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**
|
#### **--timezone**
|
||||||
|
|
||||||
Set the timezone for the machine and containers. Valid values are `local` or
|
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
|
||||||
$ podman machine init myvm
|
$ podman machine init myvm
|
||||||
|
$ podman machine init --rootful
|
||||||
$ podman machine init --disk-size 50
|
$ podman machine init --disk-size 50
|
||||||
$ podman machine init --memory=1024 myvm
|
$ podman machine init --memory=1024 myvm
|
||||||
$ podman machine init -v /Users:/mnt/Users
|
$ 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| stop | [podman-machine-stop(1)](podman-machine-stop.1.md) | Stop a virtual machine |
|
||||||
|
@ -27,6 +27,7 @@ type InitOptions struct {
|
|||||||
URI url.URL
|
URI url.URL
|
||||||
Username string
|
Username string
|
||||||
ReExec bool
|
ReExec bool
|
||||||
|
Rootful bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type QemuMachineStatus = string
|
type QemuMachineStatus = string
|
||||||
@ -35,7 +36,8 @@ const (
|
|||||||
// Running indicates the qemu vm is running
|
// Running indicates the qemu vm is running
|
||||||
Running QemuMachineStatus = "running"
|
Running QemuMachineStatus = "running"
|
||||||
// Stopped indicates the vm has stopped
|
// Stopped indicates the vm has stopped
|
||||||
Stopped QemuMachineStatus = "stopped"
|
Stopped QemuMachineStatus = "stopped"
|
||||||
|
DefaultMachineName string = "podman-machine-default"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Provider interface {
|
type Provider interface {
|
||||||
@ -89,6 +91,10 @@ type ListResponse struct {
|
|||||||
IdentityPath string
|
IdentityPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SetOptions struct {
|
||||||
|
Rootful bool
|
||||||
|
}
|
||||||
|
|
||||||
type SSHOptions struct {
|
type SSHOptions struct {
|
||||||
Username string
|
Username string
|
||||||
Args []string
|
Args []string
|
||||||
@ -107,6 +113,7 @@ type RemoveOptions struct {
|
|||||||
type VM interface {
|
type VM interface {
|
||||||
Init(opts InitOptions) (bool, error)
|
Init(opts InitOptions) (bool, error)
|
||||||
Remove(name string, opts RemoveOptions) (string, func() error, error)
|
Remove(name string, opts RemoveOptions) (string, func() error, error)
|
||||||
|
Set(name string, opts SetOptions) error
|
||||||
SSH(name string, opts SSHOptions) error
|
SSH(name string, opts SSHOptions) error
|
||||||
Start(name string, opts StartOptions) error
|
Start(name string, opts StartOptions) error
|
||||||
Stop(name string, opts StopOptions) 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()
|
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 {
|
func RemoveConnection(name string) error {
|
||||||
cfg, err := config.ReadCustomConfig()
|
cfg, err := config.ReadCustomConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -33,6 +33,8 @@ type MachineVM struct {
|
|||||||
QMPMonitor Monitor
|
QMPMonitor Monitor
|
||||||
// RemoteUsername of the vm user
|
// RemoteUsername of the vm user
|
||||||
RemoteUsername string
|
RemoteUsername string
|
||||||
|
// Whether this machine should run in a rootful or rootless manner
|
||||||
|
Rootful bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mount struct {
|
type Mount struct {
|
||||||
|
@ -5,14 +5,15 @@ package qemu
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"encoding/base64"
|
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -166,14 +167,8 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
|
|||||||
key string
|
key string
|
||||||
)
|
)
|
||||||
sshDir := filepath.Join(homedir.Get(), ".ssh")
|
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.IdentityPath = filepath.Join(sshDir, v.Name)
|
||||||
|
v.Rootful = opts.Rootful
|
||||||
|
|
||||||
switch opts.ImagePath {
|
switch opts.ImagePath {
|
||||||
case "testing", "next", "stable", "":
|
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
|
// This kind of stinks but no other way around this r/n
|
||||||
if len(opts.IgnitionPath) < 1 {
|
if len(opts.IgnitionPath) < 1 {
|
||||||
uri := machine.SSHRemoteConnection.MakeSSHURL("localhost", "/run/user/1000/podman/podman.sock", strconv.Itoa(v.Port), v.RemoteUsername)
|
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 {
|
uriRoot := machine.SSHRemoteConnection.MakeSSHURL("localhost", "/run/podman/podman.sock", strconv.Itoa(v.Port), "root")
|
||||||
return false, 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]
|
||||||
}
|
}
|
||||||
|
|
||||||
uriRoot := machine.SSHRemoteConnection.MakeSSHURL("localhost", "/run/podman/podman.sock", strconv.Itoa(v.Port), "root")
|
for i := 0; i < 2; i++ {
|
||||||
if err := machine.AddConnection(&uriRoot, v.Name+"-root", filepath.Join(sshDir, v.Name), opts.IsDefault); err != nil {
|
if err := machine.AddConnection(&uris[i], names[i], identity, opts.IsDefault && i == 0); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("An ignition path was provided. No SSH connection was added to Podman")
|
fmt.Println("An ignition path was provided. No SSH connection was added to Podman")
|
||||||
}
|
}
|
||||||
// Write the JSON file
|
// Write the JSON file
|
||||||
b, err := json.MarshalIndent(v, "", " ")
|
v.writeConfig()
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if err := ioutil.WriteFile(jsonFile, b, 0644); err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// User has provided ignition file so keygen
|
// User has provided ignition file so keygen
|
||||||
// will be skipped.
|
// will be skipped.
|
||||||
if len(opts.IgnitionPath) < 1 {
|
if len(opts.IgnitionPath) < 1 {
|
||||||
|
var err error
|
||||||
key, err = machine.CreateSSHKeys(v.IdentityPath)
|
key, err = machine.CreateSSHKeys(v.IdentityPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -325,6 +324,30 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
|
|||||||
return err == nil, err
|
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
|
// Start executes the qemu command line and forks it
|
||||||
func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
|
func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
|
||||||
var (
|
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
|
return nil
|
||||||
}
|
}
|
||||||
@ -929,9 +952,17 @@ func (v *MachineVM) setupAPIForwarding(cmd []string) ([]string, string, apiForwa
|
|||||||
return cmd, "", noForwarding
|
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-sock", socket}...)
|
||||||
cmd = append(cmd, []string{"-forward-dest", "/run/podman/podman.sock"}...)
|
cmd = append(cmd, []string{"-forward-dest", destSock}...)
|
||||||
cmd = append(cmd, []string{"-forward-user", "root"}...)
|
cmd = append(cmd, []string{"-forward-user", forwardUser}...)
|
||||||
cmd = append(cmd, []string{"-forward-identity", v.IdentityPath}...)
|
cmd = append(cmd, []string{"-forward-identity", v.IdentityPath}...)
|
||||||
link := filepath.Join(filepath.Dir(filepath.Dir(socket)), "podman.sock")
|
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 {
|
if forwardState != noForwarding {
|
||||||
waitAndPingAPI(forwardSock)
|
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)
|
fmt.Printf("API forwarding listening on: %s\n", forwardSock)
|
||||||
if forwardState == dockerGlobal {
|
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 {
|
} else {
|
||||||
stillString := "still "
|
stillString := "still "
|
||||||
switch forwardState {
|
switch forwardState {
|
||||||
case notInstalled:
|
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 {
|
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)
|
fmt.Printf("\n\tsudo %s install\n\n", helper)
|
||||||
}
|
}
|
||||||
case machineLocal:
|
case machineLocal:
|
||||||
@ -1053,9 +1097,31 @@ func printAPIForwardInstructions(forwardState apiForwardingState, forwardSock st
|
|||||||
default:
|
default:
|
||||||
stillString = ""
|
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("following command in your terminal session:\n")
|
||||||
fmt.Printf("\n\texport DOCKER_HOST='unix://%s'\n\n", forwardSock)
|
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
|
// +build windows
|
||||||
|
|
||||||
package wsl
|
package wsl
|
||||||
@ -8,6 +9,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -35,9 +37,6 @@ const (
|
|||||||
ErrorSuccessRebootRequired = 3010
|
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]
|
const containersConf = `[containers]
|
||||||
|
|
||||||
[engine]
|
[engine]
|
||||||
@ -162,6 +161,8 @@ type MachineVM struct {
|
|||||||
Port int
|
Port int
|
||||||
// RemoteUsername of the vm user
|
// RemoteUsername of the vm user
|
||||||
RemoteUsername string
|
RemoteUsername string
|
||||||
|
// Whether this machine should run in a rootful or rootless manner
|
||||||
|
Rootful bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type ExitCodeError struct {
|
type ExitCodeError struct {
|
||||||
@ -227,12 +228,13 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
|
|||||||
homeDir := homedir.Get()
|
homeDir := homedir.Get()
|
||||||
sshDir := filepath.Join(homeDir, ".ssh")
|
sshDir := filepath.Join(homeDir, ".ssh")
|
||||||
v.IdentityPath = filepath.Join(sshDir, v.Name)
|
v.IdentityPath = filepath.Join(sshDir, v.Name)
|
||||||
|
v.Rootful = opts.Rootful
|
||||||
|
|
||||||
if err := downloadDistro(v, opts); err != nil {
|
if err := downloadDistro(v, opts); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := writeJSON(v); err != nil {
|
if err := v.writeConfig(); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,7 +284,7 @@ func downloadDistro(v *MachineVM, opts machine.InitOptions) error {
|
|||||||
return machine.DownloadImage(dd)
|
return machine.DownloadImage(dd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeJSON(v *MachineVM) error {
|
func (v *MachineVM) writeConfig() error {
|
||||||
vmConfigDir, err := machine.GetConfDir(vmtype)
|
vmConfigDir, err := machine.GetConfDir(vmtype)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -302,14 +304,26 @@ func writeJSON(v *MachineVM) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setupConnections(v *MachineVM, opts machine.InitOptions, sshDir string) 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")
|
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 {
|
identity := filepath.Join(sshDir, v.Name)
|
||||||
return err
|
|
||||||
|
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
|
for i := 0; i < 2; i++ {
|
||||||
uri := machine.SSHRemoteConnection.MakeSSHURL("localhost", withUser("/run/[USER]/1000/podman/podman.sock", user), strconv.Itoa(v.Port), v.RemoteUsername)
|
if err := machine.AddConnection(&uris[i], names[i], identity, opts.IsDefault && i == 0); err != nil {
|
||||||
return machine.AddConnection(&uri, v.Name, filepath.Join(sshDir, v.Name), opts.IsDefault)
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func provisionWSLDist(v *MachineVM) (string, error) {
|
func provisionWSLDist(v *MachineVM) (string, error) {
|
||||||
@ -704,6 +718,30 @@ func pipeCmdPassThrough(name string, input string, arg ...string) error {
|
|||||||
return cmd.Run()
|
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 {
|
func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
|
||||||
if v.isRunning() {
|
if v.isRunning() {
|
||||||
return errors.Errorf("%q is already running", name)
|
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")
|
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)
|
globalName, pipeName, err := launchWinProxy(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, "API forwarding for Docker API clients is not available due to the following startup failures.")
|
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