aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@gmail.com>2018-08-13 15:39:11 -0400
committerAtomic Bot <atomic-devel@projectatomic.io>2018-08-15 18:07:04 +0000
commit0998808a752a8a7ae43f2630023b22c1b3de47a4 (patch)
tree7307d450f56898f5779c324b8c75efd2b40060f0
parentad7d46957156a2ab9ae5bae6b4e337d941a3b971 (diff)
downloadpodman-0998808a752a8a7ae43f2630023b22c1b3de47a4.tar.gz
podman-0998808a752a8a7ae43f2630023b22c1b3de47a4.tar.bz2
podman-0998808a752a8a7ae43f2630023b22c1b3de47a4.zip
Create pod CGroups when using the systemd cgroup driver
Signed-off-by: Matthew Heon <matthew.heon@gmail.com> Closes: #1266 Approved by: baude
-rw-r--r--libpod/oci_linux.go10
-rw-r--r--libpod/pod_internal.go8
-rw-r--r--libpod/runtime_pod_linux.go46
-rw-r--r--libpod/util.go58
4 files changed, 109 insertions, 13 deletions
diff --git a/libpod/oci_linux.go b/libpod/oci_linux.go
index bdf859d7d..dacc92c62 100644
--- a/libpod/oci_linux.go
+++ b/libpod/oci_linux.go
@@ -24,8 +24,14 @@ func (r *OCIRuntime) moveConmonToCgroup(ctr *Container, cgroupParent string, cmd
if r.cgroupManager == SystemdCgroupsManager {
unitName := createUnitName("libpod-conmon", ctr.ID())
- logrus.Infof("Running conmon under slice %s and unitName %s", cgroupParent, unitName)
- if err := utils.RunUnderSystemdScope(cmd.Process.Pid, cgroupParent, unitName); err != nil {
+ realCgroupParent := cgroupParent
+ splitParent := strings.Split(cgroupParent, "/")
+ if strings.HasSuffix(cgroupParent, ".slice") && len(splitParent) > 1 {
+ realCgroupParent = splitParent[len(splitParent)-1]
+ }
+
+ logrus.Infof("Running conmon under slice %s and unitName %s", realCgroupParent, unitName)
+ if err := utils.RunUnderSystemdScope(cmd.Process.Pid, realCgroupParent, unitName); err != nil {
logrus.Warnf("Failed to add conmon to systemd sandbox cgroup: %v", err)
}
} else {
diff --git a/libpod/pod_internal.go b/libpod/pod_internal.go
index c8d8405bb..1ba4487ab 100644
--- a/libpod/pod_internal.go
+++ b/libpod/pod_internal.go
@@ -2,6 +2,7 @@ package libpod
import (
"context"
+ "fmt"
"path/filepath"
"strings"
"time"
@@ -67,8 +68,11 @@ func (p *Pod) refresh() error {
if p.config.UsePodCgroup {
switch p.runtime.config.CgroupManager {
case SystemdCgroupsManager:
- // NOOP for now, until proper systemd cgroup management
- // is implemented
+ cgroupPath, err := systemdSliceFromPath(p.config.CgroupParent, fmt.Sprintf("libpod_pod_%s", p.ID()))
+ if err != nil {
+ logrus.Errorf("Error creating CGroup for pod %s: %v", p.ID(), err)
+ }
+ p.state.CgroupPath = cgroupPath
case CgroupfsCgroupsManager:
p.state.CgroupPath = filepath.Join(p.config.CgroupParent, p.ID())
diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go
index 58affa45f..3592c2fee 100644
--- a/libpod/runtime_pod_linux.go
+++ b/libpod/runtime_pod_linux.go
@@ -4,6 +4,7 @@ package libpod
import (
"context"
+ "fmt"
"path"
"path/filepath"
"strings"
@@ -70,12 +71,23 @@ func (r *Runtime) NewPod(options ...PodCreateOption) (*Pod, error) {
} else if len(pod.config.CgroupParent) < 6 || !strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") {
return nil, errors.Wrapf(ErrInvalidArg, "did not receive systemd slice as cgroup parent when using systemd to manage cgroups")
}
- // Creating CGroup path is currently a NOOP until proper systemd
- // cgroup management is merged
+ // If we are set to use pod cgroups, set the cgroup parent that
+ // all containers in the pod will share
+ if pod.config.UsePodCgroup {
+ cgroupPath, err := systemdSliceFromPath(pod.config.CgroupParent, fmt.Sprintf("libpod_pod_%s", pod.ID()))
+ if err != nil {
+ return nil, errors.Wrapf(err, "unable to create pod cgroup for pod %s", pod.ID())
+ }
+ pod.state.CgroupPath = cgroupPath
+ }
default:
return nil, errors.Wrapf(ErrInvalidArg, "unsupported CGroup manager: %s - cannot validate cgroup parent", r.config.CgroupManager)
}
+ if pod.config.UsePodCgroup {
+ logrus.Debugf("Got pod cgroup as %s", pod.state.CgroupPath)
+ }
+
if err := r.state.AddPod(pod); err != nil {
return nil, errors.Wrapf(err, "error adding pod to state")
}
@@ -91,11 +103,20 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
return ErrRuntimeStopped
}
+ if !p.valid {
+ if ok, _ := r.state.HasPod(p.ID()); !ok {
+ // Pod was either already removed, or never existed to
+ // begin with
+ return nil
+ }
+ }
+
p.lock.Lock()
defer p.lock.Unlock()
- if !p.valid {
- return ErrPodRemoved
+ // Force a pod update
+ if err := p.updatePod(); err != nil {
+ return err
}
ctrs, err := r.state.PodContainers(p)
@@ -216,20 +237,27 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
// Remove pod cgroup, if present
if p.state.CgroupPath != "" {
+ logrus.Debugf("Removing pod cgroup %s", p.state.CgroupPath)
+
switch p.runtime.config.CgroupManager {
case SystemdCgroupsManager:
- // NOOP for now, until proper systemd cgroup management
- // is implemented
+ if err := deleteSystemdCgroup(p.state.CgroupPath); err != nil {
+ // The pod is already almost gone.
+ // No point in hard-failing if we fail
+ // this bit of cleanup.
+ logrus.Errorf("Error deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err)
+ }
case CgroupfsCgroupsManager:
// Delete the cgroupfs cgroup
- logrus.Debugf("Removing pod cgroup %s", p.state.CgroupPath)
-
cgroup, err := cgroups.Load(cgroups.V1, cgroups.StaticPath(p.state.CgroupPath))
if err != nil && err != cgroups.ErrCgroupDeleted {
return err
} else if err == nil {
if err := cgroup.Delete(); err != nil {
- return err
+ // The pod is already almost gone.
+ // No point in hard-failing if we fail
+ // this bit of cleanup.
+ logrus.Errorf("Error deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err)
}
}
default:
diff --git a/libpod/util.go b/libpod/util.go
index 13235059f..5b16b5755 100644
--- a/libpod/util.go
+++ b/libpod/util.go
@@ -9,10 +9,12 @@ import (
"strings"
"time"
+ "github.com/containerd/cgroups"
"github.com/containers/image/signature"
"github.com/containers/image/types"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
// Runtime API constants
@@ -123,6 +125,62 @@ func WaitForFile(path string, timeout time.Duration) error {
}
}
+// systemdSliceFromPath makes a new systemd slice under the given parent with
+// the given name.
+// The parent must be a slice. The name must NOT include ".slice"
+func systemdSliceFromPath(parent, name string) (string, error) {
+ cgroupPath, err := assembleSystemdCgroupName(parent, name)
+ if err != nil {
+ return "", err
+ }
+
+ logrus.Debugf("Created cgroup path %s for parent %s and name %s", cgroupPath, parent, name)
+
+ if err := makeSystemdCgroup(cgroupPath); err != nil {
+ return "", errors.Wrapf(err, "error creating cgroup %s", cgroupPath)
+ }
+
+ logrus.Debugf("Created cgroup %s", cgroupPath)
+
+ return cgroupPath, nil
+}
+
+// makeSystemdCgroup creates a systemd CGroup at the given location.
+func makeSystemdCgroup(path string) error {
+ controller, err := cgroups.NewSystemd(SystemdDefaultCgroupParent)
+ if err != nil {
+ return err
+ }
+
+ return controller.Create(path, &spec.LinuxResources{})
+}
+
+// deleteSystemdCgroup deletes the systemd cgroup at the given location
+func deleteSystemdCgroup(path string) error {
+ controller, err := cgroups.NewSystemd(SystemdDefaultCgroupParent)
+ if err != nil {
+ return err
+ }
+
+ return controller.Delete(path)
+}
+
+// assembleSystemdCgroupName creates a systemd cgroup path given a base and
+// a new component to add.
+// The base MUST be systemd slice (end in .slice)
+func assembleSystemdCgroupName(baseSlice, newSlice string) (string, error) {
+ const sliceSuffix = ".slice"
+
+ if !strings.HasSuffix(baseSlice, sliceSuffix) {
+ return "", errors.Wrapf(ErrInvalidArg, "cannot assemble cgroup path with base %q - must end in .slice", baseSlice)
+ }
+
+ noSlice := strings.TrimSuffix(baseSlice, sliceSuffix)
+ final := fmt.Sprintf("%s/%s-%s%s", baseSlice, noSlice, newSlice, sliceSuffix)
+
+ return final, nil
+}
+
type byDestination []spec.Mount
func (m byDestination) Len() int {