Skip to content

Commit

Permalink
Add option parsing to nsenter and enable specifying commands with arg…
Browse files Browse the repository at this point in the history
…uments.

Docker-DCO-1.1-Signed-off-by: Mrunal Patel <mrunalp@gmail.com> (github: mrunalp)
  • Loading branch information
mrunalp committed Jun 18, 2014
1 parent 4145356 commit 88acda8
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 22 deletions.
18 changes: 8 additions & 10 deletions namespaces/execin.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -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
}
Expand Down
38 changes: 36 additions & 2 deletions namespaces/nsenter.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package namespaces
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <getopt.h>
static const kBufSize = 256;
Expand Down Expand Up @@ -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;
Expand All @@ -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);
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", argv[2], strerror(errno));
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;
Expand Down
20 changes: 10 additions & 10 deletions nsinit/nsenter.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"log"
"strconv"

"github.com/codegangsta/cli"
"github.com/docker/libcontainer/namespaces"
Expand All @@ -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>...")
}

container, err := loadContainerFromJson(args.Get(2))
if err != nil {
log.Fatalf("unable to load container: %s", err)
if len(args) == 0 {
args = []string{"/bin/bash"}
}

nspid, err := strconv.Atoi(args.Get(0))
container, err := loadContainerFromJson(context.String("containerjson"))
if err != nil {
log.Fatalf("unable to read pid: %s from %q", err, args.Get(0))
log.Fatalf("unable to load container: %s", err)
}

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)
}
}

0 comments on commit 88acda8

Please sign in to comment.