aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/machine/machine_unix.go4
-rw-r--r--docs/source/Tutorials.rst3
-rw-r--r--docs/tutorials/mac_win_client.md4
-rwxr-xr-xhack/parse-localbenchmarks104
-rw-r--r--libpod/info.go11
-rw-r--r--libpod/info_test.go8
-rw-r--r--libpod/runtime.go2
-rw-r--r--libpod/runtime_ctr.go6
-rw-r--r--pkg/machine/wsl/machine.go40
-rw-r--r--pkg/specgen/generate/pause_image.go6
-rw-r--r--test/system/170-run-userns.bats13
11 files changed, 183 insertions, 18 deletions
diff --git a/cmd/podman/machine/machine_unix.go b/cmd/podman/machine/machine_unix.go
index 213c24f8c..b56d081ec 100644
--- a/cmd/podman/machine/machine_unix.go
+++ b/cmd/podman/machine/machine_unix.go
@@ -1,5 +1,5 @@
-//go:build linux || ignore || aix || ignore || android || ignore || darwin || ignore || freebsd || ignore || hurd || ignore || illumos || ignore || ios || ignore || netbsd || ignore || openbsd || ignore || solaris
-// +build linux ignore aix ignore android ignore darwin ignore freebsd ignore hurd ignore illumos ignore ios ignore netbsd ignore openbsd ignore solaris
+//go:build linux || aix || android || darwin || dragonfly || freebsd || hurd || illumos || ios || netbsd || openbsd || solaris
+// +build linux aix android darwin dragonfly freebsd hurd illumos ios netbsd openbsd solaris
package machine
diff --git a/docs/source/Tutorials.rst b/docs/source/Tutorials.rst
index 34a029484..c2cbcb8a9 100644
--- a/docs/source/Tutorials.rst
+++ b/docs/source/Tutorials.rst
@@ -6,7 +6,8 @@ Here are a number of useful tutorials to get you up and running with Podman. If
* `Basic Setup and Use of Podman <https://github.com/containers/podman/blob/main/docs/tutorials/podman_tutorial.md>`_: Learn how to setup Podman and perform some basic commands with the utility.
* `Basic Setup and Use of Podman in a Rootless environment <https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md>`_: The steps required to setup rootless Podman are enumerated.
-* `Podman Mac/Windows tutorial <https://github.com/containers/podman/blob/main/docs/tutorials/mac_win_client.md>`_: Special setup for running the Podman remote client on a Mac or Windows PC and connecting to Podman running on a Linux VM are documented.
+* `Podman for Windows <https://github.com/containers/podman/blob/main/docs/tutorials/podman-for-windows.md>`_: A guide to installing and using Podman on Windows.
+* `Podman Remote Clients on Mac/Windows <https://github.com/containers/podman/blob/main/docs/tutorials/mac_win_client.md>`_: Advanced setup for connecting to a remote Linux system using the Podman remote client on Mac and Windows.
* `How to sign and distribute container images using Podman <https://github.com/containers/podman/blob/main/docs/tutorials/image_signing.md>`_: Learn how to setup and use image signing with Podman.
* `Podman remote-client tutorial <https://github.com/containers/podman/blob/main/docs/tutorials/remote_client.md>`_: A brief how-to on using the Podman remote-client.
* `How to use libpod for custom/derivative projects <https://github.com/containers/podman/blob/main/docs/tutorials/podman-derivative-api.md>`_: How the libpod API can be used within your own project.
diff --git a/docs/tutorials/mac_win_client.md b/docs/tutorials/mac_win_client.md
index 159296d5e..553a38394 100644
--- a/docs/tutorials/mac_win_client.md
+++ b/docs/tutorials/mac_win_client.md
@@ -1,5 +1,9 @@
# Podman Remote clients for macOS and Windows
+***
+**_NOTE:_** For running Podman on Windows, refer to the [Podman for Windows](podman-for-windows.md) guide, which uses the recommended approach of a Podman-managed Linux backend. For Mac, see the [Podman installation instructions](https://podman.io/getting-started/installation). This guide covers the advanced usage of Podman with a custom Linux VM or a remote external Linux system.
+***
+
## Introduction
The core Podman runtime environment can only run on Linux operating systems. But other operating systems can use the “remote client” to manage their containers to a Linux backend. This remote client is nearly identical to the standard Podman program. Certain functions that do not make sense for remote clients have been removed. For example, the “--latest” switch for container commands has been removed.
diff --git a/hack/parse-localbenchmarks b/hack/parse-localbenchmarks
new file mode 100755
index 000000000..6e22cabbb
--- /dev/null
+++ b/hack/parse-localbenchmarks
@@ -0,0 +1,104 @@
+#!/usr/bin/perl
+#
+# parse-localbenchmarks - convert localbenchmarks output to CSV
+#
+# This is a filter. It transforms data from one format to another. Usage:
+#
+# $ make localbenchmarks &> mylogfile
+# $ hack/parse-localbenchmarks <mylogfile > benchmarks.csv
+#
+# To be more precise, this is a very stupid simpleminded filter. It is
+# not a complete solution to the benchmarks problem. In particular,
+# other tools are still needed to:
+#
+# * Actually _run_ the benchmarks in some standard production environment
+# * Run this script on the results
+# * Save results, with identifying tags (datetime, git hash, PR id, ...)
+# * Compare two or more sets of CSVs
+#
+(our $ME = $0) =~ s|^.*/||; # script name
+
+use v5.14;
+use utf8;
+
+# FIXME: add --help. Some day. Not urgent.
+die "$ME: This is a filter, not an interactive tool\n" if -t *STDIN;
+
+my $n_samples; # Number of timing runs (FIXME: unused)
+my %results; # Timing results
+my @benchmarks; # Names of benchmarks
+my ($type, $testname); # Current context
+
+#
+# Pass 1: read in timings
+#
+while (my $line = <STDIN>) {
+ # Log will have lots of ginkgo output. The only thing we care about is
+ # the summary at the end, which will look something like:
+ #
+ # * [MEASUREMENT]
+ # Podman Benchmark Suite
+ # ....
+ # Ran 3 samples:
+ # [CPU] podman images:
+ # Fastest Time: 0.265s
+ # Slowest Time: 0.322s
+ # Average Time: 0.302s ± 0.018s
+ # [MEM] podman images:
+ # Smallest: 44076.0KB
+ # Largest: 44616.0KB
+ # Average: 44338.7KB ± 171.2KB
+ # [CPU] podman push:
+ # ....repeat [CPU] and [MEM] for each test
+ # --------------------------
+ # SSSSSSSSSSSSSSSSSSSSS (and more ginkgo output we don't care about)
+ #
+ chomp $line;
+ next unless $line =~ /^.{1,3}\s+\[MEASUREMENT\]/ .. $line =~ /^-{20,}$/;
+
+ # Trim leading & trailing whitespace
+ $line =~ s/(^\s+|\s+$)//g;
+
+ # FIXME: we don't actually emit this. What would be a good way to do so?
+ if ($line =~ /^Ran\s+(\d+)\s+samples/) {
+ $n_samples = $1;
+ }
+
+ # e.g., [CPU] podman foo:
+ elsif ($line =~ /^\[([A-Z]+)\]\s+(\S.*\S):$/) {
+ ($type, $testname) = ($1, $2);
+ }
+
+ # e.g., 'Fastest Time: 0.265s'
+ elsif ($line =~ /^(\S.*?\S):\s+(.*)/) {
+ my $benchmark = "$type $1";
+ $results{$testname}{$benchmark} = $2;
+
+ # Keep an ordered list of benchmark names (as in, the order we
+ # encounter them)
+ push @benchmarks, $benchmark
+ unless grep { $_ eq $benchmark } @benchmarks;
+ }
+
+ else {
+ warn "Cannot grok '$line'\n" if $ENV{DEBUG_PARSELOCALBENCHMARKS};
+ }
+}
+
+#
+# Pass 2: write out CSV
+#
+
+# Headings...
+print "\"Test Name\"";
+printf ", \"%s\"", $_ for @benchmarks;
+print "\n";
+
+# ...then data
+for my $t (sort keys %results) {
+ printf "\"%s\"", $t;
+ for my $benchmark (@benchmarks) {
+ printf ", \"%s\"", $results{$t}{$benchmark} || '';
+ }
+ print "\n";
+}
diff --git a/libpod/info.go b/libpod/info.go
index 321680a81..bc49a6cc9 100644
--- a/libpod/info.go
+++ b/libpod/info.go
@@ -406,26 +406,25 @@ func getCPUUtilization() (*define.CPUUsage, error) {
}
defer f.Close()
scanner := bufio.NewScanner(f)
- // Read firt line of /proc/stat
+ // Read first line of /proc/stat that has entries for system ("cpu" line)
for scanner.Scan() {
break
}
// column 1 is user, column 3 is system, column 4 is idle
- stats := strings.Split(scanner.Text(), " ")
+ stats := strings.Fields(scanner.Text())
return statToPercent(stats)
}
func statToPercent(stats []string) (*define.CPUUsage, error) {
- // There is always an extra space between cpu and the first metric
- userTotal, err := strconv.ParseFloat(stats[2], 64)
+ userTotal, err := strconv.ParseFloat(stats[1], 64)
if err != nil {
return nil, errors.Wrapf(err, "unable to parse user value %q", stats[1])
}
- systemTotal, err := strconv.ParseFloat(stats[4], 64)
+ systemTotal, err := strconv.ParseFloat(stats[3], 64)
if err != nil {
return nil, errors.Wrapf(err, "unable to parse system value %q", stats[3])
}
- idleTotal, err := strconv.ParseFloat(stats[5], 64)
+ idleTotal, err := strconv.ParseFloat(stats[4], 64)
if err != nil {
return nil, errors.Wrapf(err, "unable to parse idle value %q", stats[4])
}
diff --git a/libpod/info_test.go b/libpod/info_test.go
index 909b573c0..b0e4bf8c0 100644
--- a/libpod/info_test.go
+++ b/libpod/info_test.go
@@ -20,7 +20,7 @@ func Test_statToPercent(t *testing.T) {
}{
{
name: "GoodParse",
- args: args{in0: []string{"cpu", " ", "33628064", "27537", "9696996", "1314806705", "588142", "4775073", "2789228", "0", "598711", "0"}},
+ args: args{in0: []string{"cpu", "33628064", "27537", "9696996", "1314806705", "588142", "4775073", "2789228", "0", "598711", "0"}},
want: &define.CPUUsage{
UserPercent: 2.48,
SystemPercent: 0.71,
@@ -30,19 +30,19 @@ func Test_statToPercent(t *testing.T) {
},
{
name: "BadUserValue",
- args: args{in0: []string{"cpu", " ", "k", "27537", "9696996", "1314806705", "588142", "4775073", "2789228", "0", "598711", "0"}},
+ args: args{in0: []string{"cpu", "k", "27537", "9696996", "1314806705", "588142", "4775073", "2789228", "0", "598711", "0"}},
want: nil,
wantErr: assert.Error,
},
{
name: "BadSystemValue",
- args: args{in0: []string{"cpu", " ", "33628064", "27537", "k", "1314806705", "588142", "4775073", "2789228", "0", "598711", "0"}},
+ args: args{in0: []string{"cpu", "33628064", "27537", "k", "1314806705", "588142", "4775073", "2789228", "0", "598711", "0"}},
want: nil,
wantErr: assert.Error,
},
{
name: "BadIdleValue",
- args: args{in0: []string{"cpu", " ", "33628064", "27537", "9696996", "k", "588142", "4775073", "2789228", "0", "598711", "0"}},
+ args: args{in0: []string{"cpu", "33628064", "27537", "9696996", "k", "588142", "4775073", "2789228", "0", "598711", "0"}},
want: nil,
wantErr: assert.Error,
},
diff --git a/libpod/runtime.go b/libpod/runtime.go
index f4cd9cf00..58f20ef5b 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -349,7 +349,7 @@ func makeRuntime(runtime *Runtime) (retErr error) {
// it will try to use existing XDG_RUNTIME_DIR
// if current user has no write access to XDG_RUNTIME_DIR we will fail later
if err := unix.Access(runtime.storageConfig.RunRoot, unix.W_OK); err != nil {
- msg := "XDG_RUNTIME_DIR is pointing to a path which is not writable. Most likely podman will fail."
+ msg := fmt.Sprintf("RunRoot is pointing to a path (%s) which is not writable. Most likely podman will fail.", runtime.storageConfig.RunRoot)
if errors.Is(err, os.ErrNotExist) {
// if dir does not exists try to create it
if err := os.MkdirAll(runtime.storageConfig.RunRoot, 0700); err != nil {
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index df7174ac6..7e8a21a8c 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -732,7 +732,11 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
// after setting the state to ContainerStateRemoving will prevent that the container is
// restarted
if err := c.removeAllExecSessions(); err != nil {
- return err
+ if cleanupErr == nil {
+ cleanupErr = err
+ } else {
+ logrus.Errorf("Remove exec sessions: %v", err)
+ }
}
// Stop the container's storage
diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go
index 57fb36fc9..0b2874baf 100644
--- a/pkg/machine/wsl/machine.go
+++ b/pkg/machine/wsl/machine.go
@@ -36,6 +36,7 @@ var (
const (
ErrorSuccessRebootInitiated = 1641
ErrorSuccessRebootRequired = 3010
+ currentMachineVersion = 2
)
const containersConf = `[containers]
@@ -168,6 +169,8 @@ type MachineVM struct {
Rootful bool
// SSH identity, username, etc
machine.SSHConfig
+ // machine version
+ Version int
}
type ExitCodeError struct {
@@ -241,12 +244,29 @@ func readAndMigrate(configPath string, name string) (*MachineVM, error) {
return vm, err
}
err = json.Unmarshal(b, vm)
- if err == nil && vm.Created.IsZero() {
- err = vm.migrate40(configPath)
+ if err == nil && vm.Version < currentMachineVersion {
+ err = vm.migrateMachine(configPath)
}
+
return vm, err
}
+func (v *MachineVM) migrateMachine(configPath string) error {
+ if v.Created.IsZero() {
+ if err := v.migrate40(configPath); err != nil {
+ return err
+ }
+ }
+
+ // Update older machines to use lingering
+ if err := enableUserLinger(v, toDist(v.Name)); err != nil {
+ return err
+ }
+
+ v.Version = currentMachineVersion
+ return v.writeConfig()
+}
+
func (v *MachineVM) migrate40(configPath string) error {
v.ConfigPath = configPath
fi, err := os.Stat(configPath)
@@ -255,7 +275,7 @@ func (v *MachineVM) migrate40(configPath string) error {
}
v.Created = fi.ModTime()
v.LastUp = getLegacyLastStart(v)
- return v.writeConfig()
+ return nil
}
func getLegacyLastStart(vm *MachineVM) time.Time {
@@ -284,6 +304,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
sshDir := filepath.Join(homeDir, ".ssh")
v.IdentityPath = filepath.Join(sshDir, v.Name)
v.Rootful = opts.Rootful
+ v.Version = currentMachineVersion
if err := downloadDistro(v, opts); err != nil {
return false, err
@@ -486,6 +507,10 @@ func configureSystem(v *MachineVM, dist string) error {
return errors.Wrap(err, "could not generate linger service for guest OS")
}
+ if err := enableUserLinger(v, dist); err != nil {
+ return err
+ }
+
if err := pipeCmdPassThrough("wsl", withUser(lingerSetup, user), "-d", dist, "sh"); err != nil {
return errors.Wrap(err, "could not configure systemd settomgs for guest OS")
}
@@ -501,6 +526,15 @@ func configureSystem(v *MachineVM, dist string) error {
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 {
+ return errors.Wrap(err, "could not enable linger for remote user on guest OS")
+ }
+
+ return nil
+}
+
func installScripts(dist string) error {
if err := pipeCmdPassThrough("wsl", enterns, "-d", dist, "sh", "-c",
"cat > /usr/local/bin/enterns; chmod 755 /usr/local/bin/enterns"); err != nil {
diff --git a/pkg/specgen/generate/pause_image.go b/pkg/specgen/generate/pause_image.go
index 4aba230a3..ddf35f230 100644
--- a/pkg/specgen/generate/pause_image.go
+++ b/pkg/specgen/generate/pause_image.go
@@ -80,6 +80,12 @@ ENTRYPOINT ["/catatonit", "-P"]`, catatonitPath)
Quiet: true,
IgnoreFile: "/dev/null", // makes sure to not read a local .ignorefile (see #13529)
IIDFile: "/dev/null", // prevents Buildah from writing the ID on stdout
+ IDMappingOptions: &buildahDefine.IDMappingOptions{
+ // Use the host UID/GID mappings for the build to avoid issues when
+ // running with a custom mapping (BZ #2083997).
+ HostUIDMapping: true,
+ HostGIDMapping: true,
+ },
}
if _, _, err := rt.Build(context.Background(), buildOptions, tmpF.Name()); err != nil {
return "", err
diff --git a/test/system/170-run-userns.bats b/test/system/170-run-userns.bats
index d754306b2..b80351902 100644
--- a/test/system/170-run-userns.bats
+++ b/test/system/170-run-userns.bats
@@ -36,6 +36,19 @@ function _require_crun() {
is "$output" ".*457" "Check group leaked into container"
}
+@test "rootful pod with custom ID mapping" {
+ skip_if_rootless "does not work rootless - rootful feature"
+ skip_if_remote "remote --uidmap is broken (see #14233)"
+ random_pod_name=$(random_string 30)
+ run_podman pod create --uidmap 0:200000:5000 --name=$random_pod_name
+ run_podman pod start $random_pod_name
+
+ # Remove the pod and the pause image
+ run_podman pod rm $random_pod_name
+ run_podman version --format "{{.Server.Version}}-{{.Server.Built}}"
+ run_podman rmi -f localhost/podman-pause:$output
+}
+
@test "podman --remote --group-add keep-groups " {
if is_remote; then
run_podman 125 run --rm --group-add keep-groups $IMAGE id