From fb88074e68db25474290535e8a778e39434cc2a2 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 3 Jul 2019 18:18:02 +0200 Subject: podman: add --ulimit host add a simple way to copy ulimit values from the host. if --ulimit host is used then the current ulimits in place are copied to the container. Signed-off-by: Giuseppe Scrivano --- docs/podman-create.1.md | 2 ++ docs/podman-run.1.md | 2 ++ pkg/spec/spec.go | 20 ++++++++++++++++++++ pkg/spec/spec_linux.go | 42 ++++++++++++++++++++++++++++++++++++++++++ pkg/spec/spec_unsupported.go | 7 +++++++ test/e2e/run_test.go | 21 +++++++++++++++++++++ 6 files changed, 94 insertions(+) create mode 100644 pkg/spec/spec_linux.go create mode 100644 pkg/spec/spec_unsupported.go diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md index e22666402..2425c817b 100644 --- a/docs/podman-create.1.md +++ b/docs/podman-create.1.md @@ -723,6 +723,8 @@ The following example maps uids 0-2000 in the container to the uids 30000-31999 Ulimit options +You can pass `host` to copy the current configuration from the host. + **--user**, **-u**=*user* Sets the username or UID used and optionally the groupname or GID for the specified command. diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md index 30242080b..84bf4a11b 100644 --- a/docs/podman-run.1.md +++ b/docs/podman-run.1.md @@ -759,6 +759,8 @@ The example maps uids 0-2000 in the container to the uids 30000-31999 on the hos Ulimit options +You can pass `host` to copy the current configuration from the host. + **--user**, **-u**=*user* Sets the username or UID used and optionally the groupname or GID for the specified command. diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 06d1ac12d..c9548f0d3 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -20,6 +20,12 @@ import ( const cpuPeriod = 100000 +type systemUlimit struct { + name string + max uint64 + cur uint64 +} + func getAvailableGids() (int64, error) { idMap, err := user.ParseIDMapFile("/proc/self/gid_map") if err != nil { @@ -553,6 +559,20 @@ func addRlimits(config *CreateConfig, g *generate.Generator) error { ) for _, u := range config.Resources.Ulimit { + if u == "host" { + if len(config.Resources.Ulimit) != 1 { + return errors.New("ulimit can use host only once") + } + hostLimits, err := getHostRlimits() + if err != nil { + return err + } + for _, i := range hostLimits { + g.AddProcessRlimits(i.name, i.max, i.cur) + } + break + } + ul, err := units.ParseUlimit(u) if err != nil { return errors.Wrapf(err, "ulimit option %q requires name=SOFT:HARD, failed to be parsed", u) diff --git a/pkg/spec/spec_linux.go b/pkg/spec/spec_linux.go new file mode 100644 index 000000000..fcdfc5c4e --- /dev/null +++ b/pkg/spec/spec_linux.go @@ -0,0 +1,42 @@ +//+build linux + +package createconfig + +import ( + "syscall" + + "github.com/pkg/errors" +) + +type systemRlimit struct { + name string + value int +} + +var systemLimits = []systemRlimit{ + {"RLIMIT_AS", syscall.RLIMIT_AS}, + {"RLIMIT_CORE", syscall.RLIMIT_CORE}, + {"RLIMIT_CPU", syscall.RLIMIT_CPU}, + {"RLIMIT_DATA", syscall.RLIMIT_DATA}, + {"RLIMIT_FSIZE", syscall.RLIMIT_FSIZE}, + {"RLIMIT_NOFILE", syscall.RLIMIT_NOFILE}, + {"RLIMIT_STACK", syscall.RLIMIT_STACK}, +} + +func getHostRlimits() ([]systemUlimit, error) { + ret := []systemUlimit{} + for _, i := range systemLimits { + var l syscall.Rlimit + if err := syscall.Getrlimit(i.value, &l); err != nil { + return nil, errors.Wrapf(err, "cannot read limits for %s", i.name) + } + s := systemUlimit{ + name: i.name, + max: l.Max, + cur: l.Cur, + } + ret = append(ret, s) + } + return ret, nil + +} diff --git a/pkg/spec/spec_unsupported.go b/pkg/spec/spec_unsupported.go new file mode 100644 index 000000000..0f6a9acdc --- /dev/null +++ b/pkg/spec/spec_unsupported.go @@ -0,0 +1,7 @@ +//+build !linux + +package createconfig + +func getHostRlimits() ([]systemUlimit, error) { + return nil, nil +} diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 3fc628589..f95c5298d 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -8,7 +8,9 @@ import ( "net" "os" "path/filepath" + "strconv" "strings" + "syscall" "time" . "github.com/containers/libpod/test/utils" @@ -250,6 +252,25 @@ var _ = Describe("Podman run", func() { Expect(session.OutputToString()).To(ContainSubstring("100")) }) + It("podman run limits host test", func() { + SkipIfRemote() + + var l syscall.Rlimit + + err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l) + Expect(err).To(BeNil()) + + session := podmanTest.Podman([]string{"run", "--rm", "--ulimit", "host", fedoraMinimal, "ulimit", "-Hn"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + ulimitCtrStr := strings.TrimSpace(session.OutputToString()) + ulimitCtr, err := strconv.ParseUint(ulimitCtrStr, 10, 0) + Expect(err).To(BeNil()) + + Expect(ulimitCtr).Should(BeNumerically(">=", l.Max)) + }) + It("podman run with cidfile", func() { session := podmanTest.Podman([]string{"run", "--cidfile", tempdir + "cidfile", ALPINE, "ls"}) session.WaitWithDefaultTimeout() -- cgit v1.2.3-54-g00ecf