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 ++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 16 deletions(-) (limited to 'pkg') 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, -- 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(+) (limited to 'pkg') 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 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(-) (limited to 'pkg') 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 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(-) (limited to 'pkg') 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(+) (limited to 'pkg') 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 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(-) (limited to 'pkg') 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