Add a 'start' command

When any non-global-flag parameter appears on the command line make sure
there's a "command" even in the 'start' (run) case to ensure its not
ambiguous as to what the arg is. For example, w/o this fix its not
clear if
   runc foo
means 'foo' is the name of a config file or an unknown command.  Or worse,
you can't name a config file the same a ANY command, even future (yet to
be created) commands.

We should fix this now before we ship 1.0 and are forced to support this
ambiguous case for a long time.

Signed-off-by: Doug Davis <dug@us.ibm.com>
This commit is contained in:
Doug Davis 2015-08-17 18:30:17 -07:00
parent 744a6b0e7b
commit 714ae2acc9
3 changed files with 52 additions and 31 deletions

View File

@ -29,11 +29,9 @@ sudo make install
### Using: ### Using:
To run a container that you received just execute `runc` with the JSON format as the argument or have a To run a container, execute `runc start` in the bundle's root directory:
`config.json` file in the current working directory.
```bash ```bash
runc runc start
/ $ ps / $ ps
PID USER COMMAND PID USER COMMAND
1 daemon sh 1 daemon sh
@ -41,6 +39,18 @@ PID USER COMMAND
/ $ / $
``` ```
Or you can specify the path to a JSON configuration file:
```bash
runc start config.json
/ $ ps
PID USER COMMAND
1 daemon sh
5 daemon sh
/ $
```
Note: the use of the `start` command is required when specifying a
configuration file.
### OCF Container JSON Format: ### OCF Container JSON Format:
Below is a sample `config.json` configuration file. It assumes that Below is a sample `config.json` configuration file. It assumes that
@ -210,9 +220,9 @@ tar -C rootfs -xf busybox.tar
``` ```
* Create a file called `config.json` using the example from above. You can also * Create a file called `config.json` using the example from above. You can also
generate a spec using `runc spec`, redirecting the output into `config.json` generate a spec using `runc spec`, redirecting the output into `config.json`
* Execute `runc` and you should be placed into a shell where you can run `ps`: * Execute `runc start` and you should be placed into a shell where you can run `ps`:
``` ```
$ runc $ runc start
/ # ps / # ps
PID USER COMMAND PID USER COMMAND
1 root sh 1 root sh

10
main.go
View File

@ -24,7 +24,11 @@ After creating a spec for your root filesystem with runc, you can execute a
container in your shell by running: container in your shell by running:
cd /mycontainer cd /mycontainer
runc [ spec-file ] runc start
or
cd /mycontainer
runc start [ spec-file ]
If not specified, the default value for the 'spec-file' is 'config.json'. ` If not specified, the default value for the 'spec-file' is 'config.json'. `
) )
@ -56,6 +60,7 @@ func main() {
}, },
} }
app.Commands = []cli.Command{ app.Commands = []cli.Command{
startCommand,
checkpointCommand, checkpointCommand,
eventsCommand, eventsCommand,
restoreCommand, restoreCommand,
@ -69,7 +74,8 @@ func main() {
return nil return nil
} }
app.Action = runAction // Default to 'start' is no command is specified
app.Action = startCommand.Action
if err := app.Run(os.Args); err != nil { if err := app.Run(os.Args); err != nil {
logrus.Fatal(err) logrus.Fatal(err)

View File

@ -13,6 +13,33 @@ import (
"github.com/opencontainers/specs" "github.com/opencontainers/specs"
) )
var startCommand = cli.Command{
Name: "start",
Usage: "create and run a container",
Action: func(context *cli.Context) {
spec, err := loadSpec(context.Args().First())
notifySocket := os.Getenv("NOTIFY_SOCKET")
if notifySocket != "" {
setupSdNotify(spec, notifySocket)
}
if err != nil {
fatal(err)
}
if os.Geteuid() != 0 {
logrus.Fatal("runc should be run as root")
}
status, err := startContainer(context, spec)
if err != nil {
logrus.Fatalf("Container start failed: %v", 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)
},
}
func init() { func init() {
if len(os.Args) > 1 && os.Args[1] == "init" { if len(os.Args) > 1 && os.Args[1] == "init" {
runtime.GOMAXPROCS(1) runtime.GOMAXPROCS(1)
@ -25,7 +52,7 @@ func init() {
} }
} }
func execContainer(context *cli.Context, spec *specs.LinuxSpec) (int, error) { func startContainer(context *cli.Context, spec *specs.LinuxSpec) (int, error) {
config, err := createLibcontainerConfig(context.GlobalString("id"), spec) config, err := createLibcontainerConfig(context.GlobalString("id"), spec)
if err != nil { if err != nil {
return -1, err return -1, err
@ -65,28 +92,6 @@ func execContainer(context *cli.Context, spec *specs.LinuxSpec) (int, error) {
} }
// default action is to execute a container // default action is to execute a container
func runAction(context *cli.Context) {
spec, err := loadSpec(context.Args().First())
notifySocket := os.Getenv("NOTIFY_SOCKET")
if notifySocket != "" {
setupSdNotify(spec, notifySocket)
}
if err != nil {
fatal(err)
}
if os.Geteuid() != 0 {
logrus.Fatal("runc should be run as root")
}
status, err := execContainer(context, spec)
if err != nil {
logrus.Fatalf("Container start failed: %v", 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)
}
// If systemd is supporting sd_notify protocol, this function will add support // If systemd is supporting sd_notify protocol, this function will add support
// for sd_notify protocol from within the container. // for sd_notify protocol from within the container.