Have cgroup.Apply return paths to setup cgroups

There is no reason to have a special type returned from the cgroups
Apply function for getting the paths and cleanup.  With access to the
paths we can just delete what we need.

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2014-11-14 17:22:10 -08:00
parent 5cacd48132
commit bc7efa6b81
6 changed files with 37 additions and 108 deletions

View File

@ -53,8 +53,3 @@ type Cgroup struct {
Freezer FreezerState `json:"freezer,omitempty"` // set the freeze value for the process Freezer FreezerState `json:"freezer,omitempty"` // set the freeze value for the process
Slice string `json:"slice,omitempty"` // Parent slice to use for systemd Slice string `json:"slice,omitempty"` // Parent slice to use for systemd
} }
type ActiveCgroup interface {
Cleanup() error
Paths() (map[string]string, error)
}

View File

@ -24,16 +24,6 @@ var createCommand = cli.Command{
Action: createAction, Action: createAction,
} }
var destroyCommand = cli.Command{
Name: "destroy",
Usage: "Destroy an existing cgroup container.",
Flags: []cli.Flag{
cli.StringFlag{Name: "name, n", Value: "", Usage: "container name"},
cli.StringFlag{Name: "parent, p", Value: "", Usage: "container parent"},
},
Action: destroyAction,
}
var pauseCommand = cli.Command{ var pauseCommand = cli.Command{
Name: "pause", Name: "pause",
Usage: "Pause cgroup", Usage: "Pause cgroup",
@ -170,22 +160,6 @@ func createAction(context *cli.Context) {
} }
} }
func destroyAction(context *cli.Context) {
config, err := getConfig(context)
if err != nil {
log.Fatal(err)
}
killAll(config)
// Systemd will clean up cgroup state for empty container.
if !systemd.UseSystemd() {
err := fs.Cleanup(config)
if err != nil {
log.Fatal(err)
}
}
}
func pauseAction(context *cli.Context) { func pauseAction(context *cli.Context) {
setFreezerState(context, cgroups.Frozen) setFreezerState(context, cgroups.Frozen)
} }
@ -224,7 +198,6 @@ func main() {
app.Commands = []cli.Command{ app.Commands = []cli.Command{
createCommand, createCommand,
destroyCommand,
pauseCommand, pauseCommand,
resumeCommand, resumeCommand,
psCommand, psCommand,

View File

@ -57,20 +57,33 @@ type data struct {
pid int pid int
} }
func Apply(c *cgroups.Cgroup, pid int) (cgroups.ActiveCgroup, error) { func Apply(c *cgroups.Cgroup, pid int) (map[string]string, error) {
d, err := getCgroupData(c, pid) d, err := getCgroupData(c, pid)
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, sys := range subsystems { paths := make(map[string]string)
for name, sys := range subsystems {
if err := sys.Set(d); err != nil { if err := sys.Set(d); err != nil {
d.Cleanup() for _, p := range paths {
os.RemoveAll(p)
}
return nil, err return nil, err
} }
p, err := d.path(name)
if err != nil {
if cgroups.IsNotFound(err) {
continue
} }
for _, p := range paths {
return d, nil os.RemoveAll(p)
}
return nil, err
}
paths[name] = p
}
return paths, nil
} }
// Symmetrical public function to update device based cgroups. Also available // Symmetrical public function to update device based cgroups. Also available
@ -86,14 +99,6 @@ func ApplyDevices(c *cgroups.Cgroup, pid int) error {
return devices.Set(d) return devices.Set(d)
} }
func Cleanup(c *cgroups.Cgroup) error {
d, err := getCgroupData(c, 0)
if err != nil {
return fmt.Errorf("Could not get Cgroup data %s", err)
}
return d.Cleanup()
}
func GetStats(systemPaths map[string]string) (*cgroups.Stats, error) { func GetStats(systemPaths map[string]string) (*cgroups.Stats, error) {
stats := cgroups.NewStats() stats := cgroups.NewStats()
for name, path := range systemPaths { for name, path := range systemPaths {
@ -164,26 +169,6 @@ func (raw *data) parent(subsystem string) (string, error) {
return filepath.Join(raw.root, subsystem, initPath), nil return filepath.Join(raw.root, subsystem, initPath), nil
} }
func (raw *data) Paths() (map[string]string, error) {
paths := make(map[string]string)
for sysname := range subsystems {
path, err := raw.path(sysname)
if err != nil {
// Don't fail if a cgroup hierarchy was not found, just skip this subsystem
if cgroups.IsNotFound(err) {
continue
}
return nil, err
}
paths[sysname] = path
}
return paths, nil
}
func (raw *data) path(subsystem string) (string, error) { func (raw *data) path(subsystem string) (string, error) {
// If the cgroup name/path is absolute do not look relative to the cgroup of the init process. // If the cgroup name/path is absolute do not look relative to the cgroup of the init process.
if filepath.IsAbs(raw.cgroup) { if filepath.IsAbs(raw.cgroup) {
@ -222,13 +207,6 @@ func (raw *data) join(subsystem string) (string, error) {
return path, nil return path, nil
} }
func (raw *data) Cleanup() error {
for _, sys := range subsystems {
sys.Remove(raw)
}
return nil
}
func writeFile(dir, file, data string) error { func writeFile(dir, file, data string) error {
return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700) return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700)
} }

View File

@ -12,7 +12,7 @@ func UseSystemd() bool {
return false return false
} }
func Apply(c *cgroups.Cgroup, pid int) (cgroups.ActiveCgroup, error) { func Apply(c *cgroups.Cgroup, pid int) (map[string]string, error) {
return nil, fmt.Errorf("Systemd not supported") return nil, fmt.Errorf("Systemd not supported")
} }

View File

@ -81,7 +81,7 @@ func getIfaceForUnit(unitName string) string {
return "Unit" return "Unit"
} }
func Apply(c *cgroups.Cgroup, pid int) (cgroups.ActiveCgroup, error) { func Apply(c *cgroups.Cgroup, pid int) (map[string]string, error) {
var ( var (
unitName = getUnitName(c) unitName = getUnitName(c)
slice = "system.slice" slice = "system.slice"
@ -149,14 +149,6 @@ func Apply(c *cgroups.Cgroup, pid int) (cgroups.ActiveCgroup, error) {
} }
} }
return res, nil
}
func writeFile(dir, file, data string) error {
return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700)
}
func (c *systemdCgroup) Paths() (map[string]string, error) {
paths := make(map[string]string) paths := make(map[string]string)
for _, sysname := range []string{ for _, sysname := range []string{
"devices", "devices",
@ -168,7 +160,7 @@ func (c *systemdCgroup) Paths() (map[string]string, error) {
"perf_event", "perf_event",
"freezer", "freezer",
} { } {
subsystemPath, err := getSubsystemPath(c.cgroup, sysname) subsystemPath, err := getSubsystemPath(res.cgroup, sysname)
if err != nil { if err != nil {
// Don't fail if a cgroup hierarchy was not found, just skip this subsystem // Don't fail if a cgroup hierarchy was not found, just skip this subsystem
if cgroups.IsNotFound(err) { if cgroups.IsNotFound(err) {
@ -181,18 +173,8 @@ func (c *systemdCgroup) Paths() (map[string]string, error) {
return paths, nil return paths, nil
} }
func (c *systemdCgroup) Cleanup() error { func writeFile(dir, file, data string) error {
// systemd cleans up, we don't need to do much return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700)
paths, err := c.Paths()
if err != nil {
return err
}
for _, path := range paths {
os.RemoveAll(path)
}
return nil
} }
func joinFreezer(c *cgroups.Cgroup, pid int) error { func joinFreezer(c *cgroups.Cgroup, pid int) error {

View File

@ -10,7 +10,6 @@ import (
"syscall" "syscall"
"github.com/docker/libcontainer" "github.com/docker/libcontainer"
"github.com/docker/libcontainer/cgroups"
"github.com/docker/libcontainer/cgroups/fs" "github.com/docker/libcontainer/cgroups/fs"
"github.com/docker/libcontainer/cgroups/systemd" "github.com/docker/libcontainer/cgroups/systemd"
"github.com/docker/libcontainer/network" "github.com/docker/libcontainer/network"
@ -60,16 +59,11 @@ func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Wri
// Do this before syncing with child so that no children // Do this before syncing with child so that no children
// can escape the cgroup // can escape the cgroup
cgroupRef, err := SetupCgroups(container, command.Process.Pid) cgroupPaths, err := SetupCgroups(container, command.Process.Pid)
if err != nil {
return terminate(err)
}
defer cgroupRef.Cleanup()
cgroupPaths, err := cgroupRef.Paths()
if err != nil { if err != nil {
return terminate(err) return terminate(err)
} }
defer removeCgroupPaths(cgroupPaths)
var networkState network.NetworkState var networkState network.NetworkState
if err := InitializeNetworking(container, command.Process.Pid, &networkState); err != nil { if err := InitializeNetworking(container, command.Process.Pid, &networkState); err != nil {
@ -153,18 +147,15 @@ func DefaultCreateCommand(container *libcontainer.Config, console, dataPath, ini
// SetupCgroups applies the cgroup restrictions to the process running in the container based // SetupCgroups applies the cgroup restrictions to the process running in the container based
// on the container's configuration // on the container's configuration
func SetupCgroups(container *libcontainer.Config, nspid int) (cgroups.ActiveCgroup, error) { func SetupCgroups(container *libcontainer.Config, nspid int) (map[string]string, error) {
if container.Cgroups != nil { if container.Cgroups != nil {
c := container.Cgroups c := container.Cgroups
if systemd.UseSystemd() { if systemd.UseSystemd() {
return systemd.Apply(c, nspid) return systemd.Apply(c, nspid)
} }
return fs.Apply(c, nspid) return fs.Apply(c, nspid)
} }
return map[string]string{}, nil
return nil, nil
} }
// InitializeNetworking creates the container's network stack outside of the namespace and moves // InitializeNetworking creates the container's network stack outside of the namespace and moves
@ -181,3 +172,13 @@ func InitializeNetworking(container *libcontainer.Config, nspid int, networkStat
} }
return nil return nil
} }
// removeCgroupPaths takes the subsystem paths for each cgroup that was
// setup for the container and removes them from the cgroup filesystem.
// Errors are ignored during the removal because we don't want to end up
// with partially removed cgroups.
func removeCgroupPaths(paths map[string]string) {
for _, path := range paths {
os.RemoveAll(path)
}
}