Allow delete of created container

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2016-05-27 13:13:11 -07:00
parent 06fab0f860
commit 1d61abea46
9 changed files with 68 additions and 54 deletions

View File

@ -6,6 +6,8 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"syscall"
"time"
"github.com/codegangsta/cli" "github.com/codegangsta/cli"
"github.com/opencontainers/runc/libcontainer" "github.com/opencontainers/runc/libcontainer"
@ -41,10 +43,22 @@ status of "ubuntu01" as "stopped" the following will delete resources held for
if err != nil { if err != nil {
return err return err
} }
if s != libcontainer.Stopped { switch s {
case libcontainer.Stopped:
destroy(container)
case libcontainer.Created:
container.Signal(syscall.SIGKILL)
for i := 0; i < 100; i++ {
time.Sleep(100 * time.Millisecond)
if err := container.Signal(syscall.Signal(0)); err != nil {
destroy(container)
return nil
}
}
return fmt.Errorf("container init still running")
default:
return fmt.Errorf("cannot delete container that is not stopped: %s", s) return fmt.Errorf("cannot delete container that is not stopped: %s", s)
} }
destroy(container)
return nil return nil
}, },
} }

View File

@ -123,7 +123,7 @@ type BaseContainer interface {
// SystemError - System error. // SystemError - System error.
Start(process *Process) (err error) Start(process *Process) (err error)
// StartI immediatly starts the process inside the conatiner. Returns error if process // Run immediatly starts the process inside the conatiner. Returns error if process
// fails to start. It does not block waiting for a SIGCONT after start returns but // fails to start. It does not block waiting for a SIGCONT after start returns but
// sends the signal when the process has completed. // sends the signal when the process has completed.
// //
@ -132,7 +132,7 @@ type BaseContainer interface {
// ConfigInvalid - config is invalid, // ConfigInvalid - config is invalid,
// ContainerPaused - Container is paused, // ContainerPaused - Container is paused,
// SystemError - System error. // SystemError - System error.
StartI(process *Process) (err error) Run(process *Process) (err error)
// Destroys the container after killing all running processes. // Destroys the container after killing all running processes.
// //

View File

@ -188,7 +188,7 @@ func (c *linuxContainer) Start(process *Process) error {
return c.start(process, status == Stopped) return c.start(process, status == Stopped)
} }
func (c *linuxContainer) StartI(process *Process) error { func (c *linuxContainer) Run(process *Process) error {
c.m.Lock() c.m.Lock()
defer c.m.Unlock() defer c.m.Unlock()
status, err := c.currentStatus() status, err := c.currentStatus()

View File

@ -89,7 +89,7 @@ func TestCheckpoint(t *testing.T) {
Stdout: &stdout, Stdout: &stdout,
} }
err = container.StartI(&pconfig) err = container.Run(&pconfig)
stdinR.Close() stdinR.Close()
defer stdinW.Close() defer stdinW.Close()
if err != nil { if err != nil {

View File

@ -241,7 +241,7 @@ func TestEnter(t *testing.T) {
Stdin: stdinR, Stdin: stdinR,
Stdout: &stdout, Stdout: &stdout,
} }
err = container.StartI(&pconfig) err = container.Run(&pconfig)
stdinR.Close() stdinR.Close()
defer stdinW.Close() defer stdinW.Close()
ok(t, err) ok(t, err)
@ -259,7 +259,7 @@ func TestEnter(t *testing.T) {
pconfig2.Stdin = stdinR2 pconfig2.Stdin = stdinR2
pconfig2.Stdout = &stdout2 pconfig2.Stdout = &stdout2
err = container.StartI(&pconfig2) err = container.Run(&pconfig2)
stdinR2.Close() stdinR2.Close()
defer stdinW2.Close() defer stdinW2.Close()
ok(t, err) ok(t, err)
@ -330,7 +330,7 @@ func TestProcessEnv(t *testing.T) {
Stdin: nil, Stdin: nil,
Stdout: &stdout, Stdout: &stdout,
} }
err = container.StartI(&pconfig) err = container.Run(&pconfig)
ok(t, err) ok(t, err)
// Wait for process // Wait for process
@ -378,7 +378,7 @@ func TestProcessCaps(t *testing.T) {
Stdin: nil, Stdin: nil,
Stdout: &stdout, Stdout: &stdout,
} }
err = container.StartI(&pconfig) err = container.Run(&pconfig)
ok(t, err) ok(t, err)
// Wait for process // Wait for process
@ -448,7 +448,7 @@ func TestAdditionalGroups(t *testing.T) {
Stdin: nil, Stdin: nil,
Stdout: &stdout, Stdout: &stdout,
} }
err = container.StartI(&pconfig) err = container.Run(&pconfig)
ok(t, err) ok(t, err)
// Wait for process // Wait for process
@ -508,7 +508,7 @@ func testFreeze(t *testing.T, systemd bool) {
Env: standardEnvironment, Env: standardEnvironment,
Stdin: stdinR, Stdin: stdinR,
} }
err = container.StartI(pconfig) err = container.Run(pconfig)
stdinR.Close() stdinR.Close()
defer stdinW.Close() defer stdinW.Close()
ok(t, err) ok(t, err)
@ -719,7 +719,7 @@ func TestContainerState(t *testing.T) {
Env: standardEnvironment, Env: standardEnvironment,
Stdin: stdinR, Stdin: stdinR,
} }
err = container.StartI(p) err = container.Run(p)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -772,7 +772,7 @@ func TestPassExtraFiles(t *testing.T) {
Stdin: nil, Stdin: nil,
Stdout: &stdout, Stdout: &stdout,
} }
err = container.StartI(&process) err = container.Run(&process)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -853,7 +853,7 @@ func TestMountCmds(t *testing.T) {
Args: []string{"sh", "-c", "env"}, Args: []string{"sh", "-c", "env"},
Env: standardEnvironment, Env: standardEnvironment,
} }
err = container.StartI(&pconfig) err = container.Run(&pconfig)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -902,7 +902,7 @@ func TestSysctl(t *testing.T) {
Stdin: nil, Stdin: nil,
Stdout: &stdout, Stdout: &stdout,
} }
err = container.StartI(&pconfig) err = container.Run(&pconfig)
ok(t, err) ok(t, err)
// Wait for process // Wait for process
@ -1042,7 +1042,7 @@ func TestOomScoreAdj(t *testing.T) {
Stdin: nil, Stdin: nil,
Stdout: &stdout, Stdout: &stdout,
} }
err = container.StartI(&pconfig) err = container.Run(&pconfig)
ok(t, err) ok(t, err)
// Wait for process // Wait for process
@ -1114,7 +1114,7 @@ func TestHook(t *testing.T) {
Stdin: nil, Stdin: nil,
Stdout: &stdout, Stdout: &stdout,
} }
err = container.StartI(&pconfig) err = container.Run(&pconfig)
ok(t, err) ok(t, err)
// Wait for process // Wait for process
@ -1231,7 +1231,7 @@ func TestRootfsPropagationSlaveMount(t *testing.T) {
Stdin: stdinR, Stdin: stdinR,
} }
err = container.StartI(pconfig) err = container.Run(pconfig)
stdinR.Close() stdinR.Close()
defer stdinW.Close() defer stdinW.Close()
ok(t, err) ok(t, err)
@ -1260,7 +1260,7 @@ func TestRootfsPropagationSlaveMount(t *testing.T) {
Stdout: &stdout2, Stdout: &stdout2,
} }
err = container.StartI(pconfig2) err = container.Run(pconfig2)
stdinR2.Close() stdinR2.Close()
defer stdinW2.Close() defer stdinW2.Close()
ok(t, err) ok(t, err)
@ -1348,7 +1348,7 @@ func TestRootfsPropagationSharedMount(t *testing.T) {
Stdin: stdinR, Stdin: stdinR,
} }
err = container.StartI(pconfig) err = container.Run(pconfig)
stdinR.Close() stdinR.Close()
defer stdinW.Close() defer stdinW.Close()
ok(t, err) ok(t, err)
@ -1380,7 +1380,7 @@ func TestRootfsPropagationSharedMount(t *testing.T) {
Capabilities: processCaps, Capabilities: processCaps,
} }
err = container.StartI(pconfig2) err = container.Run(pconfig2)
stdinR2.Close() stdinR2.Close()
defer stdinW2.Close() defer stdinW2.Close()
ok(t, err) ok(t, err)
@ -1452,7 +1452,7 @@ func TestInitJoinPID(t *testing.T) {
Env: standardEnvironment, Env: standardEnvironment,
Stdin: stdinR1, Stdin: stdinR1,
} }
err = container1.StartI(init1) err = container1.Run(init1)
stdinR1.Close() stdinR1.Close()
defer stdinW1.Close() defer stdinW1.Close()
ok(t, err) ok(t, err)
@ -1462,7 +1462,7 @@ func TestInitJoinPID(t *testing.T) {
ok(t, err) ok(t, err)
pidns1 := state1.NamespacePaths[configs.NEWPID] pidns1 := state1.NamespacePaths[configs.NEWPID]
// StartI a container inside the existing pidns but with different cgroups // Run a container inside the existing pidns but with different cgroups
config2 := newTemplateConfig(rootfs) config2 := newTemplateConfig(rootfs)
config2.Namespaces.Add(configs.NEWPID, pidns1) config2.Namespaces.Add(configs.NEWPID, pidns1)
config2.Cgroups.Path = "integration/test2" config2.Cgroups.Path = "integration/test2"
@ -1478,7 +1478,7 @@ func TestInitJoinPID(t *testing.T) {
Env: standardEnvironment, Env: standardEnvironment,
Stdin: stdinR2, Stdin: stdinR2,
} }
err = container2.StartI(init2) err = container2.Run(init2)
stdinR2.Close() stdinR2.Close()
defer stdinW2.Close() defer stdinW2.Close()
ok(t, err) ok(t, err)
@ -1508,7 +1508,7 @@ func TestInitJoinPID(t *testing.T) {
Env: standardEnvironment, Env: standardEnvironment,
Stdout: buffers.Stdout, Stdout: buffers.Stdout,
} }
err = container1.StartI(ps) err = container1.Run(ps)
ok(t, err) ok(t, err)
waitProcess(ps, t) waitProcess(ps, t)
@ -1557,7 +1557,7 @@ func TestInitJoinNetworkAndUser(t *testing.T) {
Env: standardEnvironment, Env: standardEnvironment,
Stdin: stdinR1, Stdin: stdinR1,
} }
err = container1.StartI(init1) err = container1.Run(init1)
stdinR1.Close() stdinR1.Close()
defer stdinW1.Close() defer stdinW1.Close()
ok(t, err) ok(t, err)
@ -1568,7 +1568,7 @@ func TestInitJoinNetworkAndUser(t *testing.T) {
netns1 := state1.NamespacePaths[configs.NEWNET] netns1 := state1.NamespacePaths[configs.NEWNET]
userns1 := state1.NamespacePaths[configs.NEWUSER] userns1 := state1.NamespacePaths[configs.NEWUSER]
// StartI a container inside the existing pidns but with different cgroups // Run a container inside the existing pidns but with different cgroups
rootfs2, err := newRootfs() rootfs2, err := newRootfs()
ok(t, err) ok(t, err)
defer remove(rootfs2) defer remove(rootfs2)
@ -1591,7 +1591,7 @@ func TestInitJoinNetworkAndUser(t *testing.T) {
Env: standardEnvironment, Env: standardEnvironment,
Stdin: stdinR2, Stdin: stdinR2,
} }
err = container2.StartI(init2) err = container2.Run(init2)
stdinR2.Close() stdinR2.Close()
defer stdinW2.Close() defer stdinW2.Close()
ok(t, err) ok(t, err)

View File

@ -36,7 +36,7 @@ func TestExecIn(t *testing.T) {
Env: standardEnvironment, Env: standardEnvironment,
Stdin: stdinR, Stdin: stdinR,
} }
err = container.StartI(process) err = container.Run(process)
stdinR.Close() stdinR.Close()
defer stdinW.Close() defer stdinW.Close()
ok(t, err) ok(t, err)
@ -51,7 +51,7 @@ func TestExecIn(t *testing.T) {
Stderr: buffers.Stderr, Stderr: buffers.Stderr,
} }
err = container.StartI(ps) err = container.Run(ps)
ok(t, err) ok(t, err)
waitProcess(ps, t) waitProcess(ps, t)
stdinW.Close() stdinW.Close()
@ -103,7 +103,7 @@ func testExecInRlimit(t *testing.T, userns bool) {
Env: standardEnvironment, Env: standardEnvironment,
Stdin: stdinR, Stdin: stdinR,
} }
err = container.StartI(process) err = container.Run(process)
stdinR.Close() stdinR.Close()
defer stdinW.Close() defer stdinW.Close()
ok(t, err) ok(t, err)
@ -121,7 +121,7 @@ func testExecInRlimit(t *testing.T, userns bool) {
{Type: syscall.RLIMIT_NOFILE, Hard: 1026, Soft: 1026}, {Type: syscall.RLIMIT_NOFILE, Hard: 1026, Soft: 1026},
}, },
} }
err = container.StartI(ps) err = container.Run(ps)
ok(t, err) ok(t, err)
waitProcess(ps, t) waitProcess(ps, t)
@ -155,7 +155,7 @@ func TestExecInError(t *testing.T) {
Env: standardEnvironment, Env: standardEnvironment,
Stdin: stdinR, Stdin: stdinR,
} }
err = container.StartI(process) err = container.Run(process)
stdinR.Close() stdinR.Close()
defer func() { defer func() {
stdinW.Close() stdinW.Close()
@ -173,7 +173,7 @@ func TestExecInError(t *testing.T) {
Env: standardEnvironment, Env: standardEnvironment,
Stdout: &out, Stdout: &out,
} }
err = container.StartI(unexistent) err = container.Run(unexistent)
if err == nil { if err == nil {
t.Fatal("Should be an error") t.Fatal("Should be an error")
} }
@ -207,7 +207,7 @@ func TestExecInTTY(t *testing.T) {
Env: standardEnvironment, Env: standardEnvironment,
Stdin: stdinR, Stdin: stdinR,
} }
err = container.StartI(process) err = container.Run(process)
stdinR.Close() stdinR.Close()
defer stdinW.Close() defer stdinW.Close()
ok(t, err) ok(t, err)
@ -225,7 +225,7 @@ func TestExecInTTY(t *testing.T) {
close(copy) close(copy)
}() }()
ok(t, err) ok(t, err)
err = container.StartI(ps) err = container.Run(ps)
ok(t, err) ok(t, err)
select { select {
case <-time.After(5 * time.Second): case <-time.After(5 * time.Second):
@ -264,7 +264,7 @@ func TestExecInEnvironment(t *testing.T) {
Env: standardEnvironment, Env: standardEnvironment,
Stdin: stdinR, Stdin: stdinR,
} }
err = container.StartI(process) err = container.Run(process)
stdinR.Close() stdinR.Close()
defer stdinW.Close() defer stdinW.Close()
ok(t, err) ok(t, err)
@ -283,7 +283,7 @@ func TestExecInEnvironment(t *testing.T) {
Stdout: buffers.Stdout, Stdout: buffers.Stdout,
Stderr: buffers.Stderr, Stderr: buffers.Stderr,
} }
err = container.StartI(process2) err = container.Run(process2)
ok(t, err) ok(t, err)
waitProcess(process2, t) waitProcess(process2, t)
@ -328,7 +328,7 @@ func TestExecinPassExtraFiles(t *testing.T) {
Env: standardEnvironment, Env: standardEnvironment,
Stdin: stdinR, Stdin: stdinR,
} }
err = container.StartI(process) err = container.Run(process)
stdinR.Close() stdinR.Close()
defer stdinW.Close() defer stdinW.Close()
if err != nil { if err != nil {
@ -346,7 +346,7 @@ func TestExecinPassExtraFiles(t *testing.T) {
Stdin: nil, Stdin: nil,
Stdout: &stdout, Stdout: &stdout,
} }
err = container.StartI(inprocess) err = container.Run(inprocess)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -401,7 +401,7 @@ func TestExecInOomScoreAdj(t *testing.T) {
Env: standardEnvironment, Env: standardEnvironment,
Stdin: stdinR, Stdin: stdinR,
} }
err = container.StartI(process) err = container.Run(process)
stdinR.Close() stdinR.Close()
defer stdinW.Close() defer stdinW.Close()
ok(t, err) ok(t, err)
@ -415,7 +415,7 @@ func TestExecInOomScoreAdj(t *testing.T) {
Stdout: buffers.Stdout, Stdout: buffers.Stdout,
Stderr: buffers.Stderr, Stderr: buffers.Stderr,
} }
err = container.StartI(ps) err = container.Run(ps)
ok(t, err) ok(t, err)
waitProcess(ps, t) waitProcess(ps, t)
@ -456,7 +456,7 @@ func TestExecInUserns(t *testing.T) {
Env: standardEnvironment, Env: standardEnvironment,
Stdin: stdinR, Stdin: stdinR,
} }
err = container.StartI(process) err = container.Run(process)
stdinR.Close() stdinR.Close()
defer stdinW.Close() defer stdinW.Close()
ok(t, err) ok(t, err)
@ -476,7 +476,7 @@ func TestExecInUserns(t *testing.T) {
Stdout: buffers.Stdout, Stdout: buffers.Stdout,
Stderr: os.Stderr, Stderr: os.Stderr,
} }
err = container.StartI(process2) err = container.Run(process2)
ok(t, err) ok(t, err)
waitProcess(process2, t) waitProcess(process2, t)
stdinW.Close() stdinW.Close()

View File

@ -50,7 +50,7 @@ func TestSeccompDenyGetcwd(t *testing.T) {
Stderr: buffers.Stderr, Stderr: buffers.Stderr,
} }
err = container.StartI(pwd) err = container.Run(pwd)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -125,7 +125,7 @@ func TestSeccompPermitWriteConditional(t *testing.T) {
Stderr: buffers.Stderr, Stderr: buffers.Stderr,
} }
err = container.StartI(dmesg) err = container.Run(dmesg)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -186,7 +186,7 @@ func TestSeccompDenyWriteConditional(t *testing.T) {
Stderr: buffers.Stderr, Stderr: buffers.Stderr,
} }
err = container.StartI(dmesg) err = container.Run(dmesg)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -123,7 +123,7 @@ func runContainer(config *configs.Config, console string, args ...string) (buffe
Stderr: buffers.Stderr, Stderr: buffers.Stderr,
} }
err = container.StartI(process) err = container.Run(process)
if err != nil { if err != nil {
return buffers, -1, err return buffers, -1, err
} }

View File

@ -12,29 +12,29 @@ function teardown() {
} }
@test "runc create" { @test "runc create" {
run "$RUNC" create --console /dev/pts/ptmx test_busybox runc create --console /dev/pts/ptmx test_busybox
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
testcontainer test_busybox created testcontainer test_busybox created
# start the command # start the command
run "$RUNC" start test_busybox runc start test_busybox
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
testcontainer test_busybox running testcontainer test_busybox running
} }
@test "runc create exec" { @test "runc create exec" {
run "$RUNC" create --console /dev/pts/ptmx test_busybox runc create --console /dev/pts/ptmx test_busybox
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
testcontainer test_busybox created testcontainer test_busybox created
run "$RUNC" exec test_busybox true runc exec test_busybox true
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
# start the command # start the command
run "$RUNC" start test_busybox runc start test_busybox
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
testcontainer test_busybox running testcontainer test_busybox running