aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--contrib/systemd/system/podman-docker.conf2
-rw-r--r--libpod/info.go182
-rw-r--r--libpod/info_freebsd.go40
-rw-r--r--libpod/info_linux.go132
-rw-r--r--libpod/info_unsupported.go4
-rw-r--r--podman.spec.rpkg1
-rw-r--r--test/e2e/run_memory_test.go18
8 files changed, 219 insertions, 164 deletions
diff --git a/Makefile b/Makefile
index 4f222d6d4..4818ee122 100644
--- a/Makefile
+++ b/Makefile
@@ -38,6 +38,7 @@ MANDIR ?= ${PREFIX}/share/man
SHAREDIR_CONTAINERS ?= ${PREFIX}/share/containers
ETCDIR ?= ${PREFIX}/etc
TMPFILESDIR ?= ${PREFIX}/lib/tmpfiles.d
+USERTMPFILESDIR ?= ${PREFIX}/share/user-tmpfiles.d
MODULESLOADDIR ?= ${PREFIX}/lib/modules-load.d
SYSTEMDDIR ?= ${PREFIX}/lib/systemd/system
USERSYSTEMDDIR ?= ${PREFIX}/lib/systemd/user
@@ -795,8 +796,9 @@ install.completions:
install.docker:
install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(BINDIR)
install ${SELINUXOPT} -m 755 docker $(DESTDIR)$(BINDIR)/docker
- install ${SELINUXOPT} -m 755 -d ${DESTDIR}${SYSTEMDDIR} ${DESTDIR}${USERSYSTEMDDIR} ${DESTDIR}${TMPFILESDIR}
+ install ${SELINUXOPT} -m 755 -d ${DESTDIR}${SYSTEMDDIR} ${DESTDIR}${USERSYSTEMDDIR} ${DESTDIR}${TMPFILESDIR} ${DESTDIR}${USERTMPFILESDIR}
install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-docker.conf -t ${DESTDIR}${TMPFILESDIR}
+ install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-docker.conf -t ${DESTDIR}${USERTMPFILESDIR}
.PHONY: install.docker-docs
install.docker-docs:
diff --git a/contrib/systemd/system/podman-docker.conf b/contrib/systemd/system/podman-docker.conf
index e12f19bce..9d5f43101 100644
--- a/contrib/systemd/system/podman-docker.conf
+++ b/contrib/systemd/system/podman-docker.conf
@@ -1 +1 @@
-L+ /run/docker.sock - - - - /run/podman/podman.sock
+L+ %t/docker.sock - - - - %t/podman/podman.sock
diff --git a/libpod/info.go b/libpod/info.go
index 8db6df8cc..1990dc044 100644
--- a/libpod/info.go
+++ b/libpod/info.go
@@ -1,6 +1,3 @@
-//go:build linux
-// +build linux
-
package libpod
import (
@@ -8,27 +5,21 @@ import (
"bytes"
"errors"
"fmt"
- "io/ioutil"
"math"
"os"
- "os/exec"
"runtime"
- "strconv"
"strings"
"syscall"
"time"
"github.com/containers/buildah"
- "github.com/containers/common/pkg/apparmor"
- "github.com/containers/common/pkg/cgroups"
- "github.com/containers/common/pkg/seccomp"
+ "github.com/containers/buildah/pkg/util"
"github.com/containers/image/v5/pkg/sysregistriesv2"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/libpod/linkmode"
"github.com/containers/podman/v4/pkg/rootless"
"github.com/containers/storage"
"github.com/containers/storage/pkg/system"
- "github.com/opencontainers/selinux/go-selinux"
"github.com/sirupsen/logrus"
)
@@ -94,7 +85,7 @@ func (r *Runtime) hostInfo() (*define.HostInfo, error) {
hostDistributionInfo := r.GetHostDistributionInfo()
- kv, err := readKernelVersion()
+ kv, err := util.ReadKernelVersion()
if err != nil {
return nil, fmt.Errorf("error reading kernel version: %w", err)
}
@@ -104,94 +95,30 @@ func (r *Runtime) hostInfo() (*define.HostInfo, error) {
return nil, fmt.Errorf("error getting hostname: %w", err)
}
- seccompProfilePath, err := DefaultSeccompPath()
- if err != nil {
- return nil, fmt.Errorf("error getting Seccomp profile path: %w", err)
- }
-
- // Cgroups version
- unified, err := cgroups.IsCgroup2UnifiedMode()
- if err != nil {
- return nil, fmt.Errorf("error reading cgroups mode: %w", err)
- }
-
- // Get Map of all available controllers
- availableControllers, err := cgroups.GetAvailableControllers(nil, unified)
- if err != nil {
- return nil, fmt.Errorf("error getting available cgroup controllers: %w", err)
- }
cpuUtil, err := getCPUUtilization()
if err != nil {
return nil, err
}
info := define.HostInfo{
- Arch: runtime.GOARCH,
- BuildahVersion: buildah.Version,
- CgroupManager: r.config.Engine.CgroupManager,
- CgroupControllers: availableControllers,
- Linkmode: linkmode.Linkmode(),
- CPUs: runtime.NumCPU(),
- CPUUtilization: cpuUtil,
- Distribution: hostDistributionInfo,
- LogDriver: r.config.Containers.LogDriver,
- EventLogger: r.eventer.String(),
- Hostname: host,
- IDMappings: define.IDMappings{},
- Kernel: kv,
- MemFree: mi.MemFree,
- MemTotal: mi.MemTotal,
- NetworkBackend: r.config.Network.NetworkBackend,
- OS: runtime.GOOS,
- Security: define.SecurityInfo{
- AppArmorEnabled: apparmor.IsEnabled(),
- DefaultCapabilities: strings.Join(r.config.Containers.DefaultCapabilities, ","),
- Rootless: rootless.IsRootless(),
- SECCOMPEnabled: seccomp.IsEnabled(),
- SECCOMPProfilePath: seccompProfilePath,
- SELinuxEnabled: selinux.GetEnabled(),
- },
- Slirp4NetNS: define.SlirpInfo{},
- SwapFree: mi.SwapFree,
- SwapTotal: mi.SwapTotal,
- }
-
- cgroupVersion := "v1"
- if unified {
- cgroupVersion = "v2"
- }
- info.CgroupsVersion = cgroupVersion
-
- 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, fmt.Errorf("error reading uid mappings: %w", err)
- }
- gidmappings, err := rootless.ReadMappingsProc("/proc/self/gid_map")
- if err != nil {
- return nil, fmt.Errorf("error reading gid mappings: %w", err)
- }
- idmappings := define.IDMappings{
- GIDMap: gidmappings,
- UIDMap: uidmappings,
- }
- info.IDMappings = idmappings
+ Arch: runtime.GOARCH,
+ BuildahVersion: buildah.Version,
+ Linkmode: linkmode.Linkmode(),
+ CPUs: runtime.NumCPU(),
+ CPUUtilization: cpuUtil,
+ Distribution: hostDistributionInfo,
+ LogDriver: r.config.Containers.LogDriver,
+ EventLogger: r.eventer.String(),
+ Hostname: host,
+ Kernel: kv,
+ MemFree: mi.MemFree,
+ MemTotal: mi.MemTotal,
+ NetworkBackend: r.config.Network.NetworkBackend,
+ OS: runtime.GOOS,
+ SwapFree: mi.SwapFree,
+ SwapTotal: mi.SwapTotal,
+ }
+ if err := r.setPlatformHostInfo(&info); err != nil {
+ return nil, err
}
conmonInfo, ociruntimeInfo, err := r.defaultOCIRuntime.RuntimeInfo()
@@ -202,7 +129,7 @@ func (r *Runtime) hostInfo() (*define.HostInfo, error) {
info.OCIRuntime = ociruntimeInfo
}
- duration, err := procUptime()
+ duration, err := util.ReadUptime()
if err != nil {
return nil, fmt.Errorf("error reading up time: %w", err)
}
@@ -332,31 +259,6 @@ func (r *Runtime) storeInfo() (*define.StoreInfo, error) {
return &info, nil
}
-func readKernelVersion() (string, error) {
- buf, err := ioutil.ReadFile("/proc/version")
- if err != nil {
- return "", err
- }
- f := bytes.Fields(buf)
- if len(f) < 3 {
- return string(bytes.TrimSpace(buf)), nil
- }
- return string(f[2]), nil
-}
-
-func procUptime() (time.Duration, error) {
- var zero time.Duration
- buf, err := ioutil.ReadFile("/proc/uptime")
- if err != nil {
- return zero, err
- }
- f := bytes.Fields(buf)
- if len(f) < 1 {
- return zero, errors.New("unable to parse uptime from /proc/uptime")
- }
- return time.ParseDuration(string(f[0]) + "s")
-}
-
// GetHostDistributionInfo returns a map containing the host's distribution and version
func (r *Runtime) GetHostDistributionInfo() define.DistributionInfo {
// Populate values in case we cannot find the values
@@ -388,43 +290,3 @@ func (r *Runtime) GetHostDistributionInfo() define.DistributionInfo {
}
return dist
}
-
-// getCPUUtilization Returns a CPUUsage object that summarizes CPU
-// usage for userspace, system, and idle time.
-func getCPUUtilization() (*define.CPUUsage, error) {
- f, err := os.Open("/proc/stat")
- if err != nil {
- return nil, err
- }
- defer f.Close()
- scanner := bufio.NewScanner(f)
- // Read first line of /proc/stat that has entries for system ("cpu" line)
- for scanner.Scan() {
- break
- }
- // column 1 is user, column 3 is system, column 4 is idle
- stats := strings.Fields(scanner.Text())
- return statToPercent(stats)
-}
-
-func statToPercent(stats []string) (*define.CPUUsage, error) {
- userTotal, err := strconv.ParseFloat(stats[1], 64)
- if err != nil {
- return nil, fmt.Errorf("unable to parse user value %q: %w", stats[1], err)
- }
- systemTotal, err := strconv.ParseFloat(stats[3], 64)
- if err != nil {
- return nil, fmt.Errorf("unable to parse system value %q: %w", stats[3], err)
- }
- idleTotal, err := strconv.ParseFloat(stats[4], 64)
- if err != nil {
- return nil, fmt.Errorf("unable to parse idle value %q: %w", stats[4], err)
- }
- total := userTotal + systemTotal + idleTotal
- s := define.CPUUsage{
- UserPercent: math.Round((userTotal/total*100)*100) / 100,
- SystemPercent: math.Round((systemTotal/total*100)*100) / 100,
- IdlePercent: math.Round((idleTotal/total*100)*100) / 100,
- }
- return &s, nil
-}
diff --git a/libpod/info_freebsd.go b/libpod/info_freebsd.go
new file mode 100644
index 000000000..ef7b6817c
--- /dev/null
+++ b/libpod/info_freebsd.go
@@ -0,0 +1,40 @@
+package libpod
+
+import (
+ "fmt"
+ "unsafe"
+
+ "github.com/containers/podman/v4/libpod/define"
+ "golang.org/x/sys/unix"
+)
+
+func (r *Runtime) setPlatformHostInfo(info *define.HostInfo) error {
+ return nil
+}
+
+func timeToPercent(time uint64, total uint64) float64 {
+ return 100.0 * float64(time) / float64(total)
+}
+
+// getCPUUtilization Returns a CPUUsage object that summarizes CPU
+// usage for userspace, system, and idle time.
+func getCPUUtilization() (*define.CPUUsage, error) {
+ buf, err := unix.SysctlRaw("kern.cp_time")
+ if err != nil {
+ return nil, fmt.Errorf("error reading sysctl kern.cp_time: %w", err)
+ }
+
+ var total uint64 = 0
+ var times [unix.CPUSTATES]uint64
+
+ for i := 0; i < unix.CPUSTATES; i++ {
+ val := *(*uint64)(unsafe.Pointer(&buf[8*i]))
+ times[i] = val
+ total += val
+ }
+ return &define.CPUUsage{
+ UserPercent: timeToPercent(times[unix.CP_USER], total),
+ SystemPercent: timeToPercent(times[unix.CP_SYS], total),
+ IdlePercent: timeToPercent(times[unix.CP_IDLE], total),
+ }, nil
+}
diff --git a/libpod/info_linux.go b/libpod/info_linux.go
new file mode 100644
index 000000000..801dcdb43
--- /dev/null
+++ b/libpod/info_linux.go
@@ -0,0 +1,132 @@
+package libpod
+
+import (
+ "bufio"
+ "fmt"
+ "math"
+ "os"
+ "os/exec"
+ "strconv"
+ "strings"
+
+ "github.com/containers/common/pkg/apparmor"
+ "github.com/containers/common/pkg/cgroups"
+ "github.com/containers/common/pkg/seccomp"
+ "github.com/containers/podman/v4/libpod/define"
+ "github.com/containers/podman/v4/pkg/rootless"
+ "github.com/opencontainers/selinux/go-selinux"
+ "github.com/sirupsen/logrus"
+)
+
+func (r *Runtime) setPlatformHostInfo(info *define.HostInfo) error {
+ seccompProfilePath, err := DefaultSeccompPath()
+ if err != nil {
+ return fmt.Errorf("error getting Seccomp profile path: %w", err)
+ }
+
+ // Cgroups version
+ unified, err := cgroups.IsCgroup2UnifiedMode()
+ if err != nil {
+ return fmt.Errorf("error reading cgroups mode: %w", err)
+ }
+
+ // Get Map of all available controllers
+ availableControllers, err := cgroups.GetAvailableControllers(nil, unified)
+ if err != nil {
+ return fmt.Errorf("error getting available cgroup controllers: %w", err)
+ }
+
+ info.CgroupManager = r.config.Engine.CgroupManager
+ info.CgroupControllers = availableControllers
+ info.IDMappings = define.IDMappings{}
+ info.Security = define.SecurityInfo{
+ AppArmorEnabled: apparmor.IsEnabled(),
+ DefaultCapabilities: strings.Join(r.config.Containers.DefaultCapabilities, ","),
+ Rootless: rootless.IsRootless(),
+ SECCOMPEnabled: seccomp.IsEnabled(),
+ SECCOMPProfilePath: seccompProfilePath,
+ SELinuxEnabled: selinux.GetEnabled(),
+ }
+ info.Slirp4NetNS = define.SlirpInfo{}
+
+ cgroupVersion := "v1"
+ if unified {
+ cgroupVersion = "v2"
+ }
+ info.CgroupsVersion = cgroupVersion
+
+ 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 fmt.Errorf("error reading uid mappings: %w", err)
+ }
+ gidmappings, err := rootless.ReadMappingsProc("/proc/self/gid_map")
+ if err != nil {
+ return fmt.Errorf("error reading gid mappings: %w", err)
+ }
+ idmappings := define.IDMappings{
+ GIDMap: gidmappings,
+ UIDMap: uidmappings,
+ }
+ info.IDMappings = idmappings
+ }
+
+ return nil
+}
+
+func statToPercent(stats []string) (*define.CPUUsage, error) {
+ userTotal, err := strconv.ParseFloat(stats[1], 64)
+ if err != nil {
+ return nil, fmt.Errorf("unable to parse user value %q: %w", stats[1], err)
+ }
+ systemTotal, err := strconv.ParseFloat(stats[3], 64)
+ if err != nil {
+ return nil, fmt.Errorf("unable to parse system value %q: %w", stats[3], err)
+ }
+ idleTotal, err := strconv.ParseFloat(stats[4], 64)
+ if err != nil {
+ return nil, fmt.Errorf("unable to parse idle value %q: %w", stats[4], err)
+ }
+ total := userTotal + systemTotal + idleTotal
+ s := define.CPUUsage{
+ UserPercent: math.Round((userTotal/total*100)*100) / 100,
+ SystemPercent: math.Round((systemTotal/total*100)*100) / 100,
+ IdlePercent: math.Round((idleTotal/total*100)*100) / 100,
+ }
+ return &s, nil
+}
+
+// getCPUUtilization Returns a CPUUsage object that summarizes CPU
+// usage for userspace, system, and idle time.
+func getCPUUtilization() (*define.CPUUsage, error) {
+ f, err := os.Open("/proc/stat")
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ scanner := bufio.NewScanner(f)
+ // Read first line of /proc/stat that has entries for system ("cpu" line)
+ for scanner.Scan() {
+ break
+ }
+ // column 1 is user, column 3 is system, column 4 is idle
+ stats := strings.Fields(scanner.Text())
+ return statToPercent(stats)
+}
diff --git a/libpod/info_unsupported.go b/libpod/info_unsupported.go
index 53ee4b32f..0aed51247 100644
--- a/libpod/info_unsupported.go
+++ b/libpod/info_unsupported.go
@@ -1,5 +1,5 @@
-//go:build !linux
-// +build !linux
+//go:build !linux && !freebsd
+// +build !linux,!freebsd
package libpod
diff --git a/podman.spec.rpkg b/podman.spec.rpkg
index f27b31108..2962fe91e 100644
--- a/podman.spec.rpkg
+++ b/podman.spec.rpkg
@@ -233,6 +233,7 @@ done
%{_userunitdir}/%{name}-restart.service
%{_userunitdir}/%{name}-kube@.service
%{_tmpfilesdir}/%{name}.conf
+%{_user_tmpfilesdir}/%{name}-docker.conf
%if 0%{?fedora} >= 36
%{_modulesloaddir}/%{name}-iptables.conf
%endif
diff --git a/test/e2e/run_memory_test.go b/test/e2e/run_memory_test.go
index 083020f08..3f611040b 100644
--- a/test/e2e/run_memory_test.go
+++ b/test/e2e/run_memory_test.go
@@ -66,6 +66,24 @@ var _ = Describe("Podman run memory", func() {
Expect(session.OutputToString()).To(Equal("41943040"))
})
+ It("podman run memory-swap test", func() {
+ var (
+ session *PodmanSessionIntegration
+ expect string
+ )
+
+ if CGROUPSV2 {
+ session = podmanTest.Podman([]string{"run", "--memory=20m", "--memory-swap=30M", "--net=none", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/memory.swap.max"})
+ expect = "10485760"
+ } else {
+ session = podmanTest.Podman([]string{"run", "--memory=20m", "--memory-swap=30M", ALPINE, "cat", "/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes"})
+ expect = "31457280"
+ }
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(Equal(expect))
+ })
+
for _, limit := range []string{"0", "15", "100"} {
limit := limit // Keep this value in a proper scope
testName := fmt.Sprintf("podman run memory-swappiness test(%s)", limit)