Signed-off-by: Jess Frazelle <jess@mesosphere.com>
This commit is contained in:
Jess Frazelle 2016-04-16 18:23:42 -07:00
parent 61704ab871
commit 2105320daf
13 changed files with 90 additions and 112 deletions

12
main.go
View file

@ -12,6 +12,7 @@ import (
aaprofile "github.com/docker/docker/profiles/apparmor"
"github.com/opencontainers/runc/libcontainer"
"github.com/opencontainers/runc/libcontainer/apparmor"
_ "github.com/opencontainers/runc/libcontainer/nsenter"
"github.com/opencontainers/runc/libcontainer/user"
"github.com/opencontainers/runtime-spec/specs-go"
)
@ -44,9 +45,10 @@ var (
pidFile string
root string
allocateTty bool
readonly bool
detach bool
allocateTty bool
detach bool
readonly bool
useSystemdCgroup bool
hooks specs.Hooks
hookflags stringSlice
@ -122,6 +124,8 @@ func init() {
flag.BoolVar(&allocateTty, "t", true, "allocate a tty for the container")
flag.BoolVar(&detach, "d", false, "detach from the container's process")
// TODO (jess): do not enable this flag, the error is very gross on systemd
// flag.BoolVar(&useSystemdCgroup, "systemd-cgroup", false, "enable systemd cgroup support")
flag.BoolVar(&readonly, "read-only", false, "make container filesystem readonly")
flag.BoolVar(&version, "version", false, "print version and exit")
@ -200,7 +204,7 @@ func main() {
logrus.Fatal(err)
}
status, err := startContainer(spec, containerID, pidFile, detach)
status, err := startContainer(spec, containerID, pidFile, detach, useSystemdCgroup)
if err != nil {
logrus.Fatal(err)
}

View file

@ -1,5 +0,0 @@
// +build linux
package main
import _ "github.com/opencontainers/runc/libcontainer/nsenter"

View file

@ -9,46 +9,39 @@ import (
"github.com/Sirupsen/logrus"
"github.com/coreos/go-systemd/activation"
"github.com/opencontainers/runc/libcontainer"
"github.com/opencontainers/runc/libcontainer/cgroups/systemd"
"github.com/opencontainers/runc/libcontainer/configs"
"github.com/opencontainers/runc/libcontainer/specconv"
"github.com/opencontainers/runtime-spec/specs-go"
)
var container libcontainer.Container
func createContainer(id string, spec *specs.Spec) (libcontainer.Container, error) {
// startContainer starts the container. Returns the exit status or -1 and an
// error. Signals sent to the current process will be forwarded to container.
func startContainer(spec *specs.Spec, id, pidFile string, detach, useSystemdCgroup bool) (int, error) {
// create the libcontainer config
config, err := specconv.CreateLibcontainerConfig(&specconv.CreateOpts{
CgroupName: id,
UseSystemdCgroup: false,
UseSystemdCgroup: useSystemdCgroup,
NoPivotRoot: false,
Spec: spec,
})
if err != nil {
return nil, err
return -1, err
}
if _, err := os.Stat(config.Rootfs); err != nil {
if os.IsNotExist(err) {
return nil, fmt.Errorf("rootfs (%q) does not exist", config.Rootfs)
return -1, fmt.Errorf("rootfs (%q) does not exist", config.Rootfs)
}
return nil, err
return -1, err
}
logrus.Debugf("loading factory")
factory, err := loadFactory()
factory, err := loadFactory(useSystemdCgroup)
if err != nil {
return nil, err
return -1, err
}
logrus.Debugf("creating factory")
return factory.Create(id, config)
}
// startContainer starts the container. Returns the exit status or -1 and an
// error. Signals sent to the current process will be forwarded to container.
func startContainer(spec *specs.Spec, id, pidFile string, detach bool) (int, error) {
container, err := createContainer(id, spec)
container, err := factory.Create(id, config)
if err != nil {
return -1, err
}
@ -68,17 +61,23 @@ func startContainer(spec *specs.Spec, id, pidFile string, detach bool) (int, err
pidFile: pidFile,
listenFDs: listenFDs,
}
logrus.Debugf("running %#v", *r)
return r.run(&spec.Process)
}
// loadFactory returns the configured factory instance for execing containers.
func loadFactory() (libcontainer.Factory, error) {
func loadFactory(useSystemdCgroup bool) (libcontainer.Factory, error) {
abs, err := filepath.Abs(root)
if err != nil {
return nil, err
}
cgroupManager := libcontainer.Cgroupfs
if useSystemdCgroup {
if systemd.UseSystemd() {
cgroupManager = libcontainer.SystemdCgroups
} else {
return nil, fmt.Errorf("systemd cgroup flag passed, but systemd support for managing cgroups is not available")
}
}
return libcontainer.New(abs, cgroupManager, func(l *libcontainer.LinuxFactory) error {
return nil
})
@ -185,7 +184,6 @@ type runner struct {
}
func (r *runner) run(config *specs.Process) (int, error) {
logrus.Debugf("runner new process")
process, err := newProcess(*config)
if err != nil {
r.destroy()
@ -195,26 +193,22 @@ func (r *runner) run(config *specs.Process) (int, error) {
process.Env = append(process.Env, fmt.Sprintf("LISTEN_FDS=%d", len(r.listenFDs)), "LISTEN_PID=1")
process.ExtraFiles = append(process.ExtraFiles, r.listenFDs...)
}
logrus.Debugf("runner hostuid")
rootuid, err := r.container.Config().HostUID()
if err != nil {
r.destroy()
return -1, err
}
logrus.Debugf("runner setupio")
tty, err := setupIO(process, rootuid, r.console, config.Terminal, r.detach)
if err != nil {
r.destroy()
return -1, err
}
handler := newSignalHandler(tty, r.enableSubreaper)
logrus.Debugf("container start, %#v", r.container)
if err := r.container.Start(process); err != nil {
r.destroy()
tty.Close()
return -1, err
}
logrus.Debugf("close post start")
if err := tty.ClosePostStart(); err != nil {
r.terminate(process)
r.destroy()
@ -233,7 +227,6 @@ func (r *runner) run(config *specs.Process) (int, error) {
tty.Close()
return 0, nil
}
logrus.Debugf("forward handler")
status, err := handler.forward(process)
if err != nil {
r.terminate(process)

View file

@ -31,18 +31,15 @@ type Formatter interface {
// It's not exported because it's still using Data in an opinionated way. It's to
// avoid code duplication between the two default formatters.
func prefixFieldClashes(data Fields) {
_, ok := data["time"]
if ok {
data["fields.time"] = data["time"]
if t, ok := data["time"]; ok {
data["fields.time"] = t
}
_, ok = data["msg"]
if ok {
data["fields.msg"] = data["msg"]
if m, ok := data["msg"]; ok {
data["fields.msg"] = m
}
_, ok = data["level"]
if ok {
data["fields.level"] = data["level"]
if l, ok := data["level"]; ok {
data["fields.level"] = l
}
}

View file

@ -24,11 +24,13 @@ func (f *LogstashFormatter) Format(entry *logrus.Entry) ([]byte, error) {
fields["@version"] = 1
if f.TimestampFormat == "" {
f.TimestampFormat = logrus.DefaultTimestampFormat
timeStampFormat := f.TimestampFormat
if timeStampFormat == "" {
timeStampFormat = logrus.DefaultTimestampFormat
}
fields["@timestamp"] = entry.Time.Format(f.TimestampFormat)
fields["@timestamp"] = entry.Time.Format(timeStampFormat)
// set message field
v, ok := entry.Data["message"]

View file

@ -128,10 +128,10 @@ func needsQuoting(text string) bool {
(ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch <= '9') ||
ch == '-' || ch == '.') {
return false
return true
}
}
return true
return false
}
func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
@ -141,14 +141,14 @@ func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interf
switch value := value.(type) {
case string:
if needsQuoting(value) {
if !needsQuoting(value) {
b.WriteString(value)
} else {
fmt.Fprintf(b, "%q", value)
}
case error:
errmsg := value.Error()
if needsQuoting(errmsg) {
if !needsQuoting(errmsg) {
b.WriteString(errmsg)
} else {
fmt.Fprintf(b, "%q", value)

View file

@ -7,18 +7,40 @@ import (
)
func (logger *Logger) Writer() *io.PipeWriter {
return logger.WriterLevel(InfoLevel)
}
func (logger *Logger) WriterLevel(level Level) *io.PipeWriter {
reader, writer := io.Pipe()
go logger.writerScanner(reader)
var printFunc func(args ...interface{})
switch level {
case DebugLevel:
printFunc = logger.Debug
case InfoLevel:
printFunc = logger.Info
case WarnLevel:
printFunc = logger.Warn
case ErrorLevel:
printFunc = logger.Error
case FatalLevel:
printFunc = logger.Fatal
case PanicLevel:
printFunc = logger.Panic
default:
printFunc = logger.Print
}
go logger.writerScanner(reader, printFunc)
runtime.SetFinalizer(writer, writerFinalizer)
return writer
}
func (logger *Logger) writerScanner(reader *io.PipeReader) {
func (logger *Logger) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) {
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
logger.Print(scanner.Text())
printFunc(scanner.Text())
}
if err := scanner.Err(); err != nil {
logger.Errorf("Error while reading from Writer: %s", err)

View file

@ -15,7 +15,6 @@ import (
"github.com/Sirupsen/logrus"
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/configs"
"github.com/opencontainers/runc/libcontainer/user"
libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils"
)
@ -111,14 +110,11 @@ func (m *Manager) Apply(pid int) (err error) {
var c = m.Cgroups
logrus.Debugf("pre get cgroups data: %#v", c)
d, err := getCgroupData(m.Cgroups, pid)
if err != nil {
return err
}
logrus.Debugf("cgroups data: %#v, config: %#v", d, d.config)
if c.Paths != nil {
paths := make(map[string]string)
for name, path := range c.Paths {
@ -132,7 +128,6 @@ func (m *Manager) Apply(pid int) (err error) {
paths[name] = path
}
m.Paths = paths
logrus.Debugf("cgroups apply paths: %#v", m.Paths)
return cgroups.EnterPid(m.Paths, pid)
}
@ -140,7 +135,6 @@ func (m *Manager) Apply(pid int) (err error) {
defer m.mu.Unlock()
paths := make(map[string]string)
for _, sys := range subsystems {
logrus.Debugf("applying cgroups to subsystem %#v", sys)
if err := sys.Apply(d); err != nil {
return err
}
@ -358,25 +352,9 @@ func writeFile(dir, file, data string) error {
if dir == "" {
return fmt.Errorf("no such directory for %s", file)
}
// get the current user
u, err := user.CurrentUser()
if err != nil {
return err
}
if err := os.Lchown(dir, u.Uid, u.Gid); err != nil {
return fmt.Errorf("failed to chown to %d:%d -> %v", u.Uid, u.Gid, err)
}
logrus.Debugf("chown dir %s to %d:%d", dir, u.Uid, u.Gid)
if err := os.Lchown(filepath.Join(dir, file), u.Uid, u.Gid); err != nil {
return fmt.Errorf("failed to chown to %d:%d -> %v", u.Uid, u.Gid, err)
}
logrus.Debugf("chown %s to %d:%d", filepath.Join(dir, file), u.Uid, u.Gid)
if err := ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700); err != nil {
//return fmt.Errorf("failed to write %v to %v: %v", data, file, err)
logrus.Debugf("failed to write %v to %v: %v", data, file, err)
//return err
}
return nil
}

View file

@ -10,7 +10,6 @@ import (
"path/filepath"
"strconv"
"github.com/Sirupsen/logrus"
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/configs"
libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils"
@ -28,7 +27,6 @@ func (s *CpusetGroup) Apply(d *cgroupData) error {
if err != nil && !cgroups.IsNotFound(err) {
return err
}
logrus.Debugf("apply cpuset dir is %s", dir)
return s.ApplyDir(dir, d.config, d.pid)
}
@ -67,7 +65,6 @@ func (s *CpusetGroup) ApplyDir(dir string, cgroup *configs.Cgroup, pid int) erro
if err := s.ensureParent(dir, root); err != nil {
return err
}
// because we are not using d.join we need to place the pid into the procs file
// unlike the other subsystems
if err := writeFile(dir, "cgroup.procs", strconv.Itoa(pid)); err != nil {

View file

@ -13,9 +13,7 @@ import (
"strings"
"time"
"github.com/Sirupsen/logrus"
"github.com/docker/go-units"
"github.com/opencontainers/runc/libcontainer/user"
)
const cgroupNamePrefix = "name="
@ -291,21 +289,10 @@ func PathExists(path string) bool {
}
func EnterPid(cgroupPaths map[string]string, pid int) error {
// get the current user
u, err := user.CurrentUser()
if err != nil {
return err
}
for _, path := range cgroupPaths {
if PathExists(path) {
cgtasks := filepath.Join(path, "tasks")
// Chown the tasks file so that the user/group can enter the container.
if err := os.Chown(cgtasks, u.Uid, u.Gid); err != nil {
return fmt.Errorf("failed to chown %s to %d:%d -> %v", cgtasks, u.Uid, u.Gid, err)
}
if err := ioutil.WriteFile(filepath.Join(path, "cgroup.procs"),
[]byte(strconv.Itoa(pid)), 0700); err != nil {
logrus.Debug("cgroups/utils.go: ", err)
return err
}
}

View file

@ -171,7 +171,6 @@ func (c *linuxContainer) Set(config configs.Config) error {
c.m.Lock()
defer c.m.Unlock()
c.config = &config
logrus.Debugf("setting cgroups")
return c.cgroupManager.Set(c.config)
}
@ -742,7 +741,6 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error {
}
func (c *linuxContainer) criuApplyCgroups(pid int, req *criurpc.CriuReq) error {
logrus.Debugf("criu apply cgroups")
if err := c.cgroupManager.Apply(pid); err != nil {
return err
}

View file

@ -13,7 +13,6 @@ import (
"strconv"
"syscall"
"github.com/Sirupsen/logrus"
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/configs"
"github.com/opencontainers/runc/libcontainer/system"
@ -248,9 +247,6 @@ func (p *initProcess) start() error {
return newSystemError(err)
}
p.setExternalDescriptors(fds)
logrus.Debugf("starting process apply cgroups")
// Do this before syncing with child so that no children
// can escape the cgroup
if err := p.manager.Apply(p.pid()); err != nil {

35
vendor/manifest vendored
View file

@ -5,10 +5,19 @@
"importpath": "github.com/Sirupsen/logrus",
"repository": "https://github.com/Sirupsen/logrus",
"vcs": "git",
"revision": "7e6f9765803ea8356f45fd9b3c62305fb36cca51",
"revision": "081307d9bc1364753142d5962fc1d795c742baaf",
"branch": "master",
"notests": true
},
{
"importpath": "github.com/coreos/go-systemd/activation",
"repository": "https://github.com/coreos/go-systemd",
"vcs": "git",
"revision": "7b2428fec40033549c68f54e26e89e7ca9a9ce31",
"branch": "master",
"path": "/activation",
"notests": true
},
{
"importpath": "github.com/coreos/go-systemd/dbus",
"repository": "https://github.com/coreos/go-systemd",
@ -31,7 +40,7 @@
"importpath": "github.com/docker/docker/pkg/archive",
"repository": "https://github.com/docker/docker",
"vcs": "git",
"revision": "172ca1ca8c4d5157789feb97a6424104b81a3479",
"revision": "2a95488f7843a773de2b541a47d9b971a635bfff",
"branch": "master",
"path": "/pkg/archive",
"notests": true
@ -40,7 +49,7 @@
"importpath": "github.com/docker/docker/pkg/fileutils",
"repository": "https://github.com/docker/docker",
"vcs": "git",
"revision": "172ca1ca8c4d5157789feb97a6424104b81a3479",
"revision": "2a95488f7843a773de2b541a47d9b971a635bfff",
"branch": "master",
"path": "/pkg/fileutils",
"notests": true
@ -49,7 +58,7 @@
"importpath": "github.com/docker/docker/pkg/idtools",
"repository": "https://github.com/docker/docker",
"vcs": "git",
"revision": "172ca1ca8c4d5157789feb97a6424104b81a3479",
"revision": "2a95488f7843a773de2b541a47d9b971a635bfff",
"branch": "master",
"path": "/pkg/idtools",
"notests": true
@ -58,7 +67,7 @@
"importpath": "github.com/docker/docker/pkg/ioutils",
"repository": "https://github.com/docker/docker",
"vcs": "git",
"revision": "172ca1ca8c4d5157789feb97a6424104b81a3479",
"revision": "2a95488f7843a773de2b541a47d9b971a635bfff",
"branch": "master",
"path": "/pkg/ioutils",
"notests": true
@ -67,7 +76,7 @@
"importpath": "github.com/docker/docker/pkg/mount",
"repository": "https://github.com/docker/docker",
"vcs": "git",
"revision": "172ca1ca8c4d5157789feb97a6424104b81a3479",
"revision": "2a95488f7843a773de2b541a47d9b971a635bfff",
"branch": "master",
"path": "/pkg/mount",
"notests": true
@ -76,7 +85,7 @@
"importpath": "github.com/docker/docker/pkg/pools",
"repository": "https://github.com/docker/docker",
"vcs": "git",
"revision": "172ca1ca8c4d5157789feb97a6424104b81a3479",
"revision": "2a95488f7843a773de2b541a47d9b971a635bfff",
"branch": "master",
"path": "/pkg/pools",
"notests": true
@ -85,7 +94,7 @@
"importpath": "github.com/docker/docker/pkg/promise",
"repository": "https://github.com/docker/docker",
"vcs": "git",
"revision": "172ca1ca8c4d5157789feb97a6424104b81a3479",
"revision": "2a95488f7843a773de2b541a47d9b971a635bfff",
"branch": "master",
"path": "/pkg/promise",
"notests": true
@ -94,7 +103,7 @@
"importpath": "github.com/docker/docker/pkg/symlink",
"repository": "https://github.com/docker/docker",
"vcs": "git",
"revision": "172ca1ca8c4d5157789feb97a6424104b81a3479",
"revision": "2a95488f7843a773de2b541a47d9b971a635bfff",
"branch": "master",
"path": "/pkg/symlink",
"notests": true
@ -103,7 +112,7 @@
"importpath": "github.com/docker/docker/pkg/system",
"repository": "https://github.com/docker/docker",
"vcs": "git",
"revision": "172ca1ca8c4d5157789feb97a6424104b81a3479",
"revision": "2a95488f7843a773de2b541a47d9b971a635bfff",
"branch": "master",
"path": "/pkg/system",
"notests": true
@ -112,7 +121,7 @@
"importpath": "github.com/docker/docker/pkg/term",
"repository": "https://github.com/docker/docker",
"vcs": "git",
"revision": "172ca1ca8c4d5157789feb97a6424104b81a3479",
"revision": "2a95488f7843a773de2b541a47d9b971a635bfff",
"branch": "master",
"path": "/pkg/term",
"notests": true
@ -155,7 +164,7 @@
"importpath": "github.com/opencontainers/runtime-spec/specs-go",
"repository": "https://github.com/opencontainers/runtime-spec",
"vcs": "git",
"revision": "9d1998240a15ff6d226c2d4353b6dd6259728760",
"revision": "9d3aef58a7bcd98b41c11d1e42ed2d765a7b6f2c",
"branch": "master",
"path": "/specs-go",
"notests": true
@ -195,4 +204,4 @@
"notests": true
}
]
}
}