diff --git a/stage1/init/init.go b/stage1/init/init.go index 1c9e1f3..decd961 100644 --- a/stage1/init/init.go +++ b/stage1/init/init.go @@ -43,6 +43,7 @@ import ( "os/exec" "path/filepath" "runtime" + "strings" "syscall" "github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/spec/schema/types" @@ -114,6 +115,21 @@ func init() { runtime.LockOSThread() } +func getFlavor(p *Pod) (flavor, systemdVersion string, err error) { + flavor, err = os.Readlink(filepath.Join(common.Stage1RootfsPath(p.Root), "flavor")) + if err != nil { + return "", "", fmt.Errorf("unable to determine stage1 flavor: %v", err) + } + if flavor == "src" { + systemdVersionBytes, err := ioutil.ReadFile(filepath.Join(common.Stage1RootfsPath(p.Root), "systemd-version")) + if err != nil { + return "", "", fmt.Errorf("unable to determine stage1's systemd version: %v", err) + } + systemdVersion = strings.Trim(string(systemdVersionBytes), " \n") + } + return +} + // machinedRegister checks if nspawn should register the pod to machined func machinedRegister() bool { // machined has a D-Bus interface following versioning guidelines, see: @@ -149,15 +165,10 @@ func machinedRegister() bool { } // getArgsEnv returns the nspawn args and env according to the usr used -func getArgsEnv(p *Pod, debug bool) ([]string, []string, error) { +func getArgsEnv(p *Pod, flavor, systemdVersion string, debug bool) ([]string, []string, error) { args := []string{} env := os.Environ() - flavor, err := os.Readlink(filepath.Join(common.Stage1RootfsPath(p.Root), "flavor")) - if err != nil { - return nil, nil, fmt.Errorf("unable to determine stage1 flavor: %v", err) - } - switch flavor { case "coreos": // when running the coreos-derived stage1 with unpatched systemd-nspawn we need some ld-linux hackery @@ -180,16 +191,27 @@ func getArgsEnv(p *Pod, debug bool) ([]string, []string, error) { case "src": args = append(args, filepath.Join(common.Stage1RootfsPath(p.Root), nspawnBin)) args = append(args, "--boot") // Launch systemd in the pod + + switch systemdVersion { + case "v215": + fallthrough + case "v219": + lfd, err := common.GetRktLockFD() + if err != nil { + return nil, nil, err + } + args = append(args, fmt.Sprintf("--keep-fd=%v", lfd)) + default: + // since systemd-nspawn v220 (commit 6b7d2e, "nspawn: close extra fds + // before execing init"), fds remain open, so --keep-fd is not needed. + } + out, err := os.Getwd() if err != nil { return nil, nil, err } - lfd, err := common.GetRktLockFD() - if err != nil { - return nil, nil, err - } args = append(args, fmt.Sprintf("--pid-file=%v", filepath.Join(out, "pid"))) - args = append(args, fmt.Sprintf("--keep-fd=%v", lfd)) + if machinedRegister() { args = append(args, fmt.Sprintf("--register=true")) } else { @@ -335,7 +357,13 @@ func stage1() int { return 2 } - args, env, err := getArgsEnv(p, debug) + flavor, systemdVersion, err := getFlavor(p) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to get stage1 flavor: %v\n", err) + return 3 + } + + args, env, err := getArgsEnv(p, flavor, systemdVersion, debug) if err != nil { fmt.Fprintf(os.Stderr, "Failed to get execution parameters: %v\n", err) return 3 diff --git a/stage1/rootfs/usr_from_src/Makefile b/stage1/rootfs/usr_from_src/Makefile index a65ade9..c0d8682 100644 --- a/stage1/rootfs/usr_from_src/Makefile +++ b/stage1/rootfs/usr_from_src/Makefile @@ -13,6 +13,7 @@ install: Makefile host_deps.txt echo cp -af ../usr_from_src/systemd_build/installed/. \"\$${ROOT}\" >> install.tmp cat host_deps.txt | while read dep; do echo install -D \"$${dep}\" \"\$${ROOT}/$${dep}\"; done >> install.tmp echo ln -sf src \"\$${ROOT}/flavor\" >> install.tmp + echo "echo $(RKT_STAGE1_SYSTEMD_VER) > \"\$${ROOT}/systemd-version\"" >> install.tmp mv install.tmp install # discover host library dependencies for all the ELF executables in systemd_build/installed, note the LD_LIBRARY_PATH= to find systemd-produced libraries. diff --git a/stage1/rootfs/usr_from_src/patches/master/0001-nspawn-add-keep-fd-support.patch b/stage1/rootfs/usr_from_src/patches/master/0001-nspawn-add-keep-fd-support.patch deleted file mode 100644 index 1e104e3..0000000 --- a/stage1/rootfs/usr_from_src/patches/master/0001-nspawn-add-keep-fd-support.patch +++ /dev/null @@ -1,112 +0,0 @@ -From d8677552a0e1f5364432cd90a8fbeab337fb49de Mon Sep 17 00:00:00 2001 -From: Vito Caputo -Date: Mon, 16 Mar 2015 15:10:15 -0700 -Subject: [PATCH 1/2] nspawn: add --keep-fd support - -This enables inheriting a file from the executing process which persists -for the duration of the nspawn parent process. Useful in implementing a -robust lifecycle reference tied to the nspawn container, which when -combined with advisory locking can also provide a simple event mechanism -triggered at container exit. - -[patch ported to v219 -alban] ---- - src/nspawn/nspawn.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 44 insertions(+) - -diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c -index f43ffd9..d458ab4 100644 ---- a/src/nspawn/nspawn.c -+++ b/src/nspawn/nspawn.c -@@ -174,6 +174,7 @@ static bool arg_quiet = false; - static bool arg_share_system = false; - static bool arg_register = true; - static bool arg_keep_unit = false; -+static int arg_keep_fd = -1; - static char **arg_network_interfaces = NULL; - static char **arg_network_macvlan = NULL; - static char **arg_network_ipvlan = NULL; -@@ -250,6 +251,7 @@ static void help(void) { - " --keep-unit Do not register a scope for the machine, reuse\n" - " the service unit nspawn is running in\n" - " --volatile[=MODE] Run the system in volatile mode\n" -+ " --keep-fd=FDNUM Do not close the specified file descriptor\n" - , program_invocation_short_name); - } - -@@ -291,6 +293,7 @@ static int parse_argv(int argc, char *argv[]) { - ARG_SHARE_SYSTEM, - ARG_REGISTER, - ARG_KEEP_UNIT, -+ ARG_KEEP_FD, - ARG_NETWORK_INTERFACE, - ARG_NETWORK_MACVLAN, - ARG_NETWORK_IPVLAN, -@@ -329,6 +332,7 @@ static int parse_argv(int argc, char *argv[]) { - { "share-system", no_argument, NULL, ARG_SHARE_SYSTEM }, - { "register", required_argument, NULL, ARG_REGISTER }, - { "keep-unit", no_argument, NULL, ARG_KEEP_UNIT }, -+ { "keep-fd", required_argument, NULL, ARG_KEEP_FD }, - { "network-interface", required_argument, NULL, ARG_NETWORK_INTERFACE }, - { "network-macvlan", required_argument, NULL, ARG_NETWORK_MACVLAN }, - { "network-ipvlan", required_argument, NULL, ARG_NETWORK_IPVLAN }, -@@ -653,6 +657,14 @@ static int parse_argv(int argc, char *argv[]) { - arg_keep_unit = true; - break; - -+ case ARG_KEEP_FD: -+ r = safe_atoi(optarg, &arg_keep_fd); -+ if (r < 0) { -+ log_error("Failed to parse --keep-fd= argument: %s", optarg); -+ return r; -+ } -+ break; -+ - case ARG_PERSONALITY: - - arg_personality = personality_from_string(optarg); -@@ -3726,9 +3738,41 @@ int main(int argc, char *argv[]) { - goto finish; - } - } -+ -+ /* if we're keeping an fd open add it to the listen fds set temporarily across fdset_close_others() */ -+ if (arg_keep_fd >= 0) { -+ if (!fds) { -+ fds = fdset_new(); -+ if (!fds) { -+ r = log_oom(); -+ goto finish; -+ } -+ } -+ r = fdset_put(fds, arg_keep_fd); -+ if (r < 0) { -+ log_error_errno(r, "Failed to add kept fd: %m"); -+ goto finish; -+ } -+ } -+ - fdset_close_others(fds); - log_open(); - -+ if (arg_keep_fd >= 0) { -+ r = fdset_remove(fds, arg_keep_fd); -+ if (r < 0) { -+ log_error_errno(r, "Failed to remove kept fd: %m"); -+ goto finish; -+ } -+ -+ /* ensure the kept fd is closed in the child, only the parent keeps it around. */ -+ r = fd_cloexec(arg_keep_fd, true); -+ if (r < 0) { -+ log_error_errno(r, "Failed to set cloexec on kept fd: %m"); -+ goto finish; -+ } -+ } -+ - if (arg_directory) { - assert(!arg_image); - --- -2.1.4 -