From d749770fe2b11b7d0677824edc85f88c5f96245d Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Tue, 10 Aug 2021 20:29:01 -0400 Subject: Release notes for v3.3.0-RC2: Initial This does not include subsequent backports, which will be added later. Signed-off-by: Matthew Heon --- RELEASE_NOTES.md | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index ba323e6a0..a348b494b 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,95 @@ # Release Notes +## 3.3.0 +### Features +- Containers inside VMs created by `podman machine` will now automatically handle port forwarding - containers in `podman machine` VMs that publish ports via `--publish` or `--publish-all` will have these ports not just forwarded on the VM, but also on the host system. +- The `podman play kube` command's `--network` option now accepts advanced network options (e.g. `--network slirp4netns:port_handler=slirp4netns`) ([#10807](https://github.com/containers/podman/issues/10807)). +- The `podman play kube` commmand now supports Kubernetes liveness probes, which will be created as Podman healthchecks. +- Podman now provides a systemd unit, `podman-restart.service`, which, when enabled, will restart all containers that were started with `--restart=always` after the system reboots. +- Rootless Podman can now be configured to use CNI networking by default by using the `rootless_networking` option in `containers.conf`. +- Images can now be pulled using `image:tag@digest` syntax (e.g. `podman pull fedora:34@sha256:1b0d4ddd99b1a8c8a80e885aafe6034c95f266da44ead992aab388e6aa91611a`) ([#6721](https://github.com/containers/podman/issues/6721)). +- The `podman container checkpoint` and `podman container restore` commands can now be used to checkpoint containers that are in pods, and restore those containers into pods. +- The `podman container restore` command now features a new option, `--publish`, to change the ports that are forwarded to a container that is being restored from an exported checkpoint. +- The `podman container checkpoint` command now features a new option, `--compress`, to specify the compression algorithm that will be used on the generated checkpoint. +- The `podman pull` command can now pull multiple images at once (e.g. `podman pull fedora:34 ubi8:latest` will pull both specified images). +- THe `podman cp` command can now copy files from one container into another directly (e.g. `podman cp containera:/etc/hosts containerb:/etc/`) ([#7370](https://github.com/containers/podman/issues/7370)). +- The `podman cp` command now supports a new option, `--archive`, which controls whether copied files will be chown'd to the UID and GID of the user of the destination container. +- The `podman stats` command now provides two additional metrics: Average CPU, and CPU time. +- The `podman pod create` command supports a new flag, `--pid`, to specify the PID namespace of the pod. If specified, containers that join the pod will automatically share its PID namespace. +- The `podman pod create` command supports a new flag, `--infra-name`, which allows the name of the pod's infra container to be set ([#10794](https://github.com/containers/podman/issues/10794)). +- The `podman auto-update` command has had its output reformatted - it is now much more clear what images were pulled and what containers wer0e updated. +- The `podman auto-update` command now supports a new option, `--dry-run`, which reports what would be updated but does not actually perform the update ([#9949](https://github.com/containers/podman/issues/9949)). +- The `podman manifest remove` command now has a new alias, `podman manifest rm`. +- The `podman login` command now supports a new option, `--verbose`, to print detailed information about where the credentials entered were stored. +- The `podman events` command now supports a new event, `exec_died`, which is produced when an exec session exits, and includes the exit code of the exec session. +- The `podman system connection add` command now supports adding connections that connect using the `tcp://` and `unix://` URL schemes. +- The `podman system connection list` command now supports a new flag, `--format`, to determine how the output is printed. +- The `podman volume prune` and `podman volume ls` commands' `--filter` option now support a new filter, `until`, that matches volumes created before a certain time ([#10579](https://github.com/containers/podman/issues/10579)). +- The `podman ps --filter` option's `network` filter now accepts a new value: `container:`, which matches containers that share a network namespace with a specific container ([#10361](https://github.com/containers/podman/issues/10361)). +- The `podman diff` command can now accept two arguments, allowing two images or two containers to be specified; the diff between the two will be printed ([#10649](https://github.com/containers/podman/issues/10649)). +- Podman can now optionally copy-up content from containers into volumes mounted into those containers earlier (at creation time, instead of at runtime) via the `prepare_on_create` option in `containers.conf` ([#10262](https://github.com/containers/podman/issues/10262)). +- A new option, `--gpus`, has been added to `podman create` and `podman run` as a no-op for better compatibility with Docker. If the nvidia-container-runtime package is installed, GPUs should be automatically added to containers without using the flag. +- If an invalid subcommand is provided, similar commands to try will now be suggested in the error message. + +### Changes +- The `podman system reset` command now removes non-Podman (e.g. Buildah and CRI-O) containers as well. +- The new port forwarding offered by `podman machine` requires [gvproxy](https://github.com/containers/gvisor-tap-vsock) in order to function. +- Podman will now automatically create the default CNI network if it does not exist, for both root and rootless users. This will only be done once per user - if the network is subsequently removed, it will not be recreated. +- The `--root` option to Podman will not automatically clear all default storage options when set. Storage options can be set manually using `--storage-opt` ([#10393](https://github.com/containers/podman/issues/10393)). +- The `install.cni` makefile option has been removed. It is no longer required to distribute the default `87-podman.conflist` CNI configuration file, as Podman will not automatically create it. +- The output of `podman system connection list` is now deterministic, with connections being sorted alpabetically by their name. +- The auto-update service (`podman-auto-update.service`) has had its default timer adjusted so it now starts at a random time up to 15 minutes after midnight, to help prevent system congestion from numerous daily services run at once. +- Systemd unit files generated by `podman generate systemd` now depend on `network-online.target` by default ([#10655](https://github.com/containers/podman/issues/10655)). + +### Bugfixes +- Fixed a bug where the `podman play kube` command did not perform SELinux relabelling of volumes specified with a `mountPath` that included the `:z` or `:Z` options ([#9371](https://github.com/containers/podman/issues/9371)). +- Fixed a bug where the `podman play kube` command would ignore the `USER` and `EXPOSE` directives in images ([#9609](https://github.com/containers/podman/issues/9609)). +- Fixed a bug where the `podman play kube` command would only accept lowercase pull policies. +- Fixed a bug where named volumes mounted into containers with the `:z` or `:Z` options were not appropriately relabelled for access from the container ([#10273](https://github.com/containers/podman/issues/10273)). +- Fixed a bug where the `podman logs -f` command, with the `journald` log driver, could sometimes fail to pick up the last line of output from a container ([#10323](https://github.com/containers/podman/issues/10323)). +- Fixed a bug where running `podman rm` on a container created with the `--rm` option would occasionally emit an error message saying the container failed to be removed, when it was successfully removed. +- Fixed a bug where starting a Podman container would segfault if the `LISTEN_PID` and `LISTEN_FDS` environment variables were set, but `LISTEN_FDNAMES` was not ([#10435](https://github.com/containers/podman/issues/10435)). +- Fixed a bug where exec sessions in containers were sometimes not cleaned up when run without `-d` and when the associated `podman exec` process was killed before completion. +- Fixed a bug where `podman system service` could, when run in a systemd unit file with sdnotify in use, drop some connections when it was starting up. +- Fixed a bug where containers run using the REST API using the `slirp4netns` network mode would leave zombie processes that were not cleaned up until `podman system service` exited ([#9777](https://github.com/containers/podman/issues/9777)). +- Fixed a bug where the `podman system service` command would leave zombie processes after its initial launch that were not cleaned up until it exited ([#10575](https://github.com/containers/podman/issues/10575)). +- Fixed a bug where VMs created by `podman machine` could not be started after the host system restarted ([#10824](https://github.com/containers/podman/issues/10824)). +- Fixed a bug where the `podman pod ps` command would not show headers for optional information (e.g. container names when the `--ctr-names` option was given). +- Fixed a bug where the remote Podman client's `podman build` command would only respect `.containerignore` and not `.dockerignore` files (when both are present, `.containerignore` will be preferred) ([#10907](https://github.com/containers/podman/issues/10907)). +- Fixed a bug where the remote Podman client's `podman build` command would fail to send the Dockerfile being built to the server when it was excluded by the `.dockerignore` file, resulting in an error ([#9867](https://github.com/containers/podman/issues/9867)). +- Fixed a bug where the remote Podman client's `podman build` command could unexpectedly stop streaming the output of the build ([#10154](https://github.com/containers/podman/issues/10154)). +- Fixed a bug where the `podman manifest create` command accepted at most two arguments (an arbitrary number of images are allowed as arguments, which will be added to the manifest). +- Fixed a bug where named volumes would not be properly chowned to the UID and GID of the directory they were mounted over when first mounted into a container ([#10776](https://github.com/containers/podman/issues/10776)). +- Fixed a bug where the remote Podman client's `podman exec -i` command would hang when input was provided via shell redirection (e.g. `podman --remote exec -i foo cat <<<"hello"`) ([#7360](https://github.com/containers/podman/issues/7360)). +- Fixed a bug where containers created with `--rm` were not immediately removed after being started by `podman start` if they failed to start ([#10935](https://github.com/containers/podman/issues/10935)). +- Fixed a bug where the `--storage-opt` flag to `podman create` and `podman run` was nonfunctional ([#10264](https://github.com/containers/podman/issues/10264)). +- Fixed a bug where the `--device-cgroup-rule` option to `podman create` and `podman run` was nonfunctional ([#10302](https://github.com/containers/podman/issues/10302)). +- Fixed a bug where the `--tls-verify` option to `podman manifest push` was nonfunctional. +- Fixed a bug where the `podman import` command could, in some circumstances, produce empty images ([#10994](https://github.com/containers/podman/issues/10994)). +- Fixed a bug where images pulled using the `docker-daemon:` transport had the wrong registry (`localhost` instead of `docker.io/library`) ([#10998](https://github.com/containers/podman/issues/10998)). +- Fixed a bug where operations that pruned images (`podman image prune` and `podman system prune`) would prune untagged images with children ([#10832](https://github.com/containers/podman/issues/10832)). +- Fixed a bug where dual-stack networks created by `podman network create` did not properly auto-assign an IPv4 subnet when one was not explicitly specified ([#11032](https://github.com/containers/podman/issues/11032)). +- Fixed a bug where port forwarding using the `rootlessport` port forwarder would break when a network was disconnected and then reconnected ([#10052](https://github.com/containers/podman/issues/10052)). + +### API +- Fixed a bug where the Compat Create endpoint for Containers would fail to create containers with the `NetworkMode` parameter set to `default` ([#10569](https://github.com/containers/podman/issues/10569)). +- Fixed a bug where the Compat Create endpoint for Containers did not properly handle healthcheck commands ([#10617](https://github.com/containers/podman/issues/10617)). +- Fixed a bug where the Compat Wait endpoint for Containers would always send an empty string error message when no error occurred. +- Fixed a bug where the Compat List endpoint for Images omitted the `ContainerConfig` field ([#10795](https://github.com/containers/podman/issues/10795)). +- Fixed a bug where the Compat Pull endpoint for Images could fail, but return a 200 status code, if an image name that could not be parsed was provided. +- Fixed a bug where the Compat Pull endpoint for Images would continue to pull images after the client disconnected. +- Fixed a bug where the Compat List endpoint for Networks would fail for non-bridge (e.g. macvlan) networks ([#10266](https://github.com/containers/podman/issues/10266)). +- Fixed a bug where the Libpod List endpoint for Networks would return nil, instead of an empty list, when no networks were present ([#10495](https://github.com/containers/podman/issues/10495)). +- The Compat and Libpod Logs endpoints for Containers now support the `until` query parameter ([#10859](https://github.com/containers/podman/issues/10859)). +- The Compat Import endpoint for Images now supports the `platform`, `message`, and `repo` query parameters. +- The Compat Pull endpoint for Images now supports the `platform` query parameter. + +### Misc +- Updated Buildah to v1.22.0 +- Updated the containers/storage library to v1.33.1 +- Updated the containers/image library to v5.15.0 +- Updated the containers/common library to v0.42.1 + ## 3.2.3 ### Security - This release addresses CVE-2021-3602, an issue with the `podman build` command with the `--isolation chroot` flag that results in environment variables from the host leaking into build containers. -- cgit v1.2.3-54-g00ecf From cb7f0a3025437b6d00c4e4eca903f0452ba3d711 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Mon, 2 Aug 2021 16:33:33 -0400 Subject: Fix handling of user specified container labels Currently we override the SELinux labels specified by the user if the container is runing a kata container or systemd container. This PR fixes to use the label specified by the user. Fixes: https://github.com/containers/podman/issues/11100 Signed-off-by: Daniel J Walsh --- libpod/container_internal.go | 36 +++++++++++++++++++++++------------- test/system/410-selinux.bats | 12 ++++++++++++ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/libpod/container_internal.go b/libpod/container_internal.go index e7694227a..8ffcccf4c 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -472,20 +472,10 @@ func (c *Container) setupStorage(ctx context.Context) error { c.config.IDMappings.UIDMap = containerInfo.UIDMap c.config.IDMappings.GIDMap = containerInfo.GIDMap - processLabel := containerInfo.ProcessLabel - switch { - case c.ociRuntime.SupportsKVM(): - processLabel, err = selinux.KVMLabel(processLabel) - if err != nil { - return err - } - case c.config.Systemd: - processLabel, err = selinux.InitLabel(processLabel) - if err != nil { - return err - } + processLabel, err := c.processLabel(containerInfo.ProcessLabel) + if err != nil { + return err } - c.config.ProcessLabel = processLabel c.config.MountLabel = containerInfo.MountLabel c.config.StaticDir = containerInfo.Dir @@ -520,6 +510,26 @@ func (c *Container) setupStorage(ctx context.Context) error { return nil } +func (c *Container) processLabel(processLabel string) (string, error) { + if !c.config.Systemd && !c.ociRuntime.SupportsKVM() { + return processLabel, nil + } + ctrSpec, err := c.specFromState() + if err != nil { + return "", err + } + label, ok := ctrSpec.Annotations[define.InspectAnnotationLabel] + if !ok || !strings.Contains(label, "type:") { + switch { + case c.ociRuntime.SupportsKVM(): + return selinux.KVMLabel(processLabel) + case c.config.Systemd: + return selinux.InitLabel(processLabel) + } + } + return processLabel, nil +} + // Tear down a container's storage prior to removal func (c *Container) teardownStorage() error { if c.ensureState(define.ContainerStateRunning, define.ContainerStatePaused) { diff --git a/test/system/410-selinux.bats b/test/system/410-selinux.bats index 4ef9c8b30..5ee0e0715 100644 --- a/test/system/410-selinux.bats +++ b/test/system/410-selinux.bats @@ -50,6 +50,18 @@ function check_label() { check_label "--systemd=always" "container_init_t" } +@test "podman selinux: init container with --security-opt type" { + check_label "--systemd=always --security-opt=label=type:spc_t" "spc_t" +} + +@test "podman selinux: init container with --security-opt level&type" { + check_label "--systemd=always --security-opt=label=level:s0:c1,c2 --security-opt=label=type:spc_t" "spc_t" "s0:c1,c2" +} + +@test "podman selinux: init container with --security-opt level" { + check_label "--systemd=always --security-opt=label=level:s0:c1,c2" "container_init_t" "s0:c1,c2" +} + @test "podman selinux: pid=host" { # FIXME this test fails when run rootless with runc: # Error: container_linux.go:367: starting container process caused: process_linux.go:495: container init caused: readonly path /proc/asound: operation not permitted: OCI permission denied -- cgit v1.2.3-54-g00ecf From 870576b39e90cdbc029b116f9f6edecf09f56605 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 28 Jul 2021 16:52:22 +0200 Subject: test: move container process to a sub-cgroup move the container to a sub-cgroup before creating a sibling hierarchy. Signed-off-by: Giuseppe Scrivano --- test/e2e/run_cgroup_parent_test.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/test/e2e/run_cgroup_parent_test.go b/test/e2e/run_cgroup_parent_test.go index 300c3a8e0..3e261961b 100644 --- a/test/e2e/run_cgroup_parent_test.go +++ b/test/e2e/run_cgroup_parent_test.go @@ -2,6 +2,7 @@ package integration import ( "fmt" + "io/ioutil" "os" "path/filepath" "strings" @@ -80,7 +81,21 @@ var _ = Describe("Podman run with --cgroup-parent", func() { exec.WaitWithDefaultTimeout() Expect(exec).Should(Exit(0)) - cgroup := filepath.Dir(strings.TrimRight(strings.Replace(exec.OutputToString(), "0::", "", -1), "\n")) + containerCgroup := strings.TrimRight(strings.Replace(exec.OutputToString(), "0::", "", -1), "\n") + + content, err := ioutil.ReadFile(filepath.Join("/sys/fs/cgroup", containerCgroup, "cgroup.procs")) + Expect(err).To(BeNil()) + + // Move the container process to a sub cgroup + subCgroupPath := filepath.Join(filepath.Join("/sys/fs/cgroup", containerCgroup, "old-container")) + + err = os.MkdirAll(subCgroupPath, 0755) + Expect(err).To(BeNil()) + + err = ioutil.WriteFile(filepath.Join(subCgroupPath, "cgroup.procs"), content, 0644) + Expect(err).To(BeNil()) + + cgroup := filepath.Dir(containerCgroup) run = podmanTest.Podman([]string{"--cgroup-manager=cgroupfs", "run", "-d", fmt.Sprintf("--cgroup-parent=%s", cgroup), fedoraMinimal, "sleep", "100"}) run.WaitWithDefaultTimeout() -- cgit v1.2.3-54-g00ecf From 04e59f11d05f34c7cbb38cbc4918b69603e1f5e3 Mon Sep 17 00:00:00 2001 From: Ed Santiago Date: Tue, 3 Aug 2021 14:09:24 -0600 Subject: podman info: try qfile before equery podman info takes >20s on Gentoo, because equery is s..l..o..w. qfile is much faster and, I suspect, present in most Gentoo installations, so let's try it first. And, because packageVersion() was scarily unmaintainable, refactor it. Define a simple (string) list of packaging tools to query (rpm, dpkg, ...) and iterate until we find one that works. IMPORTANT NOTE: the Debian (and, presumably, Ubuntu) query does not include version number! There is no standard way on Debian to get a package version from a file path, you can only do it via pipes of chained commands, and I have no desire to implement that. Signed-off-by: Ed Santiago --- libpod/util.go | 39 ++++++++++++++------------------------- test/system/005-info.bats | 4 ++++ 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/libpod/util.go b/libpod/util.go index 7f4a01f28..3b32fb264 100644 --- a/libpod/util.go +++ b/libpod/util.go @@ -153,33 +153,22 @@ func queryPackageVersion(cmdArg ...string) string { return strings.Trim(output, "\n") } -func equeryVersion(path string) string { - return queryPackageVersion("/usr/bin/equery", "b", path) -} - -func pacmanVersion(path string) string { - return queryPackageVersion("/usr/bin/pacman", "-Qo", path) -} - -func dpkgVersion(path string) string { - return queryPackageVersion("/usr/bin/dpkg", "-S", path) -} - -func rpmVersion(path string) string { - return queryPackageVersion("/usr/bin/rpm", "-q", "-f", path) -} - -func packageVersion(program string) string { - if out := rpmVersion(program); out != unknownPackage { - return out - } - if out := dpkgVersion(program); out != unknownPackage { - return out +func packageVersion(program string) string { // program is full path + packagers := [][]string{ + {"/usr/bin/rpm", "-q", "-f"}, + {"/usr/bin/dpkg", "-S"}, // Debian, Ubuntu + {"/usr/bin/pacman", "-Qo"}, // Arch + {"/usr/bin/qfile", "-qv"}, // Gentoo (quick) + {"/usr/bin/equery", "b"}, // Gentoo (slow) } - if out := pacmanVersion(program); out != unknownPackage { - return out + + for _, cmd := range packagers { + cmd = append(cmd, program) + if out := queryPackageVersion(cmd...); out != unknownPackage { + return out + } } - return equeryVersion(program) + return unknownPackage } func programVersion(mountProgram string) (string, error) { diff --git a/test/system/005-info.bats b/test/system/005-info.bats index 4b419841e..50c3ceb30 100644 --- a/test/system/005-info.bats +++ b/test/system/005-info.bats @@ -33,12 +33,16 @@ cgroupVersion: v[12] expr_nvr="[a-z0-9-]\\\+-[a-z0-9.]\\\+-[a-z0-9]\\\+\." expr_path="/[a-z0-9\\\/.-]\\\+\\\$" + # FIXME: if we're ever able to get package versions on Debian, + # add '-[0-9]' to all '*.package' queries below. tests=" host.buildahVersion | [0-9.] host.conmon.path | $expr_path +host.conmon.package | .*conmon.* host.cgroupManager | \\\(systemd\\\|cgroupfs\\\) host.cgroupVersion | v[12] host.ociRuntime.path | $expr_path +host.ociRuntime.package | .*\\\(crun\\\|runc\\\).* store.configFile | $expr_path store.graphDriverName | [a-z0-9]\\\+\\\$ store.graphRoot | $expr_path -- cgit v1.2.3-54-g00ecf From c836ffe5bce748f215d0649f052df026fc6d8d62 Mon Sep 17 00:00:00 2001 From: Milivoje Legenovic Date: Tue, 3 Aug 2021 13:48:07 +0200 Subject: Compat API: Fix healthcheck status and healthcheck config Fixes: - Do not show healthcheck status if not available or if container status is "created" (Docker behaviour) - Show healthcheck configuration if present (Config.Healthcheck) Tests: - Ensure State.Health is not present if container status is "created" - Ensure Config.Healthcheck is present and values correct - Ensure State.Health is present if container started Signed-off-by: Milivoje Legenovic --- pkg/api/handlers/compat/containers.go | 45 ++++++++++++++-------- .../apiv2/python/rest_api/test_v2_0_0_container.py | 36 +++++++++++++---- 2 files changed, 58 insertions(+), 23 deletions(-) diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go index 2a0a0b725..95c09ff0e 100644 --- a/pkg/api/handlers/compat/containers.go +++ b/pkg/api/handlers/compat/containers.go @@ -403,22 +403,24 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON, state.Status = define.ContainerStateCreated.String() } - state.Health = &types.Health{ - Status: inspect.State.Healthcheck.Status, - FailingStreak: inspect.State.Healthcheck.FailingStreak, - } - - log := inspect.State.Healthcheck.Log + if l.HasHealthCheck() && state.Status != "created" { + state.Health = &types.Health{ + Status: inspect.State.Healthcheck.Status, + FailingStreak: inspect.State.Healthcheck.FailingStreak, + } - for _, item := range log { - res := &types.HealthcheckResult{} - s, _ := time.Parse(time.RFC3339Nano, item.Start) - e, _ := time.Parse(time.RFC3339Nano, item.End) - res.Start = s - res.End = e - res.ExitCode = item.ExitCode - res.Output = item.Output - state.Health.Log = append(state.Health.Log, res) + log := inspect.State.Healthcheck.Log + + for _, item := range log { + res := &types.HealthcheckResult{} + s, _ := time.Parse(time.RFC3339Nano, item.Start) + e, _ := time.Parse(time.RFC3339Nano, item.End) + res.Start = s + res.End = e + res.ExitCode = item.ExitCode + res.Output = item.Output + state.Health.Log = append(state.Health.Log, res) + } } formatCapabilities(inspect.HostConfig.CapDrop) @@ -495,6 +497,17 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON, exposedPorts[exposedPort] = struct{}{} } + var healthcheck *container.HealthConfig + if inspect.Config.Healthcheck != nil { + healthcheck = &container.HealthConfig{ + Test: inspect.Config.Healthcheck.Test, + Interval: inspect.Config.Healthcheck.Interval, + Timeout: inspect.Config.Healthcheck.Timeout, + StartPeriod: inspect.Config.Healthcheck.StartPeriod, + Retries: inspect.Config.Healthcheck.Retries, + } + } + config := container.Config{ Hostname: l.Hostname(), Domainname: inspect.Config.DomainName, @@ -508,7 +521,7 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON, StdinOnce: inspect.Config.StdinOnce, Env: inspect.Config.Env, Cmd: l.Command(), - Healthcheck: nil, + Healthcheck: healthcheck, ArgsEscaped: false, Image: imageName, Volumes: nil, diff --git a/test/apiv2/python/rest_api/test_v2_0_0_container.py b/test/apiv2/python/rest_api/test_v2_0_0_container.py index 30d902d8c..dbad6824f 100644 --- a/test/apiv2/python/rest_api/test_v2_0_0_container.py +++ b/test/apiv2/python/rest_api/test_v2_0_0_container.py @@ -36,26 +36,48 @@ class ContainerTestCase(APITestCase): r = requests.post( self.podman_url + "/v1.40/containers/create?name=topcontainer", - json={"Healthcheck": {"Test": ["CMD-SHELL", "exit 0"], "Interval":1000, "Timeout":1000, "Retries": 5}, "Cmd": ["top"], "Image": "alpine:latest"}, + json={"Cmd": ["top"], + "Image": "alpine:latest", + "Healthcheck": { + "Test": ["CMD", "pidof", "top"], + "Interval": 5000000000, + "Timeout": 2000000000, + "Retries": 3, + "StartPeriod": 5000000000 + } + }, ) self.assertEqual(r.status_code, 201, r.text) payload = r.json() container_id = payload["Id"] self.assertIsNotNone(container_id) - r = requests.get(self.podman_url + f"/v1.40/containers/{payload['Id']}/json") + r = requests.get(self.podman_url + f"/v1.40/containers/{container_id}/json") self.assertEqual(r.status_code, 200, r.text) self.assertId(r.content) out = r.json() - state = out["State"]["Health"] - self.assertIsInstance(state, dict) - - r = requests.get(self.uri(f"/containers/{payload['Id']}/json")) + self.assertIsNone(out["State"].get("Health")) + self.assertListEqual(["CMD", "pidof", "top"], out["Config"]["Healthcheck"]["Test"]) + self.assertEqual(5000000000, out["Config"]["Healthcheck"]["Interval"]) + self.assertEqual(2000000000, out["Config"]["Healthcheck"]["Timeout"]) + self.assertEqual(3, out["Config"]["Healthcheck"]["Retries"]) + self.assertEqual(5000000000, out["Config"]["Healthcheck"]["StartPeriod"]) + + r = requests.get(self.uri(f"/containers/{container_id}/json")) self.assertEqual(r.status_code, 200, r.text) self.assertId(r.content) out = r.json() hc = out["Config"]["Healthcheck"]["Test"] - self.assertListEqual(["CMD-SHELL", "exit 0"], hc) + self.assertListEqual(["CMD", "pidof", "top"], hc) + + r = requests.post(self.podman_url + f"/v1.40/containers/{container_id}/start") + self.assertEqual(r.status_code, 204, r.text) + + r = requests.get(self.podman_url + f"/v1.40/containers/{container_id}/json") + self.assertEqual(r.status_code, 200, r.text) + out = r.json() + state = out["State"]["Health"] + self.assertIsInstance(state, dict) def test_stats(self): r = requests.get(self.uri(self.resolve_container("/containers/{}/stats?stream=false"))) -- cgit v1.2.3-54-g00ecf From a82006160e6abbddc62f28999bca8865e5ea4806 Mon Sep 17 00:00:00 2001 From: Jhon Honce Date: Mon, 2 Aug 2021 15:18:54 -0700 Subject: Only support containers stats using cgroups v2 Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1988252 Signed-off-by: Jhon Honce --- pkg/api/handlers/libpod/containers_stats.go | 12 ++++++++++++ pkg/api/server/register_containers.go | 4 ++++ test/apiv2/20-containers.at | 10 ++++++++++ 3 files changed, 26 insertions(+) diff --git a/pkg/api/handlers/libpod/containers_stats.go b/pkg/api/handlers/libpod/containers_stats.go index 75c404d4f..22faab71f 100644 --- a/pkg/api/handlers/libpod/containers_stats.go +++ b/pkg/api/handlers/libpod/containers_stats.go @@ -7,8 +7,10 @@ import ( "github.com/containers/podman/v3/libpod" "github.com/containers/podman/v3/pkg/api/handlers/utils" + "github.com/containers/podman/v3/pkg/cgroups" "github.com/containers/podman/v3/pkg/domain/entities" "github.com/containers/podman/v3/pkg/domain/infra/abi" + "github.com/containers/podman/v3/pkg/rootless" "github.com/gorilla/schema" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -20,6 +22,16 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) decoder := r.Context().Value("decoder").(*schema.Decoder) + // Check if service is running rootless (cheap check) + if rootless.IsRootless() { + // if so, then verify cgroup v2 available (more expensive check) + if isV2, _ := cgroups.IsCgroup2UnifiedMode(); !isV2 { + msg := "Container stats resource only available for cgroup v2" + utils.Error(w, msg, http.StatusConflict, errors.New(msg)) + return + } + } + query := struct { Containers []string `schema:"containers"` Stream bool `schema:"stream"` diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go index 50e059ecc..89de84cce 100644 --- a/pkg/api/server/register_containers.go +++ b/pkg/api/server/register_containers.go @@ -1085,6 +1085,8 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { // description: no error // 404: // $ref: "#/responses/NoSuchContainer" + // 409: + // $ref: "#/responses/ConflictError" // 500: // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/{name}/stats"), s.APIHandler(compat.StatsContainer)).Methods(http.MethodGet) @@ -1113,6 +1115,8 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { // description: no error // 404: // $ref: "#/responses/NoSuchContainer" + // 409: + // $ref: "#/responses/ConflictError" // 500: // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/libpod/containers/stats"), s.APIHandler(libpod.StatsContainer)).Methods(http.MethodGet) diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at index c5b2f5ec1..610d3e36d 100644 --- a/test/apiv2/20-containers.at +++ b/test/apiv2/20-containers.at @@ -65,6 +65,16 @@ t GET libpod/containers/json?last=1 200 \ cid=$(jq -r '.[0].Id' <<<"$output") +if root; then + t GET libpod/containers/stats?containers='[$cid]' 200 +else + if have_cgroupsv2; then + t GET libpod/containers/stats?containers='[$cid]' 200 + else + t GET libpod/containers/stats?containers='[$cid]' 409 + fi +fi + t DELETE libpod/containers/$cid 204 # Issue #6799: it should be possible to start a container, even w/o args. -- cgit v1.2.3-54-g00ecf From a1afb2300f1a65a4213753c587ba8a7d66755423 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Tue, 3 Aug 2021 14:07:28 -0400 Subject: Do not add an entry to /etc/hosts with `--net=host` To match Docker's behavior, in the `--net=host` case, we need to use the host's `/etc/hosts` file, unmodified (without adding an entry for the container). We will still respect hosts from `--add-host` but will not make any automatic changes. Fortuntely, this is strictly a matter of removal and refactoring as we already base our `/etc/hosts` on the host's version - just need to remove the code that added entries when net=host was set. Fixes #10319 Signed-off-by: Matthew Heon --- libpod/container_internal_linux.go | 38 ++++++++++++++++++-------------------- test/e2e/run_networking_test.go | 11 ----------- 2 files changed, 18 insertions(+), 31 deletions(-) diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index bff64aa95..f30f622ac 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -1912,6 +1912,7 @@ func (c *Container) appendHosts(path string, netCtr *Container) (string, error) // and returns a string in a format that can be written to the host file func (c *Container) getHosts() string { var hosts string + if len(c.config.HostAdd) > 0 { for _, host := range c.config.HostAdd { // the host format has already been verified at this point @@ -1922,36 +1923,33 @@ func (c *Container) getHosts() string { hosts += c.cniHosts() - // If not making a network namespace, add our own hostname. + // Add hostname for slirp4netns if c.Hostname() != "" { if c.config.NetMode.IsSlirp4netns() { // When using slirp4netns, the interface gets a static IP slirp4netnsIP, err := GetSlirp4netnsIP(c.slirp4netnsSubnet) if err != nil { - logrus.Warn("failed to determine slirp4netnsIP: ", err.Error()) + logrus.Warnf("failed to determine slirp4netnsIP: %v", err.Error()) } else { hosts += fmt.Sprintf("# used by slirp4netns\n%s\t%s %s\n", slirp4netnsIP.String(), c.Hostname(), c.config.Name) } - } else { - hasNetNS := false - netNone := false - for _, ns := range c.config.Spec.Linux.Namespaces { - if ns.Type == spec.NetworkNamespace { - hasNetNS = true - if ns.Path == "" && !c.config.CreateNetNS { - netNone = true - } - break + } + + // Do we have a network namespace? + netNone := false + for _, ns := range c.config.Spec.Linux.Namespaces { + if ns.Type == spec.NetworkNamespace { + if ns.Path == "" && !c.config.CreateNetNS { + netNone = true } + break } - if !hasNetNS { - // 127.0.1.1 and host's hostname to match Docker - osHostname, _ := os.Hostname() - hosts += fmt.Sprintf("127.0.1.1 %s %s %s\n", osHostname, c.Hostname(), c.config.Name) - } - if netNone { - hosts += fmt.Sprintf("127.0.1.1 %s %s\n", c.Hostname(), c.config.Name) - } + } + + // If we are net=none (have a network namespace, but not connected to + // anything) add the container's name and hostname to localhost. + if netNone { + hosts += fmt.Sprintf("127.0.0.1 %s %s\n", c.Hostname(), c.config.Name) } } diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go index 80a82ea05..92388b099 100644 --- a/test/e2e/run_networking_test.go +++ b/test/e2e/run_networking_test.go @@ -685,13 +685,6 @@ var _ = Describe("Podman run networking", func() { Expect(podrm).Should(Exit(0)) }) - It("podman run net=host adds entry to /etc/hosts", func() { - run := podmanTest.Podman([]string{"run", "--net=host", ALPINE, "cat", "/etc/hosts"}) - run.WaitWithDefaultTimeout() - Expect(run).Should(Exit(0)) - Expect(strings.Contains(run.OutputToString(), "127.0.1.1")).To(BeTrue()) - }) - It("podman run with --net=host and --hostname sets correct hostname", func() { hostname := "testctr" run := podmanTest.Podman([]string{"run", "--net=host", "--hostname", hostname, ALPINE, "hostname"}) @@ -731,10 +724,6 @@ var _ = Describe("Podman run networking", func() { ping_test("--net=none") }) - It("podman attempt to ping container name and hostname --net=host", func() { - ping_test("--net=host") - }) - It("podman attempt to ping container name and hostname --net=private", func() { ping_test("--net=private") }) -- cgit v1.2.3-54-g00ecf From 67bf11e8c8418d06528bf16b184f77e99a738d05 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Tue, 3 Aug 2021 09:02:18 -0400 Subject: Fix podman unpause,pause,kill --all to work like podman stop --all Currently if you execute podman unpause --all, podman pause --all Podman shows attempts to unpause containers that are not paused and prints an error. This PR catches this error and only prints errors if a paused container was not able to be unpaused. Currently if you execute podman pause --all or podman kill --all, Podman Podman shows attempts to pause or kill containers that are not running and prints an error. This PR catches this error and only prints errors if a running container was not able to be paused or killed. Also change printing of multiple errors to go to stderr and to prefix "Error: " in front to match the output of the last error. Fixes: https://github.com/containers/podman/issues/11098 Signed-off-by: Daniel J Walsh --- cmd/podman/utils/error.go | 7 +++++-- pkg/domain/infra/abi/containers.go | 15 ++++++++++++++- pkg/domain/infra/tunnel/containers.go | 17 +++++++++++++++-- test/system/080-pause.bats | 19 +++++++++++++++++++ 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/cmd/podman/utils/error.go b/cmd/podman/utils/error.go index 3464f0779..2d58bc70d 100644 --- a/cmd/podman/utils/error.go +++ b/cmd/podman/utils/error.go @@ -1,6 +1,9 @@ package utils -import "fmt" +import ( + "fmt" + "os" +) type OutputErrors []error @@ -10,7 +13,7 @@ func (o OutputErrors) PrintErrors() (lastError error) { } lastError = o[len(o)-1] for e := 0; e < len(o)-1; e++ { - fmt.Println(o[e]) + fmt.Fprintf(os.Stderr, "Error: %s\n", o[e]) } return } diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index 2003879b8..33cd69b8a 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -119,6 +119,10 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri report := make([]*entities.PauseUnpauseReport, 0, len(ctrs)) for _, c := range ctrs { err := c.Pause() + if err != nil && options.All && errors.Cause(err) == define.ErrCtrStateInvalid { + logrus.Debugf("Container %s is not running", c.ID()) + continue + } report = append(report, &entities.PauseUnpauseReport{Id: c.ID(), Err: err}) } return report, nil @@ -132,6 +136,10 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st report := make([]*entities.PauseUnpauseReport, 0, len(ctrs)) for _, c := range ctrs { err := c.Unpause() + if err != nil && options.All && errors.Cause(err) == define.ErrCtrStateInvalid { + logrus.Debugf("Container %s is not paused", c.ID()) + continue + } report = append(report, &entities.PauseUnpauseReport{Id: c.ID(), Err: err}) } return report, nil @@ -220,9 +228,14 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin } reports := make([]*entities.KillReport, 0, len(ctrs)) for _, con := range ctrs { + err := con.Kill(uint(sig)) + if options.All && errors.Cause(err) == define.ErrCtrStateInvalid { + logrus.Debugf("Container %s is not running", con.ID()) + continue + } reports = append(reports, &entities.KillReport{ Id: con.ID(), - Err: con.Kill(uint(sig)), + Err: err, RawInput: ctrMap[con.ID()], }) } diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index 58f9c5fb0..1b01fa2ec 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -63,19 +63,27 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs)) for _, c := range ctrs { err := containers.Pause(ic.ClientCtx, c.ID, nil) + if err != nil && options.All && errors.Cause(err).Error() == define.ErrCtrStateInvalid.Error() { + logrus.Debugf("Container %s is not running", c.ID) + continue + } reports = append(reports, &entities.PauseUnpauseReport{Id: c.ID, Err: err}) } return reports, nil } func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) { + reports := []*entities.PauseUnpauseReport{} ctrs, err := getContainersByContext(ic.ClientCtx, options.All, false, namesOrIds) if err != nil { return nil, err } - reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs)) for _, c := range ctrs { err := containers.Unpause(ic.ClientCtx, c.ID, nil) + if err != nil && options.All && errors.Cause(err).Error() == define.ErrCtrStateInvalid.Error() { + logrus.Debugf("Container %s is not paused", c.ID) + continue + } reports = append(reports, &entities.PauseUnpauseReport{Id: c.ID, Err: err}) } return reports, nil @@ -136,9 +144,14 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin options := new(containers.KillOptions).WithSignal(opts.Signal) reports := make([]*entities.KillReport, 0, len(ctrs)) for _, c := range ctrs { + err := containers.Kill(ic.ClientCtx, c.ID, options) + if err != nil && opts.All && errors.Cause(err).Error() == define.ErrCtrStateInvalid.Error() { + logrus.Debugf("Container %s is not running", c.ID) + continue + } reports = append(reports, &entities.KillReport{ Id: c.ID, - Err: containers.Kill(ic.ClientCtx, c.ID, options), + Err: err, RawInput: ctrMap[c.ID], }) } diff --git a/test/system/080-pause.bats b/test/system/080-pause.bats index ea4c85f8f..1eb47dcfb 100644 --- a/test/system/080-pause.bats +++ b/test/system/080-pause.bats @@ -57,4 +57,23 @@ load helpers run_podman 125 unpause $cname } +@test "podman unpause --all" { + if is_rootless && ! is_cgroupsv2; then + skip "'podman pause' (rootless) only works with cgroups v2" + fi + + cname=$(random_string 10) + run_podman create --name notrunning $IMAGE + run_podman run -d --name $cname $IMAGE sleep 100 + cid="$output" + run_podman pause $cid + run_podman inspect --format '{{.State.Status}}' $cid + is "$output" "paused" "podman inspect .State.Status" + run_podman unpause --all + is "$output" "$cid" "podman unpause output" + run_podman ps --format '{{.ID}} {{.Names}} {{.Status}}' + is "$output" "${cid:0:12} $cname Up.*" "podman ps on resumed container" + run_podman rm -f $cname + run_podman rm -f notrunning +} # vim: filetype=sh -- cgit v1.2.3-54-g00ecf From 85d5c24ede45d5455d8ddad4ac8c1b714ce2b14a Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Wed, 4 Aug 2021 07:38:22 -0400 Subject: Handle timezone on server containers.conf Fixes: https://github.com/containers/podman/issues/11124 Signed-off-by: Daniel J Walsh Signed-off-by: Daniel J Walsh Signed-off-by: Daniel J Walsh --- libpod/runtime_ctr.go | 4 ++++ test/e2e/containers_conf_test.go | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 31e2d09ce..059f56798 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -353,6 +353,10 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai } } + if ctr.config.Timezone == "" { + ctr.config.Timezone = r.config.Containers.TZ + } + if ctr.restoreFromCheckpoint { // Remove information about bind mount // for new container from imported checkpoint diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go index 3349b8be3..08fc4e6cc 100644 --- a/test/e2e/containers_conf_test.go +++ b/test/e2e/containers_conf_test.go @@ -261,10 +261,16 @@ var _ = Describe("Podman run", func() { It("podman run containers.conf timezone", func() { //containers.conf timezone set to Pacific/Honolulu - session := podmanTest.Podman([]string{"run", ALPINE, "date", "+'%H %Z'"}) + session := podmanTest.Podman([]string{"run", "--tz", "", ALPINE, "date", "+'%H %Z'"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.OutputToString()).To(ContainSubstring("HST")) + + // verify flag still overrides + session = podmanTest.Podman([]string{"run", "--tz", "EST", ALPINE, "date", "+'%H %Z'"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(ContainSubstring("EST")) }) It("podman run containers.conf umask", func() { -- cgit v1.2.3-54-g00ecf From 4b42265b520238ecb30059430011e63fabdd23d2 Mon Sep 17 00:00:00 2001 From: Matej Vasek Date: Wed, 4 Aug 2021 21:30:47 +0200 Subject: Fix TS parsing for fractional values Parse Unix timestamps that contains fractional part. Signed-off-by: Matej Vasek --- pkg/util/utils.go | 6 ++++-- pkg/util/utils_test.go | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 60aa64ac1..774590f44 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -3,6 +3,7 @@ package util import ( "encoding/json" "fmt" + "math" "os" "os/user" "path/filepath" @@ -530,9 +531,10 @@ func ParseInputTime(inputTime string) (time.Time, error) { } } - unixTimestamp, err := strconv.ParseInt(inputTime, 10, 64) + unixTimestamp, err := strconv.ParseFloat(inputTime, 64) if err == nil { - return time.Unix(unixTimestamp, 0), nil + iPart, fPart := math.Modf(unixTimestamp) + return time.Unix(int64(iPart), int64(fPart*1_000_000_000)).UTC(), nil } // input might be a duration diff --git a/pkg/util/utils_test.go b/pkg/util/utils_test.go index cb737bd76..027acbdab 100644 --- a/pkg/util/utils_test.go +++ b/pkg/util/utils_test.go @@ -2,6 +2,7 @@ package util import ( "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -277,3 +278,17 @@ func TestPeriodAndQuotaToCores(t *testing.T) { assert.Equal(t, PeriodAndQuotaToCores(period, quota), expectedCores) } + +func TestParseInputTime(t *testing.T) { + tm, err := ParseInputTime("1.5") + if err != nil { + t.Errorf("expected error to be nil but was: %v", err) + } + + expected, err := time.ParseInLocation(time.RFC3339Nano, "1970-01-01T00:00:01.500000000Z", time.UTC) + if err != nil { + t.Fatal(err) + } + + assert.Equal(t, expected, tm) +} -- cgit v1.2.3-54-g00ecf From d746a7e0938a5e3b8dde64826961ef9259db7447 Mon Sep 17 00:00:00 2001 From: Brent Baude Date: Wed, 4 Aug 2021 15:19:29 -0500 Subject: show podman machine ssh command line A user contributed a one line PR that enabled logging the podman machine ssh command for debug. The user was not able to complete the submission so this PR replaces that. [NO TESTS NEEDED] Replaces #10798 Signed-off-by: Brent Baude --- pkg/machine/qemu/machine.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 42ae23c43..9cb04ff0a 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -482,6 +482,8 @@ func (v *MachineVM) SSH(name string, opts machine.SSHOptions) error { } cmd := exec.Command("ssh", args...) + logrus.Debugf("Executing: ssh %v\n", args) + cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Stdin = os.Stdin -- cgit v1.2.3-54-g00ecf From 66c0024a0b7975fc88dd1f457151ce925acdee8a Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Mon, 9 Aug 2021 12:43:30 +0200 Subject: podman info show correct slirp4netns path The slirp4netns path can be set in the config file or with --network-cmd-path. Podman info should read the version information correctly and not use PATH in this case. Also show the slirp4netns version information to root users. Signed-off-by: Paul Holzinger --- libpod/info.go | 29 +++++++++++++++++------------ test/system/005-info.bats | 1 + 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/libpod/info.go b/libpod/info.go index cdc73780f..2b48ea590 100644 --- a/libpod/info.go +++ b/libpod/info.go @@ -141,19 +141,24 @@ func (r *Runtime) hostInfo() (*define.HostInfo, error) { } info.CGroupsVersion = cgroupVersion - if rootless.IsRootless() { - if path, err := exec.LookPath("slirp4netns"); err == nil { - version, err := programVersion(path) - if err != nil { - logrus.Warnf("Failed to retrieve program version for %s: %v", path, err) - } - program := define.SlirpInfo{ - Executable: path, - Package: packageVersion(path), - Version: version, - } - info.Slirp4NetNS = program + slirp4netnsPath := r.config.Engine.NetworkCmdPath + if slirp4netnsPath == "" { + slirp4netnsPath, _ = exec.LookPath("slirp4netns") + } + if slirp4netnsPath != "" { + version, err := programVersion(slirp4netnsPath) + if err != nil { + logrus.Warnf("Failed to retrieve program version for %s: %v", slirp4netnsPath, err) + } + program := define.SlirpInfo{ + Executable: slirp4netnsPath, + Package: packageVersion(slirp4netnsPath), + Version: version, } + info.Slirp4NetNS = program + } + + if rootless.IsRootless() { uidmappings, err := rootless.ReadMappingsProc("/proc/self/uid_map") if err != nil { return nil, errors.Wrapf(err, "error reading uid mappings") diff --git a/test/system/005-info.bats b/test/system/005-info.bats index 50c3ceb30..96ca2c1bd 100644 --- a/test/system/005-info.bats +++ b/test/system/005-info.bats @@ -47,6 +47,7 @@ store.configFile | $expr_path store.graphDriverName | [a-z0-9]\\\+\\\$ store.graphRoot | $expr_path store.imageStore.number | 1 +host.slirp4netns.executable | $expr_path " parse_table "$tests" | while read field expect; do -- cgit v1.2.3-54-g00ecf From f9f315c7540e327a41ab5715ee6a1e0d349e42c0 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Tue, 10 Aug 2021 11:43:17 +0200 Subject: Document source ip for the rootlesskit port handler Also add some missing options to podman pod create. Fixes #10884 Signed-off-by: Paul Holzinger --- docs/source/markdown/podman-create.1.md | 17 +++++++++-------- docs/source/markdown/podman-pod-create.1.md | 14 +++++++++----- docs/source/markdown/podman-run.1.md | 17 +++++++++-------- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 7f9cf0e75..218c098fa 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -646,13 +646,13 @@ Set the network mode for the container. Invalid if using **--dns**, **--dns-opt* Valid _mode_ values are: -- **bridge**: create a network stack on the default bridge; -- **none**: no networking; -- **container:**_id_: reuse another container's network stack; -- **host**: use the Podman host network stack. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure; -- _network-id_: connect to a user-defined network, multiple networks should be comma-separated; -- **ns:**_path_: path to a network namespace to join; -- **private**: create a new namespace for the container (default) +- **bridge**: Create a network stack on the default bridge. This is the default for rootfull containers. +- **none**: Create a network namespace for the container but do not configure network interfaces for it, thus the container has no network connectivity. +- **container:**_id_: Reuse another container's network stack. +- **host**: Do not create a network namespace, the container will use the host's network. Note: The host mode gives the container full access to local system services such as D-bus and is therefore considered insecure. +- **network**: Connect to a user-defined network, multiple networks should be comma-separated. +- **ns:**_path_: Path to a network namespace to join. +- **private**: Create a new namespace for the container. This will use the **bridge** mode for rootfull containers and **slirp4netns** for rootless ones. - **slirp4netns[:OPTIONS,...]**: use **slirp4netns**(1) to create a user network stack. This is the default for rootless containers. It is possible to specify these additional options: - **allow_host_loopback=true|false**: Allow the slirp4netns to reach the host loopback IP (`10.0.2.2`, which is added to `/etc/hosts` as `host.containers.internal` for your convenience). Default is false. - **mtu=MTU**: Specify the MTU to use for this network. (Default is `65520`). @@ -663,7 +663,8 @@ Valid _mode_ values are: - **outbound_addr6=INTERFACE**: Specify the outbound interface slirp should bind to (ipv6 traffic only). - **outbound_addr6=IPv6**: Specify the outbound ipv6 address slirp should bind to. - **port_handler=rootlesskit**: Use rootlesskit for port forwarding. Default. - - **port_handler=slirp4netns**: Use the slirp4netns port forwarding. + Note: Rootlesskit changes the source IP address of incoming packets to a IP address in the container network namespace, usually `10.0.2.100`. If your application requires the real source IP address, e.g. web server logs, use the slirp4netns port handler. The rootlesskit port handler is also used for rootless containers when connected to user-defined networks. + - **port_handler=slirp4netns**: Use the slirp4netns port forwarding, it is slower than rootlesskit but preserves the correct source IP address. This port handler cannot be used for user-defined networks. #### **--network-alias**=*alias* diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md index 441995cb6..d825c4b0a 100644 --- a/docs/source/markdown/podman-pod-create.1.md +++ b/docs/source/markdown/podman-pod-create.1.md @@ -101,12 +101,15 @@ Assign a name to the pod. #### **--network**=*mode*, **--net** -Set network mode for the pod. Supported values are +Set network mode for the pod. Supported values are: - **bridge**: Create a network stack on the default bridge. This is the default for rootfull containers. +- **none**: Create a network namespace for the container but do not configure network interfaces for it, thus the container has no network connectivity. - **host**: Do not create a network namespace, all containers in the pod will use the host's network. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure. -- Comma-separated list of the names of CNI networks the pod should join. -- **slirp4netns[:OPTIONS,...]**: use slirp4netns to create a user network stack. This is the default for rootless containers. It is possible to specify these additional options: - - **allow_host_loopback=true|false**: Allow the slirp4netns to reach the host loopback IP (`10.0.2.2`). Default is false. +- **network**: Connect to a user-defined network, multiple networks should be comma-separated. +- **private**: Create a new namespace for the container. This will use the **bridge** mode for rootfull containers and **slirp4netns** for rootless ones. +- **slirp4netns[:OPTIONS,...]**: use **slirp4netns**(1) to create a user network stack. This is the default for rootless containers. It is possible to specify these additional options: + - **allow_host_loopback=true|false**: Allow the slirp4netns to reach the host loopback IP (`10.0.2.2`, which is added to `/etc/hosts` as `host.containers.internal` for your convenience). Default is false. + - **mtu=MTU**: Specify the MTU to use for this network. (Default is `65520`). - **cidr=CIDR**: Specify ip range to use for this network. (Default is `10.0.2.0/24`). - **enable_ipv6=true|false**: Enable IPv6. Default is false. (Required for `outbound_addr6`). - **outbound_addr=INTERFACE**: Specify the outbound interface slirp should bind to (ipv4 traffic only). @@ -114,7 +117,8 @@ Set network mode for the pod. Supported values are - **outbound_addr6=INTERFACE**: Specify the outbound interface slirp should bind to (ipv6 traffic only). - **outbound_addr6=IPv6**: Specify the outbound ipv6 address slirp should bind to. - **port_handler=rootlesskit**: Use rootlesskit for port forwarding. Default. - - **port_handler=slirp4netns**: Use the slirp4netns port forwarding. + Note: Rootlesskit changes the source IP address of incoming packets to a IP address in the container network namespace, usually `10.0.2.100`. If your application requires the real source IP address, e.g. web server logs, use the slirp4netns port handler. The rootlesskit port handler is also used for rootless containers when connected to user-defined networks. + - **port_handler=slirp4netns**: Use the slirp4netns port forwarding, it is slower than rootlesskit but preserves the correct source IP address. This port handler cannot be used for user-defined networks. #### **--network-alias**=strings diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index f08561904..bc2788457 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -680,13 +680,13 @@ Set the network mode for the container. Invalid if using **--dns**, **--dns-opt* Valid _mode_ values are: -- **bridge**: create a network stack on the default bridge; -- **none**: no networking; -- **container:**_id_: reuse another container's network stack; -- **host**: use the Podman host network stack. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure; -- _network-id_: connect to a user-defined network, multiple networks should be comma-separated; -- **ns:**_path_: path to a network namespace to join; -- **private**: create a new namespace for the container (default) +- **bridge**: Create a network stack on the default bridge. This is the default for rootfull containers. +- **none**: Create a network namespace for the container but do not configure network interfaces for it, thus the container has no network connectivity. +- **container:**_id_: Reuse another container's network stack. +- **host**: Do not create a network namespace, the container will use the host's network. Note: The host mode gives the container full access to local system services such as D-bus and is therefore considered insecure. +- **network**: Connect to a user-defined network, multiple networks should be comma-separated. +- **ns:**_path_: Path to a network namespace to join. +- **private**: Create a new namespace for the container. This will use the **bridge** mode for rootfull containers and **slirp4netns** for rootless ones. - **slirp4netns[:OPTIONS,...]**: use **slirp4netns**(1) to create a user network stack. This is the default for rootless containers. It is possible to specify these additional options: - **allow_host_loopback=true|false**: Allow the slirp4netns to reach the host loopback IP (`10.0.2.2`, which is added to `/etc/hosts` as `host.containers.internal` for your convenience). Default is false. - **mtu=MTU**: Specify the MTU to use for this network. (Default is `65520`). @@ -697,7 +697,8 @@ Valid _mode_ values are: - **outbound_addr6=INTERFACE**: Specify the outbound interface slirp should bind to (ipv6 traffic only). - **outbound_addr6=IPv6**: Specify the outbound ipv6 address slirp should bind to. - **port_handler=rootlesskit**: Use rootlesskit for port forwarding. Default. - - **port_handler=slirp4netns**: Use the slirp4netns port forwarding. + Note: Rootlesskit changes the source IP address of incoming packets to a IP address in the container network namespace, usually `10.0.2.100`. If your application requires the real source IP address, e.g. web server logs, use the slirp4netns port handler. The rootlesskit port handler is also used for rootless containers when connected to user-defined networks. + - **port_handler=slirp4netns**: Use the slirp4netns port forwarding, it is slower than rootlesskit but preserves the correct source IP address. This port handler cannot be used for user-defined networks. #### **--network-alias**=*alias* -- cgit v1.2.3-54-g00ecf From e63753afd686164d3c039fe2ec75ed63772257d0 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Tue, 10 Aug 2021 21:09:29 -0400 Subject: Final release notes for v3.3.0-RC2 Signed-off-by: Matthew Heon --- RELEASE_NOTES.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index a348b494b..02e554545 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -40,6 +40,7 @@ - The output of `podman system connection list` is now deterministic, with connections being sorted alpabetically by their name. - The auto-update service (`podman-auto-update.service`) has had its default timer adjusted so it now starts at a random time up to 15 minutes after midnight, to help prevent system congestion from numerous daily services run at once. - Systemd unit files generated by `podman generate systemd` now depend on `network-online.target` by default ([#10655](https://github.com/containers/podman/issues/10655)). +- The `podman info` command's logic for detecting package versions on Gentoo has been improved, and should be significantly faster. ### Bugfixes - Fixed a bug where the `podman play kube` command did not perform SELinux relabelling of volumes specified with a `mountPath` that included the `:z` or `:Z` options ([#9371](https://github.com/containers/podman/issues/9371)). @@ -55,6 +56,7 @@ - Fixed a bug where the `podman system service` command would leave zombie processes after its initial launch that were not cleaned up until it exited ([#10575](https://github.com/containers/podman/issues/10575)). - Fixed a bug where VMs created by `podman machine` could not be started after the host system restarted ([#10824](https://github.com/containers/podman/issues/10824)). - Fixed a bug where the `podman pod ps` command would not show headers for optional information (e.g. container names when the `--ctr-names` option was given). +- Fixed a bug where the remote Podman client's `podman create` and `podman run` commands would ignore timezone configuration from the server's `containers.conf` file ([#11124](https://github.com/containers/podman/issues/11124)). - Fixed a bug where the remote Podman client's `podman build` command would only respect `.containerignore` and not `.dockerignore` files (when both are present, `.containerignore` will be preferred) ([#10907](https://github.com/containers/podman/issues/10907)). - Fixed a bug where the remote Podman client's `podman build` command would fail to send the Dockerfile being built to the server when it was excluded by the `.dockerignore` file, resulting in an error ([#9867](https://github.com/containers/podman/issues/9867)). - Fixed a bug where the remote Podman client's `podman build` command could unexpectedly stop streaming the output of the build ([#10154](https://github.com/containers/podman/issues/10154)). @@ -70,11 +72,18 @@ - Fixed a bug where operations that pruned images (`podman image prune` and `podman system prune`) would prune untagged images with children ([#10832](https://github.com/containers/podman/issues/10832)). - Fixed a bug where dual-stack networks created by `podman network create` did not properly auto-assign an IPv4 subnet when one was not explicitly specified ([#11032](https://github.com/containers/podman/issues/11032)). - Fixed a bug where port forwarding using the `rootlessport` port forwarder would break when a network was disconnected and then reconnected ([#10052](https://github.com/containers/podman/issues/10052)). +- Fixed a bug where Podman would ignore user-specified SELinux policies for containers using the Kata OCI runtime, or containers using systemd as PID 1 ([#11100](https://github.com/containers/podman/issues/11100)). +- Fixed a bug where Podman containers created using `--net=host` would add an entry to `/etc/hosts` for the container's hostname pointing to `127.0.1.1` ([#10319](https://github.com/containers/podman/issues/10319)). +- Fixed a bug where the `podman unpause --all` command would throw an error for every container that was not paused ([#11098](https://github.com/containers/podman/issues/11098)). +- Fixed a bug where timestamps for the `since` and `until` filters using Unix timestamps with a nanoseconds portion could not be parsed ([#11131](https://github.com/containers/podman/issues/11131)). +- Fixed a bug where the `podman info` command would sometimes print the wrong path for the `slirp4netns` binary. ### API +- Fixed a bug where the Compat List endpoint for Containers included healthcheck information for all containers, even those that did not have a configured healthcheck. - Fixed a bug where the Compat Create endpoint for Containers would fail to create containers with the `NetworkMode` parameter set to `default` ([#10569](https://github.com/containers/podman/issues/10569)). - Fixed a bug where the Compat Create endpoint for Containers did not properly handle healthcheck commands ([#10617](https://github.com/containers/podman/issues/10617)). - Fixed a bug where the Compat Wait endpoint for Containers would always send an empty string error message when no error occurred. +- Fixed a bug where the Libpod Stats endpoint for Containers would not error when run on rootless containers on cgroups v1 systems (nonsensical results would be returned, as this configuration cannot be supportable). - Fixed a bug where the Compat List endpoint for Images omitted the `ContainerConfig` field ([#10795](https://github.com/containers/podman/issues/10795)). - Fixed a bug where the Compat Pull endpoint for Images could fail, but return a 200 status code, if an image name that could not be parsed was provided. - Fixed a bug where the Compat Pull endpoint for Images would continue to pull images after the client disconnected. -- cgit v1.2.3-54-g00ecf From 61a5e981276cca57d604108d19bcfa1beae2f271 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Wed, 11 Aug 2021 09:17:18 -0400 Subject: Address review comments Signed-off-by: Matthew Heon --- RELEASE_NOTES.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 02e554545..d74ac6cfe 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -17,8 +17,9 @@ - The `podman stats` command now provides two additional metrics: Average CPU, and CPU time. - The `podman pod create` command supports a new flag, `--pid`, to specify the PID namespace of the pod. If specified, containers that join the pod will automatically share its PID namespace. - The `podman pod create` command supports a new flag, `--infra-name`, which allows the name of the pod's infra container to be set ([#10794](https://github.com/containers/podman/issues/10794)). -- The `podman auto-update` command has had its output reformatted - it is now much more clear what images were pulled and what containers wer0e updated. +- The `podman auto-update` command has had its output reformatted - it is now much clearer what images were pulled and what containers were updated. - The `podman auto-update` command now supports a new option, `--dry-run`, which reports what would be updated but does not actually perform the update ([#9949](https://github.com/containers/podman/issues/9949)). +- The `podman build` command now supports a new option, `--secret`, to mount secrets into build containers. - The `podman manifest remove` command now has a new alias, `podman manifest rm`. - The `podman login` command now supports a new option, `--verbose`, to print detailed information about where the credentials entered were stored. - The `podman events` command now supports a new event, `exec_died`, which is produced when an exec session exits, and includes the exit code of the exec session. @@ -35,8 +36,8 @@ - The `podman system reset` command now removes non-Podman (e.g. Buildah and CRI-O) containers as well. - The new port forwarding offered by `podman machine` requires [gvproxy](https://github.com/containers/gvisor-tap-vsock) in order to function. - Podman will now automatically create the default CNI network if it does not exist, for both root and rootless users. This will only be done once per user - if the network is subsequently removed, it will not be recreated. +- The `install.cni` makefile option has been removed. It is no longer required to distribute the default `87-podman.conflist` CNI configuration file, as Podman will now automatically create it. - The `--root` option to Podman will not automatically clear all default storage options when set. Storage options can be set manually using `--storage-opt` ([#10393](https://github.com/containers/podman/issues/10393)). -- The `install.cni` makefile option has been removed. It is no longer required to distribute the default `87-podman.conflist` CNI configuration file, as Podman will not automatically create it. - The output of `podman system connection list` is now deterministic, with connections being sorted alpabetically by their name. - The auto-update service (`podman-auto-update.service`) has had its default timer adjusted so it now starts at a random time up to 15 minutes after midnight, to help prevent system congestion from numerous daily services run at once. - Systemd unit files generated by `podman generate systemd` now depend on `network-online.target` by default ([#10655](https://github.com/containers/podman/issues/10655)). -- cgit v1.2.3-54-g00ecf From 7442f0b858e5fe2d7922b3b5714030fda5b2646e Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Wed, 11 Aug 2021 14:38:02 -0400 Subject: Revert "Podman Pod Create --cpus and --cpuset-cpus flags" This reverts commit bbd085ad1e3cf9c5b543c907ad7014ccf8a5cb34. The cgroup work to enable these has not happened yet and will not be ready in time for the release of Podman 3.3.0. Signed-off-by: Matthew Heon --- cmd/podman/containers/create.go | 3 +- cmd/podman/pods/create.go | 53 -------------- docs/source/markdown/podman-pod-create.1.md | 16 ----- libpod/container_validate.go | 1 + libpod/define/pod_inspect.go | 12 ---- libpod/options.go | 42 +---------- libpod/pod.go | 108 ++++++---------------------- libpod/pod_api.go | 6 -- libpod/runtime_pod_infra_linux.go | 8 +-- pkg/domain/entities/pods.go | 37 ---------- pkg/specgen/generate/container_create.go | 1 + pkg/specgen/generate/pod_create.go | 8 --- pkg/specgen/podspecgen.go | 12 ---- pkg/specgen/specgen.go | 4 -- test/e2e/pod_create_test.go | 45 ------------ 15 files changed, 30 insertions(+), 326 deletions(-) diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index c63c074f7..c88cf050e 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -224,6 +224,7 @@ func createInit(c *cobra.Command) error { } cliVals.Env = env } + if c.Flag("cgroups").Changed && cliVals.CGroupsMode == "split" && registry.IsRemote() { return errors.Errorf("the option --cgroups=%q is not supported in remote mode", cliVals.CGroupsMode) } @@ -293,8 +294,6 @@ func createPodIfNecessary(s *specgen.SpecGenerator, netOpts *entities.NetOptions Net: netOpts, CreateCommand: os.Args, Hostname: s.ContainerBasicConfig.Hostname, - Cpus: cliVals.CPUS, - CpusetCpus: cliVals.CPUSetCPUs, Pid: cliVals.PID, } // Unset config values we passed to the pod to prevent them being used twice for the container and pod. diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go index abc47164b..0b446a599 100644 --- a/cmd/podman/pods/create.go +++ b/cmd/podman/pods/create.go @@ -5,13 +5,9 @@ import ( "fmt" "io/ioutil" "os" - "runtime" - "sort" - "strconv" "strings" "github.com/containers/common/pkg/completion" - "github.com/containers/common/pkg/sysinfo" "github.com/containers/podman/v3/cmd/podman/common" "github.com/containers/podman/v3/cmd/podman/parse" "github.com/containers/podman/v3/cmd/podman/registry" @@ -20,7 +16,6 @@ import ( "github.com/containers/podman/v3/pkg/errorhandling" "github.com/containers/podman/v3/pkg/specgen" "github.com/containers/podman/v3/pkg/util" - "github.com/docker/docker/pkg/parsers" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -60,14 +55,6 @@ func init() { common.DefineNetFlags(createCommand) - cpusetflagName := "cpuset-cpus" - flags.StringVar(&createOptions.CpusetCpus, cpusetflagName, "", "CPUs in which to allow execution") - _ = createCommand.RegisterFlagCompletionFunc(cpusetflagName, completion.AutocompleteDefault) - - cpusflagName := "cpus" - flags.Float64Var(&createOptions.Cpus, cpusflagName, 0.000, "set amount of CPUs for the pod") - _ = createCommand.RegisterFlagCompletionFunc(cpusflagName, completion.AutocompleteDefault) - cgroupParentflagName := "cgroup-parent" flags.StringVar(&createOptions.CGroupParent, cgroupParentflagName, "", "Set parent cgroup for the pod") _ = createCommand.RegisterFlagCompletionFunc(cgroupParentflagName, completion.AutocompleteDefault) @@ -211,46 +198,6 @@ func create(cmd *cobra.Command, args []string) error { } } - numCPU := sysinfo.NumCPU() - if numCPU == 0 { - numCPU = runtime.NumCPU() - } - if createOptions.Cpus > float64(numCPU) { - createOptions.Cpus = float64(numCPU) - } - copy := createOptions.CpusetCpus - cpuSet := createOptions.Cpus - if cpuSet == 0 { - cpuSet = float64(sysinfo.NumCPU()) - } - ret, err := parsers.ParseUintList(copy) - copy = "" - if err != nil { - errors.Wrapf(err, "could not parse list") - } - var vals []int - for ind, val := range ret { - if val { - vals = append(vals, ind) - } - } - sort.Ints(vals) - for ind, core := range vals { - if core > int(cpuSet) { - if copy == "" { - copy = "0-" + strconv.Itoa(int(cpuSet)) - createOptions.CpusetCpus = copy - break - } else { - createOptions.CpusetCpus = copy - break - } - } else if ind != 0 { - copy += "," + strconv.Itoa(core) - } else { - copy = "" + strconv.Itoa(core) - } - } response, err := registry.ContainerEngine().PodCreate(context.Background(), createOptions) if err != nil { return err diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md index d825c4b0a..01791c104 100644 --- a/docs/source/markdown/podman-pod-create.1.md +++ b/docs/source/markdown/podman-pod-create.1.md @@ -23,22 +23,6 @@ Add a host to the /etc/hosts file shared between all containers in the pod. Path to cgroups under which the cgroup for the pod will be created. If the path is not absolute, the path is considered to be relative to the cgroups path of the init process. Cgroups will be created if they do not already exist. -#### **--cpus**=*amount* - -Set the total number of CPUs delegated to the pod. Default is 0.000 which indicates that there is no limit on computation power. - -#### **--cpuset-cpus**=*amount* - -Limit the CPUs to support execution. First CPU is numbered 0. Unlike --cpus this is of type string and parsed as a list of numbers - -Format is 0-3,0,1 - -Examples of the List Format: - -0-4,9 # bits 0, 1, 2, 3, 4, and 9 set -0-2,7,12-14 # bits 0, 1, 2, 7, 12, 13, and 14 set - - #### **--dns**=*ipaddr* Set custom DNS servers in the /etc/resolv.conf file that will be shared between all containers in the pod. A special option, "none" is allowed which disables creation of /etc/resolv.conf for the pod. diff --git a/libpod/container_validate.go b/libpod/container_validate.go index 6ff46f1b1..aae96ae85 100644 --- a/libpod/container_validate.go +++ b/libpod/container_validate.go @@ -131,5 +131,6 @@ func (c *Container) validate() error { if c.config.User == "" && (c.config.Spec.Process.User.UID != 0 || c.config.Spec.Process.User.GID != 0) { return errors.Wrapf(define.ErrInvalidArg, "please set User explicitly via WithUser() instead of in OCI spec directly") } + return nil } diff --git a/libpod/define/pod_inspect.go b/libpod/define/pod_inspect.go index a17304875..7c9ea6f90 100644 --- a/libpod/define/pod_inspect.go +++ b/libpod/define/pod_inspect.go @@ -51,12 +51,6 @@ type InspectPodData struct { // Containers gives a brief summary of all containers in the pod and // their current status. Containers []InspectPodContainerInfo `json:"Containers,omitempty"` - // CPUPeriod contains the CPU period of the pod - CPUPeriod uint64 `json:"cpu_period,omitempty"` - // CPUQuota contains the CPU quota of the pod - CPUQuota int64 `json:"cpu_quota,omitempty"` - // CPUSetCPUs contains linux specific CPU data for the pod - CPUSetCPUs string `json:"cpuset_cpus,omitempty"` } // InspectPodInfraConfig contains the configuration of the pod's infra @@ -97,12 +91,6 @@ type InspectPodInfraConfig struct { Networks []string // NetworkOptions are additional options for each network NetworkOptions map[string][]string - // CPUPeriod contains the CPU period of the pod - CPUPeriod uint64 `json:"cpu_period,omitempty"` - // CPUQuota contains the CPU quota of the pod - CPUQuota int64 `json:"cpu_quota,omitempty"` - // CPUSetCPUs contains linux specific CPU data for the container - CPUSetCPUs string `json:"cpuset_cpus,omitempty"` // Pid is the PID namespace mode of the pod's infra container PidNS string `json:"pid_ns,omitempty"` } diff --git a/libpod/options.go b/libpod/options.go index 17a36008d..776f5ddd8 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -21,7 +21,6 @@ import ( "github.com/containers/storage" "github.com/containers/storage/pkg/idtools" "github.com/cri-o/ocicni/pkg/ocicni" - "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -574,6 +573,7 @@ func WithMaxLogSize(limit int64) CtrCreateOption { if ctr.valid { return define.ErrRuntimeFinalized } + ctr.config.LogSize = limit return nil @@ -881,6 +881,7 @@ func WithMountNSFrom(nsCtr *Container) CtrCreateOption { if err := checkDependencyContainer(nsCtr, ctr); err != nil { return err } + ctr.config.MountNsCtr = nsCtr.ID() return nil @@ -2386,45 +2387,6 @@ func WithVolatile() CtrCreateOption { } } -// WithPodCPUPAQ takes the given cpu period and quota and inserts them in the proper place. -func WithPodCPUPAQ(period uint64, quota int64) PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - if pod.CPUPeriod() != 0 && pod.CPUQuota() != 0 { - pod.config.InfraContainer.ResourceLimits.CPU = &specs.LinuxCPU{ - Period: &period, - Quota: "a, - } - } else { - pod.config.InfraContainer.ResourceLimits = &specs.LinuxResources{} - pod.config.InfraContainer.ResourceLimits.CPU = &specs.LinuxCPU{ - Period: &period, - Quota: "a, - } - } - return nil - } -} - -// WithPodCPUSetCPUS computes and sets the Cpus linux resource string which determines the amount of cores, from those available, we are allowed to execute on -func WithPodCPUSetCPUs(inp string) PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - if pod.ResourceLim().CPU.Period != nil { - pod.config.InfraContainer.ResourceLimits.CPU.Cpus = inp - } else { - pod.config.InfraContainer.ResourceLimits = &specs.LinuxResources{} - pod.config.InfraContainer.ResourceLimits.CPU = &specs.LinuxCPU{} - pod.config.InfraContainer.ResourceLimits.CPU.Cpus = inp - } - return nil - } -} - func WithPodPidNS(inp specgen.Namespace) PodCreateOption { return func(p *Pod) error { if p.valid { diff --git a/libpod/pod.go b/libpod/pod.go index 62f5c9e5b..0fbf61550 100644 --- a/libpod/pod.go +++ b/libpod/pod.go @@ -1,7 +1,6 @@ package libpod import ( - "context" "net" "time" @@ -9,7 +8,6 @@ import ( "github.com/containers/podman/v3/libpod/lock" "github.com/containers/podman/v3/pkg/specgen" "github.com/cri-o/ocicni/pkg/ocicni" - "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" ) @@ -94,28 +92,27 @@ type podState struct { // Generally speaking, aside from those two exceptions, these options will set // the equivalent field in the container's configuration. type InfraContainerConfig struct { - ConmonPidFile string `json:"conmonPidFile"` - HasInfraContainer bool `json:"makeInfraContainer"` - NoNetwork bool `json:"noNetwork,omitempty"` - HostNetwork bool `json:"infraHostNetwork,omitempty"` - PidNS specgen.Namespace `json:"infraPid,omitempty"` - PortBindings []ocicni.PortMapping `json:"infraPortBindings"` - StaticIP net.IP `json:"staticIP,omitempty"` - StaticMAC net.HardwareAddr `json:"staticMAC,omitempty"` - UseImageResolvConf bool `json:"useImageResolvConf,omitempty"` - DNSServer []string `json:"dnsServer,omitempty"` - DNSSearch []string `json:"dnsSearch,omitempty"` - DNSOption []string `json:"dnsOption,omitempty"` - UseImageHosts bool `json:"useImageHosts,omitempty"` - HostAdd []string `json:"hostsAdd,omitempty"` - Networks []string `json:"networks,omitempty"` - ExitCommand []string `json:"exitCommand,omitempty"` - InfraImage string `json:"infraImage,omitempty"` - InfraCommand []string `json:"infraCommand,omitempty"` - InfraName string `json:"infraName,omitempty"` - Slirp4netns bool `json:"slirp4netns,omitempty"` - NetworkOptions map[string][]string `json:"network_options,omitempty"` - ResourceLimits *specs.LinuxResources `json:"resource_limits,omitempty"` + ConmonPidFile string `json:"conmonPidFile"` + HasInfraContainer bool `json:"makeInfraContainer"` + NoNetwork bool `json:"noNetwork,omitempty"` + HostNetwork bool `json:"infraHostNetwork,omitempty"` + PidNS specgen.Namespace `json:"infraPid,omitempty"` + PortBindings []ocicni.PortMapping `json:"infraPortBindings"` + StaticIP net.IP `json:"staticIP,omitempty"` + StaticMAC net.HardwareAddr `json:"staticMAC,omitempty"` + UseImageResolvConf bool `json:"useImageResolvConf,omitempty"` + DNSServer []string `json:"dnsServer,omitempty"` + DNSSearch []string `json:"dnsSearch,omitempty"` + DNSOption []string `json:"dnsOption,omitempty"` + UseImageHosts bool `json:"useImageHosts,omitempty"` + HostAdd []string `json:"hostsAdd,omitempty"` + Networks []string `json:"networks,omitempty"` + ExitCommand []string `json:"exitCommand,omitempty"` + InfraImage string `json:"infraImage,omitempty"` + InfraCommand []string `json:"infraCommand,omitempty"` + InfraName string `json:"infraName,omitempty"` + Slirp4netns bool `json:"slirp4netns,omitempty"` + NetworkOptions map[string][]string `json:"network_options,omitempty"` } // ID retrieves the pod's ID @@ -134,45 +131,6 @@ func (p *Pod) Namespace() string { return p.config.Namespace } -// ResourceLim returns the cpuset resource limits for the pod -func (p *Pod) ResourceLim() *specs.LinuxResources { - resCopy := &specs.LinuxResources{} - if err := JSONDeepCopy(p.config.InfraContainer.ResourceLimits, resCopy); err != nil { - return nil - } - if resCopy != nil && resCopy.CPU != nil { - return resCopy - } - empty := &specs.LinuxResources{ - CPU: &specs.LinuxCPU{}, - } - return empty -} - -// CPUPeriod returns the pod CPU period -func (p *Pod) CPUPeriod() uint64 { - resCopy := &specs.LinuxResources{} - if err := JSONDeepCopy(p.config.InfraContainer.ResourceLimits, resCopy); err != nil { - return 0 - } - if resCopy != nil && resCopy.CPU != nil && resCopy.CPU.Period != nil { - return *resCopy.CPU.Period - } - return 0 -} - -// CPUQuota returns the pod CPU quota -func (p *Pod) CPUQuota() int64 { - resCopy := &specs.LinuxResources{} - if err := JSONDeepCopy(p.config.InfraContainer.ResourceLimits, resCopy); err != nil { - return 0 - } - if resCopy != nil && resCopy.CPU != nil && resCopy.CPU.Quota != nil { - return *resCopy.CPU.Quota - } - return 0 -} - // PidMode returns the PID mode given by the user ex: pod, private... func (p *Pod) PidMode() string { return string(p.config.InfraContainer.PidNS.NSMode) @@ -258,31 +216,7 @@ func (p *Pod) CgroupPath() (string, error) { if err := p.updatePod(); err != nil { return "", err } - if p.state.CgroupPath != "" { - return p.state.CgroupPath, nil - } - if !p.HasInfraContainer() { - return "", errors.Wrap(define.ErrNoSuchCtr, "pod has no infra container") - } - - id := p.state.InfraContainerID - if id != "" { - ctr, err := p.runtime.state.Container(id) - if err != nil { - return "", errors.Wrapf(err, "could not get infra") - } - if ctr != nil { - ctr.Start(context.Background(), false) - cgroupPath, err := ctr.CGroupPath() - if err != nil { - return "", errors.Wrapf(err, "could not get container cgroup") - } - p.state.CgroupPath = cgroupPath - p.save() - return cgroupPath, nil - } - } return p.state.CgroupPath, nil } diff --git a/libpod/pod_api.go b/libpod/pod_api.go index 1ab012a8b..6b6e94f81 100644 --- a/libpod/pod_api.go +++ b/libpod/pod_api.go @@ -538,9 +538,6 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) { infraConfig.StaticMAC = p.config.InfraContainer.StaticMAC.String() infraConfig.NoManageResolvConf = p.config.InfraContainer.UseImageResolvConf infraConfig.NoManageHosts = p.config.InfraContainer.UseImageHosts - infraConfig.CPUPeriod = p.CPUPeriod() - infraConfig.CPUQuota = p.CPUQuota() - infraConfig.CPUSetCPUs = p.ResourceLim().CPU.Cpus infraConfig.PidNS = p.PidMode() if len(p.config.InfraContainer.DNSServer) > 0 { @@ -585,9 +582,6 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) { SharedNamespaces: sharesNS, NumContainers: uint(len(containers)), Containers: ctrs, - CPUSetCPUs: p.ResourceLim().CPU.Cpus, - CPUPeriod: p.CPUPeriod(), - CPUQuota: p.CPUQuota(), } return &inspectData, nil diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go index d4f861118..46a34e2de 100644 --- a/libpod/runtime_pod_infra_linux.go +++ b/libpod/runtime_pod_infra_linux.go @@ -158,6 +158,7 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm g.Config.Linux.Namespaces = newNS } } + g.SetRootReadonly(true) g.SetProcessArgs(infraCtrCommand) @@ -184,6 +185,7 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm // Ignore mqueue sysctls if not sharing IPC if !p.config.UsePodIPC && strings.HasPrefix(sysctlKey, "fs.mqueue.") { logrus.Infof("Sysctl %s=%s ignored in containers.conf, since IPC Namespace for pod is unused", sysctlKey, sysctlVal) + continue } @@ -198,6 +200,7 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm logrus.Infof("Sysctl %s=%s ignored in containers.conf, since UTS Namespace for pod is unused", sysctlKey, sysctlVal) continue } + g.AddLinuxSysctl(sysctlKey, sysctlVal) } @@ -213,11 +216,7 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm if len(p.config.InfraContainer.ConmonPidFile) > 0 { options = append(options, WithConmonPidFile(p.config.InfraContainer.ConmonPidFile)) } - newRes := new(spec.LinuxResources) - newRes.CPU = new(spec.LinuxCPU) - newRes.CPU = p.ResourceLim().CPU - g.Config.Linux.Resources.CPU = newRes.CPU return r.newContainer(ctx, g.Config, options...) } @@ -228,6 +227,7 @@ func (r *Runtime) createInfraContainer(ctx context.Context, p *Pod) (*Container, if !r.valid { return nil, define.ErrRuntimeStopped } + imageName := p.config.InfraContainer.InfraImage if imageName == "" { imageName = r.config.Engine.InfraImage diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go index 68e335f8d..abd6ba6c6 100644 --- a/pkg/domain/entities/pods.go +++ b/pkg/domain/entities/pods.go @@ -7,8 +7,6 @@ import ( "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/specgen" - "github.com/containers/podman/v3/pkg/util" - "github.com/opencontainers/runtime-spec/specs-go" ) type PodKillOptions struct { @@ -120,34 +118,12 @@ type PodCreateOptions struct { Net *NetOptions Share []string Pid string - Cpus float64 - CpusetCpus string } type PodCreateReport struct { Id string //nolint } -func (p *PodCreateOptions) CPULimits() *specs.LinuxCPU { - cpu := &specs.LinuxCPU{} - hasLimits := false - - if p.Cpus != 0 { - period, quota := util.CoresToPeriodAndQuota(p.Cpus) - cpu.Period = &period - cpu.Quota = "a - hasLimits = true - } - if p.CpusetCpus != "" { - cpu.Cpus = p.CpusetCpus - hasLimits = true - } - if !hasLimits { - return cpu - } - return cpu -} - func setNamespaces(p *PodCreateOptions) ([4]specgen.Namespace, error) { allNS := [4]specgen.Namespace{} if p.Pid != "" { @@ -204,19 +180,6 @@ func (p *PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) error { // Cgroup s.CgroupParent = p.CGroupParent - // Resource config - cpuDat := p.CPULimits() - if s.ResourceLimits == nil { - s.ResourceLimits = &specs.LinuxResources{} - s.ResourceLimits.CPU = &specs.LinuxCPU{} - } - if cpuDat != nil { - s.ResourceLimits.CPU = cpuDat - if p.Cpus != 0 { - s.CPUPeriod = *cpuDat.Period - s.CPUQuota = *cpuDat.Quota - } - } return nil } diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go index 4e3a86ae4..2961ed849 100644 --- a/pkg/specgen/generate/container_create.go +++ b/pkg/specgen/generate/container_create.go @@ -354,6 +354,7 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen. options = append(options, libpod.WithLogDriver(s.LogConfiguration.Driver)) } } + // Security options if len(s.SelinuxOpts) > 0 { options = append(options, libpod.WithSecLabels(s.SelinuxOpts)) diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go index aab29499e..ec3ea077e 100644 --- a/pkg/specgen/generate/pod_create.go +++ b/pkg/specgen/generate/pod_create.go @@ -54,14 +54,6 @@ func createPodOptions(p *specgen.PodSpecGenerator, rt *libpod.Runtime) ([]libpod if len(p.Name) > 0 { options = append(options, libpod.WithPodName(p.Name)) } - if p.ResourceLimits != nil && p.ResourceLimits.CPU != nil && p.ResourceLimits.CPU.Period != nil && p.ResourceLimits.CPU.Quota != nil { - if *p.ResourceLimits.CPU.Period != 0 || *p.ResourceLimits.CPU.Quota != 0 { - options = append(options, libpod.WithPodCPUPAQ((*p.ResourceLimits.CPU.Period), (*p.ResourceLimits.CPU.Quota))) - } - } - if p.ResourceLimits != nil && p.ResourceLimits.CPU != nil && p.ResourceLimits.CPU.Cpus != "" { - options = append(options, libpod.WithPodCPUSetCPUs(p.ResourceLimits.CPU.Cpus)) - } if len(p.Hostname) > 0 { options = append(options, libpod.WithPodHostname(p.Hostname)) } diff --git a/pkg/specgen/podspecgen.go b/pkg/specgen/podspecgen.go index 02237afe9..b2d284f40 100644 --- a/pkg/specgen/podspecgen.go +++ b/pkg/specgen/podspecgen.go @@ -2,8 +2,6 @@ package specgen import ( "net" - - spec "github.com/opencontainers/runtime-spec/specs-go" ) // PodBasicConfig contains basic configuration options for pods. @@ -167,16 +165,6 @@ type PodSpecGenerator struct { PodBasicConfig PodNetworkConfig PodCgroupConfig - PodResourceConfig -} - -type PodResourceConfig struct { - // ResourceLimits contains linux specific CPU data for the pod - ResourceLimits *spec.LinuxResources `json:"resource_limits,omitempty"` - // CPU period of the cpuset, determined by --cpus - CPUPeriod uint64 `json:"cpu_period,omitempty"` - // CPU quota of the cpuset, determined by --cpus - CPUQuota int64 `json:"cpu_quota,omitempty"` } // NewPodSpecGenerator creates a new pod spec diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go index 7eec48a55..1e0a952de 100644 --- a/pkg/specgen/specgen.go +++ b/pkg/specgen/specgen.go @@ -473,10 +473,6 @@ type ContainerResourceConfig struct { // that are used to configure cgroup v2. // Optional. CgroupConf map[string]string `json:"unified,omitempty"` - // CPU period of the cpuset, determined by --cpus - CPUPeriod uint64 `json:"cpu_period,omitempty"` - // CPU quota of the cpuset, determined by --cpus - CPUQuota int64 `json:"cpu_quota,omitempty"` } // ContainerHealthCheckConfig describes a container healthcheck with attributes diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go index 4c6788b9d..028689211 100644 --- a/test/e2e/pod_create_test.go +++ b/test/e2e/pod_create_test.go @@ -5,12 +5,9 @@ import ( "io/ioutil" "os" "path/filepath" - "strconv" "strings" - "github.com/containers/common/pkg/sysinfo" "github.com/containers/podman/v3/pkg/rootless" - "github.com/containers/podman/v3/pkg/util" . "github.com/containers/podman/v3/test/utils" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -519,48 +516,6 @@ ENTRYPOINT ["sleep","99999"] Expect(create).Should(Exit(0)) }) - It("podman pod create --cpus", func() { - podName := "testPod" - numCPU := float64(sysinfo.NumCPU()) - period, quota := util.CoresToPeriodAndQuota(numCPU) - numCPUStr := strconv.Itoa(int(numCPU)) - podCreate := podmanTest.Podman([]string{"pod", "create", "--cpus", numCPUStr, "--name", podName}) - podCreate.WaitWithDefaultTimeout() - Expect(podCreate).Should(Exit(0)) - - contCreate := podmanTest.Podman([]string{"container", "create", "--pod", podName, "alpine"}) - contCreate.WaitWithDefaultTimeout() - Expect(podCreate).Should(Exit(0)) - - podInspect := podmanTest.Podman([]string{"pod", "inspect", podName}) - podInspect.WaitWithDefaultTimeout() - Expect(podInspect).Should(Exit(0)) - podJSON := podInspect.InspectPodToJSON() - Expect(podJSON.CPUPeriod).To(Equal(period)) - Expect(podJSON.CPUQuota).To(Equal(quota)) - }) - - It("podman pod create --cpuset-cpus", func() { - podName := "testPod" - ctrName := "testCtr" - numCPU := float64(sysinfo.NumCPU()) - numCPUStr := strconv.Itoa(int(numCPU)) - in := "0-" + numCPUStr - podCreate := podmanTest.Podman([]string{"pod", "create", "--cpuset-cpus", in, "--name", podName}) - podCreate.WaitWithDefaultTimeout() - Expect(podCreate).Should(Exit(0)) - - contCreate := podmanTest.Podman([]string{"container", "create", "--name", ctrName, "--pod", podName, "alpine"}) - contCreate.WaitWithDefaultTimeout() - Expect(podCreate).Should(Exit(0)) - - podInspect := podmanTest.Podman([]string{"pod", "inspect", podName}) - podInspect.WaitWithDefaultTimeout() - Expect(podInspect).Should(Exit(0)) - podJSON := podInspect.InspectPodToJSON() - Expect(podJSON.CPUSetCPUs).To(Equal(in)) - }) - It("podman pod create --pid", func() { podName := "pidPod" ns := "ns:/proc/self/ns/" -- cgit v1.2.3-54-g00ecf