Browse Source

Merge pull request #7019 from crosbymichael/update-libcontainer-july2

Update libcontainer to version fb67bb80b4205bece36ff7096ee7
Michael Crosby 11 years ago
parent
commit
12d58a2688
54 changed files with 945 additions and 351 deletions
  1. 2 0
      daemon/execdriver/native/create.go
  2. 8 1
      daemon/execdriver/native/driver.go
  3. 13 0
      daemon/execdriver/native/driver_unsupported.go
  4. 2 0
      daemon/execdriver/native/info.go
  5. 1 1
      hack/vendor.sh
  6. 18 5
      vendor/src/github.com/docker/libcontainer/.travis.yml
  7. 0 23
      vendor/src/github.com/docker/libcontainer/api.go
  8. 34 0
      vendor/src/github.com/docker/libcontainer/api_temp.go
  9. 264 0
      vendor/src/github.com/docker/libcontainer/cgroups/cgutil/cgutil.go
  10. 10 0
      vendor/src/github.com/docker/libcontainer/cgroups/cgutil/sample_cgroup.json
  11. 30 13
      vendor/src/github.com/docker/libcontainer/cgroups/fs/apply_raw.go
  12. 7 8
      vendor/src/github.com/docker/libcontainer/cgroups/fs/blkio.go
  13. 22 22
      vendor/src/github.com/docker/libcontainer/cgroups/fs/blkio_test.go
  14. 5 11
      vendor/src/github.com/docker/libcontainer/cgroups/fs/cpu.go
  15. 6 6
      vendor/src/github.com/docker/libcontainer/cgroups/fs/cpu_test.go
  16. 13 13
      vendor/src/github.com/docker/libcontainer/cgroups/fs/cpuacct.go
  17. 8 8
      vendor/src/github.com/docker/libcontainer/cgroups/fs/cpuset.go
  18. 4 4
      vendor/src/github.com/docker/libcontainer/cgroups/fs/devices.go
  19. 4 25
      vendor/src/github.com/docker/libcontainer/cgroups/fs/freezer.go
  20. 7 9
      vendor/src/github.com/docker/libcontainer/cgroups/fs/memory.go
  21. 16 16
      vendor/src/github.com/docker/libcontainer/cgroups/fs/memory_test.go
  22. 4 4
      vendor/src/github.com/docker/libcontainer/cgroups/fs/perf_event.go
  23. 3 10
      vendor/src/github.com/docker/libcontainer/cgroups/stats.go
  24. 4 0
      vendor/src/github.com/docker/libcontainer/cgroups/systemd/apply_nosystemd.go
  25. 54 6
      vendor/src/github.com/docker/libcontainer/cgroups/systemd/apply_systemd.go
  26. 86 0
      vendor/src/github.com/docker/libcontainer/config.go
  27. 0 0
      vendor/src/github.com/docker/libcontainer/config_test.go
  28. 59 82
      vendor/src/github.com/docker/libcontainer/container.go
  29. 25 0
      vendor/src/github.com/docker/libcontainer/factory.go
  30. 4 0
      vendor/src/github.com/docker/libcontainer/label/label.go
  31. 17 0
      vendor/src/github.com/docker/libcontainer/label/label_selinux.go
  32. 8 2
      vendor/src/github.com/docker/libcontainer/mount/init.go
  33. 1 0
      vendor/src/github.com/docker/libcontainer/mount/types.go
  34. 4 3
      vendor/src/github.com/docker/libcontainer/namespaces/exec.go
  35. 2 2
      vendor/src/github.com/docker/libcontainer/namespaces/execin.go
  36. 2 1
      vendor/src/github.com/docker/libcontainer/namespaces/init.go
  37. 5 3
      vendor/src/github.com/docker/libcontainer/nsinit/cli.go
  38. 29 0
      vendor/src/github.com/docker/libcontainer/nsinit/config.go
  39. 1 1
      vendor/src/github.com/docker/libcontainer/nsinit/exec.go
  40. 3 2
      vendor/src/github.com/docker/libcontainer/nsinit/init.go
  41. 2 2
      vendor/src/github.com/docker/libcontainer/nsinit/nsenter.go
  42. 7 0
      vendor/src/github.com/docker/libcontainer/nsinit/nsinit/nsinit.go
  43. 49 0
      vendor/src/github.com/docker/libcontainer/nsinit/pause.go
  44. 0 40
      vendor/src/github.com/docker/libcontainer/nsinit/spec.go
  45. 6 17
      vendor/src/github.com/docker/libcontainer/nsinit/stats.go
  46. 1 1
      vendor/src/github.com/docker/libcontainer/nsinit/utils.go
  47. 27 0
      vendor/src/github.com/docker/libcontainer/process.go
  48. 1 1
      vendor/src/github.com/docker/libcontainer/security/capabilities/capabilities.go
  49. 0 2
      vendor/src/github.com/docker/libcontainer/security/capabilities/types.go
  50. 43 2
      vendor/src/github.com/docker/libcontainer/selinux/selinux.go
  51. 21 2
      vendor/src/github.com/docker/libcontainer/state.go
  52. 1 1
      vendor/src/github.com/docker/libcontainer/syncpipe/sync_pipe.go
  53. 1 1
      vendor/src/github.com/docker/libcontainer/syncpipe/sync_pipe_linux.go
  54. 1 1
      vendor/src/github.com/docker/libcontainer/syncpipe/sync_pipe_test.go

+ 2 - 0
daemon/execdriver/native/create.go

@@ -1,3 +1,5 @@
+// +build linux
+
 package native
 package native
 
 
 import (
 import (

+ 8 - 1
daemon/execdriver/native/driver.go

@@ -1,3 +1,5 @@
+// +build linux
+
 package native
 package native
 
 
 import (
 import (
@@ -16,6 +18,7 @@ import (
 	"github.com/docker/libcontainer/cgroups/fs"
 	"github.com/docker/libcontainer/cgroups/fs"
 	"github.com/docker/libcontainer/cgroups/systemd"
 	"github.com/docker/libcontainer/cgroups/systemd"
 	"github.com/docker/libcontainer/namespaces"
 	"github.com/docker/libcontainer/namespaces"
+	"github.com/docker/libcontainer/syncpipe"
 	"github.com/dotcloud/docker/daemon/execdriver"
 	"github.com/dotcloud/docker/daemon/execdriver"
 	"github.com/dotcloud/docker/pkg/system"
 	"github.com/dotcloud/docker/pkg/system"
 )
 )
@@ -32,6 +35,7 @@ func init() {
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
+
 		if err := json.NewDecoder(f).Decode(&container); err != nil {
 		if err := json.NewDecoder(f).Decode(&container); err != nil {
 			f.Close()
 			f.Close()
 			return err
 			return err
@@ -42,13 +46,16 @@ func init() {
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
-		syncPipe, err := namespaces.NewSyncPipeFromFd(0, uintptr(args.Pipe))
+
+		syncPipe, err := syncpipe.NewSyncPipeFromFd(0, uintptr(args.Pipe))
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
+
 		if err := namespaces.Init(container, rootfs, args.Console, syncPipe, args.Args); err != nil {
 		if err := namespaces.Init(container, rootfs, args.Console, syncPipe, args.Args); err != nil {
 			return err
 			return err
 		}
 		}
+
 		return nil
 		return nil
 	})
 	})
 }
 }

+ 13 - 0
daemon/execdriver/native/driver_unsupported.go

@@ -0,0 +1,13 @@
+// +build !linux
+
+package native
+
+import (
+	"fmt"
+
+	"github.com/dotcloud/docker/daemon/execdriver"
+)
+
+func NewDriver(root, initPath string) (execdriver.Driver, error) {
+	return nil, fmt.Errorf("native driver not supported on non-linux")
+}

+ 2 - 0
daemon/execdriver/native/info.go

@@ -1,3 +1,5 @@
+// +build linux
+
 package native
 package native
 
 
 import (
 import (

+ 1 - 1
hack/vendor.sh

@@ -63,4 +63,4 @@ mv tmp-tar src/code.google.com/p/go/src/pkg/archive/tar
 
 
 clone git github.com/godbus/dbus v1
 clone git github.com/godbus/dbus v1
 clone git github.com/coreos/go-systemd v2
 clone git github.com/coreos/go-systemd v2
-clone git github.com/docker/libcontainer 53cfe0a1eba9145bf5329abbb52b0072ccab8a00
+clone git github.com/docker/libcontainer fb67bb80b4205bece36ff7096ee745ab0cee7e06

+ 18 - 5
vendor/src/github.com/docker/libcontainer/.travis.yml

@@ -1,12 +1,25 @@
 language: go
 language: go
 
 
+# let us have pretty experimental Docker-based Travis workers
+sudo: false
+
+env:
+    - TRAVIS_GLOBAL_WTF=1
+    - GOOS=linux GOARCH=amd64
+    - GOOS=linux GOARCH=386
+    - GOOS=linux GOARCH=arm
+    - GOOS=darwin GOARCH=amd64
+    - GOOS=darwin GOARCH=386
+    - GOOS=freebsd GOARCH=amd64
+
 install:
 install:
-    - go get -d ./...
-    - go get -d github.com/dotcloud/docker # just to be sure
+    - go get -d -v ./...
+    - go get -d -v github.com/dotcloud/docker # just to be sure
     - DOCKER_PATH="${GOPATH%%:*}/src/github.com/dotcloud/docker"
     - DOCKER_PATH="${GOPATH%%:*}/src/github.com/dotcloud/docker"
     - sed -i 's!dotcloud/docker!docker/libcontainer!' "$DOCKER_PATH/hack/make/.validate"
     - sed -i 's!dotcloud/docker!docker/libcontainer!' "$DOCKER_PATH/hack/make/.validate"
 
 
 script:
 script:
-    - bash "$DOCKER_PATH/hack/make/validate-dco"
-    - bash "$DOCKER_PATH/hack/make/validate-gofmt"
-    - go test
+    - if [ "$TRAVIS_GLOBAL_WTF" ]; then bash "$DOCKER_PATH/hack/make/validate-dco"; fi
+    - if [ "$TRAVIS_GLOBAL_WTF" ]; then bash "$DOCKER_PATH/hack/make/validate-gofmt"; fi
+    - if [ -z "$TRAVIS_GLOBAL_WTF" ]; then go build -v ./...; fi
+    - if [ -z "$TRAVIS_GLOBAL_WTF" ]; then go test -v ./...; fi

+ 0 - 23
vendor/src/github.com/docker/libcontainer/api.go

@@ -1,23 +0,0 @@
-package libcontainer
-
-import (
-	"github.com/docker/libcontainer/cgroups/fs"
-	"github.com/docker/libcontainer/network"
-)
-
-// Returns all available stats for the given container.
-func GetStats(container *Config, state *State) (*ContainerStats, error) {
-	var containerStats ContainerStats
-	stats, err := fs.GetStats(container.Cgroups)
-	if err != nil {
-		return &containerStats, err
-	}
-	containerStats.CgroupStats = stats
-	networkStats, err := network.GetStats(&state.NetworkState)
-	if err != nil {
-		return &containerStats, err
-	}
-	containerStats.NetworkStats = networkStats
-
-	return &containerStats, nil
-}

+ 34 - 0
vendor/src/github.com/docker/libcontainer/api_temp.go

@@ -0,0 +1,34 @@
+/*
+Temporary API endpoint for libcontainer while the full API is finalized (api.go).
+*/
+package libcontainer
+
+import (
+	"github.com/docker/libcontainer/cgroups/fs"
+	"github.com/docker/libcontainer/cgroups/systemd"
+	"github.com/docker/libcontainer/network"
+)
+
+// TODO(vmarmol): Complete Stats() in final libcontainer API and move users to that.
+// DEPRECATED: The below portions are only to be used during the transition to the official API.
+// Returns all available stats for the given container.
+func GetStats(container *Config, state *State) (*ContainerStats, error) {
+	var (
+		err   error
+		stats = &ContainerStats{}
+	)
+
+	if systemd.UseSystemd() {
+		stats.CgroupStats, err = systemd.GetStats(container.Cgroups)
+	} else {
+		stats.CgroupStats, err = fs.GetStats(container.Cgroups)
+	}
+
+	if err != nil {
+		return stats, err
+	}
+
+	stats.NetworkStats, err = network.GetStats(&state.NetworkState)
+
+	return stats, err
+}

+ 264 - 0
vendor/src/github.com/docker/libcontainer/cgroups/cgutil/cgutil.go

@@ -0,0 +1,264 @@
+package main
+
+import (
+	"encoding/json"
+	"fmt"
+	"log"
+	"os"
+	"syscall"
+	"time"
+
+	"github.com/codegangsta/cli"
+	"github.com/docker/libcontainer/cgroups"
+	"github.com/docker/libcontainer/cgroups/fs"
+	"github.com/docker/libcontainer/cgroups/systemd"
+)
+
+var createCommand = cli.Command{
+	Name:  "create",
+	Usage: "Create a cgroup container using the supplied configuration and initial process.",
+	Flags: []cli.Flag{
+		cli.StringFlag{"config, c", "cgroup.json", "path to container configuration (cgroups.Cgroup object)"},
+		cli.IntFlag{"pid, p", 0, "pid of the initial process in the container"},
+	},
+	Action: createAction,
+}
+
+var destroyCommand = cli.Command{
+	Name:  "destroy",
+	Usage: "Destroy an existing cgroup container.",
+	Flags: []cli.Flag{
+		cli.StringFlag{"name, n", "", "container name"},
+		cli.StringFlag{"parent, p", "", "container parent"},
+	},
+	Action: destroyAction,
+}
+
+var statsCommand = cli.Command{
+	Name:  "stats",
+	Usage: "Get stats for cgroup",
+	Flags: []cli.Flag{
+		cli.StringFlag{"name, n", "", "container name"},
+		cli.StringFlag{"parent, p", "", "container parent"},
+	},
+	Action: statsAction,
+}
+
+var pauseCommand = cli.Command{
+	Name:  "pause",
+	Usage: "Pause cgroup",
+	Flags: []cli.Flag{
+		cli.StringFlag{"name, n", "", "container name"},
+		cli.StringFlag{"parent, p", "", "container parent"},
+	},
+	Action: pauseAction,
+}
+
+var resumeCommand = cli.Command{
+	Name:  "resume",
+	Usage: "Resume a paused cgroup",
+	Flags: []cli.Flag{
+		cli.StringFlag{"name, n", "", "container name"},
+		cli.StringFlag{"parent, p", "", "container parent"},
+	},
+	Action: resumeAction,
+}
+
+var psCommand = cli.Command{
+	Name:  "ps",
+	Usage: "Get list of pids for a cgroup",
+	Flags: []cli.Flag{
+		cli.StringFlag{"name, n", "", "container name"},
+		cli.StringFlag{"parent, p", "", "container parent"},
+	},
+	Action: psAction,
+}
+
+func getConfigFromFile(c *cli.Context) (*cgroups.Cgroup, error) {
+	f, err := os.Open(c.String("config"))
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+
+	var config *cgroups.Cgroup
+	if err := json.NewDecoder(f).Decode(&config); err != nil {
+		log.Fatal(err)
+	}
+	return config, nil
+}
+
+func openLog(name string) error {
+	f, err := os.OpenFile(name, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0755)
+	if err != nil {
+		return err
+	}
+
+	log.SetOutput(f)
+	return nil
+}
+
+func getConfig(context *cli.Context) (*cgroups.Cgroup, error) {
+	name := context.String("name")
+	if name == "" {
+		log.Fatal(fmt.Errorf("Missing container name"))
+	}
+	parent := context.String("parent")
+	return &cgroups.Cgroup{
+		Name:   name,
+		Parent: parent,
+	}, nil
+}
+
+func killAll(config *cgroups.Cgroup) {
+	// We could use freezer here to prevent process spawning while we are trying
+	// to kill everything. But going with more portable solution of retrying for
+	// now.
+	pids := getPids(config)
+	retry := 10
+	for len(pids) != 0 || retry > 0 {
+		killPids(pids)
+		time.Sleep(100 * time.Millisecond)
+		retry--
+		pids = getPids(config)
+	}
+	if len(pids) != 0 {
+		log.Fatal(fmt.Errorf("Could not kill existing processes in the container."))
+	}
+}
+
+func getPids(config *cgroups.Cgroup) []int {
+	pids, err := fs.GetPids(config)
+	if err != nil {
+		log.Fatal(err)
+	}
+	return pids
+}
+
+func killPids(pids []int) {
+	for _, pid := range pids {
+		// pids might go away on their own. Ignore errors.
+		syscall.Kill(pid, syscall.SIGKILL)
+	}
+}
+
+func setFreezerState(context *cli.Context, state cgroups.FreezerState) {
+	config, err := getConfig(context)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	if systemd.UseSystemd() {
+		err = systemd.Freeze(config, state)
+	} else {
+		err = fs.Freeze(config, state)
+	}
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+func createAction(context *cli.Context) {
+	config, err := getConfigFromFile(context)
+	if err != nil {
+		log.Fatal(err)
+	}
+	pid := context.Int("pid")
+	if pid <= 0 {
+		log.Fatal(fmt.Errorf("Invalid pid : %d", pid))
+	}
+	if systemd.UseSystemd() {
+		_, err := systemd.Apply(config, pid)
+		if err != nil {
+			log.Fatal(err)
+		}
+	} else {
+		_, err := fs.Apply(config, pid)
+		if err != nil {
+			log.Fatal(err)
+		}
+	}
+}
+
+func destroyAction(context *cli.Context) {
+	config, err := getConfig(context)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	killAll(config)
+	// Systemd will clean up cgroup state for empty container.
+	if !systemd.UseSystemd() {
+		err := fs.Cleanup(config)
+		if err != nil {
+			log.Fatal(err)
+		}
+	}
+}
+
+func statsAction(context *cli.Context) {
+	config, err := getConfig(context)
+	if err != nil {
+		log.Fatal(err)
+	}
+	stats, err := fs.GetStats(config)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	out, err := json.MarshalIndent(stats, "", "\t")
+	if err != nil {
+		log.Fatal(err)
+	}
+	fmt.Printf("Usage stats for '%s':\n %v\n", config.Name, string(out))
+}
+
+func pauseAction(context *cli.Context) {
+	setFreezerState(context, cgroups.Frozen)
+}
+
+func resumeAction(context *cli.Context) {
+	setFreezerState(context, cgroups.Thawed)
+}
+
+func psAction(context *cli.Context) {
+	config, err := getConfig(context)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	pids, err := fs.GetPids(config)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("Pids in '%s':\n", config.Name)
+	fmt.Println(pids)
+}
+
+func main() {
+	logPath := os.Getenv("log")
+	if logPath != "" {
+		if err := openLog(logPath); err != nil {
+			log.Fatal(err)
+		}
+	}
+
+	app := cli.NewApp()
+	app.Name = "cgutil"
+	app.Usage = "Test utility for libcontainer cgroups package"
+	app.Version = "0.1"
+
+	app.Commands = []cli.Command{
+		createCommand,
+		destroyCommand,
+		statsCommand,
+		pauseCommand,
+		resumeCommand,
+		psCommand,
+	}
+
+	if err := app.Run(os.Args); err != nil {
+		log.Fatal(err)
+	}
+}

+ 10 - 0
vendor/src/github.com/docker/libcontainer/cgroups/cgutil/sample_cgroup.json

@@ -0,0 +1,10 @@
+{
+	"name": "luke",
+	"parent": "darth",
+	"allow_all_devices": true,
+	"memory": 1073741824,
+	"memory_swap": -1,
+	"cpu_shares": 2048,
+	"cpu_quota": 500000,
+	"cpu_period": 250000
+}

+ 30 - 13
vendor/src/github.com/docker/libcontainer/cgroups/fs/apply_raw.go

@@ -12,21 +12,21 @@ import (
 
 
 var (
 var (
 	subsystems = map[string]subsystem{
 	subsystems = map[string]subsystem{
-		"devices":    &devicesGroup{},
-		"memory":     &memoryGroup{},
-		"cpu":        &cpuGroup{},
-		"cpuset":     &cpusetGroup{},
-		"cpuacct":    &cpuacctGroup{},
-		"blkio":      &blkioGroup{},
-		"perf_event": &perfEventGroup{},
-		"freezer":    &freezerGroup{},
+		"devices":    &DevicesGroup{},
+		"memory":     &MemoryGroup{},
+		"cpu":        &CpuGroup{},
+		"cpuset":     &CpusetGroup{},
+		"cpuacct":    &CpuacctGroup{},
+		"blkio":      &BlkioGroup{},
+		"perf_event": &PerfEventGroup{},
+		"freezer":    &FreezerGroup{},
 	}
 	}
 )
 )
 
 
 type subsystem interface {
 type subsystem interface {
 	Set(*data) error
 	Set(*data) error
 	Remove(*data) error
 	Remove(*data) error
-	GetStats(*data, *cgroups.Stats) error
+	GetStats(string, *cgroups.Stats) error
 }
 }
 
 
 type data struct {
 type data struct {
@@ -52,6 +52,14 @@ func Apply(c *cgroups.Cgroup, pid int) (cgroups.ActiveCgroup, error) {
 	return d, nil
 	return d, nil
 }
 }
 
 
+func Cleanup(c *cgroups.Cgroup) error {
+	d, err := getCgroupData(c, 0)
+	if err != nil {
+		return fmt.Errorf("Could not get Cgroup data %s", err)
+	}
+	return d.Cleanup()
+}
+
 func GetStats(c *cgroups.Cgroup) (*cgroups.Stats, error) {
 func GetStats(c *cgroups.Cgroup) (*cgroups.Stats, error) {
 	stats := cgroups.NewStats()
 	stats := cgroups.NewStats()
 
 
@@ -60,10 +68,19 @@ func GetStats(c *cgroups.Cgroup) (*cgroups.Stats, error) {
 		return nil, fmt.Errorf("getting CgroupData %s", err)
 		return nil, fmt.Errorf("getting CgroupData %s", err)
 	}
 	}
 
 
-	for sysName, sys := range subsystems {
-		// Don't fail if a cgroup hierarchy was not found.
-		if err := sys.GetStats(d, stats); err != nil && err != cgroups.ErrNotFound {
-			return nil, fmt.Errorf("getting stats for system %q %s", sysName, err)
+	for sysname, sys := range subsystems {
+		path, err := d.path(sysname)
+		if err != nil {
+			// Don't fail if a cgroup hierarchy was not found, just skip this subsystem
+			if err == cgroups.ErrNotFound {
+				continue
+			}
+
+			return nil, err
+		}
+
+		if err := sys.GetStats(path, stats); err != nil {
+			return nil, err
 		}
 		}
 	}
 	}
 
 

+ 7 - 8
vendor/src/github.com/docker/libcontainer/cgroups/fs/blkio.go

@@ -11,10 +11,10 @@ import (
 	"github.com/docker/libcontainer/cgroups"
 	"github.com/docker/libcontainer/cgroups"
 )
 )
 
 
-type blkioGroup struct {
+type BlkioGroup struct {
 }
 }
 
 
-func (s *blkioGroup) Set(d *data) error {
+func (s *BlkioGroup) Set(d *data) error {
 	// we just want to join this group even though we don't set anything
 	// we just want to join this group even though we don't set anything
 	if _, err := d.join("blkio"); err != nil && err != cgroups.ErrNotFound {
 	if _, err := d.join("blkio"); err != nil && err != cgroups.ErrNotFound {
 		return err
 		return err
@@ -22,7 +22,7 @@ func (s *blkioGroup) Set(d *data) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *blkioGroup) Remove(d *data) error {
+func (s *BlkioGroup) Remove(d *data) error {
 	return removePath(d.path("blkio"))
 	return removePath(d.path("blkio"))
 }
 }
 
 
@@ -65,6 +65,9 @@ func getBlkioStat(path string) ([]cgroups.BlkioStatEntry, error) {
 	var blkioStats []cgroups.BlkioStatEntry
 	var blkioStats []cgroups.BlkioStatEntry
 	f, err := os.Open(path)
 	f, err := os.Open(path)
 	if err != nil {
 	if err != nil {
+		if os.IsNotExist(err) {
+			return blkioStats, nil
+		}
 		return nil, err
 		return nil, err
 	}
 	}
 	defer f.Close()
 	defer f.Close()
@@ -110,13 +113,9 @@ func getBlkioStat(path string) ([]cgroups.BlkioStatEntry, error) {
 	return blkioStats, nil
 	return blkioStats, nil
 }
 }
 
 
-func (s *blkioGroup) GetStats(d *data, stats *cgroups.Stats) error {
+func (s *BlkioGroup) GetStats(path string, stats *cgroups.Stats) error {
 	var blkioStats []cgroups.BlkioStatEntry
 	var blkioStats []cgroups.BlkioStatEntry
 	var err error
 	var err error
-	path, err := d.path("blkio")
-	if err != nil {
-		return err
-	}
 
 
 	if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.sectors_recursive")); err != nil {
 	if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.sectors_recursive")); err != nil {
 		return err
 		return err

+ 22 - 22
vendor/src/github.com/docker/libcontainer/cgroups/fs/blkio_test.go

@@ -44,8 +44,8 @@ func TestBlkioStats(t *testing.T) {
 		"blkio.sectors_recursive":          sectorsRecursiveContents,
 		"blkio.sectors_recursive":          sectorsRecursiveContents,
 	})
 	})
 
 
-	blkio := &blkioGroup{}
-	err := blkio.GetStats(helper.CgroupData, &actualStats)
+	blkio := &BlkioGroup{}
+	err := blkio.GetStats(helper.CgroupPath, &actualStats)
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -84,10 +84,10 @@ func TestBlkioStatsNoSectorsFile(t *testing.T) {
 		"blkio.io_queued_recursive":        queuedRecursiveContents,
 		"blkio.io_queued_recursive":        queuedRecursiveContents,
 	})
 	})
 
 
-	blkio := &blkioGroup{}
-	err := blkio.GetStats(helper.CgroupData, &actualStats)
-	if err == nil {
-		t.Fatal("Expected to fail, but did not")
+	blkio := &BlkioGroup{}
+	err := blkio.GetStats(helper.CgroupPath, &actualStats)
+	if err != nil {
+		t.Fatalf("Failed unexpectedly: %s", err)
 	}
 	}
 }
 }
 
 
@@ -100,10 +100,10 @@ func TestBlkioStatsNoServiceBytesFile(t *testing.T) {
 		"blkio.sectors_recursive":     sectorsRecursiveContents,
 		"blkio.sectors_recursive":     sectorsRecursiveContents,
 	})
 	})
 
 
-	blkio := &blkioGroup{}
-	err := blkio.GetStats(helper.CgroupData, &actualStats)
-	if err == nil {
-		t.Fatal("Expected to fail, but did not")
+	blkio := &BlkioGroup{}
+	err := blkio.GetStats(helper.CgroupPath, &actualStats)
+	if err != nil {
+		t.Fatalf("Failed unexpectedly: %s", err)
 	}
 	}
 }
 }
 
 
@@ -116,10 +116,10 @@ func TestBlkioStatsNoServicedFile(t *testing.T) {
 		"blkio.sectors_recursive":          sectorsRecursiveContents,
 		"blkio.sectors_recursive":          sectorsRecursiveContents,
 	})
 	})
 
 
-	blkio := &blkioGroup{}
-	err := blkio.GetStats(helper.CgroupData, &actualStats)
-	if err == nil {
-		t.Fatal("Expected to fail, but did not")
+	blkio := &BlkioGroup{}
+	err := blkio.GetStats(helper.CgroupPath, &actualStats)
+	if err != nil {
+		t.Fatalf("Failed unexpectedly: %s", err)
 	}
 	}
 }
 }
 
 
@@ -132,10 +132,10 @@ func TestBlkioStatsNoQueuedFile(t *testing.T) {
 		"blkio.sectors_recursive":          sectorsRecursiveContents,
 		"blkio.sectors_recursive":          sectorsRecursiveContents,
 	})
 	})
 
 
-	blkio := &blkioGroup{}
-	err := blkio.GetStats(helper.CgroupData, &actualStats)
-	if err == nil {
-		t.Fatal("Expected to fail, but did not")
+	blkio := &BlkioGroup{}
+	err := blkio.GetStats(helper.CgroupPath, &actualStats)
+	if err != nil {
+		t.Fatalf("Failed unexpectedly: %s", err)
 	}
 	}
 }
 }
 
 
@@ -149,8 +149,8 @@ func TestBlkioStatsUnexpectedNumberOfFields(t *testing.T) {
 		"blkio.sectors_recursive":          sectorsRecursiveContents,
 		"blkio.sectors_recursive":          sectorsRecursiveContents,
 	})
 	})
 
 
-	blkio := &blkioGroup{}
-	err := blkio.GetStats(helper.CgroupData, &actualStats)
+	blkio := &BlkioGroup{}
+	err := blkio.GetStats(helper.CgroupPath, &actualStats)
 	if err == nil {
 	if err == nil {
 		t.Fatal("Expected to fail, but did not")
 		t.Fatal("Expected to fail, but did not")
 	}
 	}
@@ -166,8 +166,8 @@ func TestBlkioStatsUnexpectedFieldType(t *testing.T) {
 		"blkio.sectors_recursive":          sectorsRecursiveContents,
 		"blkio.sectors_recursive":          sectorsRecursiveContents,
 	})
 	})
 
 
-	blkio := &blkioGroup{}
-	err := blkio.GetStats(helper.CgroupData, &actualStats)
+	blkio := &BlkioGroup{}
+	err := blkio.GetStats(helper.CgroupPath, &actualStats)
 	if err == nil {
 	if err == nil {
 		t.Fatal("Expected to fail, but did not")
 		t.Fatal("Expected to fail, but did not")
 	}
 	}

+ 5 - 11
vendor/src/github.com/docker/libcontainer/cgroups/fs/cpu.go

@@ -5,15 +5,14 @@ import (
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
 	"strconv"
 	"strconv"
-	"syscall"
 
 
 	"github.com/docker/libcontainer/cgroups"
 	"github.com/docker/libcontainer/cgroups"
 )
 )
 
 
-type cpuGroup struct {
+type CpuGroup struct {
 }
 }
 
 
-func (s *cpuGroup) Set(d *data) error {
+func (s *CpuGroup) Set(d *data) error {
 	// We always want to join the cpu group, to allow fair cpu scheduling
 	// We always want to join the cpu group, to allow fair cpu scheduling
 	// on a container basis
 	// on a container basis
 	dir, err := d.join("cpu")
 	dir, err := d.join("cpu")
@@ -38,19 +37,14 @@ func (s *cpuGroup) Set(d *data) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *cpuGroup) Remove(d *data) error {
+func (s *CpuGroup) Remove(d *data) error {
 	return removePath(d.path("cpu"))
 	return removePath(d.path("cpu"))
 }
 }
 
 
-func (s *cpuGroup) GetStats(d *data, stats *cgroups.Stats) error {
-	path, err := d.path("cpu")
-	if err != nil {
-		return err
-	}
-
+func (s *CpuGroup) GetStats(path string, stats *cgroups.Stats) error {
 	f, err := os.Open(filepath.Join(path, "cpu.stat"))
 	f, err := os.Open(filepath.Join(path, "cpu.stat"))
 	if err != nil {
 	if err != nil {
-		if pathErr, ok := err.(*os.PathError); ok && pathErr.Err == syscall.ENOENT {
+		if os.IsNotExist(err) {
 			return nil
 			return nil
 		}
 		}
 		return err
 		return err

+ 6 - 6
vendor/src/github.com/docker/libcontainer/cgroups/fs/cpu_test.go

@@ -23,8 +23,8 @@ func TestCpuStats(t *testing.T) {
 		"cpu.stat": cpuStatContent,
 		"cpu.stat": cpuStatContent,
 	})
 	})
 
 
-	cpu := &cpuGroup{}
-	err := cpu.GetStats(helper.CgroupData, &actualStats)
+	cpu := &CpuGroup{}
+	err := cpu.GetStats(helper.CgroupPath, &actualStats)
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -41,8 +41,8 @@ func TestNoCpuStatFile(t *testing.T) {
 	helper := NewCgroupTestUtil("cpu", t)
 	helper := NewCgroupTestUtil("cpu", t)
 	defer helper.cleanup()
 	defer helper.cleanup()
 
 
-	cpu := &cpuGroup{}
-	err := cpu.GetStats(helper.CgroupData, &actualStats)
+	cpu := &CpuGroup{}
+	err := cpu.GetStats(helper.CgroupPath, &actualStats)
 	if err != nil {
 	if err != nil {
 		t.Fatal("Expected not to fail, but did")
 		t.Fatal("Expected not to fail, but did")
 	}
 	}
@@ -58,8 +58,8 @@ func TestInvalidCpuStat(t *testing.T) {
 		"cpu.stat": cpuStatContent,
 		"cpu.stat": cpuStatContent,
 	})
 	})
 
 
-	cpu := &cpuGroup{}
-	err := cpu.GetStats(helper.CgroupData, &actualStats)
+	cpu := &CpuGroup{}
+	err := cpu.GetStats(helper.CgroupPath, &actualStats)
 	if err == nil {
 	if err == nil {
 		t.Fatal("Expected failed stat parsing.")
 		t.Fatal("Expected failed stat parsing.")
 	}
 	}

+ 13 - 13
vendor/src/github.com/docker/libcontainer/cgroups/fs/cpuacct.go

@@ -22,10 +22,10 @@ var (
 
 
 const nanosecondsInSecond = 1000000000
 const nanosecondsInSecond = 1000000000
 
 
-type cpuacctGroup struct {
+type CpuacctGroup struct {
 }
 }
 
 
-func (s *cpuacctGroup) Set(d *data) error {
+func (s *CpuacctGroup) Set(d *data) error {
 	// we just want to join this group even though we don't set anything
 	// we just want to join this group even though we don't set anything
 	if _, err := d.join("cpuacct"); err != nil && err != cgroups.ErrNotFound {
 	if _, err := d.join("cpuacct"); err != nil && err != cgroups.ErrNotFound {
 		return err
 		return err
@@ -33,20 +33,20 @@ func (s *cpuacctGroup) Set(d *data) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *cpuacctGroup) Remove(d *data) error {
+func (s *CpuacctGroup) Remove(d *data) error {
 	return removePath(d.path("cpuacct"))
 	return removePath(d.path("cpuacct"))
 }
 }
 
 
-func (s *cpuacctGroup) GetStats(d *data, stats *cgroups.Stats) error {
+func (s *CpuacctGroup) GetStats(path string, stats *cgroups.Stats) error {
 	var (
 	var (
+		err                                                                                                           error
 		startCpu, lastCpu, startSystem, lastSystem, startUsage, lastUsage, kernelModeUsage, userModeUsage, percentage uint64
 		startCpu, lastCpu, startSystem, lastSystem, startUsage, lastUsage, kernelModeUsage, userModeUsage, percentage uint64
 	)
 	)
-	path, err := d.path("cpuacct")
-	if kernelModeUsage, userModeUsage, err = s.getCpuUsage(d, path); err != nil {
+	if kernelModeUsage, userModeUsage, err = getCpuUsage(path); err != nil {
 		return err
 		return err
 	}
 	}
 	startCpu = kernelModeUsage + userModeUsage
 	startCpu = kernelModeUsage + userModeUsage
-	if startSystem, err = s.getSystemCpuUsage(d); err != nil {
+	if startSystem, err = getSystemCpuUsage(); err != nil {
 		return err
 		return err
 	}
 	}
 	startUsageTime := time.Now()
 	startUsageTime := time.Now()
@@ -55,11 +55,11 @@ func (s *cpuacctGroup) GetStats(d *data, stats *cgroups.Stats) error {
 	}
 	}
 	// sample for 100ms
 	// sample for 100ms
 	time.Sleep(100 * time.Millisecond)
 	time.Sleep(100 * time.Millisecond)
-	if kernelModeUsage, userModeUsage, err = s.getCpuUsage(d, path); err != nil {
+	if kernelModeUsage, userModeUsage, err = getCpuUsage(path); err != nil {
 		return err
 		return err
 	}
 	}
 	lastCpu = kernelModeUsage + userModeUsage
 	lastCpu = kernelModeUsage + userModeUsage
-	if lastSystem, err = s.getSystemCpuUsage(d); err != nil {
+	if lastSystem, err = getSystemCpuUsage(); err != nil {
 		return err
 		return err
 	}
 	}
 	usageSampleDuration := time.Since(startUsageTime)
 	usageSampleDuration := time.Since(startUsageTime)
@@ -80,7 +80,7 @@ func (s *cpuacctGroup) GetStats(d *data, stats *cgroups.Stats) error {
 	stats.CpuStats.CpuUsage.PercentUsage = percentage
 	stats.CpuStats.CpuUsage.PercentUsage = percentage
 	// Delta usage is in nanoseconds of CPU time so get the usage (in cores) over the sample time.
 	// Delta usage is in nanoseconds of CPU time so get the usage (in cores) over the sample time.
 	stats.CpuStats.CpuUsage.CurrentUsage = deltaUsage / uint64(usageSampleDuration.Nanoseconds())
 	stats.CpuStats.CpuUsage.CurrentUsage = deltaUsage / uint64(usageSampleDuration.Nanoseconds())
-	percpuUsage, err := s.getPercpuUsage(path)
+	percpuUsage, err := getPercpuUsage(path)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -92,7 +92,7 @@ func (s *cpuacctGroup) GetStats(d *data, stats *cgroups.Stats) error {
 }
 }
 
 
 // TODO(vmarmol): Use cgroups stats.
 // TODO(vmarmol): Use cgroups stats.
-func (s *cpuacctGroup) getSystemCpuUsage(d *data) (uint64, error) {
+func getSystemCpuUsage() (uint64, error) {
 
 
 	f, err := os.Open("/proc/stat")
 	f, err := os.Open("/proc/stat")
 	if err != nil {
 	if err != nil {
@@ -125,7 +125,7 @@ func (s *cpuacctGroup) getSystemCpuUsage(d *data) (uint64, error) {
 	return 0, fmt.Errorf("invalid stat format")
 	return 0, fmt.Errorf("invalid stat format")
 }
 }
 
 
-func (s *cpuacctGroup) getCpuUsage(d *data, path string) (uint64, uint64, error) {
+func getCpuUsage(path string) (uint64, uint64, error) {
 	kernelModeUsage := uint64(0)
 	kernelModeUsage := uint64(0)
 	userModeUsage := uint64(0)
 	userModeUsage := uint64(0)
 	data, err := ioutil.ReadFile(filepath.Join(path, "cpuacct.stat"))
 	data, err := ioutil.ReadFile(filepath.Join(path, "cpuacct.stat"))
@@ -146,7 +146,7 @@ func (s *cpuacctGroup) getCpuUsage(d *data, path string) (uint64, uint64, error)
 	return kernelModeUsage, userModeUsage, nil
 	return kernelModeUsage, userModeUsage, nil
 }
 }
 
 
-func (s *cpuacctGroup) getPercpuUsage(path string) ([]uint64, error) {
+func getPercpuUsage(path string) ([]uint64, error) {
 	percpuUsage := []uint64{}
 	percpuUsage := []uint64{}
 	data, err := ioutil.ReadFile(filepath.Join(path, "cpuacct.usage_percpu"))
 	data, err := ioutil.ReadFile(filepath.Join(path, "cpuacct.usage_percpu"))
 	if err != nil {
 	if err != nil {

+ 8 - 8
vendor/src/github.com/docker/libcontainer/cgroups/fs/cpuset.go

@@ -10,10 +10,10 @@ import (
 	"github.com/docker/libcontainer/cgroups"
 	"github.com/docker/libcontainer/cgroups"
 )
 )
 
 
-type cpusetGroup struct {
+type CpusetGroup struct {
 }
 }
 
 
-func (s *cpusetGroup) Set(d *data) error {
+func (s *CpusetGroup) Set(d *data) error {
 	// we don't want to join this cgroup unless it is specified
 	// we don't want to join this cgroup unless it is specified
 	if d.c.CpusetCpus != "" {
 	if d.c.CpusetCpus != "" {
 		dir, err := d.path("cpuset")
 		dir, err := d.path("cpuset")
@@ -36,15 +36,15 @@ func (s *cpusetGroup) Set(d *data) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *cpusetGroup) Remove(d *data) error {
+func (s *CpusetGroup) Remove(d *data) error {
 	return removePath(d.path("cpuset"))
 	return removePath(d.path("cpuset"))
 }
 }
 
 
-func (s *cpusetGroup) GetStats(d *data, stats *cgroups.Stats) error {
+func (s *CpusetGroup) GetStats(path string, stats *cgroups.Stats) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *cpusetGroup) getSubsystemSettings(parent string) (cpus []byte, mems []byte, err error) {
+func (s *CpusetGroup) getSubsystemSettings(parent string) (cpus []byte, mems []byte, err error) {
 	if cpus, err = ioutil.ReadFile(filepath.Join(parent, "cpuset.cpus")); err != nil {
 	if cpus, err = ioutil.ReadFile(filepath.Join(parent, "cpuset.cpus")); err != nil {
 		return
 		return
 	}
 	}
@@ -57,7 +57,7 @@ func (s *cpusetGroup) getSubsystemSettings(parent string) (cpus []byte, mems []b
 // ensureParent ensures that the parent directory of current is created
 // ensureParent ensures that the parent directory of current is created
 // with the proper cpus and mems files copied from it's parent if the values
 // with the proper cpus and mems files copied from it's parent if the values
 // are a file with a new line char
 // are a file with a new line char
-func (s *cpusetGroup) ensureParent(current string) error {
+func (s *CpusetGroup) ensureParent(current string) error {
 	parent := filepath.Dir(current)
 	parent := filepath.Dir(current)
 
 
 	if _, err := os.Stat(parent); err != nil {
 	if _, err := os.Stat(parent); err != nil {
@@ -78,7 +78,7 @@ func (s *cpusetGroup) ensureParent(current string) error {
 
 
 // copyIfNeeded copies the cpuset.cpus and cpuset.mems from the parent
 // copyIfNeeded copies the cpuset.cpus and cpuset.mems from the parent
 // directory to the current directory if the file's contents are 0
 // directory to the current directory if the file's contents are 0
-func (s *cpusetGroup) copyIfNeeded(current, parent string) error {
+func (s *CpusetGroup) copyIfNeeded(current, parent string) error {
 	var (
 	var (
 		err                      error
 		err                      error
 		currentCpus, currentMems []byte
 		currentCpus, currentMems []byte
@@ -105,6 +105,6 @@ func (s *cpusetGroup) copyIfNeeded(current, parent string) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *cpusetGroup) isEmpty(b []byte) bool {
+func (s *CpusetGroup) isEmpty(b []byte) bool {
 	return len(bytes.Trim(b, "\n")) == 0
 	return len(bytes.Trim(b, "\n")) == 0
 }
 }

+ 4 - 4
vendor/src/github.com/docker/libcontainer/cgroups/fs/devices.go

@@ -2,10 +2,10 @@ package fs
 
 
 import "github.com/docker/libcontainer/cgroups"
 import "github.com/docker/libcontainer/cgroups"
 
 
-type devicesGroup struct {
+type DevicesGroup struct {
 }
 }
 
 
-func (s *devicesGroup) Set(d *data) error {
+func (s *DevicesGroup) Set(d *data) error {
 	dir, err := d.join("devices")
 	dir, err := d.join("devices")
 	if err != nil {
 	if err != nil {
 		return err
 		return err
@@ -25,10 +25,10 @@ func (s *devicesGroup) Set(d *data) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *devicesGroup) Remove(d *data) error {
+func (s *DevicesGroup) Remove(d *data) error {
 	return removePath(d.path("devices"))
 	return removePath(d.path("devices"))
 }
 }
 
 
-func (s *devicesGroup) GetStats(d *data, stats *cgroups.Stats) error {
+func (s *DevicesGroup) GetStats(path string, stats *cgroups.Stats) error {
 	return nil
 	return nil
 }
 }

+ 4 - 25
vendor/src/github.com/docker/libcontainer/cgroups/fs/freezer.go

@@ -1,18 +1,16 @@
 package fs
 package fs
 
 
 import (
 import (
-	"io/ioutil"
-	"path/filepath"
 	"strings"
 	"strings"
 	"time"
 	"time"
 
 
 	"github.com/docker/libcontainer/cgroups"
 	"github.com/docker/libcontainer/cgroups"
 )
 )
 
 
-type freezerGroup struct {
+type FreezerGroup struct {
 }
 }
 
 
-func (s *freezerGroup) Set(d *data) error {
+func (s *FreezerGroup) Set(d *data) error {
 	switch d.c.Freezer {
 	switch d.c.Freezer {
 	case cgroups.Frozen, cgroups.Thawed:
 	case cgroups.Frozen, cgroups.Thawed:
 		dir, err := d.path("freezer")
 		dir, err := d.path("freezer")
@@ -43,29 +41,10 @@ func (s *freezerGroup) Set(d *data) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *freezerGroup) Remove(d *data) error {
+func (s *FreezerGroup) Remove(d *data) error {
 	return removePath(d.path("freezer"))
 	return removePath(d.path("freezer"))
 }
 }
 
 
-func getFreezerFileData(path string) (string, error) {
-	data, err := ioutil.ReadFile(path)
-	return strings.TrimSuffix(string(data), "\n"), err
-}
-
-func (s *freezerGroup) GetStats(d *data, stats *cgroups.Stats) error {
-	path, err := d.path("freezer")
-	if err != nil {
-		return err
-	}
-	var data string
-	if data, err = getFreezerFileData(filepath.Join(path, "freezer.parent_freezing")); err != nil {
-		return err
-	}
-	stats.FreezerStats.ParentState = data
-	if data, err = getFreezerFileData(filepath.Join(path, "freezer.self_freezing")); err != nil {
-		return err
-	}
-	stats.FreezerStats.SelfState = data
-
+func (s *FreezerGroup) GetStats(path string, stats *cgroups.Stats) error {
 	return nil
 	return nil
 }
 }

+ 7 - 9
vendor/src/github.com/docker/libcontainer/cgroups/fs/memory.go

@@ -9,10 +9,10 @@ import (
 	"github.com/docker/libcontainer/cgroups"
 	"github.com/docker/libcontainer/cgroups"
 )
 )
 
 
-type memoryGroup struct {
+type MemoryGroup struct {
 }
 }
 
 
-func (s *memoryGroup) Set(d *data) error {
+func (s *MemoryGroup) Set(d *data) error {
 	dir, err := d.join("memory")
 	dir, err := d.join("memory")
 	// only return an error for memory if it was not specified
 	// only return an error for memory if it was not specified
 	if err != nil && (d.c.Memory != 0 || d.c.MemoryReservation != 0 || d.c.MemorySwap != 0) {
 	if err != nil && (d.c.Memory != 0 || d.c.MemoryReservation != 0 || d.c.MemorySwap != 0) {
@@ -47,19 +47,17 @@ func (s *memoryGroup) Set(d *data) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *memoryGroup) Remove(d *data) error {
+func (s *MemoryGroup) Remove(d *data) error {
 	return removePath(d.path("memory"))
 	return removePath(d.path("memory"))
 }
 }
 
 
-func (s *memoryGroup) GetStats(d *data, stats *cgroups.Stats) error {
-	path, err := d.path("memory")
-	if err != nil {
-		return err
-	}
-
+func (s *MemoryGroup) GetStats(path string, stats *cgroups.Stats) error {
 	// Set stats from memory.stat.
 	// Set stats from memory.stat.
 	statsFile, err := os.Open(filepath.Join(path, "memory.stat"))
 	statsFile, err := os.Open(filepath.Join(path, "memory.stat"))
 	if err != nil {
 	if err != nil {
+		if os.IsNotExist(err) {
+			return nil
+		}
 		return err
 		return err
 	}
 	}
 	defer statsFile.Close()
 	defer statsFile.Close()

+ 16 - 16
vendor/src/github.com/docker/libcontainer/cgroups/fs/memory_test.go

@@ -24,8 +24,8 @@ func TestMemoryStats(t *testing.T) {
 		"memory.failcnt":            memoryFailcnt,
 		"memory.failcnt":            memoryFailcnt,
 	})
 	})
 
 
-	memory := &memoryGroup{}
-	err := memory.GetStats(helper.CgroupData, &actualStats)
+	memory := &MemoryGroup{}
+	err := memory.GetStats(helper.CgroupPath, &actualStats)
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -41,10 +41,10 @@ func TestMemoryStatsNoStatFile(t *testing.T) {
 		"memory.max_usage_in_bytes": memoryMaxUsageContents,
 		"memory.max_usage_in_bytes": memoryMaxUsageContents,
 	})
 	})
 
 
-	memory := &memoryGroup{}
-	err := memory.GetStats(helper.CgroupData, &actualStats)
-	if err == nil {
-		t.Fatal("Expected failure")
+	memory := &MemoryGroup{}
+	err := memory.GetStats(helper.CgroupPath, &actualStats)
+	if err != nil {
+		t.Fatal(err)
 	}
 	}
 }
 }
 
 
@@ -56,8 +56,8 @@ func TestMemoryStatsNoUsageFile(t *testing.T) {
 		"memory.max_usage_in_bytes": memoryMaxUsageContents,
 		"memory.max_usage_in_bytes": memoryMaxUsageContents,
 	})
 	})
 
 
-	memory := &memoryGroup{}
-	err := memory.GetStats(helper.CgroupData, &actualStats)
+	memory := &MemoryGroup{}
+	err := memory.GetStats(helper.CgroupPath, &actualStats)
 	if err == nil {
 	if err == nil {
 		t.Fatal("Expected failure")
 		t.Fatal("Expected failure")
 	}
 	}
@@ -71,8 +71,8 @@ func TestMemoryStatsNoMaxUsageFile(t *testing.T) {
 		"memory.usage_in_bytes": memoryUsageContents,
 		"memory.usage_in_bytes": memoryUsageContents,
 	})
 	})
 
 
-	memory := &memoryGroup{}
-	err := memory.GetStats(helper.CgroupData, &actualStats)
+	memory := &MemoryGroup{}
+	err := memory.GetStats(helper.CgroupPath, &actualStats)
 	if err == nil {
 	if err == nil {
 		t.Fatal("Expected failure")
 		t.Fatal("Expected failure")
 	}
 	}
@@ -87,8 +87,8 @@ func TestMemoryStatsBadStatFile(t *testing.T) {
 		"memory.max_usage_in_bytes": memoryMaxUsageContents,
 		"memory.max_usage_in_bytes": memoryMaxUsageContents,
 	})
 	})
 
 
-	memory := &memoryGroup{}
-	err := memory.GetStats(helper.CgroupData, &actualStats)
+	memory := &MemoryGroup{}
+	err := memory.GetStats(helper.CgroupPath, &actualStats)
 	if err == nil {
 	if err == nil {
 		t.Fatal("Expected failure")
 		t.Fatal("Expected failure")
 	}
 	}
@@ -103,8 +103,8 @@ func TestMemoryStatsBadUsageFile(t *testing.T) {
 		"memory.max_usage_in_bytes": memoryMaxUsageContents,
 		"memory.max_usage_in_bytes": memoryMaxUsageContents,
 	})
 	})
 
 
-	memory := &memoryGroup{}
-	err := memory.GetStats(helper.CgroupData, &actualStats)
+	memory := &MemoryGroup{}
+	err := memory.GetStats(helper.CgroupPath, &actualStats)
 	if err == nil {
 	if err == nil {
 		t.Fatal("Expected failure")
 		t.Fatal("Expected failure")
 	}
 	}
@@ -119,8 +119,8 @@ func TestMemoryStatsBadMaxUsageFile(t *testing.T) {
 		"memory.max_usage_in_bytes": "bad",
 		"memory.max_usage_in_bytes": "bad",
 	})
 	})
 
 
-	memory := &memoryGroup{}
-	err := memory.GetStats(helper.CgroupData, &actualStats)
+	memory := &MemoryGroup{}
+	err := memory.GetStats(helper.CgroupPath, &actualStats)
 	if err == nil {
 	if err == nil {
 		t.Fatal("Expected failure")
 		t.Fatal("Expected failure")
 	}
 	}

+ 4 - 4
vendor/src/github.com/docker/libcontainer/cgroups/fs/perf_event.go

@@ -4,10 +4,10 @@ import (
 	"github.com/docker/libcontainer/cgroups"
 	"github.com/docker/libcontainer/cgroups"
 )
 )
 
 
-type perfEventGroup struct {
+type PerfEventGroup struct {
 }
 }
 
 
-func (s *perfEventGroup) Set(d *data) error {
+func (s *PerfEventGroup) Set(d *data) error {
 	// we just want to join this group even though we don't set anything
 	// we just want to join this group even though we don't set anything
 	if _, err := d.join("perf_event"); err != nil && err != cgroups.ErrNotFound {
 	if _, err := d.join("perf_event"); err != nil && err != cgroups.ErrNotFound {
 		return err
 		return err
@@ -15,10 +15,10 @@ func (s *perfEventGroup) Set(d *data) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *perfEventGroup) Remove(d *data) error {
+func (s *PerfEventGroup) Remove(d *data) error {
 	return removePath(d.path("perf_event"))
 	return removePath(d.path("perf_event"))
 }
 }
 
 
-func (s *perfEventGroup) GetStats(d *data, stats *cgroups.Stats) error {
+func (s *PerfEventGroup) GetStats(path string, stats *cgroups.Stats) error {
 	return nil
 	return nil
 }
 }

+ 3 - 10
vendor/src/github.com/docker/libcontainer/cgroups/stats.go

@@ -55,17 +55,10 @@ type BlkioStats struct {
 	SectorsRecursive        []BlkioStatEntry `json:"sectors_recursive,omitempty"`
 	SectorsRecursive        []BlkioStatEntry `json:"sectors_recursive,omitempty"`
 }
 }
 
 
-// TODO(Vishh): Remove freezer from stats since it does not logically belong in stats.
-type FreezerStats struct {
-	ParentState string `json:"parent_state,omitempty"`
-	SelfState   string `json:"self_state,omitempty"`
-}
-
 type Stats struct {
 type Stats struct {
-	CpuStats     CpuStats     `json:"cpu_stats,omitempty"`
-	MemoryStats  MemoryStats  `json:"memory_stats,omitempty"`
-	BlkioStats   BlkioStats   `json:"blkio_stats,omitempty"`
-	FreezerStats FreezerStats `json:"freezer_stats,omitempty"`
+	CpuStats    CpuStats    `json:"cpu_stats,omitempty"`
+	MemoryStats MemoryStats `json:"memory_stats,omitempty"`
+	BlkioStats  BlkioStats  `json:"blkio_stats,omitempty"`
 }
 }
 
 
 func NewStats() *Stats {
 func NewStats() *Stats {

+ 4 - 0
vendor/src/github.com/docker/libcontainer/cgroups/systemd/apply_nosystemd.go

@@ -23,3 +23,7 @@ func GetPids(c *cgroups.Cgroup) ([]int, error) {
 func Freeze(c *cgroups.Cgroup, state cgroups.FreezerState) error {
 func Freeze(c *cgroups.Cgroup, state cgroups.FreezerState) error {
 	return fmt.Errorf("Systemd not supported")
 	return fmt.Errorf("Systemd not supported")
 }
 }
+
+func GetStats(c *cgroups.Cgroup) (*cgroups.Stats, error) {
+	return nil, fmt.Errorf("Systemd not supported")
+}

+ 54 - 6
vendor/src/github.com/docker/libcontainer/cgroups/systemd/apply_systemd.go

@@ -15,6 +15,7 @@ import (
 
 
 	systemd1 "github.com/coreos/go-systemd/dbus"
 	systemd1 "github.com/coreos/go-systemd/dbus"
 	"github.com/docker/libcontainer/cgroups"
 	"github.com/docker/libcontainer/cgroups"
+	"github.com/docker/libcontainer/cgroups/fs"
 	"github.com/dotcloud/docker/pkg/systemd"
 	"github.com/dotcloud/docker/pkg/systemd"
 	"github.com/godbus/dbus"
 	"github.com/godbus/dbus"
 )
 )
@@ -23,10 +24,24 @@ type systemdCgroup struct {
 	cleanupDirs []string
 	cleanupDirs []string
 }
 }
 
 
+type subsystem interface {
+	GetStats(string, *cgroups.Stats) error
+}
+
 var (
 var (
 	connLock              sync.Mutex
 	connLock              sync.Mutex
 	theConn               *systemd1.Conn
 	theConn               *systemd1.Conn
 	hasStartTransientUnit bool
 	hasStartTransientUnit bool
+	subsystems            = map[string]subsystem{
+		"devices":    &fs.DevicesGroup{},
+		"memory":     &fs.MemoryGroup{},
+		"cpu":        &fs.CpuGroup{},
+		"cpuset":     &fs.CpusetGroup{},
+		"cpuacct":    &fs.CpuacctGroup{},
+		"blkio":      &fs.BlkioGroup{},
+		"perf_event": &fs.PerfEventGroup{},
+		"freezer":    &fs.FreezerGroup{},
+	}
 )
 )
 
 
 func UseSystemd() bool {
 func UseSystemd() bool {
@@ -316,7 +331,7 @@ func (c *systemdCgroup) Cleanup() error {
 }
 }
 
 
 func joinFreezer(c *cgroups.Cgroup, pid int) (string, error) {
 func joinFreezer(c *cgroups.Cgroup, pid int) (string, error) {
-	path, err := getFreezerPath(c)
+	path, err := getSubsystemPath(c, "freezer")
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
@@ -332,23 +347,27 @@ func joinFreezer(c *cgroups.Cgroup, pid int) (string, error) {
 	return path, nil
 	return path, nil
 }
 }
 
 
-func getFreezerPath(c *cgroups.Cgroup) (string, error) {
-	mountpoint, err := cgroups.FindCgroupMountpoint("freezer")
+func getSubsystemPath(c *cgroups.Cgroup, subsystem string) (string, error) {
+	mountpoint, err := cgroups.FindCgroupMountpoint(subsystem)
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
 
 
-	initPath, err := cgroups.GetInitCgroupDir("freezer")
+	initPath, err := cgroups.GetInitCgroupDir(subsystem)
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
 
 
-	return filepath.Join(mountpoint, initPath, fmt.Sprintf("%s-%s", c.Parent, c.Name)), nil
+	slice := "system.slice"
+	if c.Slice != "" {
+		slice = c.Slice
+	}
 
 
+	return filepath.Join(mountpoint, initPath, slice, getUnitName(c)), nil
 }
 }
 
 
 func Freeze(c *cgroups.Cgroup, state cgroups.FreezerState) error {
 func Freeze(c *cgroups.Cgroup, state cgroups.FreezerState) error {
-	path, err := getFreezerPath(c)
+	path, err := getSubsystemPath(c, "freezer")
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -389,3 +408,32 @@ func GetPids(c *cgroups.Cgroup) ([]int, error) {
 func getUnitName(c *cgroups.Cgroup) string {
 func getUnitName(c *cgroups.Cgroup) string {
 	return fmt.Sprintf("%s-%s.scope", c.Parent, c.Name)
 	return fmt.Sprintf("%s-%s.scope", c.Parent, c.Name)
 }
 }
+
+/*
+ * This would be nicer to get from the systemd API when accounting
+ * is enabled, but sadly there is no way to do that yet.
+ * The lack of this functionality in the API & the approach taken
+ * is guided by
+ * http://www.freedesktop.org/wiki/Software/systemd/ControlGroupInterface/#readingaccountinginformation.
+ */
+func GetStats(c *cgroups.Cgroup) (*cgroups.Stats, error) {
+	stats := cgroups.NewStats()
+
+	for sysname, sys := range subsystems {
+		subsystemPath, err := getSubsystemPath(c, sysname)
+		if err != nil {
+			// Don't fail if a cgroup hierarchy was not found, just skip this subsystem
+			if err == cgroups.ErrNotFound {
+				continue
+			}
+
+			return nil, err
+		}
+
+		if err := sys.GetStats(subsystemPath, stats); err != nil {
+			return nil, err
+		}
+	}
+
+	return stats, nil
+}

+ 86 - 0
vendor/src/github.com/docker/libcontainer/config.go

@@ -0,0 +1,86 @@
+package libcontainer
+
+import (
+	"github.com/docker/libcontainer/cgroups"
+	"github.com/docker/libcontainer/mount"
+	"github.com/docker/libcontainer/network"
+)
+
+type MountConfig mount.MountConfig
+
+type Network network.Network
+
+// Config defines configuration options for executing a process inside a contained environment.
+type Config struct {
+	// Mount specific options.
+	MountConfig *MountConfig `json:"mount_config,omitempty"`
+
+	// Hostname optionally sets the container's hostname if provided
+	Hostname string `json:"hostname,omitempty"`
+
+	// User will set the uid and gid of the executing process running inside the container
+	User string `json:"user,omitempty"`
+
+	// WorkingDir will change the processes current working directory inside the container's rootfs
+	WorkingDir string `json:"working_dir,omitempty"`
+
+	// Env will populate the processes environment with the provided values
+	// Any values from the parent processes will be cleared before the values
+	// provided in Env are provided to the process
+	Env []string `json:"environment,omitempty"`
+
+	// Tty when true will allocate a pty slave on the host for access by the container's process
+	// and ensure that it is mounted inside the container's rootfs
+	Tty bool `json:"tty,omitempty"`
+
+	// Namespaces specifies the container's namespaces that it should setup when cloning the init process
+	// If a namespace is not provided that namespace is shared from the container's parent process
+	Namespaces map[string]bool `json:"namespaces,omitempty"`
+
+	// Capabilities specify the capabilities to keep when executing the process inside the container
+	// All capbilities not specified will be dropped from the processes capability mask
+	Capabilities []string `json:"capabilities,omitempty"`
+
+	// Networks specifies the container's network setup to be created
+	Networks []*Network `json:"networks,omitempty"`
+
+	// Routes can be specified to create entries in the route table as the container is started
+	Routes []*Route `json:"routes,omitempty"`
+
+	// Cgroups specifies specific cgroup settings for the various subsystems that the container is
+	// placed into to limit the resources the container has available
+	Cgroups *cgroups.Cgroup `json:"cgroups,omitempty"`
+
+	// AppArmorProfile specifies the profile to apply to the process running in the container and is
+	// change at the time the process is execed
+	AppArmorProfile string `json:"apparmor_profile,omitempty"`
+
+	// ProcessLabel specifies the label to apply to the process running in the container.  It is
+	// commonly used by selinux
+	ProcessLabel string `json:"process_label,omitempty"`
+
+	// RestrictSys will remount /proc/sys, /sys, and mask over sysrq-trigger as well as /proc/irq and
+	// /proc/bus
+	RestrictSys bool `json:"restrict_sys,omitempty"`
+}
+
+// Routes can be specified to create entries in the route table as the container is started
+//
+// All of destination, source, and gateway should be either IPv4 or IPv6.
+// One of the three options must be present, and ommitted entries will use their
+// IP family default for the route table.  For IPv4 for example, setting the
+// gateway to 1.2.3.4 and the interface to eth0 will set up a standard
+// destination of 0.0.0.0(or *) when viewed in the route table.
+type Route struct {
+	// Sets the destination and mask, should be a CIDR.  Accepts IPv4 and IPv6
+	Destination string `json:"destination,omitempty"`
+
+	// Sets the source and mask, should be a CIDR.  Accepts IPv4 and IPv6
+	Source string `json:"source,omitempty"`
+
+	// Sets the gateway.  Accepts IPv4 and IPv6
+	Gateway string `json:"gateway,omitempty"`
+
+	// The device to set this route up for, for example: eth0
+	InterfaceName string `json:"interface_name,omitempty"`
+}

+ 0 - 0
vendor/src/github.com/docker/libcontainer/container_test.go → vendor/src/github.com/docker/libcontainer/config_test.go


+ 59 - 82
vendor/src/github.com/docker/libcontainer/container.go

@@ -1,86 +1,63 @@
+/*
+NOTE: The API is in flux and mainly not implemented. Proceed with caution until further notice.
+*/
 package libcontainer
 package libcontainer
 
 
-import (
-	"github.com/docker/libcontainer/cgroups"
-	"github.com/docker/libcontainer/mount"
-	"github.com/docker/libcontainer/network"
-)
-
-type MountConfig mount.MountConfig
-
-type Network network.Network
-
-// Config defines configuration options for executing a process inside a contained environment.
-type Config struct {
-	// Mount specific options.
-	MountConfig *MountConfig `json:"mount_config,omitempty"`
-
-	// Hostname optionally sets the container's hostname if provided
-	Hostname string `json:"hostname,omitempty"`
-
-	// User will set the uid and gid of the executing process running inside the container
-	User string `json:"user,omitempty"`
-
-	// WorkingDir will change the processes current working directory inside the container's rootfs
-	WorkingDir string `json:"working_dir,omitempty"`
-
-	// Env will populate the processes environment with the provided values
-	// Any values from the parent processes will be cleared before the values
-	// provided in Env are provided to the process
-	Env []string `json:"environment,omitempty"`
-
-	// Tty when true will allocate a pty slave on the host for access by the container's process
-	// and ensure that it is mounted inside the container's rootfs
-	Tty bool `json:"tty,omitempty"`
-
-	// Namespaces specifies the container's namespaces that it should setup when cloning the init process
-	// If a namespace is not provided that namespace is shared from the container's parent process
-	Namespaces map[string]bool `json:"namespaces,omitempty"`
-
-	// Capabilities specify the capabilities to keep when executing the process inside the container
-	// All capbilities not specified will be dropped from the processes capability mask
-	Capabilities []string `json:"capabilities,omitempty"`
-
-	// Networks specifies the container's network setup to be created
-	Networks []*Network `json:"networks,omitempty"`
-
-	// Routes can be specified to create entries in the route table as the container is started
-	Routes []*Route `json:"routes,omitempty"`
-
-	// Cgroups specifies specific cgroup settings for the various subsystems that the container is
-	// placed into to limit the resources the container has available
-	Cgroups *cgroups.Cgroup `json:"cgroups,omitempty"`
-
-	// AppArmorProfile specifies the profile to apply to the process running in the container and is
-	// change at the time the process is execed
-	AppArmorProfile string `json:"apparmor_profile,omitempty"`
-
-	// ProcessLabel specifies the label to apply to the process running in the container.  It is
-	// commonly used by selinux
-	ProcessLabel string `json:"process_label,omitempty"`
-
-	// RestrictSys will remount /proc/sys, /sys, and mask over sysrq-trigger as well as /proc/irq and
-	// /proc/bus
-	RestrictSys bool `json:"restrict_sys,omitempty"`
-}
-
-// Routes can be specified to create entries in the route table as the container is started
+// A libcontainer container object.
 //
 //
-// All of destination, source, and gateway should be either IPv4 or IPv6.
-// One of the three options must be present, and ommitted entries will use their
-// IP family default for the route table.  For IPv4 for example, setting the
-// gateway to 1.2.3.4 and the interface to eth0 will set up a standard
-// destination of 0.0.0.0(or *) when viewed in the route table.
-type Route struct {
-	// Sets the destination and mask, should be a CIDR.  Accepts IPv4 and IPv6
-	Destination string `json:"destination,omitempty"`
-
-	// Sets the source and mask, should be a CIDR.  Accepts IPv4 and IPv6
-	Source string `json:"source,omitempty"`
-
-	// Sets the gateway.  Accepts IPv4 and IPv6
-	Gateway string `json:"gateway,omitempty"`
-
-	// The device to set this route up for, for example: eth0
-	InterfaceName string `json:"interface_name,omitempty"`
+// Each container is thread-safe within the same process. Since a container can
+// be destroyed by a separate process, any function may return that the container
+// was not found.
+type Container interface {
+	// Returns the path to the container which contains the state
+	Path() string
+
+	// Returns the current run state of the container.
+	//
+	// Errors: container no longer exists,
+	//         system error.
+	RunState() (*RunState, error)
+
+	// Returns the current config of the container.
+	Config() *Config
+
+	// Destroys the container after killing all running processes.
+	//
+	// Any event registrations are removed before the container is destroyed.
+	// No error is returned if the container is already destroyed.
+	//
+	// Errors: system error.
+	Destroy() error
+
+	// Returns the PIDs inside this container. The PIDs are in the namespace of the calling process.
+	//
+	// Errors: container no longer exists,
+	//         system error.
+	//
+	// Some of the returned PIDs may no longer refer to processes in the Container, unless
+	// the Container state is PAUSED in which case every PID in the slice is valid.
+	Processes() ([]int, error)
+
+	// Returns statistics for the container.
+	//
+	// Errors: container no longer exists,
+	//         system error.
+	Stats() (*ContainerStats, error)
+
+	// If the Container state is RUNNING or PAUSING, sets the Container state to PAUSING and pauses
+	// the execution of any user processes. Asynchronously, when the container finished being paused the
+	// state is changed to PAUSED.
+	// If the Container state is PAUSED, do nothing.
+	//
+	// Errors: container no longer exists,
+	//         system error.
+	Pause() error
+
+	// If the Container state is PAUSED, resumes the execution of any user processes in the
+	// Container before setting the Container state to RUNNING.
+	// If the Container state is RUNNING, do nothing.
+	//
+	// Errors: container no longer exists,
+	//         system error.
+	Resume() error
 }
 }

+ 25 - 0
vendor/src/github.com/docker/libcontainer/factory.go

@@ -0,0 +1,25 @@
+package libcontainer
+
+type Factory interface {
+	// Creates a new container in the given path. A unique ID is generated for the container and
+	// starts the initial process inside the container.
+	//
+	// Returns the new container with a running process.
+	//
+	// Errors:
+	// Path already exists
+	// Config or initialConfig is invalid
+	// System error
+	//
+	// On error, any partially created container parts are cleaned up (the operation is atomic).
+	Create(path string, config *Config) (Container, error)
+
+	// Load takes the path for an existing container and reconstructs the container
+	// from the state.
+	//
+	// Errors:
+	// Path does not exist
+	// Container is stopped
+	// System error
+	Load(path string) (Container, error)
+}

+ 4 - 0
vendor/src/github.com/docker/libcontainer/label/label.go

@@ -18,6 +18,10 @@ func SetFileLabel(path string, fileLabel string) error {
 	return nil
 	return nil
 }
 }
 
 
+func Relabel(path string, fileLabel string, relabel string) error {
+	return nil
+}
+
 func GetPidCon(pid int) (string, error) {
 func GetPidCon(pid int) (string, error) {
 	return "", nil
 	return "", nil
 }
 }

+ 17 - 0
vendor/src/github.com/docker/libcontainer/label/label_selinux.go

@@ -66,6 +66,23 @@ func SetFileLabel(path string, fileLabel string) error {
 	return nil
 	return nil
 }
 }
 
 
+// Change the label of path to the filelabel string.  If the relabel string
+// is "z", relabel will change the MCS label to s0.  This will allow all
+// containers to share the content.  If the relabel string is a "Z" then
+// the MCS label should continue to be used.  SELinux will use this field
+// to make sure the content can not be shared by other containes.
+func Relabel(path string, fileLabel string, relabel string) error {
+	if fileLabel == "" {
+		return nil
+	}
+	if relabel == "z" {
+		c := selinux.NewContext(fileLabel)
+		c["level"] = "s0"
+		fileLabel = c.Get()
+	}
+	return selinux.Chcon(path, fileLabel, true)
+}
+
 func GetPidCon(pid int) (string, error) {
 func GetPidCon(pid int) (string, error) {
 	if !selinux.SelinuxEnabled() {
 	if !selinux.SelinuxEnabled() {
 		return "", nil
 		return "", nil

+ 8 - 2
vendor/src/github.com/docker/libcontainer/mount/init.go

@@ -44,7 +44,7 @@ func InitializeMountNamespace(rootfs, console string, mountConfig *MountConfig)
 	if err := mountSystem(rootfs, mountConfig); err != nil {
 	if err := mountSystem(rootfs, mountConfig); err != nil {
 		return fmt.Errorf("mount system %s", err)
 		return fmt.Errorf("mount system %s", err)
 	}
 	}
-	if err := setupBindmounts(rootfs, mountConfig.Mounts); err != nil {
+	if err := setupBindmounts(rootfs, mountConfig); err != nil {
 		return fmt.Errorf("bind mounts %s", err)
 		return fmt.Errorf("bind mounts %s", err)
 	}
 	}
 	if err := nodes.CreateDeviceNodes(rootfs, mountConfig.DeviceNodes); err != nil {
 	if err := nodes.CreateDeviceNodes(rootfs, mountConfig.DeviceNodes); err != nil {
@@ -144,7 +144,8 @@ func setupDevSymlinks(rootfs string) error {
 	return nil
 	return nil
 }
 }
 
 
-func setupBindmounts(rootfs string, bindMounts Mounts) error {
+func setupBindmounts(rootfs string, mountConfig *MountConfig) error {
+	bindMounts := mountConfig.Mounts
 	for _, m := range bindMounts.OfType("bind") {
 	for _, m := range bindMounts.OfType("bind") {
 		var (
 		var (
 			flags = syscall.MS_BIND | syscall.MS_REC
 			flags = syscall.MS_BIND | syscall.MS_REC
@@ -176,6 +177,11 @@ func setupBindmounts(rootfs string, bindMounts Mounts) error {
 				return fmt.Errorf("remounting %s into %s %s", m.Source, dest, err)
 				return fmt.Errorf("remounting %s into %s %s", m.Source, dest, err)
 			}
 			}
 		}
 		}
+		if m.Relabel != "" {
+			if err := label.Relabel(m.Source, mountConfig.MountLabel, m.Relabel); err != nil {
+				return fmt.Errorf("relabeling %s to %s %s", m.Source, mountConfig.MountLabel, err)
+			}
+		}
 		if m.Private {
 		if m.Private {
 			if err := system.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil {
 			if err := system.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil {
 				return fmt.Errorf("mounting %s private %s", dest, err)
 				return fmt.Errorf("mounting %s private %s", dest, err)

+ 1 - 0
vendor/src/github.com/docker/libcontainer/mount/types.go

@@ -30,6 +30,7 @@ type Mount struct {
 	Source      string `json:"source,omitempty"`      // Source path, in the host namespace
 	Source      string `json:"source,omitempty"`      // Source path, in the host namespace
 	Destination string `json:"destination,omitempty"` // Destination path, in the container
 	Destination string `json:"destination,omitempty"` // Destination path, in the container
 	Writable    bool   `json:"writable,omitempty"`
 	Writable    bool   `json:"writable,omitempty"`
+	Relabel     string `json:"relabel,omitempty"` // Relabel source if set, "z" indicates shared, "Z" indicates unshared
 	Private     bool   `json:"private,omitempty"`
 	Private     bool   `json:"private,omitempty"`
 }
 }
 
 

+ 4 - 3
vendor/src/github.com/docker/libcontainer/namespaces/exec.go

@@ -12,6 +12,7 @@ import (
 	"github.com/docker/libcontainer/cgroups/fs"
 	"github.com/docker/libcontainer/cgroups/fs"
 	"github.com/docker/libcontainer/cgroups/systemd"
 	"github.com/docker/libcontainer/cgroups/systemd"
 	"github.com/docker/libcontainer/network"
 	"github.com/docker/libcontainer/network"
+	"github.com/docker/libcontainer/syncpipe"
 	"github.com/dotcloud/docker/pkg/system"
 	"github.com/dotcloud/docker/pkg/system"
 )
 )
 
 
@@ -28,7 +29,7 @@ func Exec(container *libcontainer.Config, term Terminal, rootfs, dataPath string
 
 
 	// create a pipe so that we can syncronize with the namespaced process and
 	// create a pipe so that we can syncronize with the namespaced process and
 	// pass the veth name to the child
 	// pass the veth name to the child
-	syncPipe, err := NewSyncPipe()
+	syncPipe, err := syncpipe.NewSyncPipe()
 	if err != nil {
 	if err != nil {
 		return -1, err
 		return -1, err
 	}
 	}
@@ -42,7 +43,7 @@ func Exec(container *libcontainer.Config, term Terminal, rootfs, dataPath string
 		term.SetMaster(master)
 		term.SetMaster(master)
 	}
 	}
 
 
-	command := createCommand(container, console, rootfs, dataPath, os.Args[0], syncPipe.child, args)
+	command := createCommand(container, console, rootfs, dataPath, os.Args[0], syncPipe.Child(), args)
 
 
 	if err := term.Attach(command); err != nil {
 	if err := term.Attach(command); err != nil {
 		return -1, err
 		return -1, err
@@ -166,7 +167,7 @@ func SetupCgroups(container *libcontainer.Config, nspid int) (cgroups.ActiveCgro
 
 
 // InitializeNetworking creates the container's network stack outside of the namespace and moves
 // InitializeNetworking creates the container's network stack outside of the namespace and moves
 // interfaces into the container's net namespaces if necessary
 // interfaces into the container's net namespaces if necessary
-func InitializeNetworking(container *libcontainer.Config, nspid int, pipe *SyncPipe, networkState *network.NetworkState) error {
+func InitializeNetworking(container *libcontainer.Config, nspid int, pipe *syncpipe.SyncPipe, networkState *network.NetworkState) error {
 	for _, config := range container.Networks {
 	for _, config := range container.Networks {
 		strategy, err := network.GetStrategy(config.Type)
 		strategy, err := network.GetStrategy(config.Type)
 		if err != nil {
 		if err != nil {

+ 2 - 2
vendor/src/github.com/docker/libcontainer/namespaces/execin.go

@@ -30,8 +30,8 @@ func ExecIn(container *libcontainer.Config, state *libcontainer.State, args []st
 	panic("unreachable")
 	panic("unreachable")
 }
 }
 
 
-// NsEnter is run after entering the namespace.
-func NsEnter(container *libcontainer.Config, nspid int, args []string) error {
+// Run a command in a container after entering the namespace.
+func NsEnter(container *libcontainer.Config, args []string) error {
 	// clear the current processes env and replace it with the environment
 	// clear the current processes env and replace it with the environment
 	// defined on the container
 	// defined on the container
 	if err := LoadContainerEnvironment(container); err != nil {
 	if err := LoadContainerEnvironment(container); err != nil {

+ 2 - 1
vendor/src/github.com/docker/libcontainer/namespaces/init.go

@@ -18,6 +18,7 @@ import (
 	"github.com/docker/libcontainer/network"
 	"github.com/docker/libcontainer/network"
 	"github.com/docker/libcontainer/security/capabilities"
 	"github.com/docker/libcontainer/security/capabilities"
 	"github.com/docker/libcontainer/security/restrict"
 	"github.com/docker/libcontainer/security/restrict"
+	"github.com/docker/libcontainer/syncpipe"
 	"github.com/docker/libcontainer/utils"
 	"github.com/docker/libcontainer/utils"
 	"github.com/dotcloud/docker/pkg/system"
 	"github.com/dotcloud/docker/pkg/system"
 	"github.com/dotcloud/docker/pkg/user"
 	"github.com/dotcloud/docker/pkg/user"
@@ -27,7 +28,7 @@ import (
 // Move this to libcontainer package.
 // Move this to libcontainer package.
 // Init is the init process that first runs inside a new namespace to setup mounts, users, networking,
 // Init is the init process that first runs inside a new namespace to setup mounts, users, networking,
 // and other options required for the new container.
 // and other options required for the new container.
-func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, syncPipe *SyncPipe, args []string) (err error) {
+func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, syncPipe *syncpipe.SyncPipe, args []string) (err error) {
 	defer func() {
 	defer func() {
 		if err != nil {
 		if err != nil {
 			syncPipe.ReportChildError(err)
 			syncPipe.ReportChildError(err)

+ 5 - 3
vendor/src/github.com/docker/libcontainer/nsinit/main.go → vendor/src/github.com/docker/libcontainer/nsinit/cli.go

@@ -1,4 +1,4 @@
-package main
+package nsinit
 
 
 import (
 import (
 	"log"
 	"log"
@@ -19,7 +19,7 @@ func preload(context *cli.Context) error {
 	return nil
 	return nil
 }
 }
 
 
-func main() {
+func NsInit() {
 	app := cli.NewApp()
 	app := cli.NewApp()
 	app.Name = "nsinit"
 	app.Name = "nsinit"
 	app.Version = "0.1"
 	app.Version = "0.1"
@@ -30,8 +30,10 @@ func main() {
 		execCommand,
 		execCommand,
 		initCommand,
 		initCommand,
 		statsCommand,
 		statsCommand,
-		specCommand,
+		configCommand,
 		nsenterCommand,
 		nsenterCommand,
+		pauseCommand,
+		unpauseCommand,
 	}
 	}
 
 
 	if err := app.Run(os.Args); err != nil {
 	if err := app.Run(os.Args); err != nil {

+ 29 - 0
vendor/src/github.com/docker/libcontainer/nsinit/config.go

@@ -0,0 +1,29 @@
+package nsinit
+
+import (
+	"encoding/json"
+	"fmt"
+	"log"
+
+	"github.com/codegangsta/cli"
+)
+
+var configCommand = cli.Command{
+	Name:   "config",
+	Usage:  "display the container configuration",
+	Action: configAction,
+}
+
+func configAction(context *cli.Context) {
+	container, err := loadContainer()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	data, err := json.MarshalIndent(container, "", "\t")
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("%s", data)
+}

+ 1 - 1
vendor/src/github.com/docker/libcontainer/nsinit/exec.go

@@ -1,4 +1,4 @@
-package main
+package nsinit
 
 
 import (
 import (
 	"fmt"
 	"fmt"

+ 3 - 2
vendor/src/github.com/docker/libcontainer/nsinit/init.go

@@ -1,4 +1,4 @@
-package main
+package nsinit
 
 
 import (
 import (
 	"log"
 	"log"
@@ -7,6 +7,7 @@ import (
 
 
 	"github.com/codegangsta/cli"
 	"github.com/codegangsta/cli"
 	"github.com/docker/libcontainer/namespaces"
 	"github.com/docker/libcontainer/namespaces"
+	"github.com/docker/libcontainer/syncpipe"
 )
 )
 
 
 var (
 var (
@@ -37,7 +38,7 @@ func initAction(context *cli.Context) {
 		log.Fatal(err)
 		log.Fatal(err)
 	}
 	}
 
 
-	syncPipe, err := namespaces.NewSyncPipeFromFd(0, uintptr(pipeFd))
+	syncPipe, err := syncpipe.NewSyncPipeFromFd(0, uintptr(pipeFd))
 	if err != nil {
 	if err != nil {
 		log.Fatalf("unable to create sync pipe: %s", err)
 		log.Fatalf("unable to create sync pipe: %s", err)
 	}
 	}

+ 2 - 2
vendor/src/github.com/docker/libcontainer/nsinit/nsenter.go

@@ -1,4 +1,4 @@
-package main
+package nsinit
 
 
 import (
 import (
 	"log"
 	"log"
@@ -34,7 +34,7 @@ func nsenterAction(context *cli.Context) {
 		log.Fatalf("cannot enter into namespaces without valid pid: %q", nspid)
 		log.Fatalf("cannot enter into namespaces without valid pid: %q", nspid)
 	}
 	}
 
 
-	if err := namespaces.NsEnter(container, nspid, args); err != nil {
+	if err := namespaces.NsEnter(container, args); err != nil {
 		log.Fatalf("failed to nsenter: %s", err)
 		log.Fatalf("failed to nsenter: %s", err)
 	}
 	}
 }
 }

+ 7 - 0
vendor/src/github.com/docker/libcontainer/nsinit/nsinit/nsinit.go

@@ -0,0 +1,7 @@
+package main
+
+import "github.com/docker/libcontainer/nsinit"
+
+func main() {
+	nsinit.NsInit()
+}

+ 49 - 0
vendor/src/github.com/docker/libcontainer/nsinit/pause.go

@@ -0,0 +1,49 @@
+package nsinit
+
+import (
+	"log"
+
+	"github.com/codegangsta/cli"
+	"github.com/docker/libcontainer/cgroups"
+	"github.com/docker/libcontainer/cgroups/fs"
+	"github.com/docker/libcontainer/cgroups/systemd"
+)
+
+var pauseCommand = cli.Command{
+	Name:   "pause",
+	Usage:  "pause the container's processes",
+	Action: pauseAction,
+}
+
+var unpauseCommand = cli.Command{
+	Name:   "unpause",
+	Usage:  "unpause the container's processes",
+	Action: unpauseAction,
+}
+
+func pauseAction(context *cli.Context) {
+	if err := toggle(cgroups.Frozen); err != nil {
+		log.Fatal(err)
+	}
+}
+
+func unpauseAction(context *cli.Context) {
+	if err := toggle(cgroups.Thawed); err != nil {
+		log.Fatal(err)
+	}
+}
+
+func toggle(state cgroups.FreezerState) error {
+	container, err := loadContainer()
+	if err != nil {
+		return err
+	}
+
+	if systemd.UseSystemd() {
+		err = systemd.Freeze(container.Cgroups, state)
+	} else {
+		err = fs.Freeze(container.Cgroups, state)
+	}
+
+	return err
+}

+ 0 - 40
vendor/src/github.com/docker/libcontainer/nsinit/spec.go

@@ -1,40 +0,0 @@
-package main
-
-import (
-	"encoding/json"
-	"fmt"
-	"log"
-
-	"github.com/codegangsta/cli"
-	"github.com/docker/libcontainer"
-)
-
-var specCommand = cli.Command{
-	Name:   "spec",
-	Usage:  "display the container specification",
-	Action: specAction,
-}
-
-func specAction(context *cli.Context) {
-	container, err := loadContainer()
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	spec, err := getContainerSpec(container)
-	if err != nil {
-		log.Fatalf("Failed to get spec - %v\n", err)
-	}
-
-	fmt.Printf("Spec:\n%v\n", spec)
-}
-
-// returns the container spec in json format.
-func getContainerSpec(container *libcontainer.Config) (string, error) {
-	spec, err := json.MarshalIndent(container, "", "\t")
-	if err != nil {
-		return "", err
-	}
-
-	return string(spec), nil
-}

+ 6 - 17
vendor/src/github.com/docker/libcontainer/nsinit/stats.go

@@ -1,4 +1,4 @@
-package main
+package nsinit
 
 
 import (
 import (
 	"encoding/json"
 	"encoding/json"
@@ -21,30 +21,19 @@ func statsAction(context *cli.Context) {
 		log.Fatal(err)
 		log.Fatal(err)
 	}
 	}
 
 
-	runtimeCkpt, err := libcontainer.GetState(dataPath)
+	state, err := libcontainer.GetState(dataPath)
 	if err != nil {
 	if err != nil {
 		log.Fatal(err)
 		log.Fatal(err)
 	}
 	}
 
 
-	stats, err := getStats(container, runtimeCkpt)
-	if err != nil {
-		log.Fatalf("Failed to get stats - %v\n", err)
-	}
-
-	fmt.Printf("Stats:\n%v\n", stats)
-}
-
-// returns the container stats in json format.
-func getStats(container *libcontainer.Config, state *libcontainer.State) (string, error) {
 	stats, err := libcontainer.GetStats(container, state)
 	stats, err := libcontainer.GetStats(container, state)
 	if err != nil {
 	if err != nil {
-		return "", err
+		log.Fatal(err)
 	}
 	}
-
-	out, err := json.MarshalIndent(stats, "", "\t")
+	data, err := json.MarshalIndent(stats, "", "\t")
 	if err != nil {
 	if err != nil {
-		return "", err
+		log.Fatal(err)
 	}
 	}
 
 
-	return string(out), nil
+	fmt.Printf("%s", data)
 }
 }

+ 1 - 1
vendor/src/github.com/docker/libcontainer/nsinit/utils.go

@@ -1,4 +1,4 @@
-package main
+package nsinit
 
 
 import (
 import (
 	"encoding/json"
 	"encoding/json"

+ 27 - 0
vendor/src/github.com/docker/libcontainer/process.go

@@ -0,0 +1,27 @@
+package libcontainer
+
+import "io"
+
+// Configuration for a process to be run inside a container.
+type ProcessConfig struct {
+	// The command to be run followed by any arguments.
+	Args []string
+
+	// Map of environment variables to their values.
+	Env []string
+
+	// Stdin is a pointer to a reader which provides the standard input stream.
+	// Stdout is a pointer to a writer which receives the standard output stream.
+	// Stderr is a pointer to a writer which receives the standard error stream.
+	//
+	// If a reader or writer is nil, the input stream is assumed to be empty and the output is
+	// discarded.
+	//
+	// The readers and writers, if supplied, are closed when the process terminates. Their Close
+	// methods should be idempotent.
+	//
+	// Stdout and Stderr may refer to the same writer in which case the output is interspersed.
+	Stdin  io.ReadCloser
+	Stdout io.WriteCloser
+	Stderr io.WriteCloser
+}

+ 1 - 1
vendor/src/github.com/docker/libcontainer/security/capabilities/capabilities.go

@@ -27,7 +27,7 @@ func DropBoundingSet(capabilities []string) error {
 	return nil
 	return nil
 }
 }
 
 
-// DropCapabilities drops all capabilities for the current process expect those specified in the container configuration.
+// DropCapabilities drops all capabilities for the current process except those specified in the container configuration.
 func DropCapabilities(capList []string) error {
 func DropCapabilities(capList []string) error {
 	c, err := capability.NewPid(os.Getpid())
 	c, err := capability.NewPid(os.Getpid())
 	if err != nil {
 	if err != nil {

+ 0 - 2
vendor/src/github.com/docker/libcontainer/security/capabilities/types.go

@@ -64,8 +64,6 @@ var capabilityList = Capabilities{
 	{Key: "MAC_ADMIN", Value: capability.CAP_MAC_ADMIN},
 	{Key: "MAC_ADMIN", Value: capability.CAP_MAC_ADMIN},
 	{Key: "NET_ADMIN", Value: capability.CAP_NET_ADMIN},
 	{Key: "NET_ADMIN", Value: capability.CAP_NET_ADMIN},
 	{Key: "SYSLOG", Value: capability.CAP_SYSLOG},
 	{Key: "SYSLOG", Value: capability.CAP_SYSLOG},
-	{Key: "SETUID", Value: capability.CAP_SETUID},
-	{Key: "SETGID", Value: capability.CAP_SETGID},
 	{Key: "CHOWN", Value: capability.CAP_CHOWN},
 	{Key: "CHOWN", Value: capability.CAP_CHOWN},
 	{Key: "NET_RAW", Value: capability.CAP_NET_RAW},
 	{Key: "NET_RAW", Value: capability.CAP_NET_RAW},
 	{Key: "DAC_OVERRIDE", Value: capability.CAP_DAC_OVERRIDE},
 	{Key: "DAC_OVERRIDE", Value: capability.CAP_DAC_OVERRIDE},

+ 43 - 2
vendor/src/github.com/docker/libcontainer/selinux/selinux.go

@@ -9,6 +9,7 @@ import (
 	"github.com/dotcloud/docker/pkg/system"
 	"github.com/dotcloud/docker/pkg/system"
 	"io"
 	"io"
 	"os"
 	"os"
+	"path/filepath"
 	"regexp"
 	"regexp"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
@@ -76,7 +77,7 @@ func SelinuxEnabled() bool {
 	}
 	}
 	selinuxEnabledChecked = true
 	selinuxEnabledChecked = true
 	if fs := getSelinuxMountPoint(); fs != "" {
 	if fs := getSelinuxMountPoint(); fs != "" {
-		if con, _ := getcon(); con != "kernel" {
+		if con, _ := Getcon(); con != "kernel" {
 			selinuxEnabled = true
 			selinuxEnabled = true
 		}
 		}
 	}
 	}
@@ -145,6 +146,12 @@ func Setfilecon(path string, scon string) error {
 	return system.Lsetxattr(path, xattrNameSelinux, []byte(scon), 0)
 	return system.Lsetxattr(path, xattrNameSelinux, []byte(scon), 0)
 }
 }
 
 
+// Return the SELinux label for this path
+func Getfilecon(path string) (string, error) {
+	con, err := system.Lgetxattr(path, xattrNameSelinux)
+	return string(con), err
+}
+
 func Setfscreatecon(scon string) error {
 func Setfscreatecon(scon string) error {
 	return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", system.Gettid()), scon)
 	return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", system.Gettid()), scon)
 }
 }
@@ -153,7 +160,8 @@ func Getfscreatecon() (string, error) {
 	return readCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", system.Gettid()))
 	return readCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", system.Gettid()))
 }
 }
 
 
-func getcon() (string, error) {
+// Return the SELinux label of the current process thread.
+func Getcon() (string, error) {
 	return readCon(fmt.Sprintf("/proc/self/task/%d/attr/current", system.Gettid()))
 	return readCon(fmt.Sprintf("/proc/self/task/%d/attr/current", system.Gettid()))
 }
 }
 
 
@@ -396,3 +404,36 @@ func CopyLevel(src, dest string) (string, error) {
 	tcon["level"] = scon["level"]
 	tcon["level"] = scon["level"]
 	return tcon.Get(), nil
 	return tcon.Get(), nil
 }
 }
+
+// Prevent users from relabing system files
+func badPrefix(fpath string) error {
+	var badprefixes = []string{"/usr"}
+
+	for _, prefix := range badprefixes {
+		if fpath == prefix || strings.HasPrefix(fpath, fmt.Sprintf("%s/", prefix)) {
+			return fmt.Errorf("Relabeling content in %s is not allowed.", prefix)
+		}
+	}
+	return nil
+}
+
+// Change the fpath file object to the SELinux label scon.
+// If the fpath is a directory and recurse is true Chcon will walk the
+// directory tree setting the label
+func Chcon(fpath string, scon string, recurse bool) error {
+	if !SelinuxEnabled() {
+		return nil
+	}
+	if err := badPrefix(fpath); err != nil {
+		return err
+	}
+	callback := func(p string, info os.FileInfo, err error) error {
+		return Setfilecon(p, scon)
+	}
+
+	if recurse {
+		return filepath.Walk(fpath, callback)
+	}
+
+	return Setfilecon(fpath, scon)
+}

+ 21 - 2
vendor/src/github.com/docker/libcontainer/state.go

@@ -12,14 +12,33 @@ import (
 type State struct {
 type State struct {
 	// InitPid is the init process id in the parent namespace
 	// InitPid is the init process id in the parent namespace
 	InitPid int `json:"init_pid,omitempty"`
 	InitPid int `json:"init_pid,omitempty"`
+
 	// InitStartTime is the init process start time
 	// InitStartTime is the init process start time
 	InitStartTime string `json:"init_start_time,omitempty"`
 	InitStartTime string `json:"init_start_time,omitempty"`
+
 	// Network runtime state.
 	// Network runtime state.
 	NetworkState network.NetworkState `json:"network_state,omitempty"`
 	NetworkState network.NetworkState `json:"network_state,omitempty"`
 }
 }
 
 
-// The name of the runtime state file
-const stateFile = "state.json"
+// The running state of the container.
+type RunState int
+
+const (
+	// The name of the runtime state file
+	stateFile = "state.json"
+
+	// The container exists and is running.
+	Running RunState = iota
+
+	// The container exists, it is in the process of being paused.
+	Pausing
+
+	// The container exists, but all its processes are paused.
+	Paused
+
+	// The container does not exist.
+	Destroyed
+)
 
 
 // SaveState writes the container's runtime state to a state.json file
 // SaveState writes the container's runtime state to a state.json file
 // in the specified path
 // in the specified path

+ 1 - 1
vendor/src/github.com/docker/libcontainer/namespaces/sync_pipe.go → vendor/src/github.com/docker/libcontainer/syncpipe/sync_pipe.go

@@ -1,4 +1,4 @@
-package namespaces
+package syncpipe
 
 
 import (
 import (
 	"encoding/json"
 	"encoding/json"

+ 1 - 1
vendor/src/github.com/docker/libcontainer/namespaces/sync_pipe_linux.go → vendor/src/github.com/docker/libcontainer/syncpipe/sync_pipe_linux.go

@@ -1,4 +1,4 @@
-package namespaces
+package syncpipe
 
 
 import (
 import (
 	"os"
 	"os"

+ 1 - 1
vendor/src/github.com/docker/libcontainer/namespaces/sync_pipe_test.go → vendor/src/github.com/docker/libcontainer/syncpipe/sync_pipe_test.go

@@ -1,4 +1,4 @@
-package namespaces
+package syncpipe
 
 
 import (
 import (
 	"fmt"
 	"fmt"