summaryrefslogtreecommitdiff
path: root/pkg/machine
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/machine')
-rw-r--r--pkg/machine/config.go1
-rw-r--r--pkg/machine/config_test.go3
-rw-r--r--pkg/machine/e2e/config_info.go20
-rw-r--r--pkg/machine/e2e/info_test.go58
-rw-r--r--pkg/machine/qemu/config_test.go3
-rw-r--r--pkg/machine/qemu/machine.go49
-rw-r--r--pkg/machine/qemu/machine_test.go3
-rw-r--r--pkg/machine/wsl/machine.go106
8 files changed, 223 insertions, 20 deletions
diff --git a/pkg/machine/config.go b/pkg/machine/config.go
index fcc129338..66fa6ab91 100644
--- a/pkg/machine/config.go
+++ b/pkg/machine/config.go
@@ -55,6 +55,7 @@ type Provider interface {
IsValidVMName(name string) (bool, error)
CheckExclusiveActiveVM() (bool, string, error)
RemoveAndCleanMachines() error
+ VMType() string
}
type RemoteConnectionType string
diff --git a/pkg/machine/config_test.go b/pkg/machine/config_test.go
index d9fc5425e..ca08660b9 100644
--- a/pkg/machine/config_test.go
+++ b/pkg/machine/config_test.go
@@ -1,3 +1,6 @@
+//go:build amd64 || arm64
+// +build amd64 arm64
+
package machine
import (
diff --git a/pkg/machine/e2e/config_info.go b/pkg/machine/e2e/config_info.go
new file mode 100644
index 000000000..410c7e518
--- /dev/null
+++ b/pkg/machine/e2e/config_info.go
@@ -0,0 +1,20 @@
+package e2e
+
+type infoMachine struct {
+ format string
+ cmd []string
+}
+
+func (i *infoMachine) buildCmd(m *machineTestBuilder) []string {
+ cmd := []string{"machine", "info"}
+ if len(i.format) > 0 {
+ cmd = append(cmd, "--format", i.format)
+ }
+ i.cmd = cmd
+ return cmd
+}
+
+func (i *infoMachine) withFormat(format string) *infoMachine {
+ i.format = format
+ return i
+}
diff --git a/pkg/machine/e2e/info_test.go b/pkg/machine/e2e/info_test.go
new file mode 100644
index 000000000..eeabb78af
--- /dev/null
+++ b/pkg/machine/e2e/info_test.go
@@ -0,0 +1,58 @@
+package e2e
+
+import (
+ "github.com/containers/podman/v4/cmd/podman/machine"
+ jsoniter "github.com/json-iterator/go"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ . "github.com/onsi/gomega/gexec"
+)
+
+var _ = Describe("podman machine info", func() {
+ var (
+ mb *machineTestBuilder
+ testDir string
+ )
+
+ BeforeEach(func() {
+ testDir, mb = setup()
+ })
+ AfterEach(func() {
+ teardown(originalHomeDir, testDir, mb)
+ })
+
+ It("machine info", func() {
+ info := new(infoMachine)
+ infoSession, err := mb.setCmd(info).run()
+ Expect(err).NotTo(HaveOccurred())
+ Expect(infoSession).Should(Exit(0))
+
+ // Verify go template works and check for no running machines
+ info = new(infoMachine)
+ infoSession, err = mb.setCmd(info.withFormat("{{.Host.NumberOfMachines}}")).run()
+ Expect(err).NotTo(HaveOccurred())
+ Expect(infoSession).Should(Exit(0))
+ Expect(infoSession.outputToString()).To(Equal("0"))
+
+ // Create a machine and check if info has been updated
+ i := new(initMachine)
+ initSession, err := mb.setCmd(i.withImagePath(mb.imagePath)).run()
+ Expect(err).To(BeNil())
+ Expect(initSession).To(Exit(0))
+
+ info = new(infoMachine)
+ infoSession, err = mb.setCmd(info.withFormat("{{.Host.NumberOfMachines}}")).run()
+ Expect(err).NotTo(HaveOccurred())
+ Expect(infoSession).Should(Exit(0))
+ Expect(infoSession.outputToString()).To(Equal("1"))
+
+ // Check if json is in correct format
+ infoSession, err = mb.setCmd(info.withFormat("json")).run()
+ Expect(err).NotTo(HaveOccurred())
+ Expect(infoSession).Should(Exit(0))
+
+ infoReport := &machine.Info{}
+ err = jsoniter.Unmarshal(infoSession.Bytes(), infoReport)
+ Expect(err).To(BeNil())
+ })
+})
diff --git a/pkg/machine/qemu/config_test.go b/pkg/machine/qemu/config_test.go
index 4d96ec6e7..72cb3ed90 100644
--- a/pkg/machine/qemu/config_test.go
+++ b/pkg/machine/qemu/config_test.go
@@ -1,3 +1,6 @@
+//go:build (amd64 && !windows) || (arm64 && !windows)
+// +build amd64,!windows arm64,!windows
+
package qemu
import (
diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go
index 2fe0230cf..322aa3a15 100644
--- a/pkg/machine/qemu/machine.go
+++ b/pkg/machine/qemu/machine.go
@@ -8,6 +8,7 @@ import (
"context"
"encoding/base64"
"encoding/json"
+ "errors"
"fmt"
"io/fs"
"io/ioutil"
@@ -30,7 +31,6 @@ import (
"github.com/containers/storage/pkg/homedir"
"github.com/digitalocean/go-qemu/qmp"
"github.com/docker/go-units"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
@@ -318,6 +318,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
source := paths[0]
target := source
readonly := false
+ securityModel := "mapped-xattr"
if len(paths) > 1 {
target = paths[1]
}
@@ -325,18 +326,20 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
options := paths[2]
volopts := strings.Split(options, ",")
for _, o := range volopts {
- switch o {
- case "rw":
+ switch {
+ case o == "rw":
readonly = false
- case "ro":
+ case o == "ro":
readonly = true
+ case strings.HasPrefix(o, "security_model="):
+ securityModel = strings.Split(o, "=")[1]
default:
fmt.Printf("Unknown option: %s\n", o)
}
}
}
if volumeType == VolumeTypeVirtfs {
- virtfsOptions := fmt.Sprintf("local,path=%s,mount_tag=%s,security_model=mapped-xattr", source, tag)
+ virtfsOptions := fmt.Sprintf("local,path=%s,mount_tag=%s,security_model=%s", source, tag, securityModel)
if readonly {
virtfsOptions += ",readonly"
}
@@ -434,12 +437,12 @@ func (v *MachineVM) Set(_ string, opts machine.SetOptions) ([]error, error) {
if v.Name != machine.DefaultMachineName {
suffix = " " + v.Name
}
- return setErrors, errors.Errorf("cannot change settings while the vm is running, run 'podman machine stop%s' first", suffix)
+ return setErrors, fmt.Errorf("cannot change settings while the vm is running, run 'podman machine stop%s' first", suffix)
}
if opts.Rootful != nil && v.Rootful != *opts.Rootful {
if err := v.setRootful(*opts.Rootful); err != nil {
- setErrors = append(setErrors, errors.Wrapf(err, "failed to set rootful option"))
+ setErrors = append(setErrors, fmt.Errorf("failed to set rootful option: %w", err))
} else {
v.Rootful = *opts.Rootful
}
@@ -457,7 +460,7 @@ func (v *MachineVM) Set(_ string, opts machine.SetOptions) ([]error, error) {
if opts.DiskSize != nil && v.DiskSize != *opts.DiskSize {
if err := v.resizeDisk(*opts.DiskSize, v.DiskSize); err != nil {
- setErrors = append(setErrors, errors.Wrapf(err, "failed to resize disk"))
+ setErrors = append(setErrors, fmt.Errorf("failed to resize disk: %w", err))
} else {
v.DiskSize = *opts.DiskSize
}
@@ -514,7 +517,7 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
forwardSock, forwardState, err := v.startHostNetworking()
if err != nil {
- return errors.Errorf("unable to start host networking: %q", err)
+ return fmt.Errorf("unable to start host networking: %q", err)
}
rtPath, err := getRuntimeDir()
@@ -593,7 +596,7 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
}
_, err = os.StartProcess(cmd[0], cmd, attr)
if err != nil {
- return errors.Wrapf(err, "unable to execute %q", cmd)
+ return fmt.Errorf("unable to execute %q: %w", cmd, err)
}
}
fmt.Println("Waiting for VM ...")
@@ -700,7 +703,7 @@ func (v *MachineVM) checkStatus(monitor *qmp.SocketMonitor) (machine.Status, err
}
b, err := monitor.Run(input)
if err != nil {
- if errors.Cause(err) == os.ErrNotExist {
+ if errors.Is(err, os.ErrNotExist) {
return machine.Stopped, nil
}
return "", err
@@ -879,7 +882,7 @@ func (v *MachineVM) Remove(_ string, opts machine.RemoveOptions) (string, func()
}
if state == machine.Running {
if !opts.Force {
- return "", nil, errors.Errorf("running vm %q cannot be destroyed", v.Name)
+ return "", nil, fmt.Errorf("running vm %q cannot be destroyed", v.Name)
}
err := v.Stop(v.Name, machine.StopOptions{})
if err != nil {
@@ -1001,7 +1004,7 @@ func (v *MachineVM) SSH(_ string, opts machine.SSHOptions) error {
return err
}
if state != machine.Running {
- return errors.Errorf("vm %q is not running", v.Name)
+ return fmt.Errorf("vm %q is not running", v.Name)
}
username := opts.Username
@@ -1013,7 +1016,7 @@ func (v *MachineVM) SSH(_ string, opts machine.SSHOptions) error {
port := strconv.Itoa(v.Port)
args := []string{"-i", v.IdentityPath, "-p", port, sshDestination, "-o", "UserKnownHostsFile=/dev/null",
- "-o", "StrictHostKeyChecking=no", "-o", "LogLevel=ERROR"}
+ "-o", "StrictHostKeyChecking=no", "-o", "LogLevel=ERROR", "-o", "SetEnv=LC_ALL="}
if len(opts.Args) > 0 {
args = append(args, opts.Args...)
} else {
@@ -1165,7 +1168,7 @@ func (p *Provider) IsValidVMName(name string) (bool, error) {
func (p *Provider) CheckExclusiveActiveVM() (bool, string, error) {
vms, err := getVMInfos()
if err != nil {
- return false, "", errors.Wrap(err, "error checking VM active")
+ return false, "", fmt.Errorf("error checking VM active: %w", err)
}
for _, vm := range vms {
if vm.Running || vm.Starting {
@@ -1217,7 +1220,10 @@ func (v *MachineVM) startHostNetworking() (string, apiForwardingState, error) {
fmt.Println(cmd)
}
_, err = os.StartProcess(cmd[0], cmd, attr)
- return forwardSock, state, errors.Wrapf(err, "unable to execute: %q", cmd)
+ if err != nil {
+ return "", 0, fmt.Errorf("unable to execute: %q: %w", cmd, err)
+ }
+ return forwardSock, state, nil
}
func (v *MachineVM) setupAPIForwarding(cmd []string) ([]string, string, apiForwardingState) {
@@ -1486,7 +1492,7 @@ func (v *MachineVM) update() error {
b, err := v.ConfigPath.Read()
if err != nil {
if errors.Is(err, os.ErrNotExist) {
- return errors.Wrap(machine.ErrNoSuchVM, v.Name)
+ return fmt.Errorf("%v: %w", v.Name, machine.ErrNoSuchVM)
}
return err
}
@@ -1562,7 +1568,7 @@ func (v *MachineVM) resizeDisk(diskSize uint64, oldSize uint64) error {
// only if the virtualdisk size is less than
// the given disk size
if diskSize < oldSize {
- return errors.Errorf("new disk size must be larger than current disk size: %vGB", oldSize)
+ return fmt.Errorf("new disk size must be larger than current disk size: %vGB", oldSize)
}
// Find the qemu executable
@@ -1578,7 +1584,7 @@ func (v *MachineVM) resizeDisk(diskSize uint64, oldSize uint64) error {
resize.Stdout = os.Stdout
resize.Stderr = os.Stderr
if err := resize.Run(); err != nil {
- return errors.Errorf("resizing image: %q", err)
+ return fmt.Errorf("resizing image: %q", err)
}
return nil
@@ -1698,6 +1704,9 @@ func isProcessAlive(pid int) bool {
if err == nil || err == unix.EPERM {
return true
}
-
return false
}
+
+func (p *Provider) VMType() string {
+ return vmtype
+}
diff --git a/pkg/machine/qemu/machine_test.go b/pkg/machine/qemu/machine_test.go
index 62ca6068a..4c393d0f4 100644
--- a/pkg/machine/qemu/machine_test.go
+++ b/pkg/machine/qemu/machine_test.go
@@ -1,3 +1,6 @@
+//go:build (amd64 && !windows) || (arm64 && !windows)
+// +build amd64,!windows arm64,!windows
+
package qemu
import (
diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go
index 075f42cb2..492b66659 100644
--- a/pkg/machine/wsl/machine.go
+++ b/pkg/machine/wsl/machine.go
@@ -18,6 +18,7 @@ import (
"strings"
"time"
+ "github.com/containers/common/pkg/config"
"github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/utils"
"github.com/containers/storage/pkg/homedir"
@@ -116,6 +117,43 @@ ln -fs /home/[USER]/.config/systemd/[USER]/linger-example.service \
/home/[USER]/.config/systemd/[USER]/default.target.wants/linger-example.service
`
+const proxyConfigSetup = `#!/bin/bash
+
+SYSTEMD_CONF=/etc/systemd/system.conf.d/default-env.conf
+ENVD_CONF=/etc/environment.d/default-env.conf
+PROFILE_CONF=/etc/profile.d/default-env.sh
+
+IFS="|"
+read proxies
+
+mkdir -p /etc/profile.d /etc/environment.d /etc/systemd/system.conf.d/
+rm -f $SYSTEMD_CONF
+for proxy in $proxies; do
+ output+="$proxy "
+done
+echo "[Manager]" >> $SYSTEMD_CONF
+echo -ne "DefaultEnvironment=" >> $SYSTEMD_CONF
+
+echo $output >> $SYSTEMD_CONF
+rm -f $ENVD_CONF
+for proxy in $proxies; do
+ echo "$proxy" >> $ENVD_CONF
+done
+rm -f $PROFILE_CONF
+for proxy in $proxies; do
+ echo "export $proxy" >> $PROFILE_CONF
+done
+`
+
+const proxyConfigAttempt = `if [ -f /usr/local/bin/proxyinit ]; \
+then /usr/local/bin/proxyinit; \
+else exit 42; \
+fi`
+
+const clearProxySettings = `rm -f /etc/systemd/system.conf.d/default-env.conf \
+ /etc/environment.d/default-env.conf \
+ /etc/profile.d/default-env.sh`
+
const wslInstallError = `Could not %s. See previous output for any potential failure details.
If you can not resolve the issue, and rerunning fails, try the "wsl --install" process
outlined in the following article:
@@ -300,6 +338,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
return cont, err
}
+ _ = setupWslProxyEnv()
homeDir := homedir.Get()
sshDir := filepath.Join(homeDir, ".ssh")
v.IdentityPath = filepath.Join(sshDir, v.Name)
@@ -526,6 +565,40 @@ func configureSystem(v *MachineVM, dist string) error {
return nil
}
+func configureProxy(dist string, useProxy bool) error {
+ if !useProxy {
+ _ = runCmdPassThrough("wsl", "-d", dist, "sh", "-c", clearProxySettings)
+ return nil
+ }
+ var content string
+ for i, key := range config.ProxyEnv {
+ if value, _ := os.LookupEnv(key); len(value) > 0 {
+ var suffix string
+ if i < (len(config.ProxyEnv) - 1) {
+ suffix = "|"
+ }
+ content = fmt.Sprintf("%s%s=\"%s\"%s", content, key, value, suffix)
+ }
+ }
+
+ if err := pipeCmdPassThrough("wsl", content, "-d", dist, "sh", "-c", proxyConfigAttempt); err != nil {
+ const failMessage = "Failure creating proxy configuration"
+ if exitErr, isExit := err.(*exec.ExitError); isExit && exitErr.ExitCode() != 42 {
+ return errors.Wrap(err, failMessage)
+ }
+
+ fmt.Println("Installing proxy support")
+ _ = pipeCmdPassThrough("wsl", proxyConfigSetup, "-d", dist, "sh", "-c",
+ "cat > /usr/local/bin/proxyinit; chmod 755 /usr/local/bin/proxyinit")
+
+ if err = pipeCmdPassThrough("wsl", content, "-d", dist, "/usr/local/bin/proxyinit"); err != nil {
+ return errors.Wrap(err, failMessage)
+ }
+ }
+
+ return nil
+}
+
func enableUserLinger(v *MachineVM, dist string) error {
lingerCmd := "mkdir -p /var/lib/systemd/linger; touch /var/lib/systemd/linger/" + v.RemoteUsername
if err := runCmdPassThrough("wsl", "-d", dist, "sh", "-c", lingerCmd); err != nil {
@@ -555,6 +628,11 @@ func installScripts(dist string) error {
return errors.Wrap(err, "could not create bootstrap script for guest OS")
}
+ if err := pipeCmdPassThrough("wsl", proxyConfigSetup, "-d", dist, "sh", "-c",
+ "cat > /usr/local/bin/proxyinit; chmod 755 /usr/local/bin/proxyinit"); err != nil {
+ return errors.Wrap(err, "could not create proxyinit script for guest OS")
+ }
+
return nil
}
@@ -816,6 +894,26 @@ func pipeCmdPassThrough(name string, input string, arg ...string) error {
return cmd.Run()
}
+func setupWslProxyEnv() (hasProxy bool) {
+ current, _ := os.LookupEnv("WSLENV")
+ for _, key := range config.ProxyEnv {
+ if value, _ := os.LookupEnv(key); len(value) < 1 {
+ continue
+ }
+
+ hasProxy = true
+ delim := ""
+ if len(current) > 0 {
+ delim = ":"
+ }
+ current = fmt.Sprintf("%s%s%s/u", current, delim, key)
+ }
+ if hasProxy {
+ os.Setenv("WSLENV", current)
+ }
+ return
+}
+
func (v *MachineVM) Set(_ string, opts machine.SetOptions) ([]error, error) {
// If one setting fails to be applied, the others settings will not fail and still be applied.
// The setting(s) that failed to be applied will have its errors returned in setErrors
@@ -852,6 +950,10 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
}
dist := toDist(name)
+ useProxy := setupWslProxyEnv()
+ if err := configureProxy(dist, useProxy); err != nil {
+ return err
+ }
err := runCmdPassThrough("wsl", "-d", dist, "/root/bootstrap")
if err != nil {
@@ -1553,3 +1655,7 @@ func (p *Provider) RemoveAndCleanMachines() error {
}
return prevErr
}
+
+func (p *Provider) VMType() string {
+ return vmtype
+}