diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/api/handlers/compat/containers_stats.go | 13 | ||||
-rw-r--r-- | pkg/api/handlers/compat/system.go | 2 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/containers.go | 16 | ||||
-rw-r--r-- | pkg/bindings/containers/checkpoint.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/system.go | 18 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/containers.go | 7 | ||||
-rw-r--r-- | pkg/machine/e2e/inspect_test.go | 8 | ||||
-rw-r--r-- | pkg/rctl/rctl.go | 47 | ||||
-rw-r--r-- | pkg/rootless/rootless_linux.c | 1 | ||||
-rw-r--r-- | pkg/specgen/generate/container.go | 2 | ||||
-rw-r--r-- | pkg/systemd/generate/containers.go | 12 | ||||
-rw-r--r-- | pkg/systemd/generate/pods.go | 15 | ||||
-rw-r--r-- | pkg/systemd/generate/pods_test.go | 85 |
13 files changed, 171 insertions, 57 deletions
diff --git a/pkg/api/handlers/compat/containers_stats.go b/pkg/api/handlers/compat/containers_stats.go index c115b4181..519661675 100644 --- a/pkg/api/handlers/compat/containers_stats.go +++ b/pkg/api/handlers/compat/containers_stats.go @@ -11,6 +11,7 @@ import ( "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/api/handlers/utils" api "github.com/containers/podman/v4/pkg/api/types" + "github.com/containers/storage/pkg/system" docker "github.com/docker/docker/api/types" "github.com/gorilla/schema" runccgroups "github.com/opencontainers/runc/libcontainer/cgroups" @@ -139,6 +140,16 @@ streamLabel: // A label to flatten the scope memoryLimit = uint64(*cfg.Spec.Linux.Resources.Memory.Limit) } + memInfo, err := system.ReadMemInfo() + if err != nil { + logrus.Errorf("Unable to get cgroup stats: %v", err) + return + } + // cap the memory limit to the available memory. + if memInfo.MemTotal > 0 && memoryLimit > uint64(memInfo.MemTotal) { + memoryLimit = uint64(memInfo.MemTotal) + } + systemUsage, _ := cgroups.GetSystemCPUUsage() s := StatsJSON{ Stats: Stats{ @@ -177,7 +188,7 @@ streamLabel: // A label to flatten the scope PreCPUStats: preCPUStats, MemoryStats: docker.MemoryStats{ Usage: cgroupStat.MemoryStats.Usage.Usage, - MaxUsage: cgroupStat.MemoryStats.Usage.Limit, + MaxUsage: cgroupStat.MemoryStats.Usage.MaxUsage, Stats: nil, Failcnt: 0, Limit: memoryLimit, diff --git a/pkg/api/handlers/compat/system.go b/pkg/api/handlers/compat/system.go index 97bc9eac2..23f116d16 100644 --- a/pkg/api/handlers/compat/system.go +++ b/pkg/api/handlers/compat/system.go @@ -76,7 +76,7 @@ func GetDiskUsage(w http.ResponseWriter, r *http.Request) { Scope: "local", Status: nil, UsageData: &docker.VolumeUsageData{ - RefCount: 1, + RefCount: int64(o.Links), Size: o.Size, }, } diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go index d1460569f..a76e3d988 100644 --- a/pkg/api/handlers/libpod/containers.go +++ b/pkg/api/handlers/libpod/containers.go @@ -266,16 +266,16 @@ func Checkpoint(w http.ResponseWriter, r *http.Request) { utils.InternalServerError(w, err) return } + if len(reports) != 1 { + utils.InternalServerError(w, fmt.Errorf("expected 1 restore report but got %d", len(reports))) + return + } + if reports[0].Err != nil { + utils.InternalServerError(w, reports[0].Err) + return + } if !query.Export { - if len(reports) != 1 { - utils.InternalServerError(w, fmt.Errorf("expected 1 restore report but got %d", len(reports))) - return - } - if reports[0].Err != nil { - utils.InternalServerError(w, reports[0].Err) - return - } utils.WriteResponse(w, http.StatusOK, reports[0]) return } diff --git a/pkg/bindings/containers/checkpoint.go b/pkg/bindings/containers/checkpoint.go index bcb944488..8c072f588 100644 --- a/pkg/bindings/containers/checkpoint.go +++ b/pkg/bindings/containers/checkpoint.go @@ -39,7 +39,7 @@ func Checkpoint(ctx context.Context, nameOrID string, options *CheckpointOptions } defer response.Body.Close() - if !export { + if response.StatusCode != http.StatusOK || !export { return &report, response.Process(&report) } diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go index 3389abd88..da903df9e 100644 --- a/pkg/domain/infra/abi/system.go +++ b/pkg/domain/infra/abi/system.go @@ -11,7 +11,6 @@ import ( "github.com/containers/common/pkg/cgroups" "github.com/containers/common/pkg/config" - cutil "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/entities/reports" @@ -321,19 +320,9 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System return nil, err } - running, err := ic.Libpod.GetRunningContainers() - if err != nil { - return nil, err - } - runningContainers := make([]string, 0, len(running)) - for _, c := range running { - runningContainers = append(runningContainers, c.ID()) - } - dfVolumes := make([]*entities.SystemDfVolumeReport, 0, len(vols)) for _, v := range vols { var reclaimableSize uint64 - var consInUse int mountPoint, err := v.MountPoint() if err != nil { return nil, err @@ -355,14 +344,9 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System if len(inUse) == 0 { reclaimableSize = volSize } - for _, viu := range inUse { - if cutil.StringInSlice(viu, runningContainers) { - consInUse++ - } - } report := entities.SystemDfVolumeReport{ VolumeName: v.Name(), - Links: consInUse, + Links: len(inUse), Size: int64(volSize), ReclaimableSize: int64(reclaimableSize), } diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index 324802a1f..c82c9ba33 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -413,7 +413,7 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [ if err != nil { reports = append(reports, &entities.CheckpointReport{Id: c.ID, Err: err}) } else { - report.RawInput = idToRawInput[report.Id] + report.RawInput = idToRawInput[c.ID] reports = append(reports, report) } } @@ -517,7 +517,7 @@ func (ic *ContainerEngine) ContainerLogs(_ context.Context, nameOrIDs []string, stdout := opts.StdoutWriter != nil stderr := opts.StderrWriter != nil options := new(containers.LogOptions).WithFollow(opts.Follow).WithSince(since).WithUntil(until).WithStderr(stderr) - options.WithStdout(stdout).WithTail(tail) + options.WithStdout(stdout).WithTail(tail).WithTimestamps(opts.Timestamps) var err error stdoutCh := make(chan string) @@ -620,6 +620,9 @@ func (ic *ContainerEngine) ContainerExecDetached(ctx context.Context, nameOrID s } func startAndAttach(ic *ContainerEngine, name string, detachKeys *string, input, output, errput *os.File) error { + if output == nil && errput == nil { + fmt.Printf("%s\n", name) + } attachErr := make(chan error) attachReady := make(chan bool) options := new(containers.AttachOptions).WithStream(true) diff --git a/pkg/machine/e2e/inspect_test.go b/pkg/machine/e2e/inspect_test.go index 0ab928205..fac9f7ebe 100644 --- a/pkg/machine/e2e/inspect_test.go +++ b/pkg/machine/e2e/inspect_test.go @@ -75,5 +75,13 @@ var _ = Describe("podman machine stop", func() { Expect(err).To(BeNil()) Expect(inspectSession).To(Exit(0)) Expect(inspectSession.Bytes()).To(ContainSubstring(name)) + + // check invalid template returns error + inspect = new(inspectMachine) + inspect = inspect.withFormat("{{.Abcde}}") + inspectSession, err = mb.setName(name).setCmd(inspect).run() + Expect(err).To(BeNil()) + Expect(inspectSession).To(Exit(125)) + Expect(inspectSession.errorToString()).To(ContainSubstring("can't evaluate field Abcde in type machine.InspectInfo")) }) }) diff --git a/pkg/rctl/rctl.go b/pkg/rctl/rctl.go new file mode 100644 index 000000000..135cc60cb --- /dev/null +++ b/pkg/rctl/rctl.go @@ -0,0 +1,47 @@ +//go:build freebsd +// +build freebsd + +package rctl + +// #include <sys/rctl.h> +import "C" + +import ( + "bytes" + "fmt" + "strconv" + "strings" + "syscall" + "unsafe" + + "github.com/sirupsen/logrus" +) + +func GetRacct(filter string) (map[string]uint64, error) { + bp, err := syscall.ByteSliceFromString(filter) + if err != nil { + return nil, err + } + var buf [1024]byte + _, _, errno := syscall.Syscall6(syscall.SYS_RCTL_GET_RACCT, + uintptr(unsafe.Pointer(&bp[0])), + uintptr(len(bp)), + uintptr(unsafe.Pointer(&buf[0])), + uintptr(len(buf)), 0, 0) + if errno != 0 { + return nil, fmt.Errorf("error calling rctl_get_racct with filter %s: %v", errno) + } + len := bytes.IndexByte(buf[:], byte(0)) + entries := strings.Split(string(buf[:len]), ",") + res := make(map[string]uint64) + for _, entry := range entries { + kv := strings.SplitN(entry, "=", 2) + key := kv[0] + val, err := strconv.ParseUint(kv[1], 10, 0) + if err != nil { + logrus.Warnf("unexpected rctl entry, ignoring: %s", entry) + } + res[key] = val + } + return res, nil +} diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index 3588313c6..fb22ed221 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -235,6 +235,7 @@ can_use_shortcut () if (strcmp (argv[argc], "mount") == 0 || strcmp (argv[argc], "machine") == 0 + || strcmp (argv[argc], "context") == 0 || strcmp (argv[argc], "search") == 0 || (strcmp (argv[argc], "system") == 0 && argv[argc+1] && strcmp (argv[argc+1], "service") != 0)) { diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go index c18b5654a..736fa5ab3 100644 --- a/pkg/specgen/generate/container.go +++ b/pkg/specgen/generate/container.go @@ -352,7 +352,7 @@ func ConfigToSpec(rt *libpod.Runtime, specg *specgen.SpecGenerator, contaierID s if conf.Spec.Process != nil && conf.Spec.Process.Env != nil { env := make(map[string]string) for _, entry := range conf.Spec.Process.Env { - split := strings.Split(entry, "=") + split := strings.SplitN(entry, "=", 2) if len(split) == 2 { env[split[0]] = split[1] } diff --git a/pkg/systemd/generate/containers.go b/pkg/systemd/generate/containers.go index 0274dd7b7..8510cfd42 100644 --- a/pkg/systemd/generate/containers.go +++ b/pkg/systemd/generate/containers.go @@ -148,6 +148,18 @@ func generateContainerInfo(ctr *libpod.Container, options entities.GenerateSyste return nil, errors.New("conmon PID file path is empty, try to recreate the container with --conmon-pidfile flag") } + // #15284: old units generated without --new can lead to issues on + // shutdown when the containers are created with a custom restart + // policy. + if !options.New { + switch config.RestartPolicy { + case libpodDefine.RestartPolicyNo, libpodDefine.RestartPolicyNone: + // All good + default: + logrus.Warnf("Container %s has restart policy %q which can lead to issues on shutdown: consider recreating the container without a restart policy and use systemd's restart mechanism instead", ctr.ID(), config.RestartPolicy) + } + } + createCommand := []string{} if config.CreateCommand != nil { createCommand = config.CreateCommand diff --git a/pkg/systemd/generate/pods.go b/pkg/systemd/generate/pods.go index 22f568220..729a038a5 100644 --- a/pkg/systemd/generate/pods.go +++ b/pkg/systemd/generate/pods.go @@ -92,7 +92,7 @@ type podInfo struct { Requires []string } -const podTemplate = headerTemplate + `Requires={{{{- range $index, $value := .RequiredServices -}}}}{{{{if $index}}}} {{{{end}}}}{{{{ $value }}}}.service{{{{end}}}} +const podTemplate = headerTemplate + `Wants={{{{- range $index, $value := .RequiredServices -}}}}{{{{if $index}}}} {{{{end}}}}{{{{ $value }}}}.service{{{{end}}}} Before={{{{- range $index, $value := .RequiredServices -}}}}{{{{if $index}}}} {{{{end}}}}{{{{ $value }}}}.service{{{{end}}}} {{{{- if or .Wants .After .Requires }}}} @@ -252,18 +252,19 @@ func generatePodInfo(pod *libpod.Pod, options entities.GenerateSystemdOptions) ( StopTimeout: stopTimeout, GenerateTimestamp: true, CreateCommand: createCommand, + RunRoot: infraCtr.Runtime().RunRoot(), } return &info, nil } -// Unless already specified, the pod's exit policy to "stop". -func setPodExitPolicy(cmd []string) []string { +// Determine whether the command array includes an exit-policy setting +func hasPodExitPolicy(cmd []string) bool { for _, arg := range cmd { if strings.HasPrefix(arg, "--exit-policy=") || arg == "--exit-policy" { - return cmd + return true } } - return append(cmd, "--exit-policy=stop") + return false } // executePodTemplate executes the pod template on the specified podInfo. Note @@ -364,8 +365,10 @@ func executePodTemplate(info *podInfo, options entities.GenerateSystemdOptions) podCreateArgs = append(podCreateArgs, "--replace") } + if !hasPodExitPolicy(append(startCommand, podCreateArgs...)) { + startCommand = append(startCommand, "--exit-policy=stop") + } startCommand = append(startCommand, podCreateArgs...) - startCommand = setPodExitPolicy(startCommand) startCommand = escapeSystemdArguments(startCommand) info.ExecStartPre1 = "/bin/rm -f {{{{.PIDFile}}}} {{{{.PodIDFile}}}}" diff --git a/pkg/systemd/generate/pods_test.go b/pkg/systemd/generate/pods_test.go index 59f217256..000d73e9a 100644 --- a/pkg/systemd/generate/pods_test.go +++ b/pkg/systemd/generate/pods_test.go @@ -7,25 +7,26 @@ import ( "github.com/stretchr/testify/assert" ) -func TestSetPodExitPolicy(t *testing.T) { +func TestHasPodExitPolicy(t *testing.T) { tests := []struct { - input, expected []string + input []string + expected bool }{ { []string{"podman", "pod", "create"}, - []string{"podman", "pod", "create", "--exit-policy=stop"}, + false, }, { []string{"podman", "pod", "create", "--exit-policy=continue"}, - []string{"podman", "pod", "create", "--exit-policy=continue"}, + true, }, { []string{"podman", "pod", "create", "--exit-policy", "continue"}, - []string{"podman", "pod", "create", "--exit-policy", "continue"}, + true, }, } for _, test := range tests { - assert.Equalf(t, test.expected, setPodExitPolicy(test.input), "%v", test.input) + assert.Equalf(t, test.expected, hasPodExitPolicy(test.input), "%v", test.input) } } @@ -70,7 +71,7 @@ Documentation=man:podman-generate-systemd(1) Wants=network-online.target After=network-online.target RequiresMountsFor=/var/run/containers/storage -Requires=container-1.service container-2.service +Wants=container-1.service container-2.service Before=container-1.service container-2.service [Service] @@ -98,7 +99,7 @@ Documentation=man:podman-generate-systemd(1) Wants=network-online.target After=network-online.target RequiresMountsFor=/var/run/containers/storage -Requires=container-1.service container-2.service +Wants=container-1.service container-2.service Before=container-1.service container-2.service [Service] @@ -124,7 +125,7 @@ Documentation=man:podman-generate-systemd(1) Wants=network-online.target After=network-online.target RequiresMountsFor=/var/run/containers/storage -Requires=container-1.service container-2.service +Wants=container-1.service container-2.service Before=container-1.service container-2.service # User-defined dependencies @@ -152,7 +153,7 @@ Documentation=man:podman-generate-systemd(1) Wants=network-online.target After=network-online.target RequiresMountsFor=/var/run/containers/storage -Requires=container-1.service container-2.service +Wants=container-1.service container-2.service Before=container-1.service container-2.service # User-defined dependencies @@ -180,7 +181,7 @@ Documentation=man:podman-generate-systemd(1) Wants=network-online.target After=network-online.target RequiresMountsFor=/var/run/containers/storage -Requires=container-1.service container-2.service +Wants=container-1.service container-2.service Before=container-1.service container-2.service # User-defined dependencies @@ -208,7 +209,7 @@ Documentation=man:podman-generate-systemd(1) Wants=network-online.target After=network-online.target RequiresMountsFor=/var/run/containers/storage -Requires=container-1.service container-2.service +Wants=container-1.service container-2.service Before=container-1.service container-2.service # User-defined dependencies @@ -229,6 +230,33 @@ Type=forking [Install] WantedBy=default.target ` + podNoExplicitName := `# pod-123abc.service +# autogenerated by Podman CI + +[Unit] +Description=Podman pod-123abc.service +Documentation=man:podman-generate-systemd(1) +Wants=network-online.target +After=network-online.target +RequiresMountsFor=/var/run/containers/storage +Wants= +Before= + +[Service] +Environment=PODMAN_SYSTEMD_UNIT=%n +Restart=on-failure +TimeoutStopSec=70 +ExecStartPre=/bin/rm -f %t/pod-123abc.pid %t/pod-123abc.pod-id +ExecStartPre=/usr/bin/podman pod create --infra-conmon-pidfile %t/pod-123abc.pid --pod-id-file %t/pod-123abc.pod-id --exit-policy=stop foo +ExecStart=/usr/bin/podman pod start --pod-id-file %t/pod-123abc.pod-id +ExecStop=/usr/bin/podman pod stop --ignore --pod-id-file %t/pod-123abc.pod-id -t 10 +ExecStopPost=/usr/bin/podman pod rm --ignore -f --pod-id-file %t/pod-123abc.pod-id +PIDFile=%t/pod-123abc.pid +Type=forking + +[Install] +WantedBy=default.target +` podGoodRestartSec := `# pod-123abc.service # autogenerated by Podman CI @@ -239,7 +267,7 @@ Documentation=man:podman-generate-systemd(1) Wants=network-online.target After=network-online.target RequiresMountsFor=/var/run/containers/storage -Requires=container-1.service container-2.service +Wants=container-1.service container-2.service Before=container-1.service container-2.service [Service] @@ -266,7 +294,7 @@ Documentation=man:podman-generate-systemd(1) Wants=network-online.target After=network-online.target RequiresMountsFor=/var/run/containers/storage -Requires=container-1.service container-2.service +Wants=container-1.service container-2.service Before=container-1.service container-2.service [Service] @@ -274,7 +302,7 @@ Environment=PODMAN_SYSTEMD_UNIT=%n Restart=on-failure TimeoutStopSec=70 ExecStartPre=/bin/rm -f %t/pod-123abc.pid %t/pod-123abc.pod-id -ExecStartPre=/usr/bin/podman pod create --infra-conmon-pidfile %t/pod-123abc.pid --pod-id-file %t/pod-123abc.pod-id --name foo "bar=arg with space" --replace --exit-policy=stop +ExecStartPre=/usr/bin/podman pod create --infra-conmon-pidfile %t/pod-123abc.pid --pod-id-file %t/pod-123abc.pod-id --exit-policy=stop --name foo "bar=arg with space" --replace ExecStart=/usr/bin/podman pod start --pod-id-file %t/pod-123abc.pod-id ExecStop=/usr/bin/podman pod stop --ignore --pod-id-file %t/pod-123abc.pod-id -t 10 ExecStopPost=/usr/bin/podman pod rm --ignore -f --pod-id-file %t/pod-123abc.pod-id @@ -294,7 +322,7 @@ Documentation=man:podman-generate-systemd(1) Wants=network-online.target After=network-online.target RequiresMountsFor=/var/run/containers/storage -Requires=container-1.service container-2.service +Wants=container-1.service container-2.service Before=container-1.service container-2.service [Service] @@ -302,7 +330,7 @@ Environment=PODMAN_SYSTEMD_UNIT=%n Restart=on-failure TimeoutStopSec=70 ExecStartPre=/bin/rm -f %t/pod-123abc.pid %t/pod-123abc.pod-id -ExecStartPre=/usr/bin/podman --events-backend none --runroot /root pod create --infra-conmon-pidfile %t/pod-123abc.pid --pod-id-file %t/pod-123abc.pod-id --name foo "bar=arg with space" --replace --exit-policy=stop +ExecStartPre=/usr/bin/podman --events-backend none --runroot /root pod create --infra-conmon-pidfile %t/pod-123abc.pid --pod-id-file %t/pod-123abc.pod-id --exit-policy=stop --name foo "bar=arg with space" --replace ExecStart=/usr/bin/podman --events-backend none --runroot /root pod start --pod-id-file %t/pod-123abc.pod-id ExecStop=/usr/bin/podman --events-backend none --runroot /root pod stop --ignore --pod-id-file %t/pod-123abc.pod-id -t 10 ExecStopPost=/usr/bin/podman --events-backend none --runroot /root pod rm --ignore -f --pod-id-file %t/pod-123abc.pod-id @@ -322,7 +350,7 @@ Documentation=man:podman-generate-systemd(1) Wants=network-online.target After=network-online.target RequiresMountsFor=/var/run/containers/storage -Requires=container-1.service container-2.service +Wants=container-1.service container-2.service Before=container-1.service container-2.service [Service] @@ -330,7 +358,7 @@ Environment=PODMAN_SYSTEMD_UNIT=%n Restart=on-failure TimeoutStopSec=70 ExecStartPre=/bin/rm -f %t/pod-123abc.pid %t/pod-123abc.pod-id -ExecStartPre=/usr/bin/podman pod create --infra-conmon-pidfile %t/pod-123abc.pid --pod-id-file %t/pod-123abc.pod-id --name foo --replace --exit-policy=stop +ExecStartPre=/usr/bin/podman pod create --infra-conmon-pidfile %t/pod-123abc.pid --pod-id-file %t/pod-123abc.pod-id --exit-policy=stop --name foo --replace ExecStart=/usr/bin/podman pod start --pod-id-file %t/pod-123abc.pod-id ExecStop=/usr/bin/podman pod stop --ignore --pod-id-file %t/pod-123abc.pod-id -t 10 ExecStopPost=/usr/bin/podman pod rm --ignore -f --pod-id-file %t/pod-123abc.pod-id @@ -350,7 +378,7 @@ Documentation=man:podman-generate-systemd(1) Wants=network-online.target After=network-online.target RequiresMountsFor=/var/run/containers/storage -Requires=container-1.service container-2.service +Wants=container-1.service container-2.service Before=container-1.service container-2.service [Service] @@ -483,6 +511,23 @@ WantedBy=default.target false, false, }, + {"pod without --name", + podInfo{ + Executable: "/usr/bin/podman", + ServiceName: "pod-123abc", + InfraNameOrID: "jadda-jadda-infra", + PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid", + StopTimeout: 10, + PodmanVersion: "CI", + GraphRoot: "/var/lib/containers/storage", + RunRoot: "/var/run/containers/storage", + CreateCommand: []string{"podman", "pod", "create", "foo"}, + }, + podNoExplicitName, + true, + false, + false, + }, {"pod restartSec", podInfo{ Executable: "/usr/bin/podman", |