Fix SystemError and env lookup

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2016-05-25 11:24:26 -07:00
parent b9bc020f0d
commit 6eba9b8ffb
9 changed files with 99 additions and 93 deletions

View File

@ -43,30 +43,18 @@ command(s) that get executed on start, edit the args parameter of the spec. See
Usage: "do not use pivot root to jail process inside rootfs. This should be used whenever the rootfs is on top of a ramdisk",
},
},
Action: func(context *cli.Context) {
bundle := context.String("bundle")
if bundle != "" {
if err := os.Chdir(bundle); err != nil {
fatal(err)
}
}
spec, err := loadSpec(specConfig)
Action: func(context *cli.Context) error {
spec, err := setupSpec(context)
if err != nil {
fatal(err)
}
notifySocket := os.Getenv("NOTIFY_SOCKET")
if notifySocket != "" {
setupSdNotify(spec, notifySocket)
}
if os.Geteuid() != 0 {
fatalf("runc should be run as root")
return err
}
status, err := startContainer(context, spec, true)
if err != nil {
fatal(err)
return err
}
// exit with the container's exit status so any external supervisor is
// notified of the exit with the correct exit status.
os.Exit(status)
return nil
},
}

View File

@ -3,9 +3,9 @@
package main
import (
"fmt"
"os"
"path/filepath"
"syscall"
"github.com/codegangsta/cli"
"github.com/opencontainers/runc/libcontainer"
@ -20,7 +20,7 @@ Where "<container-id>" is the name for the instance of the container.
EXAMPLE:
For example, if the container id is "ubuntu01" and runc list currently shows the
status of "ubuntu01" as "destroyed" the following will delete resources held for
status of "ubuntu01" as "stopped" the following will delete resources held for
"ubuntu01" removing "ubuntu01" from the runc list of containers:
# runc delete ubuntu01`,
@ -38,8 +38,11 @@ status of "ubuntu01" as "destroyed" the following will delete resources held for
return nil
}
s, err := container.Status()
if err == nil && s == libcontainer.Created {
container.Signal(syscall.SIGKILL)
if err != nil {
return err
}
if s != libcontainer.Stopped {
return fmt.Errorf("cannot delete container that is not stopped: %s", s)
}
destroy(container)
return nil

View File

@ -76,13 +76,13 @@ type BaseContainer interface {
//
// errors:
// ContainerDestroyed - Container no longer exists,
// Systemerror - System error.
// SystemError - System error.
Status() (Status, error)
// State returns the current container's state information.
//
// errors:
// Systemerror - System error.
// SystemError - System error.
State() (*State, error)
// Returns the current config of the container.
@ -92,7 +92,7 @@ type BaseContainer interface {
//
// errors:
// ContainerDestroyed - Container no longer exists,
// Systemerror - System error.
// SystemError - System error.
//
// Some of the returned PIDs may no longer refer to processes in the Container, unless
// the Container state is PAUSED in which case every PID in the slice is valid.
@ -102,7 +102,7 @@ type BaseContainer interface {
//
// errors:
// ContainerDestroyed - Container no longer exists,
// Systemerror - System error.
// SystemError - System error.
Stats() (*Stats, error)
// Set resources of container as configured
@ -110,7 +110,7 @@ type BaseContainer interface {
// We can use this to change resources when containers are running.
//
// errors:
// Systemerror - System error.
// SystemError - System error.
Set(config configs.Config) error
// Start a process inside the container. Returns error if process fails to
@ -120,7 +120,7 @@ type BaseContainer interface {
// ContainerDestroyed - Container no longer exists,
// ConfigInvalid - config is invalid,
// ContainerPaused - Container is paused,
// Systemerror - System error.
// SystemError - System error.
Start(process *Process) (err error)
// StartI immediatly starts the process inside the conatiner. Returns error if process
@ -131,7 +131,7 @@ type BaseContainer interface {
// ContainerDestroyed - Container no longer exists,
// ConfigInvalid - config is invalid,
// ContainerPaused - Container is paused,
// Systemerror - System error.
// SystemError - System error.
StartI(process *Process) (err error)
// Destroys the container after killing all running processes.
@ -140,12 +140,12 @@ type BaseContainer interface {
// No error is returned if the container is already destroyed.
//
// errors:
// Systemerror - System error.
// SystemError - System error.
Destroy() error
// Signal sends the provided signal code to the container's initial process.
//
// errors:
// Systemerror - System error.
// SystemError - System error.
Signal(s os.Signal) error
}

View File

@ -1096,11 +1096,9 @@ func (c *linuxContainer) runType() (Status, error) {
return Stopped, newSystemErrorWithCausef(err, "reading /proc/%d/environ", pid)
}
check := []byte("_LIBCONTAINER")
for _, v := range bytes.Split(environ, []byte("\x00")) {
if bytes.Contains(v, check) {
if bytes.Contains(environ, check) {
return Created, nil
}
}
return Running, nil
}

View File

@ -90,6 +90,7 @@ func newTemplateConfig(rootfs string) *configs.Config {
Flags: defaultMountFlags,
},
/*
CI is broken on the debian based kernels with this
{
Source: "mqueue",
Destination: "/dev/mqueue",

46
run.go
View File

@ -3,12 +3,9 @@
package main
import (
"fmt"
"os"
"github.com/codegangsta/cli"
"github.com/coreos/go-systemd/activation"
"github.com/opencontainers/runtime-spec/specs-go"
)
// default action is to start a container
@ -58,23 +55,10 @@ command(s) that get executed on start, edit the args parameter of the spec. See
},
},
Action: func(context *cli.Context) error {
bundle := context.String("bundle")
if bundle != "" {
if err := os.Chdir(bundle); err != nil {
return err
}
}
spec, err := loadSpec(specConfig)
spec, err := setupSpec(context)
if err != nil {
return err
}
notifySocket := os.Getenv("NOTIFY_SOCKET")
if notifySocket != "" {
setupSdNotify(spec, notifySocket)
}
if os.Geteuid() != 0 {
return fmt.Errorf("runc should be run as root")
}
status, err := startContainer(context, spec, false)
if err == nil {
// exit with the container's exit status so any external supervisor is
@ -84,31 +68,3 @@ command(s) that get executed on start, edit the args parameter of the spec. See
return err
},
}
func startContainer(context *cli.Context, spec *specs.Spec, create bool) (int, error) {
id := context.Args().First()
if id == "" {
return -1, errEmptyID
}
container, err := createContainer(context, id, spec)
if err != nil {
return -1, err
}
detach := context.Bool("detach")
// Support on-demand socket activation by passing file descriptors into the container init process.
listenFDs := []*os.File{}
if os.Getenv("LISTEN_FDS") != "" {
listenFDs = activation.Files(false)
}
r := &runner{
enableSubreaper: !context.Bool("no-subreaper"),
shouldDestroy: true,
container: container,
listenFDs: listenFDs,
console: context.String("console"),
detach: detach,
pidFile: context.String("pid-file"),
create: create,
}
return r.run(&spec.Process)
}

View File

@ -1,32 +1,39 @@
package main
import (
"fmt"
"github.com/codegangsta/cli"
"github.com/opencontainers/runc/libcontainer"
)
var startCommand = cli.Command{
Name: "start",
Usage: "start signals a created container to execute the users defined process",
Usage: "start signals a created container to execute the user defined process",
ArgsUsage: `<container-id>
Where "<container-id>" is your name for the instance of the container that you
are starting. The name you provide for the container instance must be unique on
your host.`,
Description: `The start command signals the container to start the user's defined process.`,
Action: func(context *cli.Context) {
Action: func(context *cli.Context) error {
container, err := getContainer(context)
if err != nil {
fatal(err)
return err
}
status, err := container.Status()
if err != nil {
fatal(err)
}
if status == libcontainer.Created {
if err := container.Signal(libcontainer.InitContinueSignal); err != nil {
fatal(err)
return err
}
switch status {
case libcontainer.Created:
return container.Signal(libcontainer.InitContinueSignal)
case libcontainer.Stopped:
return fmt.Errorf("cannot start a container that has run and stopped")
case libcontainer.Running:
return fmt.Errorf("cannot start an already running container")
default:
return fmt.Errorf("cannot start a container in the %s state", status)
}
},
}

View File

@ -5,6 +5,8 @@ import (
"os"
"github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/opencontainers/runtime-spec/specs-go"
)
// fatal prints the error's details if it is a libcontainer specific error type
@ -15,3 +17,25 @@ func fatal(err error) {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
// setupSpec performs inital setup based on the cli.Context for the container
func setupSpec(context *cli.Context) (*specs.Spec, error) {
bundle := context.String("bundle")
if bundle != "" {
if err := os.Chdir(bundle); err != nil {
return nil, err
}
}
spec, err := loadSpec(specConfig)
if err != nil {
return nil, err
}
notifySocket := os.Getenv("NOTIFY_SOCKET")
if notifySocket != "" {
setupSdNotify(spec, notifySocket)
}
if os.Geteuid() != 0 {
return nil, fmt.Errorf("runc should be run as root")
}
return spec, nil
}

View File

@ -11,6 +11,7 @@ import (
"github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/coreos/go-systemd/activation"
"github.com/opencontainers/runc/libcontainer"
"github.com/opencontainers/runc/libcontainer/cgroups/systemd"
"github.com/opencontainers/runc/libcontainer/specconv"
@ -290,3 +291,31 @@ func validateProcessSpec(spec *specs.Process) error {
}
return nil
}
func startContainer(context *cli.Context, spec *specs.Spec, create bool) (int, error) {
id := context.Args().First()
if id == "" {
return -1, errEmptyID
}
container, err := createContainer(context, id, spec)
if err != nil {
return -1, err
}
detach := context.Bool("detach")
// Support on-demand socket activation by passing file descriptors into the container init process.
listenFDs := []*os.File{}
if os.Getenv("LISTEN_FDS") != "" {
listenFDs = activation.Files(false)
}
r := &runner{
enableSubreaper: !context.Bool("no-subreaper"),
shouldDestroy: true,
container: container,
listenFDs: listenFDs,
console: context.String("console"),
detach: detach,
pidFile: context.String("pid-file"),
create: create,
}
return r.run(&spec.Process)
}