From 6b9d64eefecf5f0f6f8f9d33542eaf049fb27828 Mon Sep 17 00:00:00 2001 From: Shishir Mahajan Date: Thu, 27 Aug 2015 11:34:46 -0400 Subject: [PATCH] Systemd integration with runc, for on-demand socket activation Signed-off-by: Shishir Mahajan --- start.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/start.go b/start.go index 8d5b6deb99a..827783dbb65 100644 --- a/start.go +++ b/start.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "runtime" + "strconv" "github.com/Sirupsen/logrus" "github.com/codegangsta/cli" @@ -13,6 +14,8 @@ import ( "github.com/opencontainers/specs" ) +const SD_LISTEN_FDS_START = 3 + var startCommand = cli.Command{ Name: "start", Usage: "create and run a container", @@ -27,6 +30,13 @@ var startCommand = cli.Command{ setupSdNotify(spec, notifySocket) } + listenFds := os.Getenv("LISTEN_FDS") + listenPid := os.Getenv("LISTEN_PID") + + if listenFds != "" && listenPid == strconv.Itoa(os.Getpid()) { + setupSocketActivation(spec, listenFds) + } + if os.Geteuid() != 0 { logrus.Fatal("runc should be run as root") } @@ -79,6 +89,19 @@ func startContainer(context *cli.Context, spec *specs.LinuxSpec) (int, error) { // that created it. defer destroy(container) process := newProcess(spec.Process) + + // Support on-demand socket activation by passing file descriptors into the container init process. + if os.Getenv("LISTEN_FDS") != "" { + listenFdsInt, err := strconv.Atoi(os.Getenv("LISTEN_FDS")) + if err != nil { + return -1, err + } + + for i := SD_LISTEN_FDS_START; i < (listenFdsInt + SD_LISTEN_FDS_START); i++ { + process.ExtraFiles = append(process.ExtraFiles, os.NewFile(uintptr(i), "")) + } + } + tty, err := newTty(spec.Process.Terminal, process, rootuid) if err != nil { return -1, err @@ -100,6 +123,12 @@ func setupSdNotify(spec *specs.LinuxSpec, notifySocket string) { spec.Process.Env = append(spec.Process.Env, fmt.Sprintf("NOTIFY_SOCKET=%s", notifySocket)) } +// If systemd is supporting on-demand socket activation, this function will add support +// for on-demand socket activation for the containerized service. +func setupSocketActivation(spec *specs.LinuxSpec, listenFds string) { + spec.Process.Env = append(spec.Process.Env, fmt.Sprintf("LISTEN_FDS=%s", listenFds), "LISTEN_PID=1") +} + func destroy(container libcontainer.Container) { status, err := container.Status() if err != nil {