Merge pull request #339 from avagin/api-freezer
new-api: implement Pause() and Resume()
This commit is contained in:
commit
c70b6812b5
|
@ -143,14 +143,16 @@ func (m *Manager) Freeze(state cgroups.FreezerState) error {
|
|||
return err
|
||||
}
|
||||
|
||||
prevState := m.Cgroups.Freezer
|
||||
m.Cgroups.Freezer = state
|
||||
|
||||
freezer := subsystems["freezer"]
|
||||
err = freezer.Set(d)
|
||||
if err != nil {
|
||||
m.Cgroups.Freezer = prevState
|
||||
return err
|
||||
}
|
||||
|
||||
m.Cgroups.Freezer = state
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -204,6 +204,9 @@ func newTestRoot() (string, error) {
|
|||
}
|
||||
|
||||
func TestEnter(t *testing.T) {
|
||||
if testing.Short() {
|
||||
return
|
||||
}
|
||||
root, err := newTestRoot()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -300,3 +303,77 @@ func TestEnter(t *testing.T) {
|
|||
t.Fatal("The second process isn't in the required pid namespace", pidns, pidns2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFreeze(t *testing.T) {
|
||||
if testing.Short() {
|
||||
return
|
||||
}
|
||||
root, err := newTestRoot()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(root)
|
||||
|
||||
rootfs, err := newRootFs()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer remove(rootfs)
|
||||
|
||||
config := newTemplateConfig(rootfs)
|
||||
|
||||
factory, err := libcontainer.New(root, []string{os.Args[0], "init", "--"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
container, err := factory.Create("test", config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer container.Destroy()
|
||||
|
||||
stdinR, stdinW, err := os.Pipe()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
pconfig := libcontainer.ProcessConfig{
|
||||
Args: []string{"cat"},
|
||||
Stdin: stdinR,
|
||||
}
|
||||
pid, err := container.StartProcess(&pconfig)
|
||||
stdinR.Close()
|
||||
defer stdinW.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
process, err := os.FindProcess(pid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := container.Pause(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
state, err := container.RunState()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if state != configs.Paused {
|
||||
t.Fatal("Unexpected state: ", state)
|
||||
}
|
||||
if err := container.Resume(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
stdinW.Close()
|
||||
s, err := process.Wait()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !s.Success() {
|
||||
t.Fatal(s.String())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,11 @@ func (c *linuxContainer) RunState() (configs.RunState, error) {
|
|||
return 0, err
|
||||
}
|
||||
|
||||
if c.config.Cgroups != nil &&
|
||||
c.config.Cgroups.Freezer == cgroups.Frozen {
|
||||
return configs.Paused, nil
|
||||
}
|
||||
|
||||
//FIXME get a cgroup state to check other states
|
||||
|
||||
return configs.Running, nil
|
||||
|
@ -163,13 +168,11 @@ func (c *linuxContainer) Destroy() error {
|
|||
}
|
||||
|
||||
func (c *linuxContainer) Pause() error {
|
||||
glog.Info("pause container")
|
||||
panic("not implemented")
|
||||
return c.cgroupManager.Freeze(cgroups.Frozen)
|
||||
}
|
||||
|
||||
func (c *linuxContainer) Resume() error {
|
||||
glog.Info("resume container")
|
||||
panic("not implemented")
|
||||
return c.cgroupManager.Freeze(cgroups.Thawed)
|
||||
}
|
||||
|
||||
func (c *linuxContainer) Signal(pid, signal int) error {
|
||||
|
|
|
@ -19,9 +19,7 @@ import (
|
|||
// Move this to libcontainer package.
|
||||
// Exec performs setup outside of a namespace so that a container can be
|
||||
// executed. Exec is a high level function for working with container namespaces.
|
||||
func Exec(args []string, env []string, console string, command *exec.Cmd, container *configs.Config, cgroupManager cgroups.Manager, state *configs.State) error {
|
||||
var err error
|
||||
|
||||
func Exec(args []string, env []string, console string, command *exec.Cmd, container *configs.Config, cgroupManager cgroups.Manager, state *configs.State) (err error) {
|
||||
// create a pipe so that we can syncronize with the namespaced process and
|
||||
// pass the state and configuration to the child process
|
||||
parent, child, err := newInitPipe()
|
||||
|
@ -73,7 +71,11 @@ func Exec(args []string, env []string, console string, command *exec.Cmd, contai
|
|||
if err != nil {
|
||||
return terminate(err)
|
||||
}
|
||||
defer cgroupManager.Destroy()
|
||||
defer func() {
|
||||
if err != nil {
|
||||
cgroupManager.Destroy()
|
||||
}
|
||||
}()
|
||||
|
||||
var networkState network.NetworkState
|
||||
if err := InitializeNetworking(container, command.Process.Pid, &networkState); err != nil {
|
||||
|
|
Loading…
Reference in New Issue