Merge pull request #27 from mrunalp/dev/nsenter_flags

Add option parsing to nsenter and enable specifying commands with arguments
This commit is contained in:
Michael Crosby 2014-06-18 14:05:44 -07:00
commit 2c29550226
3 changed files with 55 additions and 23 deletions

View File

@ -21,14 +21,8 @@ func ExecIn(container *libcontainer.Container, nspid int, args []string) error {
return err
}
// TODO(vmarmol): Move this to the container JSON.
processLabel, err := label.GetPidCon(nspid)
if err != nil {
return err
}
// Enter the namespace and then finish setup
finalArgs := []string{os.Args[0], "nsenter", strconv.Itoa(nspid), processLabel, string(containerJson)}
finalArgs := []string{os.Args[0], "nsenter", "--nspid", strconv.Itoa(nspid), "--containerjson", string(containerJson), "--"}
finalArgs = append(finalArgs, args...)
if err := system.Execv(finalArgs[0], finalArgs[0:], os.Environ()); err != nil {
return err
@ -37,7 +31,7 @@ func ExecIn(container *libcontainer.Container, nspid int, args []string) error {
}
// NsEnter is run after entering the namespace.
func NsEnter(container *libcontainer.Container, processLabel string, nspid int, args []string) error {
func NsEnter(container *libcontainer.Container, nspid int, args []string) error {
// clear the current processes env and replace it with the environment
// defined on the container
if err := LoadContainerEnvironment(container); err != nil {
@ -46,9 +40,13 @@ func NsEnter(container *libcontainer.Container, processLabel string, nspid int,
if err := FinalizeNamespace(container); err != nil {
return err
}
if err := label.SetProcessLabel(processLabel); err != nil {
return err
if process_label, ok := container.Context["process_label"]; ok {
if err := label.SetProcessLabel(process_label); err != nil {
return err
}
}
if err := system.Execv(args[0], args[0:], container.Env); err != nil {
return err
}

View File

@ -15,6 +15,7 @@ package namespaces
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <getopt.h>
static const kBufSize = 256;
@ -64,6 +65,10 @@ int setns(int fd, int nstype) {
#endif
#endif
void print_usage() {
fprintf(stderr, "<binary> nsenter --nspid <pid> --containerjson <container_json> -- cmd1 arg1 arg2...\n");
}
void nsenter() {
int argc;
char **argv;
@ -79,11 +84,40 @@ void nsenter() {
fprintf(stderr, "nsenter: Incorrect usage, not enough arguments\n");
exit(1);
}
pid_t init_pid = strtol(argv[2], NULL, 10);
if (errno != 0 || init_pid <= 0) {
fprintf(stderr, "nsenter: Failed to parse PID from \"%s\" with error: \"%s\"\n", argv[2], strerror(errno));
static const struct option longopts[] = {
{ "nspid", required_argument, NULL, 'n' },
{ "containerjson", required_argument, NULL, 'c' },
{ NULL, 0, NULL, 0 }
};
int c;
pid_t init_pid = -1;
char *init_pid_str = NULL;
char *container_json = NULL;
while ((c = getopt_long_only(argc, argv, "n:s:c:", longopts, NULL)) != -1) {
switch (c) {
case 'n':
init_pid_str = optarg;
break;
case 'c':
container_json = optarg;
break;
}
}
if (container_json == NULL || init_pid_str == NULL) {
print_usage();
exit(1);
}
init_pid = strtol(init_pid_str, NULL, 10);
if (errno != 0 || init_pid <= 0) {
fprintf(stderr, "nsenter: Failed to parse PID from \"%s\" with error: \"%s\"\n", init_pid_str, strerror(errno));
print_usage();
exit(1);
}
argc -= 3;
argv += 3;

View File

@ -2,7 +2,6 @@ package main
import (
"log"
"strconv"
"github.com/codegangsta/cli"
"github.com/docker/libcontainer/namespaces"
@ -12,29 +11,30 @@ var nsenterCommand = cli.Command{
Name: "nsenter",
Usage: "init process for entering an existing namespace",
Action: nsenterAction,
Flags: []cli.Flag{
cli.IntFlag{Name: "nspid"},
cli.StringFlag{Name: "containerjson"},
},
}
func nsenterAction(context *cli.Context) {
args := context.Args()
if len(args) < 4 {
log.Fatalf("incorrect usage: <pid> <process label> <container JSON> <cmd>...")
if len(args) == 0 {
args = []string{"/bin/bash"}
}
container, err := loadContainerFromJson(args.Get(2))
container, err := loadContainerFromJson(context.String("containerjson"))
if err != nil {
log.Fatalf("unable to load container: %s", err)
}
nspid, err := strconv.Atoi(args.Get(0))
if err != nil {
log.Fatalf("unable to read pid: %s from %q", err, args.Get(0))
}
nspid := context.Int("nspid")
if nspid <= 0 {
log.Fatalf("cannot enter into namespaces without valid pid: %q", nspid)
}
if err := namespaces.NsEnter(container, args.Get(1), nspid, args[3:]); err != nil {
if err := namespaces.NsEnter(container, nspid, args); err != nil {
log.Fatalf("failed to nsenter: %s", err)
}
}