Add ability to pause/unpause containers via cgroups freeze

This patch adds pause/unpause to the command line, api, and drivers
for use on containers.  This is implemented using the cgroups/freeze
utility in libcontainer and lxc freeze/unfreeze.

Co-Authored-By: Eric Windisch <ewindisch@docker.com>
Co-Authored-By: Chris Alfonso <calfonso@redhat.com>
Docker-DCO-1.1-Signed-off-by: Ian Main <imain@redhat.com> (github: imain)
This commit is contained in:
Ian Main
2014-06-04 13:33:44 -06:00
committed by Chris Alfonso
parent 1f5b323208
commit b054569cde
10 changed files with 248 additions and 0 deletions
+2
View File
@@ -83,6 +83,8 @@ type TtyTerminal interface {
type Driver interface {
Run(c *Command, pipes *Pipes, startCallback StartCallback) (int, error) // Run executes the process and blocks until the process exits and returns the exit code
Kill(c *Command, sig int) error
Pause(c *Command) error
Unpause(c *Command) error
Name() string // Driver name
Info(id string) Info // "temporary" hack (until we move state from core to plugins)
GetPidsForContainer(id string) ([]int, error) // Returns a list of pids for the given container.
+24
View File
@@ -218,6 +218,30 @@ func (d *driver) Kill(c *execdriver.Command, sig int) error {
return KillLxc(c.ID, sig)
}
func (d *driver) Pause(c *execdriver.Command) error {
_, err := exec.LookPath("lxc-freeze")
if err == nil {
output, errExec := exec.Command("lxc-freeze", "-n", c.ID).CombinedOutput()
if errExec != nil {
return fmt.Errorf("Err: %s Output: %s", errExec, output)
}
}
return err
}
func (d *driver) Unpause(c *execdriver.Command) error {
_, err := exec.LookPath("lxc-unfreeze")
if err == nil {
output, errExec := exec.Command("lxc-unfreeze", "-n", c.ID).CombinedOutput()
if errExec != nil {
return fmt.Errorf("Err: %s Output: %s", errExec, output)
}
}
return err
}
func (d *driver) Terminate(c *execdriver.Command) error {
return KillLxc(c.ID, 9)
}
@@ -27,6 +27,7 @@ var actions = map[string]Action{
"cgroups.memory_reservation": memoryReservation, // set the memory reservation
"cgroups.memory_swap": memorySwap, // set the memory swap limit
"cgroups.cpuset.cpus": cpusetCpus, // set the cpus used
"cgroups.freezer": freezer, // set the frozen/thaw state
"systemd.slice": systemdSlice, // set parent Slice used for systemd unit
@@ -35,6 +36,16 @@ var actions = map[string]Action{
"fs.readonly": readonlyFs, // make the rootfs of the container read only
}
func freezer(container *libcontainer.Container, context interface{}, value string) error {
if container.Cgroups == nil {
return fmt.Errorf("cannot set cgroups when they are disabled")
}
container.Cgroups.Freezer = value
return nil
}
func cpusetCpus(container *libcontainer.Container, context interface{}, value string) error {
if container.Cgroups == nil {
return fmt.Errorf("cannot set cgroups when they are disabled")
+26
View File
@@ -145,6 +145,32 @@ func (d *driver) Kill(p *execdriver.Command, sig int) error {
return syscall.Kill(p.Process.Pid, syscall.Signal(sig))
}
func (d *driver) Pause(c *execdriver.Command) error {
active := d.activeContainers[c.ID]
active.container.Cgroups.Freezer = "FROZEN"
pid := c.Process.Pid
if systemd.UseSystemd() {
_, err := systemd.Apply(active.container.Cgroups, pid)
return err
}
_, err := fs.Apply(active.container.Cgroups, pid)
return err
}
func (d *driver) Unpause(c *execdriver.Command) error {
active := d.activeContainers[c.ID]
active.container.Cgroups.Freezer = "THAWED"
pid := c.Process.Pid
if systemd.UseSystemd() {
_, err := systemd.Apply(active.container.Cgroups, pid)
return err
}
_, err := fs.Apply(active.container.Cgroups, pid)
return err
}
func (d *driver) Terminate(p *execdriver.Command) error {
// lets check the start time for the process
started, err := d.readStartTime(p)