*: use coreos/go-systemd/activation for socket activation
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
This commit is contained in:
parent
8e8d01d38d
commit
0dea09bce7
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"ImportPath": "github.com/opencontainers/runc",
|
||||
"GoVersion": "go1.4.2",
|
||||
"GoVersion": "go1.5.3",
|
||||
"Deps": [
|
||||
{
|
||||
"ImportPath": "github.com/Sirupsen/logrus",
|
||||
|
@ -12,6 +12,11 @@
|
|||
"Comment": "1.2.0-187-gc31a797",
|
||||
"Rev": "c31a7975863e7810c92e2e288a9ab074f9a88f29"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/go-systemd/activation",
|
||||
"Comment": "v4",
|
||||
"Rev": "b4a58d95188dd092ae20072bac14cece0e67c388"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/coreos/go-systemd/dbus",
|
||||
"Comment": "v4",
|
||||
|
|
52
Godeps/_workspace/src/github.com/coreos/go-systemd/activation/files.go
generated
vendored
Normal file
52
Godeps/_workspace/src/github.com/coreos/go-systemd/activation/files.go
generated
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package activation implements primitives for systemd socket activation.
|
||||
package activation
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// based on: https://gist.github.com/alberts/4640792
|
||||
const (
|
||||
listenFdsStart = 3
|
||||
)
|
||||
|
||||
func Files(unsetEnv bool) []*os.File {
|
||||
if unsetEnv {
|
||||
defer os.Unsetenv("LISTEN_PID")
|
||||
defer os.Unsetenv("LISTEN_FDS")
|
||||
}
|
||||
|
||||
pid, err := strconv.Atoi(os.Getenv("LISTEN_PID"))
|
||||
if err != nil || pid != os.Getpid() {
|
||||
return nil
|
||||
}
|
||||
|
||||
nfds, err := strconv.Atoi(os.Getenv("LISTEN_FDS"))
|
||||
if err != nil || nfds == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
files := make([]*os.File, 0, nfds)
|
||||
for fd := listenFdsStart; fd < listenFdsStart+nfds; fd++ {
|
||||
syscall.CloseOnExec(fd)
|
||||
files = append(files, os.NewFile(uintptr(fd), "LISTEN_FD_"+strconv.Itoa(fd)))
|
||||
}
|
||||
|
||||
return files
|
||||
}
|
62
Godeps/_workspace/src/github.com/coreos/go-systemd/activation/listeners.go
generated
vendored
Normal file
62
Godeps/_workspace/src/github.com/coreos/go-systemd/activation/listeners.go
generated
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package activation
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net"
|
||||
)
|
||||
|
||||
// Listeners returns a slice containing a net.Listener for each matching socket type
|
||||
// passed to this process.
|
||||
//
|
||||
// The order of the file descriptors is preserved in the returned slice.
|
||||
// Nil values are used to fill any gaps. For example if systemd were to return file descriptors
|
||||
// corresponding with "udp, tcp, tcp", then the slice would contain {nil, net.Listener, net.Listener}
|
||||
func Listeners(unsetEnv bool) ([]net.Listener, error) {
|
||||
files := Files(unsetEnv)
|
||||
listeners := make([]net.Listener, len(files))
|
||||
|
||||
for i, f := range files {
|
||||
if pc, err := net.FileListener(f); err == nil {
|
||||
listeners[i] = pc
|
||||
}
|
||||
}
|
||||
return listeners, nil
|
||||
}
|
||||
|
||||
// TLSListeners returns a slice containing a net.listener for each matching TCP socket type
|
||||
// passed to this process.
|
||||
// It uses default Listeners func and forces TCP sockets handlers to use TLS based on tlsConfig.
|
||||
func TLSListeners(unsetEnv bool, tlsConfig *tls.Config) ([]net.Listener, error) {
|
||||
listeners, err := Listeners(unsetEnv)
|
||||
|
||||
if listeners == nil || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if tlsConfig != nil && err == nil {
|
||||
tlsConfig.NextProtos = []string{"http/1.1"}
|
||||
|
||||
for i, l := range listeners {
|
||||
// Activate TLS only for TCP sockets
|
||||
if l.Addr().Network() == "tcp" {
|
||||
listeners[i] = tls.NewListener(l, tlsConfig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return listeners, err
|
||||
}
|
37
Godeps/_workspace/src/github.com/coreos/go-systemd/activation/packetconns.go
generated
vendored
Normal file
37
Godeps/_workspace/src/github.com/coreos/go-systemd/activation/packetconns.go
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package activation
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
// PacketConns returns a slice containing a net.PacketConn for each matching socket type
|
||||
// passed to this process.
|
||||
//
|
||||
// The order of the file descriptors is preserved in the returned slice.
|
||||
// Nil values are used to fill any gaps. For example if systemd were to return file descriptors
|
||||
// corresponding with "udp, tcp, udp", then the slice would contain {net.PacketConn, nil, net.PacketConn}
|
||||
func PacketConns(unsetEnv bool) ([]net.PacketConn, error) {
|
||||
files := Files(unsetEnv)
|
||||
conns := make([]net.PacketConn, len(files))
|
||||
|
||||
for i, f := range files {
|
||||
if pc, err := net.FilePacketConn(f); err == nil {
|
||||
conns[i] = pc
|
||||
}
|
||||
}
|
||||
return conns, nil
|
||||
}
|
23
start.go
23
start.go
|
@ -6,17 +6,15 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/coreos/go-systemd/activation"
|
||||
"github.com/opencontainers/runc/libcontainer"
|
||||
"github.com/opencontainers/specs"
|
||||
)
|
||||
|
||||
const SD_LISTEN_FDS_START = 3
|
||||
|
||||
// default action is to start a container
|
||||
var startCommand = cli.Command{
|
||||
Name: "start",
|
||||
|
@ -59,17 +57,10 @@ var startCommand = cli.Command{
|
|||
setupSdNotify(spec, notifySocket)
|
||||
}
|
||||
|
||||
var (
|
||||
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")
|
||||
}
|
||||
|
||||
status, err := startContainer(context, spec)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Container start failed: %v", err)
|
||||
|
@ -124,12 +115,10 @@ func startContainer(context *cli.Context, spec *specs.LinuxSpec) (int, error) {
|
|||
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), ""))
|
||||
listenFds := activation.Files(false)
|
||||
if len(listenFds) > 0 {
|
||||
process.Env = append(process.Env, fmt.Sprintf("LISTEN_FDS=%d", len(listenFds)), "LISTEN_PID=1")
|
||||
process.ExtraFiles = append(process.ExtraFiles, listenFds...)
|
||||
}
|
||||
}
|
||||
tty, err := setupIO(process, rootuid, context.String("console"), spec.Process.Terminal, detach)
|
||||
|
|
6
utils.go
6
utils.go
|
@ -236,12 +236,6 @@ 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) {
|
||||
if err := container.Destroy(); err != nil {
|
||||
logrus.Error(err)
|
||||
|
|
Loading…
Reference in New Issue