瀏覽代碼

vendor: bump deps

bump runc/libcontainer to v0.0.5
bump runc deps to latest
bump docker/libnetwork to 04cc1fa0a89f8c407b7be8cab883d4b17531ea7d

Signed-off-by: Antonio Murdaca <runcom@redhat.com>
Antonio Murdaca 9 年之前
父節點
當前提交
65900d7603
共有 65 個文件被更改,包括 1344 次插入828 次删除
  1. 7 7
      hack/vendor.sh
  2. 33 9
      vendor/src/github.com/coreos/go-systemd/dbus/dbus.go
  3. 17 5
      vendor/src/github.com/coreos/go-systemd/journal/journal.go
  4. 1 0
      vendor/src/github.com/docker/libnetwork/.dockerignore
  5. 2 1
      vendor/src/github.com/docker/libnetwork/.gitignore
  6. 8 0
      vendor/src/github.com/docker/libnetwork/Dockerfile.build
  7. 48 40
      vendor/src/github.com/docker/libnetwork/Makefile
  8. 1 1
      vendor/src/github.com/docker/libnetwork/bitseq/sequence.go
  9. 12 6
      vendor/src/github.com/docker/libnetwork/circle.yml
  10. 24 22
      vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go
  11. 8 2
      vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go
  12. 5 1
      vendor/src/github.com/docker/libnetwork/endpoint_info.go
  13. 1 1
      vendor/src/github.com/docker/libnetwork/iptables/firewalld.go
  14. 20 4
      vendor/src/github.com/docker/libnetwork/iptables/iptables.go
  15. 0 38
      vendor/src/github.com/docker/libnetwork/netutils/utils.go
  16. 50 0
      vendor/src/github.com/docker/libnetwork/netutils/utils_linux.go
  17. 6 0
      vendor/src/github.com/docker/libnetwork/network.go
  18. 1 174
      vendor/src/github.com/docker/libnetwork/sandbox_externalkey.go
  19. 177 0
      vendor/src/github.com/docker/libnetwork/sandbox_externalkey_unix.go
  20. 45 0
      vendor/src/github.com/docker/libnetwork/sandbox_externalkey_windows.go
  21. 1 1
      vendor/src/github.com/godbus/dbus/LICENSE
  22. 3 0
      vendor/src/github.com/godbus/dbus/README.markdown
  23. 0 111
      vendor/src/github.com/godbus/dbus/call.go
  24. 32 16
      vendor/src/github.com/godbus/dbus/conn.go
  25. 35 6
      vendor/src/github.com/godbus/dbus/encoder.go
  26. 156 47
      vendor/src/github.com/godbus/dbus/export.go
  27. 126 0
      vendor/src/github.com/godbus/dbus/object.go
  28. 1 1
      vendor/src/github.com/golang/protobuf/proto/Makefile
  29. 4 6
      vendor/src/github.com/golang/protobuf/proto/encode.go
  30. 13 44
      vendor/src/github.com/golang/protobuf/proto/lib.go
  31. 1 6
      vendor/src/github.com/golang/protobuf/proto/properties.go
  32. 6 6
      vendor/src/github.com/opencontainers/runc/libcontainer/SPEC.md
  33. 66 49
      vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/apply_raw.go
  34. 7 3
      vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/blkio.go
  35. 7 3
      vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go
  36. 6 2
      vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuacct.go
  37. 12 9
      vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset.go
  38. 7 3
      vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices.go
  39. 7 3
      vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer.go
  40. 7 3
      vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/hugetlb.go
  41. 28 13
      vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go
  42. 9 2
      vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/name.go
  43. 9 3
      vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_cls.go
  44. 9 3
      vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_prio.go
  45. 6 2
      vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/perf_event.go
  46. 8 3
      vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/utils.go
  47. 64 36
      vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_systemd.go
  48. 2 3
      vendor/src/github.com/opencontainers/runc/libcontainer/configs/cgroup_unix.go
  49. 6 0
      vendor/src/github.com/opencontainers/runc/libcontainer/configs/cgroup_windows.go
  50. 6 2
      vendor/src/github.com/opencontainers/runc/libcontainer/configs/config.go
  51. 2 0
      vendor/src/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go
  52. 6 53
      vendor/src/github.com/opencontainers/runc/libcontainer/container.go
  53. 112 9
      vendor/src/github.com/opencontainers/runc/libcontainer/container_linux.go
  54. 20 0
      vendor/src/github.com/opencontainers/runc/libcontainer/container_windows.go
  55. 2 0
      vendor/src/github.com/opencontainers/runc/libcontainer/criu_opts_unix.go
  56. 6 0
      vendor/src/github.com/opencontainers/runc/libcontainer/criu_opts_windows.go
  57. 3 0
      vendor/src/github.com/opencontainers/runc/libcontainer/devices/devices_unsupported.go
  58. 0 16
      vendor/src/github.com/opencontainers/runc/libcontainer/devices/devices_windows.go
  59. 6 5
      vendor/src/github.com/opencontainers/runc/libcontainer/factory_linux.go
  60. 5 3
      vendor/src/github.com/opencontainers/runc/libcontainer/process_linux.go
  61. 18 14
      vendor/src/github.com/opencontainers/runc/libcontainer/rootfs_linux.go
  62. 46 28
      vendor/src/github.com/opencontainers/runc/libcontainer/seccomp/config.go
  63. 3 0
      vendor/src/github.com/opencontainers/runc/libcontainer/seccomp/seccomp_linux.go
  64. 1 1
      vendor/src/github.com/opencontainers/runc/libcontainer/utils/utils.go
  65. 4 2
      vendor/src/github.com/syndtr/gocapability/capability/syscall_linux.go

+ 7 - 7
hack/vendor.sh

@@ -22,7 +22,7 @@ clone git github.com/vdemeester/shakers 3c10293ce22b900c27acad7b28656196fcc2f73b
 clone git golang.org/x/net 47990a1ba55743e6ef1affd3a14e5bac8553615d https://github.com/golang/net.git
 clone git golang.org/x/net 47990a1ba55743e6ef1affd3a14e5bac8553615d https://github.com/golang/net.git
 
 
 #get libnetwork packages
 #get libnetwork packages
-clone git github.com/docker/libnetwork b4ddf18317b19d6e4bcc821145589749206a7d00
+clone git github.com/docker/libnetwork 04cc1fa0a89f8c407b7be8cab883d4b17531ea7d
 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
 clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
 clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
 clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4
 clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4
@@ -49,14 +49,14 @@ clone git github.com/miekg/pkcs11 80f102b5cac759de406949c47f0928b99bd64cdf
 clone git github.com/jfrazelle/go v1.5.1-1
 clone git github.com/jfrazelle/go v1.5.1-1
 clone git github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c
 clone git github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c
 
 
-# this runc commit from branch relabel_fix_docker_1.9.1, pls remove it when you
-# update next time
-clone git github.com/opencontainers/runc 1349b37bd56f4f5ce2690b5b2c0f53f88a261c67 # libcontainer
+clone git github.com/opencontainers/runc v0.0.5 # libcontainer
 # libcontainer deps (see src/github.com/opencontainers/runc/Godeps/Godeps.json)
 # libcontainer deps (see src/github.com/opencontainers/runc/Godeps/Godeps.json)
 clone git github.com/coreos/go-systemd v4
 clone git github.com/coreos/go-systemd v4
-clone git github.com/godbus/dbus v2
-clone git github.com/syndtr/gocapability 66ef2aa7a23ba682594e2b6f74cf40c0692b49fb
-clone git github.com/golang/protobuf 655cdfa588ea
+clone git github.com/godbus/dbus v3
+clone git github.com/syndtr/gocapability 2c00daeb6c3b45114c80ac44119e7b8801fdd852
+clone git github.com/golang/protobuf f7137ae6b19afbfd61a94b746fda3b3fe0491874
+
+# gelf logging driver deps
 clone git github.com/Graylog2/go-gelf 6c62a85f1d47a67f2a5144c0e745b325889a8120
 clone git github.com/Graylog2/go-gelf 6c62a85f1d47a67f2a5144c0e745b325889a8120
 
 
 clone git github.com/fluent/fluent-logger-golang v1.0.0
 clone git github.com/fluent/fluent-logger-golang v1.0.0

+ 33 - 9
vendor/src/github.com/coreos/go-systemd/dbus/dbus.go

@@ -64,11 +64,11 @@ func PathBusEscape(path string) string {
 type Conn struct {
 type Conn struct {
 	// sysconn/sysobj are only used to call dbus methods
 	// sysconn/sysobj are only used to call dbus methods
 	sysconn *dbus.Conn
 	sysconn *dbus.Conn
-	sysobj  *dbus.Object
+	sysobj  dbus.BusObject
 
 
 	// sigconn/sigobj are only used to receive dbus signals
 	// sigconn/sigobj are only used to receive dbus signals
 	sigconn *dbus.Conn
 	sigconn *dbus.Conn
-	sigobj  *dbus.Object
+	sigobj  dbus.BusObject
 
 
 	jobListener struct {
 	jobListener struct {
 		jobs map[dbus.ObjectPath]chan<- string
 		jobs map[dbus.ObjectPath]chan<- string
@@ -86,14 +86,30 @@ type Conn struct {
 // New establishes a connection to the system bus and authenticates.
 // New establishes a connection to the system bus and authenticates.
 // Callers should call Close() when done with the connection.
 // Callers should call Close() when done with the connection.
 func New() (*Conn, error) {
 func New() (*Conn, error) {
-	return newConnection(dbus.SystemBusPrivate)
+	return newConnection(func() (*dbus.Conn, error) {
+		return dbusAuthHelloConnection(dbus.SystemBusPrivate)
+	})
 }
 }
 
 
 // NewUserConnection establishes a connection to the session bus and
 // NewUserConnection establishes a connection to the session bus and
 // authenticates. This can be used to connect to systemd user instances.
 // authenticates. This can be used to connect to systemd user instances.
 // Callers should call Close() when done with the connection.
 // Callers should call Close() when done with the connection.
 func NewUserConnection() (*Conn, error) {
 func NewUserConnection() (*Conn, error) {
-	return newConnection(dbus.SessionBusPrivate)
+	return newConnection(func() (*dbus.Conn, error) {
+		return dbusAuthHelloConnection(dbus.SessionBusPrivate)
+	})
+}
+
+// NewSystemdConnection establishes a private, direct connection to systemd.
+// This can be used for communicating with systemd without a dbus daemon.
+// Callers should call Close() when done with the connection.
+func NewSystemdConnection() (*Conn, error) {
+	return newConnection(func() (*dbus.Conn, error) {
+		// We skip Hello when talking directly to systemd.
+		return dbusAuthConnection(func() (*dbus.Conn, error) {
+			return dbus.Dial("unix:path=/run/systemd/private")
+		})
+	})
 }
 }
 
 
 // Close closes an established connection
 // Close closes an established connection
@@ -103,12 +119,12 @@ func (c *Conn) Close() {
 }
 }
 
 
 func newConnection(createBus func() (*dbus.Conn, error)) (*Conn, error) {
 func newConnection(createBus func() (*dbus.Conn, error)) (*Conn, error) {
-	sysconn, err := dbusConnection(createBus)
+	sysconn, err := createBus()
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	sigconn, err := dbusConnection(createBus)
+	sigconn, err := createBus()
 	if err != nil {
 	if err != nil {
 		sysconn.Close()
 		sysconn.Close()
 		return nil, err
 		return nil, err
@@ -132,7 +148,7 @@ func newConnection(createBus func() (*dbus.Conn, error)) (*Conn, error) {
 	return c, nil
 	return c, nil
 }
 }
 
 
-func dbusConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error) {
+func dbusAuthConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error) {
 	conn, err := createBus()
 	conn, err := createBus()
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
@@ -149,8 +165,16 @@ func dbusConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error) {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	err = conn.Hello()
+	return conn, nil
+}
+
+func dbusAuthHelloConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error) {
+	conn, err := dbusAuthConnection(createBus)
 	if err != nil {
 	if err != nil {
+		return nil, err
+	}
+
+	if err = conn.Hello(); err != nil {
 		conn.Close()
 		conn.Close()
 		return nil, err
 		return nil, err
 	}
 	}
@@ -158,6 +182,6 @@ func dbusConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error) {
 	return conn, nil
 	return conn, nil
 }
 }
 
 
-func systemdObject(conn *dbus.Conn) *dbus.Object {
+func systemdObject(conn *dbus.Conn) dbus.BusObject {
 	return conn.Object("org.freedesktop.systemd1", dbus.ObjectPath("/org/freedesktop/systemd1"))
 	return conn.Object("org.freedesktop.systemd1", dbus.ObjectPath("/org/freedesktop/systemd1"))
 }
 }

+ 17 - 5
vendor/src/github.com/coreos/go-systemd/journal/send.go → vendor/src/github.com/coreos/go-systemd/journal/journal.go

@@ -12,7 +12,14 @@
 // See the License for the specific language governing permissions and
 // See the License for the specific language governing permissions and
 // limitations under the License.
 // limitations under the License.
 
 
-// Package journal provides write bindings to the systemd journal
+// Package journal provides write bindings to the local systemd journal.
+// It is implemented in pure Go and connects to the journal directly over its
+// unix socket.
+//
+// To read from the journal, see the "sdjournal" package, which wraps the
+// sd-journal a C API.
+//
+// http://www.freedesktop.org/software/systemd/man/systemd-journald.service.html
 package journal
 package journal
 
 
 import (
 import (
@@ -53,14 +60,14 @@ func init() {
 	}
 	}
 }
 }
 
 
-// Enabled returns true iff the systemd journal is available for logging
+// Enabled returns true if the local systemd journal is available for logging
 func Enabled() bool {
 func Enabled() bool {
 	return conn != nil
 	return conn != nil
 }
 }
 
 
-// Send a message to the systemd journal. vars is a map of journald fields to
-// values.  Fields must be composed of uppercase letters, numbers, and
-// underscores, but must not start with an underscore. Within these
+// Send a message to the local systemd journal. vars is a map of journald
+// fields to values.  Fields must be composed of uppercase letters, numbers,
+// and underscores, but must not start with an underscore. Within these
 // restrictions, any arbitrary field name may be used.  Some names have special
 // restrictions, any arbitrary field name may be used.  Some names have special
 // significance: see the journalctl documentation
 // significance: see the journalctl documentation
 // (http://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html)
 // (http://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html)
@@ -102,6 +109,11 @@ func Send(message string, priority Priority, vars map[string]string) error {
 	return nil
 	return nil
 }
 }
 
 
+// Print prints a message to the local systemd journal using Send().
+func Print(priority Priority, format string, a ...interface{}) error {
+	return Send(fmt.Sprintf(format, a...), priority, nil)
+}
+
 func appendVariable(w io.Writer, name, value string) {
 func appendVariable(w io.Writer, name, value string) {
 	if !validVarName(name) {
 	if !validVarName(name) {
 		journalError("variable name contains invalid character, ignoring")
 		journalError("variable name contains invalid character, ignoring")

+ 1 - 0
vendor/src/github.com/docker/libnetwork/.dockerignore

@@ -0,0 +1 @@
+*

+ 2 - 1
vendor/src/github.com/docker/libnetwork/.gitignore

@@ -2,6 +2,7 @@
 *.o
 *.o
 *.a
 *.a
 *.so
 *.so
+bin/
 
 
 # Folders
 # Folders
 integration-tmp/
 integration-tmp/
@@ -33,4 +34,4 @@ cmd/dnet/dnet
 .project
 .project
 .settings/
 .settings/
 
 
-libnetwork-build.created
+libnetworkbuild.created

+ 8 - 0
vendor/src/github.com/docker/libnetwork/Dockerfile.build

@@ -0,0 +1,8 @@
+FROM golang:1.4-cross
+RUN apt-get update && apt-get -y install iptables
+RUN go get github.com/tools/godep \
+		github.com/golang/lint/golint \
+		golang.org/x/tools/cmd/vet \
+		golang.org/x/tools/cmd/goimports \
+		golang.org/x/tools/cmd/cover\
+		github.com/mattn/goveralls

+ 48 - 40
vendor/src/github.com/docker/libnetwork/Makefile

@@ -1,42 +1,46 @@
-.PHONY: all all-local build build-local check check-code check-format run-tests check-local integration-tests install-deps coveralls circle-ci start-services clean
+.PHONY: all all-local build build-local clean cross cross-local check check-code check-format run-tests integration-tests check-local coveralls circle-ci-cross circle-ci-build circle-ci-check circle-ci
 SHELL=/bin/bash
 SHELL=/bin/bash
 build_image=libnetworkbuild
 build_image=libnetworkbuild
 dockerargs = --privileged -v $(shell pwd):/go/src/github.com/docker/libnetwork -w /go/src/github.com/docker/libnetwork
 dockerargs = --privileged -v $(shell pwd):/go/src/github.com/docker/libnetwork -w /go/src/github.com/docker/libnetwork
 container_env = -e "INSIDECONTAINER=-incontainer=true"
 container_env = -e "INSIDECONTAINER=-incontainer=true"
-docker = docker run --rm -it ${dockerargs} ${container_env} ${build_image}
+docker = docker run --rm -it ${dockerargs} $$EXTRA_ARGS ${container_env} ${build_image}
 ciargs = -e "COVERALLS_TOKEN=$$COVERALLS_TOKEN" -e "INSIDECONTAINER=-incontainer=true"
 ciargs = -e "COVERALLS_TOKEN=$$COVERALLS_TOKEN" -e "INSIDECONTAINER=-incontainer=true"
-cidocker = docker run ${ciargs} ${dockerargs} golang:1.4
-
-all: ${build_image}.created build check integration-tests clean
-
-integration-tests: ./cmd/dnet/dnet
-	@./test/integration/dnet/run-integration-tests.sh
-
-./cmd/dnet/dnet:
-	make build
-
-clean:
-	@if [ -e ./cmd/dnet/dnet ]; then \
-		echo "Removing dnet binary"; \
-		rm -rf ./cmd/dnet/dnet; \
-	fi
-
-all-local: check-local build-local
+cidocker = docker run ${dockerargs} ${ciargs} ${container_env} ${build_image}
+CROSS_PLATFORMS = linux/amd64 linux/386 linux/arm windows/amd64 windows/386
 
 
 ${build_image}.created:
 ${build_image}.created:
-	docker run --name=libnetworkbuild -v $(shell pwd):/go/src/github.com/docker/libnetwork -w /go/src/github.com/docker/libnetwork golang:1.4 make install-deps
-	docker commit libnetworkbuild ${build_image}
-	docker rm libnetworkbuild
+	docker build -f Dockerfile.build -t ${build_image} .
 	touch ${build_image}.created
 	touch ${build_image}.created
 
 
+all: ${build_image}.created build check integration-tests clean
+
+all-local: build-local check-local integration-tests-local clean
+
 build: ${build_image}.created
 build: ${build_image}.created
 	@echo "Building code... "
 	@echo "Building code... "
 	@${docker} ./wrapmake.sh build-local
 	@${docker} ./wrapmake.sh build-local
 	@echo "Done building code"
 	@echo "Done building code"
 
 
 build-local:
 build-local:
-	@$(shell which godep) go build  ./...
-	@$(shell which godep) go build -o ./cmd/dnet/dnet ./cmd/dnet
+	@mkdir -p "bin"
+	$(shell which godep) go build -o "bin/dnet" ./cmd/dnet
+
+clean:
+	@if [ -d bin ]; then \
+		echo "Removing dnet binaries"; \
+		rm -rf bin; \
+	fi
+
+cross: ${build_image}.created
+	@mkdir -p "bin"
+	@for platform in ${CROSS_PLATFORMS}; do \
+	        EXTRA_ARGS="-e GOOS=$${platform%/*} -e GOARCH=$${platform##*/}" ; \
+		echo "$${platform}..." ; \
+	        ${docker} make cross-local ; \
+	done
+
+cross-local:
+	$(shell which godep) go build -o "bin/dnet-$$GOOS-$$GOARCH" ./cmd/dnet
 
 
 check: ${build_image}.created
 check: ${build_image}.created
 	@${docker} ./wrapmake.sh check-local
 	@${docker} ./wrapmake.sh check-local
@@ -71,27 +75,31 @@ run-tests:
 	done
 	done
 	@echo "Done running tests"
 	@echo "Done running tests"
 
 
-check-local:	check-format check-code start-services run-tests
+check-local:	check-format check-code run-tests
+
+integration-tests: ./bin/dnet
+	@./test/integration/dnet/run-integration-tests.sh
 
 
-install-deps:
-	apt-get update && apt-get -y install iptables zookeeperd
-	git clone https://github.com/golang/tools /go/src/golang.org/x/tools
-	go install golang.org/x/tools/cmd/vet
-	go install golang.org/x/tools/cmd/goimports
-	go install golang.org/x/tools/cmd/cover
-	go get github.com/tools/godep
-	go get github.com/golang/lint/golint
-	go get github.com/mattn/goveralls
+./bin/dnet:
+	make build
 
 
 coveralls:
 coveralls:
 	-@goveralls -service circleci -coverprofile=coverage.coverprofile -repotoken $$COVERALLS_TOKEN
 	-@goveralls -service circleci -coverprofile=coverage.coverprofile -repotoken $$COVERALLS_TOKEN
 
 
 # CircleCI's Docker fails when cleaning up using the --rm flag
 # CircleCI's Docker fails when cleaning up using the --rm flag
-# The following target is a workaround for this
+# The following targets are a workaround for this
+circle-ci-cross: ${build_image}.created
+	@mkdir -p "bin"
+	@for platform in ${CROSS_PLATFORMS}; do \
+	        EXTRA_ARGS="-e GOOS=$${platform%/*} -e GOARCH=$${platform##*/}" ; \
+		echo "$${platform}..." ; \
+	        ${cidocker} make cross-local ; \
+	done
+
+circle-ci-check: ${build_image}.created
+	@${cidocker} make check-local coveralls
 
 
-circle-ci:
-	@${cidocker} make install-deps build-local check-local coveralls
-	make integration-tests
+circle-ci-build: ${build_image}.created
+	@${cidocker} make build-local
 
 
-start-services:
-	service zookeeper start
+circle-ci: circle-ci-check circle-ci-build integration-tests

+ 1 - 1
vendor/src/github.com/docker/libnetwork/bitseq/sequence.go

@@ -552,7 +552,7 @@ func pushReservation(bytePos, bitPos uint64, head *sequence, release bool) *sequ
 		}
 		}
 		removeCurrentIfEmpty(&newHead, newSequence, current)
 		removeCurrentIfEmpty(&newHead, newSequence, current)
 		mergeSequences(previous)
 		mergeSequences(previous)
-	} else if precBlocks == current.count-2 { // Last in sequence (B)
+	} else if precBlocks == current.count { // Last in sequence (B)
 		newSequence.next = current.next
 		newSequence.next = current.next
 		current.next = newSequence
 		current.next = newSequence
 		mergeSequences(current)
 		mergeSequences(current)

+ 12 - 6
vendor/src/github.com/docker/libnetwork/circle.yml

@@ -1,12 +1,18 @@
 machine:
 machine:
-    services:
-        - docker
+  services:
+    - docker
 
 
 dependencies:
 dependencies:
-    override:
-        - echo "Nothing to install"
+  override:
+    - sudo apt-get update; sudo apt-get install -y iptables zookeeperd
+    - go get golang.org/x/tools/cmd/vet
+    - go get golang.org/x/tools/cmd/goimports
+    - go get golang.org/x/tools/cmd/cover
+    - go get github.com/tools/godep
+    - go get github.com/golang/lint/golint
+    - go get github.com/mattn/goveralls
 
 
 test:
 test:
-    override:
-        - make circle-ci
+  override:
+    - make circle-ci
 
 

+ 24 - 22
vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go

@@ -41,6 +41,9 @@ const (
 	DefaultGatewayV6AuxKey = "DefaultGatewayIPv6"
 	DefaultGatewayV6AuxKey = "DefaultGatewayIPv6"
 )
 )
 
 
+type iptableCleanFunc func() error
+type iptablesCleanFuncs []iptableCleanFunc
+
 // configuration info for the "bridge" driver.
 // configuration info for the "bridge" driver.
 type configuration struct {
 type configuration struct {
 	EnableIPForwarding  bool
 	EnableIPForwarding  bool
@@ -92,12 +95,13 @@ type bridgeEndpoint struct {
 }
 }
 
 
 type bridgeNetwork struct {
 type bridgeNetwork struct {
-	id         string
-	bridge     *bridgeInterface // The bridge's L3 interface
-	config     *networkConfiguration
-	endpoints  map[string]*bridgeEndpoint // key: endpoint id
-	portMapper *portmapper.PortMapper
-	driver     *driver // The network's driver
+	id            string
+	bridge        *bridgeInterface // The bridge's L3 interface
+	config        *networkConfiguration
+	endpoints     map[string]*bridgeEndpoint // key: endpoint id
+	portMapper    *portmapper.PortMapper
+	driver        *driver // The network's driver
+	iptCleanFuncs iptablesCleanFuncs
 	sync.Mutex
 	sync.Mutex
 }
 }
 
 
@@ -236,6 +240,10 @@ func parseErr(label, value, errString string) error {
 	return types.BadRequestErrorf("failed to parse %s value: %v (%s)", label, value, errString)
 	return types.BadRequestErrorf("failed to parse %s value: %v (%s)", label, value, errString)
 }
 }
 
 
+func (n *bridgeNetwork) registerIptCleanFunc(clean iptableCleanFunc) {
+	n.iptCleanFuncs = append(n.iptCleanFuncs, clean)
+}
+
 func (n *bridgeNetwork) getDriverChains() (*iptables.ChainInfo, *iptables.ChainInfo, error) {
 func (n *bridgeNetwork) getDriverChains() (*iptables.ChainInfo, *iptables.ChainInfo, error) {
 	n.Lock()
 	n.Lock()
 	defer n.Unlock()
 	defer n.Unlock()
@@ -604,6 +612,10 @@ func (d *driver) createNetwork(config *networkConfiguration) error {
 			}
 			}
 			return err
 			return err
 		}
 		}
+		network.registerIptCleanFunc(func() error {
+			nwList := d.getNetworks()
+			return network.isolateNetwork(nwList, false)
+		})
 		return nil
 		return nil
 	}
 	}
 
 
@@ -722,22 +734,6 @@ func (d *driver) DeleteNetwork(nid string) error {
 		return err
 		return err
 	}
 	}
 
 
-	// In case of failures after this point, restore the network isolation rules
-	nwList := d.getNetworks()
-	defer func() {
-		if err != nil {
-			if err := n.isolateNetwork(nwList, true); err != nil {
-				logrus.Warnf("Failed on restoring the inter-network iptables rules on cleanup: %v", err)
-			}
-		}
-	}()
-
-	// Remove inter-network communication rules.
-	err = n.isolateNetwork(nwList, false)
-	if err != nil {
-		return err
-	}
-
 	// We only delete the bridge when it's not the default bridge. This is keep the backward compatible behavior.
 	// We only delete the bridge when it's not the default bridge. This is keep the backward compatible behavior.
 	if !config.DefaultBridge {
 	if !config.DefaultBridge {
 		if err := netlink.LinkDel(n.bridge.Link); err != nil {
 		if err := netlink.LinkDel(n.bridge.Link); err != nil {
@@ -745,6 +741,12 @@ func (d *driver) DeleteNetwork(nid string) error {
 		}
 		}
 	}
 	}
 
 
+	// clean all relevant iptables rules
+	for _, cleanFunc := range n.iptCleanFuncs {
+		if errClean := cleanFunc(); errClean != nil {
+			logrus.Warnf("Failed to clean iptables rules for bridge network: %v", errClean)
+		}
+	}
 	return d.storeDelete(config)
 	return d.storeDelete(config)
 }
 }
 
 

+ 8 - 2
vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go

@@ -68,21 +68,27 @@ func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInt
 	if err = setupIPTablesInternal(config.BridgeName, maskedAddrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, true); err != nil {
 	if err = setupIPTablesInternal(config.BridgeName, maskedAddrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, true); err != nil {
 		return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
 		return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
 	}
 	}
+	n.registerIptCleanFunc(func() error {
+		return setupIPTablesInternal(config.BridgeName, maskedAddrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, false)
+	})
 
 
 	natChain, filterChain, err := n.getDriverChains()
 	natChain, filterChain, err := n.getDriverChains()
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf("Failed to setup IP tables, cannot acquire chain info %s", err.Error())
 		return fmt.Errorf("Failed to setup IP tables, cannot acquire chain info %s", err.Error())
 	}
 	}
 
 
-	err = iptables.ProgramChain(natChain, config.BridgeName, hairpinMode)
+	err = iptables.ProgramChain(natChain, config.BridgeName, hairpinMode, true)
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf("Failed to program NAT chain: %s", err.Error())
 		return fmt.Errorf("Failed to program NAT chain: %s", err.Error())
 	}
 	}
 
 
-	err = iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode)
+	err = iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode, true)
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf("Failed to program FILTER chain: %s", err.Error())
 		return fmt.Errorf("Failed to program FILTER chain: %s", err.Error())
 	}
 	}
+	n.registerIptCleanFunc(func() error {
+		return iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode, false)
+	})
 
 
 	n.portMapper.SetIptablesChain(filterChain, n.getNetworkBridgeName())
 	n.portMapper.SetIptablesChain(filterChain, n.getNetworkBridgeName())
 
 

+ 5 - 1
vendor/src/github.com/docker/libnetwork/endpoint_info.go

@@ -159,7 +159,11 @@ func (ep *endpoint) Info() EndpointInfo {
 		return ep
 		return ep
 	}
 	}
 
 
-	return sb.getEndpoint(ep.ID())
+	if epi := sb.getEndpoint(ep.ID()); epi != nil {
+		return epi
+	}
+
+	return nil
 }
 }
 
 
 func (ep *endpoint) DriverInfo() (map[string]interface{}, error) {
 func (ep *endpoint) DriverInfo() (map[string]interface{}, error) {

+ 1 - 1
vendor/src/github.com/docker/libnetwork/iptables/firewalld.go

@@ -27,7 +27,7 @@ const (
 // Conn is a connection to firewalld dbus endpoint.
 // Conn is a connection to firewalld dbus endpoint.
 type Conn struct {
 type Conn struct {
 	sysconn *dbus.Conn
 	sysconn *dbus.Conn
-	sysobj  *dbus.Object
+	sysobj  dbus.BusObject
 	signal  chan *dbus.Signal
 	signal  chan *dbus.Signal
 }
 }
 
 

+ 20 - 4
vendor/src/github.com/docker/libnetwork/iptables/iptables.go

@@ -95,7 +95,7 @@ func NewChain(name string, table Table, hairpinMode bool) (*ChainInfo, error) {
 }
 }
 
 
 // ProgramChain is used to add rules to a chain
 // ProgramChain is used to add rules to a chain
-func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode bool) error {
+func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode, enable bool) error {
 	if c.Name == "" {
 	if c.Name == "" {
 		return fmt.Errorf("Could not program chain, missing chain name.")
 		return fmt.Errorf("Could not program chain, missing chain name.")
 	}
 	}
@@ -106,10 +106,14 @@ func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode bool) error {
 			"-m", "addrtype",
 			"-m", "addrtype",
 			"--dst-type", "LOCAL",
 			"--dst-type", "LOCAL",
 			"-j", c.Name}
 			"-j", c.Name}
-		if !Exists(Nat, "PREROUTING", preroute...) {
+		if !Exists(Nat, "PREROUTING", preroute...) && enable {
 			if err := c.Prerouting(Append, preroute...); err != nil {
 			if err := c.Prerouting(Append, preroute...); err != nil {
 				return fmt.Errorf("Failed to inject docker in PREROUTING chain: %s", err)
 				return fmt.Errorf("Failed to inject docker in PREROUTING chain: %s", err)
 			}
 			}
+		} else if Exists(Nat, "PREROUTING", preroute...) && !enable {
+			if err := c.Prerouting(Delete, preroute...); err != nil {
+				return fmt.Errorf("Failed to remove docker in PREROUTING chain: %s", err)
+			}
 		}
 		}
 		output := []string{
 		output := []string{
 			"-m", "addrtype",
 			"-m", "addrtype",
@@ -118,10 +122,14 @@ func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode bool) error {
 		if !hairpinMode {
 		if !hairpinMode {
 			output = append(output, "!", "--dst", "127.0.0.0/8")
 			output = append(output, "!", "--dst", "127.0.0.0/8")
 		}
 		}
-		if !Exists(Nat, "OUTPUT", output...) {
+		if !Exists(Nat, "OUTPUT", output...) && enable {
 			if err := c.Output(Append, output...); err != nil {
 			if err := c.Output(Append, output...); err != nil {
 				return fmt.Errorf("Failed to inject docker in OUTPUT chain: %s", err)
 				return fmt.Errorf("Failed to inject docker in OUTPUT chain: %s", err)
 			}
 			}
+		} else if Exists(Nat, "OUTPUT", output...) && !enable {
+			if err := c.Output(Delete, output...); err != nil {
+				return fmt.Errorf("Failed to inject docker in OUTPUT chain: %s", err)
+			}
 		}
 		}
 	case Filter:
 	case Filter:
 		if bridgeName == "" {
 		if bridgeName == "" {
@@ -131,13 +139,21 @@ func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode bool) error {
 		link := []string{
 		link := []string{
 			"-o", bridgeName,
 			"-o", bridgeName,
 			"-j", c.Name}
 			"-j", c.Name}
-		if !Exists(Filter, "FORWARD", link...) {
+		if !Exists(Filter, "FORWARD", link...) && enable {
 			insert := append([]string{string(Insert), "FORWARD"}, link...)
 			insert := append([]string{string(Insert), "FORWARD"}, link...)
 			if output, err := Raw(insert...); err != nil {
 			if output, err := Raw(insert...); err != nil {
 				return err
 				return err
 			} else if len(output) != 0 {
 			} else if len(output) != 0 {
 				return fmt.Errorf("Could not create linking rule to %s/%s: %s", c.Table, c.Name, output)
 				return fmt.Errorf("Could not create linking rule to %s/%s: %s", c.Table, c.Name, output)
 			}
 			}
+		} else if Exists(Filter, "FORWARD", link...) && !enable {
+			del := append([]string{string(Delete), "FORWARD"}, link...)
+			if output, err := Raw(del...); err != nil {
+				return err
+			} else if len(output) != 0 {
+				return fmt.Errorf("Could not delete linking rule from %s/%s: %s", c.Table, c.Name, output)
+			}
+
 		}
 		}
 	}
 	}
 	return nil
 	return nil

+ 0 - 38
vendor/src/github.com/docker/libnetwork/netutils/utils.go

@@ -9,10 +9,8 @@ import (
 	"fmt"
 	"fmt"
 	"io"
 	"io"
 	"net"
 	"net"
-	"strings"
 
 
 	"github.com/docker/libnetwork/types"
 	"github.com/docker/libnetwork/types"
-	"github.com/vishvananda/netlink"
 )
 )
 
 
 var (
 var (
@@ -22,8 +20,6 @@ var (
 	ErrNetworkOverlaps = errors.New("requested network overlaps with existing network")
 	ErrNetworkOverlaps = errors.New("requested network overlaps with existing network")
 	// ErrNoDefaultRoute preformatted error
 	// ErrNoDefaultRoute preformatted error
 	ErrNoDefaultRoute = errors.New("no default route")
 	ErrNoDefaultRoute = errors.New("no default route")
-
-	networkGetRoutesFct = netlink.RouteList
 )
 )
 
 
 // CheckNameserverOverlaps checks whether the passed network overlaps with any of the nameservers
 // CheckNameserverOverlaps checks whether the passed network overlaps with any of the nameservers
@@ -42,21 +38,6 @@ func CheckNameserverOverlaps(nameservers []string, toCheck *net.IPNet) error {
 	return nil
 	return nil
 }
 }
 
 
-// CheckRouteOverlaps checks whether the passed network overlaps with any existing routes
-func CheckRouteOverlaps(toCheck *net.IPNet) error {
-	networks, err := networkGetRoutesFct(nil, netlink.FAMILY_V4)
-	if err != nil {
-		return err
-	}
-
-	for _, network := range networks {
-		if network.Dst != nil && NetworkOverlaps(toCheck, network.Dst) {
-			return ErrNetworkOverlaps
-		}
-	}
-	return nil
-}
-
 // NetworkOverlaps detects overlap between one IPNet and another
 // NetworkOverlaps detects overlap between one IPNet and another
 func NetworkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
 func NetworkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
 	return netX.Contains(netY.IP) || netY.Contains(netX.IP)
 	return netX.Contains(netY.IP) || netY.Contains(netX.IP)
@@ -151,22 +132,3 @@ func GenerateRandomName(prefix string, size int) (string, error) {
 	}
 	}
 	return prefix + hex.EncodeToString(id)[:size], nil
 	return prefix + hex.EncodeToString(id)[:size], nil
 }
 }
-
-// GenerateIfaceName returns an interface name using the passed in
-// prefix and the length of random bytes. The api ensures that the
-// there are is no interface which exists with that name.
-func GenerateIfaceName(prefix string, len int) (string, error) {
-	for i := 0; i < 3; i++ {
-		name, err := GenerateRandomName(prefix, len)
-		if err != nil {
-			continue
-		}
-		if _, err := netlink.LinkByName(name); err != nil {
-			if strings.Contains(err.Error(), "not found") {
-				return name, nil
-			}
-			return "", err
-		}
-	}
-	return "", types.InternalErrorf("could not generate interface name")
-}

+ 50 - 0
vendor/src/github.com/docker/libnetwork/netutils/utils_linux.go

@@ -0,0 +1,50 @@
+// +build linux
+// Network utility functions.
+
+package netutils
+
+import (
+	"net"
+	"strings"
+
+	"github.com/docker/libnetwork/types"
+	"github.com/vishvananda/netlink"
+)
+
+var (
+	networkGetRoutesFct = netlink.RouteList
+)
+
+// CheckRouteOverlaps checks whether the passed network overlaps with any existing routes
+func CheckRouteOverlaps(toCheck *net.IPNet) error {
+	networks, err := networkGetRoutesFct(nil, netlink.FAMILY_V4)
+	if err != nil {
+		return err
+	}
+
+	for _, network := range networks {
+		if network.Dst != nil && NetworkOverlaps(toCheck, network.Dst) {
+			return ErrNetworkOverlaps
+		}
+	}
+	return nil
+}
+
+// GenerateIfaceName returns an interface name using the passed in
+// prefix and the length of random bytes. The api ensures that the
+// there are is no interface which exists with that name.
+func GenerateIfaceName(prefix string, len int) (string, error) {
+	for i := 0; i < 3; i++ {
+		name, err := GenerateRandomName(prefix, len)
+		if err != nil {
+			continue
+		}
+		if _, err := netlink.LinkByName(name); err != nil {
+			if strings.Contains(err.Error(), "not found") {
+				return name, nil
+			}
+			return "", err
+		}
+	}
+	return "", types.InternalErrorf("could not generate interface name")
+}

+ 6 - 0
vendor/src/github.com/docker/libnetwork/network.go

@@ -671,6 +671,12 @@ func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoi
 
 
 	ep.processOptions(options...)
 	ep.processOptions(options...)
 
 
+	if opt, ok := ep.generic[netlabel.MacAddress]; ok {
+		if mac, ok := opt.(net.HardwareAddr); ok {
+			ep.iface.mac = mac
+		}
+	}
+
 	if err = ep.assignAddress(true, !n.postIPv6); err != nil {
 	if err = ep.assignAddress(true, !n.postIPv6); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

+ 1 - 174
vendor/src/github.com/docker/libnetwork/sandbox_externalkey.go

@@ -1,19 +1,6 @@
 package libnetwork
 package libnetwork
 
 
-import (
-	"encoding/json"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"net"
-	"os"
-
-	"github.com/Sirupsen/logrus"
-	"github.com/docker/docker/pkg/reexec"
-	"github.com/docker/libnetwork/types"
-	"github.com/opencontainers/runc/libcontainer"
-	"github.com/opencontainers/runc/libcontainer/configs"
-)
+import "github.com/docker/docker/pkg/reexec"
 
 
 type setKeyData struct {
 type setKeyData struct {
 	ContainerID string
 	ContainerID string
@@ -23,163 +10,3 @@ type setKeyData struct {
 func init() {
 func init() {
 	reexec.Register("libnetwork-setkey", processSetKeyReexec)
 	reexec.Register("libnetwork-setkey", processSetKeyReexec)
 }
 }
-
-const udsBase = "/var/lib/docker/network/files/"
-const success = "success"
-
-// processSetKeyReexec is a private function that must be called only on an reexec path
-// It expects 3 args { [0] = "libnetwork-setkey", [1] = <container-id>, [2] = <controller-id> }
-// It also expects libcontainer.State as a json string in <stdin>
-// Refer to https://github.com/opencontainers/runc/pull/160/ for more information
-func processSetKeyReexec() {
-	var err error
-
-	// Return a failure to the calling process via ExitCode
-	defer func() {
-		if err != nil {
-			logrus.Fatalf("%v", err)
-		}
-	}()
-
-	// expecting 3 args {[0]="libnetwork-setkey", [1]=<container-id>, [2]=<controller-id> }
-	if len(os.Args) < 3 {
-		err = fmt.Errorf("Re-exec expects 3 args, received : %d", len(os.Args))
-		return
-	}
-	containerID := os.Args[1]
-
-	// We expect libcontainer.State as a json string in <stdin>
-	stateBuf, err := ioutil.ReadAll(os.Stdin)
-	if err != nil {
-		return
-	}
-	var state libcontainer.State
-	if err = json.Unmarshal(stateBuf, &state); err != nil {
-		return
-	}
-
-	controllerID := os.Args[2]
-	key := state.NamespacePaths[configs.NamespaceType("NEWNET")]
-
-	err = SetExternalKey(controllerID, containerID, key)
-	return
-}
-
-// SetExternalKey provides a convenient way to set an External key to a sandbox
-func SetExternalKey(controllerID string, containerID string, key string) error {
-	keyData := setKeyData{
-		ContainerID: containerID,
-		Key:         key}
-
-	c, err := net.Dial("unix", udsBase+controllerID+".sock")
-	if err != nil {
-		return err
-	}
-	defer c.Close()
-
-	if err = sendKey(c, keyData); err != nil {
-		return fmt.Errorf("sendKey failed with : %v", err)
-	}
-	return processReturn(c)
-}
-
-func sendKey(c net.Conn, data setKeyData) error {
-	var err error
-	defer func() {
-		if err != nil {
-			c.Close()
-		}
-	}()
-
-	var b []byte
-	if b, err = json.Marshal(data); err != nil {
-		return err
-	}
-
-	_, err = c.Write(b)
-	return err
-}
-
-func processReturn(r io.Reader) error {
-	buf := make([]byte, 1024)
-	n, err := r.Read(buf[:])
-	if err != nil {
-		return fmt.Errorf("failed to read buf in processReturn : %v", err)
-	}
-	if string(buf[0:n]) != success {
-		return fmt.Errorf(string(buf[0:n]))
-	}
-	return nil
-}
-
-func (c *controller) startExternalKeyListener() error {
-	if err := os.MkdirAll(udsBase, 0600); err != nil {
-		return err
-	}
-	uds := udsBase + c.id + ".sock"
-	l, err := net.Listen("unix", uds)
-	if err != nil {
-		return err
-	}
-	if err := os.Chmod(uds, 0600); err != nil {
-		l.Close()
-		return err
-	}
-	c.Lock()
-	c.extKeyListener = l
-	c.Unlock()
-
-	go c.acceptClientConnections(uds, l)
-	return nil
-}
-
-func (c *controller) acceptClientConnections(sock string, l net.Listener) {
-	for {
-		conn, err := l.Accept()
-		if err != nil {
-			if _, err1 := os.Stat(sock); os.IsNotExist(err1) {
-				logrus.Debugf("Unix socket %s doesnt exist. cannot accept client connections", sock)
-				return
-			}
-			logrus.Errorf("Error accepting connection %v", err)
-			continue
-		}
-		go func() {
-			err := c.processExternalKey(conn)
-			ret := success
-			if err != nil {
-				ret = err.Error()
-			}
-
-			_, err = conn.Write([]byte(ret))
-			if err != nil {
-				logrus.Errorf("Error returning to the client %v", err)
-			}
-		}()
-	}
-}
-
-func (c *controller) processExternalKey(conn net.Conn) error {
-	buf := make([]byte, 1280)
-	nr, err := conn.Read(buf)
-	if err != nil {
-		return err
-	}
-	var s setKeyData
-	if err = json.Unmarshal(buf[0:nr], &s); err != nil {
-		return err
-	}
-
-	var sandbox Sandbox
-	search := SandboxContainerWalker(&sandbox, s.ContainerID)
-	c.WalkSandboxes(search)
-	if sandbox == nil {
-		return types.BadRequestErrorf("no sandbox present for %s", s.ContainerID)
-	}
-
-	return sandbox.SetKey(s.Key)
-}
-
-func (c *controller) stopExternalKeyListener() {
-	c.extKeyListener.Close()
-}

+ 177 - 0
vendor/src/github.com/docker/libnetwork/sandbox_externalkey_unix.go

@@ -0,0 +1,177 @@
+// +build !windows
+
+package libnetwork
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net"
+	"os"
+
+	"github.com/Sirupsen/logrus"
+	"github.com/docker/libnetwork/types"
+	"github.com/opencontainers/runc/libcontainer"
+	"github.com/opencontainers/runc/libcontainer/configs"
+)
+
+const udsBase = "/var/lib/docker/network/files/"
+const success = "success"
+
+// processSetKeyReexec is a private function that must be called only on an reexec path
+// It expects 3 args { [0] = "libnetwork-setkey", [1] = <container-id>, [2] = <controller-id> }
+// It also expects libcontainer.State as a json string in <stdin>
+// Refer to https://github.com/opencontainers/runc/pull/160/ for more information
+func processSetKeyReexec() {
+	var err error
+
+	// Return a failure to the calling process via ExitCode
+	defer func() {
+		if err != nil {
+			logrus.Fatalf("%v", err)
+		}
+	}()
+
+	// expecting 3 args {[0]="libnetwork-setkey", [1]=<container-id>, [2]=<controller-id> }
+	if len(os.Args) < 3 {
+		err = fmt.Errorf("Re-exec expects 3 args, received : %d", len(os.Args))
+		return
+	}
+	containerID := os.Args[1]
+
+	// We expect libcontainer.State as a json string in <stdin>
+	stateBuf, err := ioutil.ReadAll(os.Stdin)
+	if err != nil {
+		return
+	}
+	var state libcontainer.State
+	if err = json.Unmarshal(stateBuf, &state); err != nil {
+		return
+	}
+
+	controllerID := os.Args[2]
+	key := state.NamespacePaths[configs.NamespaceType("NEWNET")]
+
+	err = SetExternalKey(controllerID, containerID, key)
+	return
+}
+
+// SetExternalKey provides a convenient way to set an External key to a sandbox
+func SetExternalKey(controllerID string, containerID string, key string) error {
+	keyData := setKeyData{
+		ContainerID: containerID,
+		Key:         key}
+
+	c, err := net.Dial("unix", udsBase+controllerID+".sock")
+	if err != nil {
+		return err
+	}
+	defer c.Close()
+
+	if err = sendKey(c, keyData); err != nil {
+		return fmt.Errorf("sendKey failed with : %v", err)
+	}
+	return processReturn(c)
+}
+
+func sendKey(c net.Conn, data setKeyData) error {
+	var err error
+	defer func() {
+		if err != nil {
+			c.Close()
+		}
+	}()
+
+	var b []byte
+	if b, err = json.Marshal(data); err != nil {
+		return err
+	}
+
+	_, err = c.Write(b)
+	return err
+}
+
+func processReturn(r io.Reader) error {
+	buf := make([]byte, 1024)
+	n, err := r.Read(buf[:])
+	if err != nil {
+		return fmt.Errorf("failed to read buf in processReturn : %v", err)
+	}
+	if string(buf[0:n]) != success {
+		return fmt.Errorf(string(buf[0:n]))
+	}
+	return nil
+}
+
+func (c *controller) startExternalKeyListener() error {
+	if err := os.MkdirAll(udsBase, 0600); err != nil {
+		return err
+	}
+	uds := udsBase + c.id + ".sock"
+	l, err := net.Listen("unix", uds)
+	if err != nil {
+		return err
+	}
+	if err := os.Chmod(uds, 0600); err != nil {
+		l.Close()
+		return err
+	}
+	c.Lock()
+	c.extKeyListener = l
+	c.Unlock()
+
+	go c.acceptClientConnections(uds, l)
+	return nil
+}
+
+func (c *controller) acceptClientConnections(sock string, l net.Listener) {
+	for {
+		conn, err := l.Accept()
+		if err != nil {
+			if _, err1 := os.Stat(sock); os.IsNotExist(err1) {
+				logrus.Debugf("Unix socket %s doesnt exist. cannot accept client connections", sock)
+				return
+			}
+			logrus.Errorf("Error accepting connection %v", err)
+			continue
+		}
+		go func() {
+			err := c.processExternalKey(conn)
+			ret := success
+			if err != nil {
+				ret = err.Error()
+			}
+
+			_, err = conn.Write([]byte(ret))
+			if err != nil {
+				logrus.Errorf("Error returning to the client %v", err)
+			}
+		}()
+	}
+}
+
+func (c *controller) processExternalKey(conn net.Conn) error {
+	buf := make([]byte, 1280)
+	nr, err := conn.Read(buf)
+	if err != nil {
+		return err
+	}
+	var s setKeyData
+	if err = json.Unmarshal(buf[0:nr], &s); err != nil {
+		return err
+	}
+
+	var sandbox Sandbox
+	search := SandboxContainerWalker(&sandbox, s.ContainerID)
+	c.WalkSandboxes(search)
+	if sandbox == nil {
+		return types.BadRequestErrorf("no sandbox present for %s", s.ContainerID)
+	}
+
+	return sandbox.SetKey(s.Key)
+}
+
+func (c *controller) stopExternalKeyListener() {
+	c.extKeyListener.Close()
+}

+ 45 - 0
vendor/src/github.com/docker/libnetwork/sandbox_externalkey_windows.go

@@ -0,0 +1,45 @@
+// +build windows
+
+package libnetwork
+
+import (
+	"io"
+	"net"
+
+	"github.com/docker/libnetwork/types"
+)
+
+// processSetKeyReexec is a private function that must be called only on an reexec path
+// It expects 3 args { [0] = "libnetwork-setkey", [1] = <container-id>, [2] = <controller-id> }
+// It also expects libcontainer.State as a json string in <stdin>
+// Refer to https://github.com/opencontainers/runc/pull/160/ for more information
+func processSetKeyReexec() {
+}
+
+// SetExternalKey provides a convenient way to set an External key to a sandbox
+func SetExternalKey(controllerID string, containerID string, key string) error {
+	return types.NotImplementedErrorf("SetExternalKey isn't supported on non linux systems")
+}
+
+func sendKey(c net.Conn, data setKeyData) error {
+	return types.NotImplementedErrorf("sendKey isn't supported on non linux systems")
+}
+
+func processReturn(r io.Reader) error {
+	return types.NotImplementedErrorf("processReturn isn't supported on non linux systems")
+}
+
+// no-op on non linux systems
+func (c *controller) startExternalKeyListener() error {
+	return nil
+}
+
+func (c *controller) acceptClientConnections(sock string, l net.Listener) {
+}
+
+func (c *controller) processExternalKey(conn net.Conn) error {
+	return types.NotImplementedErrorf("processExternalKey isn't supported on non linux systems")
+}
+
+func (c *controller) stopExternalKeyListener() {
+}

+ 1 - 1
vendor/src/github.com/godbus/dbus/LICENSE

@@ -1,4 +1,4 @@
-Copyright (c) 2013, Georg Reinke (<guelfey at gmail dot com>)
+Copyright (c) 2013, Georg Reinke (<guelfey at gmail dot com>), Google
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use in source and binary forms, with or without
 Redistribution and use in source and binary forms, with or without

+ 3 - 0
vendor/src/github.com/godbus/dbus/README.markdown

@@ -27,6 +27,9 @@ The complete package documentation and some simple examples are available at
 [_examples](https://github.com/godbus/dbus/tree/master/_examples) directory
 [_examples](https://github.com/godbus/dbus/tree/master/_examples) directory
 gives a short overview over the basic usage. 
 gives a short overview over the basic usage. 
 
 
+#### Projects using godbus
+- [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library.
+
 Please note that the API is considered unstable for now and may change without
 Please note that the API is considered unstable for now and may change without
 further notice.
 further notice.
 
 

+ 0 - 111
vendor/src/github.com/godbus/dbus/call.go

@@ -2,7 +2,6 @@ package dbus
 
 
 import (
 import (
 	"errors"
 	"errors"
-	"strings"
 )
 )
 
 
 // Call represents a pending or completed method call.
 // Call represents a pending or completed method call.
@@ -35,113 +34,3 @@ func (c *Call) Store(retvalues ...interface{}) error {
 
 
 	return Store(c.Body, retvalues...)
 	return Store(c.Body, retvalues...)
 }
 }
-
-// Object represents a remote object on which methods can be invoked.
-type Object struct {
-	conn *Conn
-	dest string
-	path ObjectPath
-}
-
-// Call calls a method with (*Object).Go and waits for its reply.
-func (o *Object) Call(method string, flags Flags, args ...interface{}) *Call {
-	return <-o.Go(method, flags, make(chan *Call, 1), args...).Done
-}
-
-// GetProperty calls org.freedesktop.DBus.Properties.GetProperty on the given
-// object. The property name must be given in interface.member notation.
-func (o *Object) GetProperty(p string) (Variant, error) {
-	idx := strings.LastIndex(p, ".")
-	if idx == -1 || idx+1 == len(p) {
-		return Variant{}, errors.New("dbus: invalid property " + p)
-	}
-
-	iface := p[:idx]
-	prop := p[idx+1:]
-
-	result := Variant{}
-	err := o.Call("org.freedesktop.DBus.Properties.Get", 0, iface, prop).Store(&result)
-
-	if err != nil {
-		return Variant{}, err
-	}
-
-	return result, nil
-}
-
-// Go calls a method with the given arguments asynchronously. It returns a
-// Call structure representing this method call. The passed channel will
-// return the same value once the call is done. If ch is nil, a new channel
-// will be allocated. Otherwise, ch has to be buffered or Go will panic.
-//
-// If the flags include FlagNoReplyExpected, ch is ignored and a Call structure
-// is returned of which only the Err member is valid.
-//
-// If the method parameter contains a dot ('.'), the part before the last dot
-// specifies the interface on which the method is called.
-func (o *Object) Go(method string, flags Flags, ch chan *Call, args ...interface{}) *Call {
-	iface := ""
-	i := strings.LastIndex(method, ".")
-	if i != -1 {
-		iface = method[:i]
-	}
-	method = method[i+1:]
-	msg := new(Message)
-	msg.Type = TypeMethodCall
-	msg.serial = o.conn.getSerial()
-	msg.Flags = flags & (FlagNoAutoStart | FlagNoReplyExpected)
-	msg.Headers = make(map[HeaderField]Variant)
-	msg.Headers[FieldPath] = MakeVariant(o.path)
-	msg.Headers[FieldDestination] = MakeVariant(o.dest)
-	msg.Headers[FieldMember] = MakeVariant(method)
-	if iface != "" {
-		msg.Headers[FieldInterface] = MakeVariant(iface)
-	}
-	msg.Body = args
-	if len(args) > 0 {
-		msg.Headers[FieldSignature] = MakeVariant(SignatureOf(args...))
-	}
-	if msg.Flags&FlagNoReplyExpected == 0 {
-		if ch == nil {
-			ch = make(chan *Call, 10)
-		} else if cap(ch) == 0 {
-			panic("dbus: unbuffered channel passed to (*Object).Go")
-		}
-		call := &Call{
-			Destination: o.dest,
-			Path:        o.path,
-			Method:      method,
-			Args:        args,
-			Done:        ch,
-		}
-		o.conn.callsLck.Lock()
-		o.conn.calls[msg.serial] = call
-		o.conn.callsLck.Unlock()
-		o.conn.outLck.RLock()
-		if o.conn.closed {
-			call.Err = ErrClosed
-			call.Done <- call
-		} else {
-			o.conn.out <- msg
-		}
-		o.conn.outLck.RUnlock()
-		return call
-	}
-	o.conn.outLck.RLock()
-	defer o.conn.outLck.RUnlock()
-	if o.conn.closed {
-		return &Call{Err: ErrClosed}
-	}
-	o.conn.out <- msg
-	return &Call{Err: nil}
-}
-
-// Destination returns the destination that calls on o are sent to.
-func (o *Object) Destination() string {
-	return o.dest
-}
-
-// Path returns the path that calls on o are sent to.
-func (o *Object) Path() ObjectPath {
-	return o.path
-}

+ 32 - 16
vendor/src/github.com/godbus/dbus/conn.go

@@ -32,7 +32,7 @@ var ErrClosed = errors.New("dbus: connection closed by user")
 type Conn struct {
 type Conn struct {
 	transport
 	transport
 
 
-	busObj *Object
+	busObj BusObject
 	unixFD bool
 	unixFD bool
 	uuid   string
 	uuid   string
 
 
@@ -46,7 +46,7 @@ type Conn struct {
 	calls    map[uint32]*Call
 	calls    map[uint32]*Call
 	callsLck sync.RWMutex
 	callsLck sync.RWMutex
 
 
-	handlers    map[ObjectPath]map[string]interface{}
+	handlers    map[ObjectPath]map[string]exportWithMapping
 	handlersLck sync.RWMutex
 	handlersLck sync.RWMutex
 
 
 	out    chan *Message
 	out    chan *Message
@@ -157,7 +157,7 @@ func newConn(tr transport) (*Conn, error) {
 	conn.transport = tr
 	conn.transport = tr
 	conn.calls = make(map[uint32]*Call)
 	conn.calls = make(map[uint32]*Call)
 	conn.out = make(chan *Message, 10)
 	conn.out = make(chan *Message, 10)
-	conn.handlers = make(map[ObjectPath]map[string]interface{})
+	conn.handlers = make(map[ObjectPath]map[string]exportWithMapping)
 	conn.nextSerial = 1
 	conn.nextSerial = 1
 	conn.serialUsed = map[uint32]bool{0: true}
 	conn.serialUsed = map[uint32]bool{0: true}
 	conn.busObj = conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus")
 	conn.busObj = conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus")
@@ -166,7 +166,7 @@ func newConn(tr transport) (*Conn, error) {
 
 
 // BusObject returns the object owned by the bus daemon which handles
 // BusObject returns the object owned by the bus daemon which handles
 // administrative requests.
 // administrative requests.
-func (conn *Conn) BusObject() *Object {
+func (conn *Conn) BusObject() BusObject {
 	return conn.busObj
 	return conn.busObj
 }
 }
 
 
@@ -303,18 +303,33 @@ func (conn *Conn) inWorker() {
 				// as per http://dbus.freedesktop.org/doc/dbus-specification.html ,
 				// as per http://dbus.freedesktop.org/doc/dbus-specification.html ,
 				// sender is optional for signals.
 				// sender is optional for signals.
 				sender, _ := msg.Headers[FieldSender].value.(string)
 				sender, _ := msg.Headers[FieldSender].value.(string)
-				if iface == "org.freedesktop.DBus" && member == "NameLost" &&
-					sender == "org.freedesktop.DBus" {
-
-					name, _ := msg.Body[0].(string)
-					conn.namesLck.Lock()
-					for i, v := range conn.names {
-						if v == name {
-							copy(conn.names[i:], conn.names[i+1:])
-							conn.names = conn.names[:len(conn.names)-1]
+				if iface == "org.freedesktop.DBus" && sender == "org.freedesktop.DBus" {
+					if member == "NameLost" {
+						// If we lost the name on the bus, remove it from our
+						// tracking list.
+						name, ok := msg.Body[0].(string)
+						if !ok {
+							panic("Unable to read the lost name")
 						}
 						}
+						conn.namesLck.Lock()
+						for i, v := range conn.names {
+							if v == name {
+								conn.names = append(conn.names[:i],
+									conn.names[i+1:]...)
+							}
+						}
+						conn.namesLck.Unlock()
+					} else if member == "NameAcquired" {
+						// If we acquired the name on the bus, add it to our
+						// tracking list.
+						name, ok := msg.Body[0].(string)
+						if !ok {
+							panic("Unable to read the acquired name")
+						}
+						conn.namesLck.Lock()
+						conn.names = append(conn.names, name)
+						conn.namesLck.Unlock()
 					}
 					}
-					conn.namesLck.Unlock()
 				}
 				}
 				signal := &Signal{
 				signal := &Signal{
 					Sender: sender,
 					Sender: sender,
@@ -360,7 +375,7 @@ func (conn *Conn) Names() []string {
 }
 }
 
 
 // Object returns the object identified by the given destination name and path.
 // Object returns the object identified by the given destination name and path.
-func (conn *Conn) Object(dest string, path ObjectPath) *Object {
+func (conn *Conn) Object(dest string, path ObjectPath) BusObject {
 	return &Object{conn, dest, path}
 	return &Object{conn, dest, path}
 }
 }
 
 
@@ -554,7 +569,7 @@ type transport interface {
 }
 }
 
 
 var (
 var (
-	transports map[string]func(string) (transport, error) = make(map[string]func(string) (transport, error))
+	transports = make(map[string]func(string) (transport, error))
 )
 )
 
 
 func getTransport(address string) (transport, error) {
 func getTransport(address string) (transport, error) {
@@ -571,6 +586,7 @@ func getTransport(address string) (transport, error) {
 		f := transports[v[:i]]
 		f := transports[v[:i]]
 		if f == nil {
 		if f == nil {
 			err = errors.New("dbus: invalid bus address (invalid or unsupported transport)")
 			err = errors.New("dbus: invalid bus address (invalid or unsupported transport)")
+			continue
 		}
 		}
 		t, err = f(v[i+1:])
 		t, err = f(v[i+1:])
 		if err == nil {
 		if err == nil {

+ 35 - 6
vendor/src/github.com/godbus/dbus/encoder.go

@@ -16,24 +16,43 @@ type encoder struct {
 
 
 // NewEncoder returns a new encoder that writes to out in the given byte order.
 // NewEncoder returns a new encoder that writes to out in the given byte order.
 func newEncoder(out io.Writer, order binary.ByteOrder) *encoder {
 func newEncoder(out io.Writer, order binary.ByteOrder) *encoder {
+	return newEncoderAtOffset(out, 0, order)
+}
+
+// newEncoderAtOffset returns a new encoder that writes to out in the given
+// byte order. Specify the offset to initialize pos for proper alignment
+// computation.
+func newEncoderAtOffset(out io.Writer, offset int, order binary.ByteOrder) *encoder {
 	enc := new(encoder)
 	enc := new(encoder)
 	enc.out = out
 	enc.out = out
 	enc.order = order
 	enc.order = order
+	enc.pos = offset
 	return enc
 	return enc
 }
 }
 
 
 // Aligns the next output to be on a multiple of n. Panics on write errors.
 // Aligns the next output to be on a multiple of n. Panics on write errors.
 func (enc *encoder) align(n int) {
 func (enc *encoder) align(n int) {
-	if enc.pos%n != 0 {
-		newpos := (enc.pos + n - 1) & ^(n - 1)
-		empty := make([]byte, newpos-enc.pos)
+	pad := enc.padding(0, n)
+	if pad > 0 {
+		empty := make([]byte, pad)
 		if _, err := enc.out.Write(empty); err != nil {
 		if _, err := enc.out.Write(empty); err != nil {
 			panic(err)
 			panic(err)
 		}
 		}
-		enc.pos = newpos
+		enc.pos += pad
 	}
 	}
 }
 }
 
 
+// pad returns the number of bytes of padding, based on current position and additional offset.
+// and alignment.
+func (enc *encoder) padding(offset, algn int) int {
+	abs := enc.pos + offset
+	if abs%algn != 0 {
+		newabs := (abs + algn - 1) & ^(algn - 1)
+		return newabs - abs
+	}
+	return 0
+}
+
 // Calls binary.Write(enc.out, enc.order, v) and panics on write errors.
 // Calls binary.Write(enc.out, enc.order, v) and panics on write errors.
 func (enc *encoder) binwrite(v interface{}) {
 func (enc *encoder) binwrite(v interface{}) {
 	if err := binary.Write(enc.out, enc.order, v); err != nil {
 	if err := binary.Write(enc.out, enc.order, v); err != nil {
@@ -108,8 +127,13 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
 		if depth >= 64 {
 		if depth >= 64 {
 			panic(FormatError("input exceeds container depth limit"))
 			panic(FormatError("input exceeds container depth limit"))
 		}
 		}
+		// Lookahead offset: 4 bytes for uint32 length (with alignment),
+		// plus alignment for elements.
+		n := enc.padding(0, 4) + 4
+		offset := enc.pos + n + enc.padding(n, alignment(v.Type().Elem()))
+
 		var buf bytes.Buffer
 		var buf bytes.Buffer
-		bufenc := newEncoder(&buf, enc.order)
+		bufenc := newEncoderAtOffset(&buf, offset, enc.order)
 
 
 		for i := 0; i < v.Len(); i++ {
 		for i := 0; i < v.Len(); i++ {
 			bufenc.encode(v.Index(i), depth+1)
 			bufenc.encode(v.Index(i), depth+1)
@@ -159,8 +183,13 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
 			panic(InvalidTypeError{v.Type()})
 			panic(InvalidTypeError{v.Type()})
 		}
 		}
 		keys := v.MapKeys()
 		keys := v.MapKeys()
+		// Lookahead offset: 4 bytes for uint32 length (with alignment),
+		// plus 8-byte alignment
+		n := enc.padding(0, 4) + 4
+		offset := enc.pos + n + enc.padding(n, 8)
+
 		var buf bytes.Buffer
 		var buf bytes.Buffer
-		bufenc := newEncoder(&buf, enc.order)
+		bufenc := newEncoderAtOffset(&buf, offset, enc.order)
 		for _, k := range keys {
 		for _, k := range keys {
 			bufenc.align(8)
 			bufenc.align(8)
 			bufenc.encode(k, depth+2)
 			bufenc.encode(k, depth+2)

+ 156 - 47
vendor/src/github.com/godbus/dbus/export.go

@@ -2,9 +2,9 @@ package dbus
 
 
 import (
 import (
 	"errors"
 	"errors"
+	"fmt"
 	"reflect"
 	"reflect"
 	"strings"
 	"strings"
-	"unicode"
 )
 )
 
 
 var (
 var (
@@ -22,16 +22,52 @@ var (
 	}
 	}
 )
 )
 
 
+// exportWithMapping represents an exported struct along with a method name
+// mapping to allow for exporting lower-case methods, etc.
+type exportWithMapping struct {
+	export interface{}
+
+	// Method name mapping; key -> struct method, value -> dbus method.
+	mapping map[string]string
+
+	// Whether or not this export is for the entire subtree
+	includeSubtree bool
+}
+
 // Sender is a type which can be used in exported methods to receive the message
 // Sender is a type which can be used in exported methods to receive the message
 // sender.
 // sender.
 type Sender string
 type Sender string
 
 
-func exportedMethod(v interface{}, name string) reflect.Value {
-	if v == nil {
+func exportedMethod(export exportWithMapping, name string) reflect.Value {
+	if export.export == nil {
 		return reflect.Value{}
 		return reflect.Value{}
 	}
 	}
-	m := reflect.ValueOf(v).MethodByName(name)
-	if !m.IsValid() {
+
+	// If a mapping was included in the export, check the map to see if we
+	// should be looking for a different method in the export.
+	if export.mapping != nil {
+		for key, value := range export.mapping {
+			if value == name {
+				name = key
+				break
+			}
+
+			// Catch the case where a method is aliased but the client is calling
+			// the original, e.g. the "Foo" method was exported mapped to
+			// "foo," and dbus client called the original "Foo."
+			if key == name {
+				return reflect.Value{}
+			}
+		}
+	}
+
+	value := reflect.ValueOf(export.export)
+	m := value.MethodByName(name)
+
+	// Catch the case of attempting to call an unexported method
+	method, ok := value.Type().MethodByName(name)
+
+	if !m.IsValid() || !ok || method.PkgPath != "" {
 		return reflect.Value{}
 		return reflect.Value{}
 	}
 	}
 	t := m.Type()
 	t := m.Type()
@@ -43,6 +79,42 @@ func exportedMethod(v interface{}, name string) reflect.Value {
 	return m
 	return m
 }
 }
 
 
+// searchHandlers will look through all registered handlers looking for one
+// to handle the given path. If a verbatim one isn't found, it will check for
+// a subtree registration for the path as well.
+func (conn *Conn) searchHandlers(path ObjectPath) (map[string]exportWithMapping, bool) {
+	conn.handlersLck.RLock()
+	defer conn.handlersLck.RUnlock()
+
+	handlers, ok := conn.handlers[path]
+	if ok {
+		return handlers, ok
+	}
+
+	// If handlers weren't found for this exact path, look for a matching subtree
+	// registration
+	handlers = make(map[string]exportWithMapping)
+	path = path[:strings.LastIndex(string(path), "/")]
+	for len(path) > 0 {
+		var subtreeHandlers map[string]exportWithMapping
+		subtreeHandlers, ok = conn.handlers[path]
+		if ok {
+			for iface, handler := range subtreeHandlers {
+				// Only include this handler if it registered for the subtree
+				if handler.includeSubtree {
+					handlers[iface] = handler
+				}
+			}
+
+			break
+		}
+
+		path = path[:strings.LastIndex(string(path), "/")]
+	}
+
+	return handlers, ok
+}
+
 // handleCall handles the given method call (i.e. looks if it's one of the
 // handleCall handles the given method call (i.e. looks if it's one of the
 // pre-implemented ones and searches for a corresponding handler if not).
 // pre-implemented ones and searches for a corresponding handler if not).
 func (conn *Conn) handleCall(msg *Message) {
 func (conn *Conn) handleCall(msg *Message) {
@@ -62,40 +134,35 @@ func (conn *Conn) handleCall(msg *Message) {
 		}
 		}
 		return
 		return
 	}
 	}
-	if len(name) == 0 || unicode.IsLower([]rune(name)[0]) {
+	if len(name) == 0 {
 		conn.sendError(errmsgUnknownMethod, sender, serial)
 		conn.sendError(errmsgUnknownMethod, sender, serial)
 	}
 	}
+
+	// Find the exported handler (if any) for this path
+	handlers, ok := conn.searchHandlers(path)
+	if !ok {
+		conn.sendError(errmsgNoObject, sender, serial)
+		return
+	}
+
 	var m reflect.Value
 	var m reflect.Value
 	if hasIface {
 	if hasIface {
-		conn.handlersLck.RLock()
-		obj, ok := conn.handlers[path]
-		if !ok {
-			conn.sendError(errmsgNoObject, sender, serial)
-			conn.handlersLck.RUnlock()
-			return
-		}
-		iface := obj[ifaceName]
-		conn.handlersLck.RUnlock()
+		iface := handlers[ifaceName]
 		m = exportedMethod(iface, name)
 		m = exportedMethod(iface, name)
 	} else {
 	} else {
-		conn.handlersLck.RLock()
-		if _, ok := conn.handlers[path]; !ok {
-			conn.sendError(errmsgNoObject, sender, serial)
-			conn.handlersLck.RUnlock()
-			return
-		}
-		for _, v := range conn.handlers[path] {
+		for _, v := range handlers {
 			m = exportedMethod(v, name)
 			m = exportedMethod(v, name)
 			if m.IsValid() {
 			if m.IsValid() {
 				break
 				break
 			}
 			}
 		}
 		}
-		conn.handlersLck.RUnlock()
 	}
 	}
+
 	if !m.IsValid() {
 	if !m.IsValid() {
 		conn.sendError(errmsgUnknownMethod, sender, serial)
 		conn.sendError(errmsgUnknownMethod, sender, serial)
 		return
 		return
 	}
 	}
+
 	t := m.Type()
 	t := m.Type()
 	vs := msg.Body
 	vs := msg.Body
 	pointers := make([]interface{}, t.NumIn())
 	pointers := make([]interface{}, t.NumIn())
@@ -106,27 +173,36 @@ func (conn *Conn) handleCall(msg *Message) {
 		pointers[i] = val.Interface()
 		pointers[i] = val.Interface()
 		if tp == reflect.TypeOf((*Sender)(nil)).Elem() {
 		if tp == reflect.TypeOf((*Sender)(nil)).Elem() {
 			val.Elem().SetString(sender)
 			val.Elem().SetString(sender)
+		} else if tp == reflect.TypeOf((*Message)(nil)).Elem() {
+			val.Elem().Set(reflect.ValueOf(*msg))
 		} else {
 		} else {
 			decode = append(decode, pointers[i])
 			decode = append(decode, pointers[i])
 		}
 		}
 	}
 	}
+
 	if len(decode) != len(vs) {
 	if len(decode) != len(vs) {
 		conn.sendError(errmsgInvalidArg, sender, serial)
 		conn.sendError(errmsgInvalidArg, sender, serial)
 		return
 		return
 	}
 	}
+
 	if err := Store(vs, decode...); err != nil {
 	if err := Store(vs, decode...); err != nil {
 		conn.sendError(errmsgInvalidArg, sender, serial)
 		conn.sendError(errmsgInvalidArg, sender, serial)
 		return
 		return
 	}
 	}
+
+	// Extract parameters
 	params := make([]reflect.Value, len(pointers))
 	params := make([]reflect.Value, len(pointers))
 	for i := 0; i < len(pointers); i++ {
 	for i := 0; i < len(pointers); i++ {
 		params[i] = reflect.ValueOf(pointers[i]).Elem()
 		params[i] = reflect.ValueOf(pointers[i]).Elem()
 	}
 	}
+
+	// Call method
 	ret := m.Call(params)
 	ret := m.Call(params)
 	if em := ret[t.NumOut()-1].Interface().(*Error); em != nil {
 	if em := ret[t.NumOut()-1].Interface().(*Error); em != nil {
 		conn.sendError(*em, sender, serial)
 		conn.sendError(*em, sender, serial)
 		return
 		return
 	}
 	}
+
 	if msg.Flags&FlagNoReplyExpected == 0 {
 	if msg.Flags&FlagNoReplyExpected == 0 {
 		reply := new(Message)
 		reply := new(Message)
 		reply.Type = TypeMethodReply
 		reply.Type = TypeMethodReply
@@ -203,6 +279,10 @@ func (conn *Conn) Emit(path ObjectPath, name string, values ...interface{}) erro
 // contribute to the dbus signature of the method (i.e. the method is exposed
 // contribute to the dbus signature of the method (i.e. the method is exposed
 // as if the parameters of type Sender were not there).
 // as if the parameters of type Sender were not there).
 //
 //
+// Similarly, any parameters with the type Message are set to the raw message
+// received on the bus. Again, parameters of this type do not contribute to the
+// dbus signature of the method.
+//
 // Every method call is executed in a new goroutine, so the method may be called
 // Every method call is executed in a new goroutine, so the method may be called
 // in multiple goroutines at once.
 // in multiple goroutines at once.
 //
 //
@@ -214,10 +294,51 @@ func (conn *Conn) Emit(path ObjectPath, name string, values ...interface{}) erro
 //
 //
 // Export returns an error if path is not a valid path name.
 // Export returns an error if path is not a valid path name.
 func (conn *Conn) Export(v interface{}, path ObjectPath, iface string) error {
 func (conn *Conn) Export(v interface{}, path ObjectPath, iface string) error {
+	return conn.ExportWithMap(v, nil, path, iface)
+}
+
+// ExportWithMap works exactly like Export but provides the ability to remap
+// method names (e.g. export a lower-case method).
+//
+// The keys in the map are the real method names (exported on the struct), and
+// the values are the method names to be exported on DBus.
+func (conn *Conn) ExportWithMap(v interface{}, mapping map[string]string, path ObjectPath, iface string) error {
+	return conn.exportWithMap(v, mapping, path, iface, false)
+}
+
+// ExportSubtree works exactly like Export but registers the given value for
+// an entire subtree rather under the root path provided.
+//
+// In order to make this useful, one parameter in each of the value's exported
+// methods should be a Message, in which case it will contain the raw message
+// (allowing one to get access to the path that caused the method to be called).
+//
+// Note that more specific export paths take precedence over less specific. For
+// example, a method call using the ObjectPath /foo/bar/baz will call a method
+// exported on /foo/bar before a method exported on /foo.
+func (conn *Conn) ExportSubtree(v interface{}, path ObjectPath, iface string) error {
+	return conn.ExportSubtreeWithMap(v, nil, path, iface)
+}
+
+// ExportSubtreeWithMap works exactly like ExportSubtree but provides the
+// ability to remap method names (e.g. export a lower-case method).
+//
+// The keys in the map are the real method names (exported on the struct), and
+// the values are the method names to be exported on DBus.
+func (conn *Conn) ExportSubtreeWithMap(v interface{}, mapping map[string]string, path ObjectPath, iface string) error {
+	return conn.exportWithMap(v, mapping, path, iface, true)
+}
+
+// exportWithMap is the worker function for all exports/registrations.
+func (conn *Conn) exportWithMap(v interface{}, mapping map[string]string, path ObjectPath, iface string, includeSubtree bool) error {
 	if !path.IsValid() {
 	if !path.IsValid() {
-		return errors.New("dbus: invalid path name")
+		return fmt.Errorf(`dbus: Invalid path name: "%s"`, path)
 	}
 	}
+
 	conn.handlersLck.Lock()
 	conn.handlersLck.Lock()
+	defer conn.handlersLck.Unlock()
+
+	// Remove a previous export if the interface is nil
 	if v == nil {
 	if v == nil {
 		if _, ok := conn.handlers[path]; ok {
 		if _, ok := conn.handlers[path]; ok {
 			delete(conn.handlers[path], iface)
 			delete(conn.handlers[path], iface)
@@ -225,51 +346,39 @@ func (conn *Conn) Export(v interface{}, path ObjectPath, iface string) error {
 				delete(conn.handlers, path)
 				delete(conn.handlers, path)
 			}
 			}
 		}
 		}
+
 		return nil
 		return nil
 	}
 	}
+
+	// If this is the first handler for this path, make a new map to hold all
+	// handlers for this path.
 	if _, ok := conn.handlers[path]; !ok {
 	if _, ok := conn.handlers[path]; !ok {
-		conn.handlers[path] = make(map[string]interface{})
+		conn.handlers[path] = make(map[string]exportWithMapping)
 	}
 	}
-	conn.handlers[path][iface] = v
-	conn.handlersLck.Unlock()
+
+	// Finally, save this handler
+	conn.handlers[path][iface] = exportWithMapping{export: v, mapping: mapping, includeSubtree: includeSubtree}
+
 	return nil
 	return nil
 }
 }
 
 
-// ReleaseName calls org.freedesktop.DBus.ReleaseName. You should use only this
-// method to release a name (see below).
+// ReleaseName calls org.freedesktop.DBus.ReleaseName and awaits a response.
 func (conn *Conn) ReleaseName(name string) (ReleaseNameReply, error) {
 func (conn *Conn) ReleaseName(name string) (ReleaseNameReply, error) {
 	var r uint32
 	var r uint32
 	err := conn.busObj.Call("org.freedesktop.DBus.ReleaseName", 0, name).Store(&r)
 	err := conn.busObj.Call("org.freedesktop.DBus.ReleaseName", 0, name).Store(&r)
 	if err != nil {
 	if err != nil {
 		return 0, err
 		return 0, err
 	}
 	}
-	if r == uint32(ReleaseNameReplyReleased) {
-		conn.namesLck.Lock()
-		for i, v := range conn.names {
-			if v == name {
-				copy(conn.names[i:], conn.names[i+1:])
-				conn.names = conn.names[:len(conn.names)-1]
-			}
-		}
-		conn.namesLck.Unlock()
-	}
 	return ReleaseNameReply(r), nil
 	return ReleaseNameReply(r), nil
 }
 }
 
 
-// RequestName calls org.freedesktop.DBus.RequestName. You should use only this
-// method to request a name because package dbus needs to keep track of all
-// names that the connection has.
+// RequestName calls org.freedesktop.DBus.RequestName and awaits a response.
 func (conn *Conn) RequestName(name string, flags RequestNameFlags) (RequestNameReply, error) {
 func (conn *Conn) RequestName(name string, flags RequestNameFlags) (RequestNameReply, error) {
 	var r uint32
 	var r uint32
 	err := conn.busObj.Call("org.freedesktop.DBus.RequestName", 0, name, flags).Store(&r)
 	err := conn.busObj.Call("org.freedesktop.DBus.RequestName", 0, name, flags).Store(&r)
 	if err != nil {
 	if err != nil {
 		return 0, err
 		return 0, err
 	}
 	}
-	if r == uint32(RequestNameReplyPrimaryOwner) {
-		conn.namesLck.Lock()
-		conn.names = append(conn.names, name)
-		conn.namesLck.Unlock()
-	}
 	return RequestNameReply(r), nil
 	return RequestNameReply(r), nil
 }
 }
 
 

+ 126 - 0
vendor/src/github.com/godbus/dbus/object.go

@@ -0,0 +1,126 @@
+package dbus
+
+import (
+	"errors"
+	"strings"
+)
+
+// BusObject is the interface of a remote object on which methods can be
+// invoked.
+type BusObject interface {
+	Call(method string, flags Flags, args ...interface{}) *Call
+	Go(method string, flags Flags, ch chan *Call, args ...interface{}) *Call
+	GetProperty(p string) (Variant, error)
+	Destination() string
+	Path() ObjectPath
+}
+
+// Object represents a remote object on which methods can be invoked.
+type Object struct {
+	conn *Conn
+	dest string
+	path ObjectPath
+}
+
+// Call calls a method with (*Object).Go and waits for its reply.
+func (o *Object) Call(method string, flags Flags, args ...interface{}) *Call {
+	return <-o.Go(method, flags, make(chan *Call, 1), args...).Done
+}
+
+// Go calls a method with the given arguments asynchronously. It returns a
+// Call structure representing this method call. The passed channel will
+// return the same value once the call is done. If ch is nil, a new channel
+// will be allocated. Otherwise, ch has to be buffered or Go will panic.
+//
+// If the flags include FlagNoReplyExpected, ch is ignored and a Call structure
+// is returned of which only the Err member is valid.
+//
+// If the method parameter contains a dot ('.'), the part before the last dot
+// specifies the interface on which the method is called.
+func (o *Object) Go(method string, flags Flags, ch chan *Call, args ...interface{}) *Call {
+	iface := ""
+	i := strings.LastIndex(method, ".")
+	if i != -1 {
+		iface = method[:i]
+	}
+	method = method[i+1:]
+	msg := new(Message)
+	msg.Type = TypeMethodCall
+	msg.serial = o.conn.getSerial()
+	msg.Flags = flags & (FlagNoAutoStart | FlagNoReplyExpected)
+	msg.Headers = make(map[HeaderField]Variant)
+	msg.Headers[FieldPath] = MakeVariant(o.path)
+	msg.Headers[FieldDestination] = MakeVariant(o.dest)
+	msg.Headers[FieldMember] = MakeVariant(method)
+	if iface != "" {
+		msg.Headers[FieldInterface] = MakeVariant(iface)
+	}
+	msg.Body = args
+	if len(args) > 0 {
+		msg.Headers[FieldSignature] = MakeVariant(SignatureOf(args...))
+	}
+	if msg.Flags&FlagNoReplyExpected == 0 {
+		if ch == nil {
+			ch = make(chan *Call, 10)
+		} else if cap(ch) == 0 {
+			panic("dbus: unbuffered channel passed to (*Object).Go")
+		}
+		call := &Call{
+			Destination: o.dest,
+			Path:        o.path,
+			Method:      method,
+			Args:        args,
+			Done:        ch,
+		}
+		o.conn.callsLck.Lock()
+		o.conn.calls[msg.serial] = call
+		o.conn.callsLck.Unlock()
+		o.conn.outLck.RLock()
+		if o.conn.closed {
+			call.Err = ErrClosed
+			call.Done <- call
+		} else {
+			o.conn.out <- msg
+		}
+		o.conn.outLck.RUnlock()
+		return call
+	}
+	o.conn.outLck.RLock()
+	defer o.conn.outLck.RUnlock()
+	if o.conn.closed {
+		return &Call{Err: ErrClosed}
+	}
+	o.conn.out <- msg
+	return &Call{Err: nil}
+}
+
+// GetProperty calls org.freedesktop.DBus.Properties.GetProperty on the given
+// object. The property name must be given in interface.member notation.
+func (o *Object) GetProperty(p string) (Variant, error) {
+	idx := strings.LastIndex(p, ".")
+	if idx == -1 || idx+1 == len(p) {
+		return Variant{}, errors.New("dbus: invalid property " + p)
+	}
+
+	iface := p[:idx]
+	prop := p[idx+1:]
+
+	result := Variant{}
+	err := o.Call("org.freedesktop.DBus.Properties.Get", 0, iface, prop).Store(&result)
+
+	if err != nil {
+		return Variant{}, err
+	}
+
+	return result, nil
+}
+
+// Destination returns the destination that calls on o are sent to.
+func (o *Object) Destination() string {
+	return o.dest
+}
+
+// Path returns the path that calls on o are sent to.
+func (o *Object) Path() ObjectPath {
+	return o.path
+}

+ 1 - 1
vendor/src/github.com/golang/protobuf/proto/Makefile

@@ -39,5 +39,5 @@ test: install generate-test-pbs
 generate-test-pbs:
 generate-test-pbs:
 	make install
 	make install
 	make -C testdata
 	make -C testdata
-	protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata:. proto3_proto/proto3.proto
+	make -C proto3_proto
 	make
 	make

+ 4 - 6
vendor/src/github.com/golang/protobuf/proto/encode.go

@@ -1128,12 +1128,10 @@ func size_new_map(p *Properties, base structPointer) int {
 		keycopy.Set(key)
 		keycopy.Set(key)
 		valcopy.Set(val)
 		valcopy.Set(val)
 
 
-		// Tag codes for key and val are the responsibility of the sub-sizer.
-		keysize := p.mkeyprop.size(p.mkeyprop, keybase)
-		valsize := p.mvalprop.size(p.mvalprop, valbase)
-		entry := keysize + valsize
-		// Add on tag code and length of map entry itself.
-		n += len(p.tagcode) + sizeVarint(uint64(entry)) + entry
+		// Tag codes are two bytes per map entry.
+		n += 2
+		n += p.mkeyprop.size(p.mkeyprop, keybase)
+		n += p.mvalprop.size(p.mvalprop, valbase)
 	}
 	}
 	return n
 	return n
 }
 }

+ 13 - 44
vendor/src/github.com/golang/protobuf/proto/lib.go

@@ -607,15 +607,13 @@ func setDefaults(v reflect.Value, recur, zeros bool) {
 
 
 	for _, ni := range dm.nested {
 	for _, ni := range dm.nested {
 		f := v.Field(ni)
 		f := v.Field(ni)
-		// f is *T or []*T or map[T]*T
-		switch f.Kind() {
-		case reflect.Ptr:
-			if f.IsNil() {
-				continue
-			}
+		if f.IsNil() {
+			continue
+		}
+		// f is *T or []*T
+		if f.Kind() == reflect.Ptr {
 			setDefaults(f, recur, zeros)
 			setDefaults(f, recur, zeros)
-
-		case reflect.Slice:
+		} else {
 			for i := 0; i < f.Len(); i++ {
 			for i := 0; i < f.Len(); i++ {
 				e := f.Index(i)
 				e := f.Index(i)
 				if e.IsNil() {
 				if e.IsNil() {
@@ -623,15 +621,6 @@ func setDefaults(v reflect.Value, recur, zeros bool) {
 				}
 				}
 				setDefaults(e, recur, zeros)
 				setDefaults(e, recur, zeros)
 			}
 			}
-
-		case reflect.Map:
-			for _, k := range f.MapKeys() {
-				e := f.MapIndex(k)
-				if e.IsNil() {
-					continue
-				}
-				setDefaults(e, recur, zeros)
-			}
 		}
 		}
 	}
 	}
 }
 }
@@ -657,6 +646,10 @@ type scalarField struct {
 	value interface{}  // the proto-declared default value, or nil
 	value interface{}  // the proto-declared default value, or nil
 }
 }
 
 
+func ptrToStruct(t reflect.Type) bool {
+	return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
+}
+
 // t is a struct type.
 // t is a struct type.
 func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
 func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
 	sprop := GetProperties(t)
 	sprop := GetProperties(t)
@@ -668,33 +661,9 @@ func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
 		}
 		}
 		ft := t.Field(fi).Type
 		ft := t.Field(fi).Type
 
 
-		var canHaveDefault, nestedMessage bool
-		switch ft.Kind() {
-		case reflect.Ptr:
-			if ft.Elem().Kind() == reflect.Struct {
-				nestedMessage = true
-			} else {
-				canHaveDefault = true // proto2 scalar field
-			}
-
-		case reflect.Slice:
-			switch ft.Elem().Kind() {
-			case reflect.Ptr:
-				nestedMessage = true // repeated message
-			case reflect.Uint8:
-				canHaveDefault = true // bytes field
-			}
-
-		case reflect.Map:
-			if ft.Elem().Kind() == reflect.Ptr {
-				nestedMessage = true // map with message values
-			}
-		}
-
-		if !canHaveDefault {
-			if nestedMessage {
-				dm.nested = append(dm.nested, fi)
-			}
+		// nested messages
+		if ptrToStruct(ft) || (ft.Kind() == reflect.Slice && ptrToStruct(ft.Elem())) {
+			dm.nested = append(dm.nested, fi)
 			continue
 			continue
 		}
 		}
 
 

+ 1 - 6
vendor/src/github.com/golang/protobuf/proto/properties.go

@@ -440,12 +440,7 @@ func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lock
 			p.enc = (*Buffer).enc_slice_byte
 			p.enc = (*Buffer).enc_slice_byte
 			p.dec = (*Buffer).dec_slice_byte
 			p.dec = (*Buffer).dec_slice_byte
 			p.size = size_slice_byte
 			p.size = size_slice_byte
-			// This is a []byte, which is either a bytes field,
-			// or the value of a map field. In the latter case,
-			// we always encode an empty []byte, so we should not
-			// use the proto3 enc/size funcs.
-			// f == nil iff this is the key/value of a map field.
-			if p.proto3 && f != nil {
+			if p.proto3 {
 				p.enc = (*Buffer).enc_proto3_slice_byte
 				p.enc = (*Buffer).enc_proto3_slice_byte
 				p.size = size_proto3_slice_byte
 				p.size = size_proto3_slice_byte
 			}
 			}

+ 6 - 6
vendor/src/github.com/opencontainers/runc/libcontainer/SPEC.md

@@ -97,12 +97,12 @@ that is local to the container's rootfs.
 After the container has `/proc` mounted a few standard symlinks are setup 
 After the container has `/proc` mounted a few standard symlinks are setup 
 within `/dev/` for the io.
 within `/dev/` for the io.
 
 
-|    Source    | Destination |
-| ------------ | ----------- |
-| /proc/1/fd   | /dev/fd     |
-| /proc/1/fd/0 | /dev/stdin  |
-| /proc/1/fd/1 | /dev/stdout |
-| /proc/1/fd/2 | /dev/stderr |
+|    Source       | Destination |
+| --------------- | ----------- |
+| /proc/self/fd   | /dev/fd     |
+| /proc/self/fd/0 | /dev/stdin  |
+| /proc/self/fd/1 | /dev/stdout |
+| /proc/self/fd/2 | /dev/stderr |
 
 
 A `pivot_root` is used to change the root for the process, effectively 
 A `pivot_root` is used to change the root for the process, effectively 
 jailing the process inside the rootfs.
 jailing the process inside the rootfs.

+ 66 - 49
vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/apply_raw.go

@@ -3,6 +3,7 @@
 package fs
 package fs
 
 
 import (
 import (
+	"errors"
 	"fmt"
 	"fmt"
 	"io"
 	"io"
 	"io/ioutil"
 	"io/ioutil"
@@ -16,30 +17,45 @@ import (
 )
 )
 
 
 var (
 var (
-	subsystems = map[string]subsystem{
-		"devices":    &DevicesGroup{},
-		"memory":     &MemoryGroup{},
-		"cpu":        &CpuGroup{},
-		"cpuset":     &CpusetGroup{},
-		"cpuacct":    &CpuacctGroup{},
-		"blkio":      &BlkioGroup{},
-		"hugetlb":    &HugetlbGroup{},
-		"net_cls":    &NetClsGroup{},
-		"net_prio":   &NetPrioGroup{},
-		"perf_event": &PerfEventGroup{},
-		"freezer":    &FreezerGroup{},
+	subsystems = subsystemSet{
+		&CpusetGroup{},
+		&DevicesGroup{},
+		&MemoryGroup{},
+		&CpuGroup{},
+		&CpuacctGroup{},
+		&BlkioGroup{},
+		&HugetlbGroup{},
+		&NetClsGroup{},
+		&NetPrioGroup{},
+		&PerfEventGroup{},
+		&FreezerGroup{},
 	}
 	}
 	CgroupProcesses  = "cgroup.procs"
 	CgroupProcesses  = "cgroup.procs"
 	HugePageSizes, _ = cgroups.GetHugePageSize()
 	HugePageSizes, _ = cgroups.GetHugePageSize()
 )
 )
 
 
+var errSubsystemDoesNotExist = errors.New("cgroup: subsystem does not exist")
+
+type subsystemSet []subsystem
+
+func (s subsystemSet) Get(name string) (subsystem, error) {
+	for _, ss := range s {
+		if ss.Name() == name {
+			return ss, nil
+		}
+	}
+	return nil, errSubsystemDoesNotExist
+}
+
 type subsystem interface {
 type subsystem interface {
+	// Name returns the name of the subsystem.
+	Name() string
 	// Returns the stats, as 'stats', corresponding to the cgroup under 'path'.
 	// Returns the stats, as 'stats', corresponding to the cgroup under 'path'.
 	GetStats(path string, stats *cgroups.Stats) error
 	GetStats(path string, stats *cgroups.Stats) error
-	// Removes the cgroup represented by 'data'.
-	Remove(*data) error
-	// Creates and joins the cgroup represented by data.
-	Apply(*data) error
+	// Removes the cgroup represented by 'cgroupData'.
+	Remove(*cgroupData) error
+	// Creates and joins the cgroup represented by 'cgroupData'.
+	Apply(*cgroupData) error
 	// Set the cgroup represented by cgroup.
 	// Set the cgroup represented by cgroup.
 	Set(path string, cgroup *configs.Cgroup) error
 	Set(path string, cgroup *configs.Cgroup) error
 }
 }
@@ -76,10 +92,11 @@ func getCgroupRoot() (string, error) {
 	return cgroupRoot, nil
 	return cgroupRoot, nil
 }
 }
 
 
-type data struct {
+type cgroupData struct {
 	root   string
 	root   string
-	cgroup string
-	c      *configs.Cgroup
+	parent string
+	name   string
+	config *configs.Cgroup
 	pid    int
 	pid    int
 }
 }
 
 
@@ -101,21 +118,21 @@ func (m *Manager) Apply(pid int) (err error) {
 			cgroups.RemovePaths(paths)
 			cgroups.RemovePaths(paths)
 		}
 		}
 	}()
 	}()
-	for name, sys := range subsystems {
+	for _, sys := range subsystems {
 		if err := sys.Apply(d); err != nil {
 		if err := sys.Apply(d); err != nil {
 			return err
 			return err
 		}
 		}
 		// TODO: Apply should, ideally, be reentrant or be broken up into a separate
 		// TODO: Apply should, ideally, be reentrant or be broken up into a separate
 		// create and join phase so that the cgroup hierarchy for a container can be
 		// create and join phase so that the cgroup hierarchy for a container can be
 		// created then join consists of writing the process pids to cgroup.procs
 		// created then join consists of writing the process pids to cgroup.procs
-		p, err := d.path(name)
+		p, err := d.path(sys.Name())
 		if err != nil {
 		if err != nil {
 			if cgroups.IsNotFound(err) {
 			if cgroups.IsNotFound(err) {
 				continue
 				continue
 			}
 			}
 			return err
 			return err
 		}
 		}
-		paths[name] = p
+		paths[sys.Name()] = p
 	}
 	}
 	m.Paths = paths
 	m.Paths = paths
 
 
@@ -150,29 +167,27 @@ func (m *Manager) GetStats() (*cgroups.Stats, error) {
 	defer m.mu.Unlock()
 	defer m.mu.Unlock()
 	stats := cgroups.NewStats()
 	stats := cgroups.NewStats()
 	for name, path := range m.Paths {
 	for name, path := range m.Paths {
-		sys, ok := subsystems[name]
-		if !ok || !cgroups.PathExists(path) {
+		sys, err := subsystems.Get(name)
+		if err == errSubsystemDoesNotExist || !cgroups.PathExists(path) {
 			continue
 			continue
 		}
 		}
 		if err := sys.GetStats(path, stats); err != nil {
 		if err := sys.GetStats(path, stats); err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
 	}
 	}
-
 	return stats, nil
 	return stats, nil
 }
 }
 
 
 func (m *Manager) Set(container *configs.Config) error {
 func (m *Manager) Set(container *configs.Config) error {
 	for name, path := range m.Paths {
 	for name, path := range m.Paths {
-		sys, ok := subsystems[name]
-		if !ok || !cgroups.PathExists(path) {
+		sys, err := subsystems.Get(name)
+		if err == errSubsystemDoesNotExist || !cgroups.PathExists(path) {
 			continue
 			continue
 		}
 		}
 		if err := sys.Set(path, container.Cgroups); err != nil {
 		if err := sys.Set(path, container.Cgroups); err != nil {
 			return err
 			return err
 		}
 		}
 	}
 	}
-
 	return nil
 	return nil
 }
 }
 
 
@@ -183,22 +198,21 @@ func (m *Manager) Freeze(state configs.FreezerState) error {
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-
 	dir, err := d.path("freezer")
 	dir, err := d.path("freezer")
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-
 	prevState := m.Cgroups.Freezer
 	prevState := m.Cgroups.Freezer
 	m.Cgroups.Freezer = state
 	m.Cgroups.Freezer = state
-
-	freezer := subsystems["freezer"]
+	freezer, err := subsystems.Get("freezer")
+	if err != nil {
+		return err
+	}
 	err = freezer.Set(dir, m.Cgroups)
 	err = freezer.Set(dir, m.Cgroups)
 	if err != nil {
 	if err != nil {
 		m.Cgroups.Freezer = prevState
 		m.Cgroups.Freezer = prevState
 		return err
 		return err
 	}
 	}
-
 	return nil
 	return nil
 }
 }
 
 
@@ -216,30 +230,31 @@ func (m *Manager) GetPids() ([]int, error) {
 	return cgroups.GetPids(dir)
 	return cgroups.GetPids(dir)
 }
 }
 
 
-func getCgroupData(c *configs.Cgroup, pid int) (*data, error) {
+func getCgroupData(c *configs.Cgroup, pid int) (*cgroupData, error) {
 	root, err := getCgroupRoot()
 	root, err := getCgroupRoot()
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	cgroup := c.Name
-	if c.Parent != "" {
-		cgroup = filepath.Join(c.Parent, cgroup)
-	}
-
-	return &data{
+	return &cgroupData{
 		root:   root,
 		root:   root,
-		cgroup: cgroup,
-		c:      c,
+		parent: c.Parent,
+		name:   c.Name,
+		config: c,
 		pid:    pid,
 		pid:    pid,
 	}, nil
 	}, nil
 }
 }
 
 
-func (raw *data) parent(subsystem, mountpoint, root string) (string, error) {
+func (raw *cgroupData) parentPath(subsystem, mountpoint, root string) (string, error) {
+	// Use GetThisCgroupDir instead of GetInitCgroupDir, because the creating
+	// process could in container and shared pid namespace with host, and
+	// /proc/1/cgroup could point to whole other world of cgroups.
 	initPath, err := cgroups.GetThisCgroupDir(subsystem)
 	initPath, err := cgroups.GetThisCgroupDir(subsystem)
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
+	// This is needed for nested containers, because in /proc/self/cgroup we
+	// see pathes from host, which don't exist in container.
 	relDir, err := filepath.Rel(root, initPath)
 	relDir, err := filepath.Rel(root, initPath)
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
@@ -247,27 +262,29 @@ func (raw *data) parent(subsystem, mountpoint, root string) (string, error) {
 	return filepath.Join(mountpoint, relDir), nil
 	return filepath.Join(mountpoint, relDir), nil
 }
 }
 
 
-func (raw *data) path(subsystem string) (string, error) {
+func (raw *cgroupData) path(subsystem string) (string, error) {
 	mnt, root, err := cgroups.FindCgroupMountpointAndRoot(subsystem)
 	mnt, root, err := cgroups.FindCgroupMountpointAndRoot(subsystem)
 	// If we didn't mount the subsystem, there is no point we make the path.
 	// If we didn't mount the subsystem, there is no point we make the path.
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
 
 
+	cgPath := filepath.Join(raw.parent, raw.name)
 	// If the cgroup name/path is absolute do not look relative to the cgroup of the init process.
 	// If the cgroup name/path is absolute do not look relative to the cgroup of the init process.
-	if filepath.IsAbs(raw.cgroup) {
-		return filepath.Join(raw.root, filepath.Base(mnt), raw.cgroup), nil
+	if filepath.IsAbs(cgPath) {
+		// Sometimes subsystems can be mounted togethger as 'cpu,cpuacct'.
+		return filepath.Join(raw.root, filepath.Base(mnt), cgPath), nil
 	}
 	}
 
 
-	parent, err := raw.parent(subsystem, mnt, root)
+	parentPath, err := raw.parentPath(subsystem, mnt, root)
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
 
 
-	return filepath.Join(parent, raw.cgroup), nil
+	return filepath.Join(parentPath, cgPath), nil
 }
 }
 
 
-func (raw *data) join(subsystem string) (string, error) {
+func (raw *cgroupData) join(subsystem string) (string, error) {
 	path, err := raw.path(subsystem)
 	path, err := raw.path(subsystem)
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err

+ 7 - 3
vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/blkio.go

@@ -17,13 +17,17 @@ import (
 type BlkioGroup struct {
 type BlkioGroup struct {
 }
 }
 
 
-func (s *BlkioGroup) Apply(d *data) error {
+func (s *BlkioGroup) Name() string {
+	return "blkio"
+}
+
+func (s *BlkioGroup) Apply(d *cgroupData) error {
 	dir, err := d.join("blkio")
 	dir, err := d.join("blkio")
 	if err != nil && !cgroups.IsNotFound(err) {
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 		return err
 	}
 	}
 
 
-	if err := s.Set(dir, d.c); err != nil {
+	if err := s.Set(dir, d.config); err != nil {
 		return err
 		return err
 	}
 	}
 
 
@@ -74,7 +78,7 @@ func (s *BlkioGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *BlkioGroup) Remove(d *data) error {
+func (s *BlkioGroup) Remove(d *cgroupData) error {
 	return removePath(d.path("blkio"))
 	return removePath(d.path("blkio"))
 }
 }
 
 

+ 7 - 3
vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go

@@ -15,7 +15,11 @@ import (
 type CpuGroup struct {
 type CpuGroup struct {
 }
 }
 
 
-func (s *CpuGroup) Apply(d *data) error {
+func (s *CpuGroup) Name() string {
+	return "cpu"
+}
+
+func (s *CpuGroup) Apply(d *cgroupData) 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")
@@ -23,7 +27,7 @@ func (s *CpuGroup) Apply(d *data) error {
 		return err
 		return err
 	}
 	}
 
 
-	if err := s.Set(dir, d.c); err != nil {
+	if err := s.Set(dir, d.config); err != nil {
 		return err
 		return err
 	}
 	}
 
 
@@ -60,7 +64,7 @@ func (s *CpuGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *CpuGroup) Remove(d *data) error {
+func (s *CpuGroup) Remove(d *cgroupData) error {
 	return removePath(d.path("cpu"))
 	return removePath(d.path("cpu"))
 }
 }
 
 

+ 6 - 2
vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuacct.go

@@ -24,7 +24,11 @@ var clockTicks = uint64(system.GetClockTicks())
 type CpuacctGroup struct {
 type CpuacctGroup struct {
 }
 }
 
 
-func (s *CpuacctGroup) Apply(d *data) error {
+func (s *CpuacctGroup) Name() string {
+	return "cpuacct"
+}
+
+func (s *CpuacctGroup) Apply(d *cgroupData) 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 && !cgroups.IsNotFound(err) {
 	if _, err := d.join("cpuacct"); err != nil && !cgroups.IsNotFound(err) {
 		return err
 		return err
@@ -37,7 +41,7 @@ func (s *CpuacctGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *CpuacctGroup) Remove(d *data) error {
+func (s *CpuacctGroup) Remove(d *cgroupData) error {
 	return removePath(d.path("cpuacct"))
 	return removePath(d.path("cpuacct"))
 }
 }
 
 

+ 12 - 9
vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset.go

@@ -16,12 +16,16 @@ import (
 type CpusetGroup struct {
 type CpusetGroup struct {
 }
 }
 
 
-func (s *CpusetGroup) Apply(d *data) error {
+func (s *CpusetGroup) Name() string {
+	return "cpuset"
+}
+
+func (s *CpusetGroup) Apply(d *cgroupData) error {
 	dir, err := d.path("cpuset")
 	dir, err := d.path("cpuset")
 	if err != nil && !cgroups.IsNotFound(err) {
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 		return err
 	}
 	}
-	return s.ApplyDir(dir, d.c, d.pid)
+	return s.ApplyDir(dir, d.config, d.pid)
 }
 }
 
 
 func (s *CpusetGroup) Set(path string, cgroup *configs.Cgroup) error {
 func (s *CpusetGroup) Set(path string, cgroup *configs.Cgroup) error {
@@ -38,7 +42,7 @@ func (s *CpusetGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *CpusetGroup) Remove(d *data) error {
+func (s *CpusetGroup) Remove(d *cgroupData) error {
 	return removePath(d.path("cpuset"))
 	return removePath(d.path("cpuset"))
 }
 }
 
 
@@ -59,17 +63,16 @@ func (s *CpusetGroup) ApplyDir(dir string, cgroup *configs.Cgroup, pid int) erro
 	if err := s.ensureParent(dir, root); err != nil {
 	if err := s.ensureParent(dir, root); err != nil {
 		return err
 		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 {
-		return err
-	}
-
 	// the default values inherit from parent cgroup are already set in
 	// the default values inherit from parent cgroup are already set in
 	// s.ensureParent, cover these if we have our own
 	// s.ensureParent, cover these if we have our own
 	if err := s.Set(dir, cgroup); err != nil {
 	if err := s.Set(dir, cgroup); err != nil {
 		return err
 		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 {
+		return err
+	}
 
 
 	return nil
 	return nil
 }
 }

+ 7 - 3
vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices.go

@@ -10,7 +10,11 @@ import (
 type DevicesGroup struct {
 type DevicesGroup struct {
 }
 }
 
 
-func (s *DevicesGroup) Apply(d *data) error {
+func (s *DevicesGroup) Name() string {
+	return "devices"
+}
+
+func (s *DevicesGroup) Apply(d *cgroupData) error {
 	dir, err := d.join("devices")
 	dir, err := d.join("devices")
 	if err != nil {
 	if err != nil {
 		// We will return error even it's `not found` error, devices
 		// We will return error even it's `not found` error, devices
@@ -18,7 +22,7 @@ func (s *DevicesGroup) Apply(d *data) error {
 		return err
 		return err
 	}
 	}
 
 
-	if err := s.Set(dir, d.c); err != nil {
+	if err := s.Set(dir, d.config); err != nil {
 		return err
 		return err
 	}
 	}
 
 
@@ -52,7 +56,7 @@ func (s *DevicesGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *DevicesGroup) Remove(d *data) error {
+func (s *DevicesGroup) Remove(d *cgroupData) error {
 	return removePath(d.path("devices"))
 	return removePath(d.path("devices"))
 }
 }
 
 

+ 7 - 3
vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer.go

@@ -14,13 +14,17 @@ import (
 type FreezerGroup struct {
 type FreezerGroup struct {
 }
 }
 
 
-func (s *FreezerGroup) Apply(d *data) error {
+func (s *FreezerGroup) Name() string {
+	return "freezer"
+}
+
+func (s *FreezerGroup) Apply(d *cgroupData) error {
 	dir, err := d.join("freezer")
 	dir, err := d.join("freezer")
 	if err != nil && !cgroups.IsNotFound(err) {
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 		return err
 	}
 	}
 
 
-	if err := s.Set(dir, d.c); err != nil {
+	if err := s.Set(dir, d.config); err != nil {
 		return err
 		return err
 	}
 	}
 
 
@@ -53,7 +57,7 @@ func (s *FreezerGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *FreezerGroup) Remove(d *data) error {
+func (s *FreezerGroup) Remove(d *cgroupData) error {
 	return removePath(d.path("freezer"))
 	return removePath(d.path("freezer"))
 }
 }
 
 

+ 7 - 3
vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/hugetlb.go

@@ -14,13 +14,17 @@ import (
 type HugetlbGroup struct {
 type HugetlbGroup struct {
 }
 }
 
 
-func (s *HugetlbGroup) Apply(d *data) error {
+func (s *HugetlbGroup) Name() string {
+	return "hugetlb"
+}
+
+func (s *HugetlbGroup) Apply(d *cgroupData) error {
 	dir, err := d.join("hugetlb")
 	dir, err := d.join("hugetlb")
 	if err != nil && !cgroups.IsNotFound(err) {
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 		return err
 	}
 	}
 
 
-	if err := s.Set(dir, d.c); err != nil {
+	if err := s.Set(dir, d.config); err != nil {
 		return err
 		return err
 	}
 	}
 
 
@@ -37,7 +41,7 @@ func (s *HugetlbGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *HugetlbGroup) Remove(d *data) error {
+func (s *HugetlbGroup) Remove(d *cgroupData) error {
 	return removePath(d.path("hugetlb"))
 	return removePath(d.path("hugetlb"))
 }
 }
 
 

+ 28 - 13
vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go

@@ -17,16 +17,25 @@ import (
 type MemoryGroup struct {
 type MemoryGroup struct {
 }
 }
 
 
-func (s *MemoryGroup) Apply(d *data) (err error) {
+func (s *MemoryGroup) Name() string {
+	return "memory"
+}
+
+func (s *MemoryGroup) Apply(d *cgroupData) (err error) {
 	path, err := d.path("memory")
 	path, err := d.path("memory")
-	if err != nil {
-		if cgroups.IsNotFound(err) {
-			return nil
-		}
+	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 		return err
 	}
 	}
-	if err := os.MkdirAll(path, 0755); err != nil {
-		return err
+	if memoryAssigned(d.config) {
+		if path != "" {
+			if err := os.MkdirAll(path, 0755); err != nil {
+				return err
+			}
+		}
+
+		if err := s.Set(path, d.config); err != nil {
+			return err
+		}
 	}
 	}
 
 
 	defer func() {
 	defer func() {
@@ -35,13 +44,10 @@ func (s *MemoryGroup) Apply(d *data) (err error) {
 		}
 		}
 	}()
 	}()
 
 
-	if err := s.Set(path, d.c); err != nil {
-		return err
-	}
-
 	// We need to join memory cgroup after set memory limits, because
 	// We need to join memory cgroup after set memory limits, because
 	// kmem.limit_in_bytes can only be set when the cgroup is empty.
 	// kmem.limit_in_bytes can only be set when the cgroup is empty.
-	if _, err = d.join("memory"); err != nil {
+	_, err = d.join("memory")
+	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 		return err
 	}
 	}
 
 
@@ -88,7 +94,7 @@ func (s *MemoryGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *MemoryGroup) Remove(d *data) error {
+func (s *MemoryGroup) Remove(d *cgroupData) error {
 	return removePath(d.path("memory"))
 	return removePath(d.path("memory"))
 }
 }
 
 
@@ -132,6 +138,15 @@ func (s *MemoryGroup) GetStats(path string, stats *cgroups.Stats) error {
 	return nil
 	return nil
 }
 }
 
 
+func memoryAssigned(cgroup *configs.Cgroup) bool {
+	return cgroup.Memory != 0 ||
+		cgroup.MemoryReservation != 0 ||
+		cgroup.MemorySwap > 0 ||
+		cgroup.KernelMemory > 0 ||
+		cgroup.OomKillDisable ||
+		cgroup.MemorySwappiness != -1
+}
+
 func getMemoryData(path, name string) (cgroups.MemoryData, error) {
 func getMemoryData(path, name string) (cgroups.MemoryData, error) {
 	memoryData := cgroups.MemoryData{}
 	memoryData := cgroups.MemoryData{}
 
 

+ 9 - 2
vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/name.go

@@ -1,3 +1,5 @@
+// +build linux
+
 package fs
 package fs
 
 
 import (
 import (
@@ -6,9 +8,14 @@ import (
 )
 )
 
 
 type NameGroup struct {
 type NameGroup struct {
+	GroupName string
+}
+
+func (s *NameGroup) Name() string {
+	return s.GroupName
 }
 }
 
 
-func (s *NameGroup) Apply(d *data) error {
+func (s *NameGroup) Apply(d *cgroupData) error {
 	return nil
 	return nil
 }
 }
 
 
@@ -16,7 +23,7 @@ func (s *NameGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *NameGroup) Remove(d *data) error {
+func (s *NameGroup) Remove(d *cgroupData) error {
 	return nil
 	return nil
 }
 }
 
 

+ 9 - 3
vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_cls.go

@@ -1,3 +1,5 @@
+// +build linux
+
 package fs
 package fs
 
 
 import (
 import (
@@ -8,13 +10,17 @@ import (
 type NetClsGroup struct {
 type NetClsGroup struct {
 }
 }
 
 
-func (s *NetClsGroup) Apply(d *data) error {
+func (s *NetClsGroup) Name() string {
+	return "net_cls"
+}
+
+func (s *NetClsGroup) Apply(d *cgroupData) error {
 	dir, err := d.join("net_cls")
 	dir, err := d.join("net_cls")
 	if err != nil && !cgroups.IsNotFound(err) {
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 		return err
 	}
 	}
 
 
-	if err := s.Set(dir, d.c); err != nil {
+	if err := s.Set(dir, d.config); err != nil {
 		return err
 		return err
 	}
 	}
 
 
@@ -31,7 +37,7 @@ func (s *NetClsGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *NetClsGroup) Remove(d *data) error {
+func (s *NetClsGroup) Remove(d *cgroupData) error {
 	return removePath(d.path("net_cls"))
 	return removePath(d.path("net_cls"))
 }
 }
 
 

+ 9 - 3
vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_prio.go

@@ -1,3 +1,5 @@
+// +build linux
+
 package fs
 package fs
 
 
 import (
 import (
@@ -8,13 +10,17 @@ import (
 type NetPrioGroup struct {
 type NetPrioGroup struct {
 }
 }
 
 
-func (s *NetPrioGroup) Apply(d *data) error {
+func (s *NetPrioGroup) Name() string {
+	return "net_prio"
+}
+
+func (s *NetPrioGroup) Apply(d *cgroupData) error {
 	dir, err := d.join("net_prio")
 	dir, err := d.join("net_prio")
 	if err != nil && !cgroups.IsNotFound(err) {
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 		return err
 	}
 	}
 
 
-	if err := s.Set(dir, d.c); err != nil {
+	if err := s.Set(dir, d.config); err != nil {
 		return err
 		return err
 	}
 	}
 
 
@@ -31,7 +37,7 @@ func (s *NetPrioGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *NetPrioGroup) Remove(d *data) error {
+func (s *NetPrioGroup) Remove(d *cgroupData) error {
 	return removePath(d.path("net_prio"))
 	return removePath(d.path("net_prio"))
 }
 }
 
 

+ 6 - 2
vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/perf_event.go

@@ -10,7 +10,11 @@ import (
 type PerfEventGroup struct {
 type PerfEventGroup struct {
 }
 }
 
 
-func (s *PerfEventGroup) Apply(d *data) error {
+func (s *PerfEventGroup) Name() string {
+	return "perf_event"
+}
+
+func (s *PerfEventGroup) Apply(d *cgroupData) 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 && !cgroups.IsNotFound(err) {
 	if _, err := d.join("perf_event"); err != nil && !cgroups.IsNotFound(err) {
 		return err
 		return err
@@ -22,7 +26,7 @@ func (s *PerfEventGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 	return nil
 }
 }
 
 
-func (s *PerfEventGroup) Remove(d *data) error {
+func (s *PerfEventGroup) Remove(d *cgroupData) error {
 	return removePath(d.path("perf_event"))
 	return removePath(d.path("perf_event"))
 }
 }
 
 

+ 8 - 3
vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/utils.go

@@ -44,7 +44,7 @@ func getCgroupParamKeyValue(t string) (string, uint64, error) {
 	case 2:
 	case 2:
 		value, err := parseUint(parts[1], 10, 64)
 		value, err := parseUint(parts[1], 10, 64)
 		if err != nil {
 		if err != nil {
-			return "", 0, fmt.Errorf("Unable to convert param value (%q) to uint64: %v", parts[1], err)
+			return "", 0, fmt.Errorf("unable to convert param value (%q) to uint64: %v", parts[1], err)
 		}
 		}
 
 
 		return parts[0], value, nil
 		return parts[0], value, nil
@@ -55,12 +55,17 @@ func getCgroupParamKeyValue(t string) (string, uint64, error) {
 
 
 // Gets a single uint64 value from the specified cgroup file.
 // Gets a single uint64 value from the specified cgroup file.
 func getCgroupParamUint(cgroupPath, cgroupFile string) (uint64, error) {
 func getCgroupParamUint(cgroupPath, cgroupFile string) (uint64, error) {
-	contents, err := ioutil.ReadFile(filepath.Join(cgroupPath, cgroupFile))
+	fileName := filepath.Join(cgroupPath, cgroupFile)
+	contents, err := ioutil.ReadFile(fileName)
 	if err != nil {
 	if err != nil {
 		return 0, err
 		return 0, err
 	}
 	}
 
 
-	return parseUint(strings.TrimSpace(string(contents)), 10, 64)
+	res, err := parseUint(strings.TrimSpace(string(contents)), 10, 64)
+	if err != nil {
+		return res, fmt.Errorf("unable to parse %q as a uint from Cgroup file %q", string(contents), fileName)
+	}
+	return res, nil
 }
 }
 
 
 // Gets a string value from the specified cgroup file
 // Gets a string value from the specified cgroup file

+ 64 - 36
vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_systemd.go

@@ -3,6 +3,7 @@
 package systemd
 package systemd
 
 
 import (
 import (
+	"errors"
 	"fmt"
 	"fmt"
 	"io/ioutil"
 	"io/ioutil"
 	"os"
 	"os"
@@ -27,25 +28,40 @@ type Manager struct {
 }
 }
 
 
 type subsystem interface {
 type subsystem interface {
+	// Name returns the name of the subsystem.
+	Name() string
 	// Returns the stats, as 'stats', corresponding to the cgroup under 'path'.
 	// Returns the stats, as 'stats', corresponding to the cgroup under 'path'.
 	GetStats(path string, stats *cgroups.Stats) error
 	GetStats(path string, stats *cgroups.Stats) error
 	// Set the cgroup represented by cgroup.
 	// Set the cgroup represented by cgroup.
 	Set(path string, cgroup *configs.Cgroup) error
 	Set(path string, cgroup *configs.Cgroup) error
 }
 }
 
 
-var subsystems = map[string]subsystem{
-	"devices":      &fs.DevicesGroup{},
-	"memory":       &fs.MemoryGroup{},
-	"cpu":          &fs.CpuGroup{},
-	"cpuset":       &fs.CpusetGroup{},
-	"cpuacct":      &fs.CpuacctGroup{},
-	"blkio":        &fs.BlkioGroup{},
-	"hugetlb":      &fs.HugetlbGroup{},
-	"perf_event":   &fs.PerfEventGroup{},
-	"freezer":      &fs.FreezerGroup{},
-	"net_prio":     &fs.NetPrioGroup{},
-	"net_cls":      &fs.NetClsGroup{},
-	"name=systemd": &fs.NameGroup{},
+var errSubsystemDoesNotExist = errors.New("cgroup: subsystem does not exist")
+
+type subsystemSet []subsystem
+
+func (s subsystemSet) Get(name string) (subsystem, error) {
+	for _, ss := range s {
+		if ss.Name() == name {
+			return ss, nil
+		}
+	}
+	return nil, errSubsystemDoesNotExist
+}
+
+var subsystems = subsystemSet{
+	&fs.CpusetGroup{},
+	&fs.DevicesGroup{},
+	&fs.MemoryGroup{},
+	&fs.CpuGroup{},
+	&fs.CpuacctGroup{},
+	&fs.BlkioGroup{},
+	&fs.HugetlbGroup{},
+	&fs.PerfEventGroup{},
+	&fs.FreezerGroup{},
+	&fs.NetPrioGroup{},
+	&fs.NetClsGroup{},
+	&fs.NameGroup{GroupName: "name=systemd"},
 }
 }
 
 
 const (
 const (
@@ -249,8 +265,8 @@ func (m *Manager) Apply(pid int) error {
 	}
 	}
 
 
 	paths := make(map[string]string)
 	paths := make(map[string]string)
-	for sysname := range subsystems {
-		subsystemPath, err := getSubsystemPath(m.Cgroups, sysname)
+	for _, s := range subsystems {
+		subsystemPath, err := getSubsystemPath(m.Cgroups, s.Name())
 		if err != nil {
 		if err != nil {
 			// Don't fail if a cgroup hierarchy was not found, just skip this subsystem
 			// Don't fail if a cgroup hierarchy was not found, just skip this subsystem
 			if cgroups.IsNotFound(err) {
 			if cgroups.IsNotFound(err) {
@@ -258,7 +274,7 @@ func (m *Manager) Apply(pid int) error {
 			}
 			}
 			return err
 			return err
 		}
 		}
-		paths[sysname] = subsystemPath
+		paths[s.Name()] = subsystemPath
 	}
 	}
 	m.Paths = paths
 	m.Paths = paths
 
 
@@ -347,8 +363,10 @@ func joinFreezer(c *configs.Cgroup, pid int) error {
 	if err != nil && !cgroups.IsNotFound(err) {
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 		return err
 	}
 	}
-
-	freezer := subsystems["freezer"]
+	freezer, err := subsystems.Get("freezer")
+	if err != nil {
+		return err
+	}
 	return freezer.Set(path, c)
 	return freezer.Set(path, c)
 }
 }
 
 
@@ -357,8 +375,10 @@ func joinNetPrio(c *configs.Cgroup, pid int) error {
 	if err != nil && !cgroups.IsNotFound(err) {
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 		return err
 	}
 	}
-	netPrio := subsystems["net_prio"]
-
+	netPrio, err := subsystems.Get("net_prio")
+	if err != nil {
+		return err
+	}
 	return netPrio.Set(path, c)
 	return netPrio.Set(path, c)
 }
 }
 
 
@@ -367,8 +387,10 @@ func joinNetCls(c *configs.Cgroup, pid int) error {
 	if err != nil && !cgroups.IsNotFound(err) {
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 		return err
 	}
 	}
-	netcls := subsystems["net_cls"]
-
+	netcls, err := subsystems.Get("net_cls")
+	if err != nil {
+		return err
+	}
 	return netcls.Set(path, c)
 	return netcls.Set(path, c)
 }
 }
 
 
@@ -396,17 +418,17 @@ func (m *Manager) Freeze(state configs.FreezerState) error {
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-
 	prevState := m.Cgroups.Freezer
 	prevState := m.Cgroups.Freezer
 	m.Cgroups.Freezer = state
 	m.Cgroups.Freezer = state
-
-	freezer := subsystems["freezer"]
+	freezer, err := subsystems.Get("freezer")
+	if err != nil {
+		return err
+	}
 	err = freezer.Set(path, m.Cgroups)
 	err = freezer.Set(path, m.Cgroups)
 	if err != nil {
 	if err != nil {
 		m.Cgroups.Freezer = prevState
 		m.Cgroups.Freezer = prevState
 		return err
 		return err
 	}
 	}
-
 	return nil
 	return nil
 }
 }
 
 
@@ -423,8 +445,8 @@ func (m *Manager) GetStats() (*cgroups.Stats, error) {
 	defer m.mu.Unlock()
 	defer m.mu.Unlock()
 	stats := cgroups.NewStats()
 	stats := cgroups.NewStats()
 	for name, path := range m.Paths {
 	for name, path := range m.Paths {
-		sys, ok := subsystems[name]
-		if !ok || !cgroups.PathExists(path) {
+		sys, err := subsystems.Get(name)
+		if err == errSubsystemDoesNotExist || !cgroups.PathExists(path) {
 			continue
 			continue
 		}
 		}
 		if err := sys.GetStats(path, stats); err != nil {
 		if err := sys.GetStats(path, stats); err != nil {
@@ -437,8 +459,8 @@ func (m *Manager) GetStats() (*cgroups.Stats, error) {
 
 
 func (m *Manager) Set(container *configs.Config) error {
 func (m *Manager) Set(container *configs.Config) error {
 	for name, path := range m.Paths {
 	for name, path := range m.Paths {
-		sys, ok := subsystems[name]
-		if !ok || !cgroups.PathExists(path) {
+		sys, err := subsystems.Get(name)
+		if err == errSubsystemDoesNotExist || !cgroups.PathExists(path) {
 			continue
 			continue
 		}
 		}
 		if err := sys.Set(path, container.Cgroups); err != nil {
 		if err := sys.Set(path, container.Cgroups); err != nil {
@@ -471,8 +493,10 @@ func joinDevices(c *configs.Cgroup, pid int) error {
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-
-	devices := subsystems["devices"]
+	devices, err := subsystems.Get("devices")
+	if err != nil {
+		return err
+	}
 	return devices.Set(path, c)
 	return devices.Set(path, c)
 }
 }
 
 
@@ -600,8 +624,10 @@ func joinHugetlb(c *configs.Cgroup, pid int) error {
 	if err != nil && !cgroups.IsNotFound(err) {
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 		return err
 	}
 	}
-
-	hugetlb := subsystems["hugetlb"]
+	hugetlb, err := subsystems.Get("hugetlb")
+	if err != nil {
+		return err
+	}
 	return hugetlb.Set(path, c)
 	return hugetlb.Set(path, c)
 }
 }
 
 
@@ -610,7 +636,9 @@ func joinPerfEvent(c *configs.Cgroup, pid int) error {
 	if err != nil && !cgroups.IsNotFound(err) {
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 		return err
 	}
 	}
-
-	perfEvent := subsystems["perf_event"]
+	perfEvent, err := subsystems.Get("perf_event")
+	if err != nil {
+		return err
+	}
 	return perfEvent.Set(path, c)
 	return perfEvent.Set(path, c)
 }
 }

+ 2 - 3
vendor/src/github.com/opencontainers/runc/libcontainer/configs/cgroup.go → vendor/src/github.com/opencontainers/runc/libcontainer/configs/cgroup_unix.go

@@ -1,3 +1,5 @@
+// +build linux freebsd
+
 package configs
 package configs
 
 
 type FreezerState string
 type FreezerState string
@@ -8,9 +10,6 @@ const (
 	Thawed    FreezerState = "THAWED"
 	Thawed    FreezerState = "THAWED"
 )
 )
 
 
-// TODO Windows: This can be factored out in the future as Cgroups are not
-// supported on the Windows platform.
-
 type Cgroup struct {
 type Cgroup struct {
 	Name string `json:"name"`
 	Name string `json:"name"`
 
 

+ 6 - 0
vendor/src/github.com/opencontainers/runc/libcontainer/configs/cgroup_windows.go

@@ -0,0 +1,6 @@
+package configs
+
+// TODO Windows: This can ultimately be entirely factored out on Windows as
+// cgroups are a Unix-specific construct.
+type Cgroup struct {
+}

+ 6 - 2
vendor/src/github.com/opencontainers/runc/libcontainer/configs/config.go

@@ -33,17 +33,18 @@ type Seccomp struct {
 type Action int
 type Action int
 
 
 const (
 const (
-	Kill Action = iota - 4
+	Kill Action = iota + 1
 	Errno
 	Errno
 	Trap
 	Trap
 	Allow
 	Allow
+	Trace
 )
 )
 
 
 // A comparison operator to be used when matching syscall arguments in Seccomp
 // A comparison operator to be used when matching syscall arguments in Seccomp
 type Operator int
 type Operator int
 
 
 const (
 const (
-	EqualTo Operator = iota
+	EqualTo Operator = iota + 1
 	NotEqualTo
 	NotEqualTo
 	GreaterThan
 	GreaterThan
 	GreaterThanOrEqualTo
 	GreaterThanOrEqualTo
@@ -183,6 +184,9 @@ type Hooks struct {
 	// but before the user supplied command is executed from init.
 	// but before the user supplied command is executed from init.
 	Prestart []Hook
 	Prestart []Hook
 
 
+	// Poststart commands are executed after the container init process starts.
+	Poststart []Hook
+
 	// Poststop commands are executed after the container init process exits.
 	// Poststop commands are executed after the container init process exits.
 	Poststop []Hook
 	Poststop []Hook
 }
 }

+ 2 - 0
vendor/src/github.com/opencontainers/runc/libcontainer/configs/namespaces_windows.go → vendor/src/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go

@@ -1,3 +1,5 @@
+// +build !linux,!freebsd
+
 package configs
 package configs
 
 
 // Namespace defines configuration for each namespace.  It specifies an
 // Namespace defines configuration for each namespace.  It specifies an

+ 6 - 53
vendor/src/github.com/opencontainers/runc/libcontainer/container.go

@@ -30,8 +30,9 @@ const (
 	Destroyed
 	Destroyed
 )
 )
 
 
-// State represents a running container's state
-type State struct {
+// BaseState represents the platform agnostic pieces relating to a
+// running container's state
+type BaseState struct {
 	// ID is the container ID.
 	// ID is the container ID.
 	ID string `json:"id"`
 	ID string `json:"id"`
 
 
@@ -41,27 +42,16 @@ type State struct {
 	// InitProcessStartTime is the init process start time.
 	// InitProcessStartTime is the init process start time.
 	InitProcessStartTime string `json:"init_process_start"`
 	InitProcessStartTime string `json:"init_process_start"`
 
 
-	// Path to all the cgroups setup for a container. Key is cgroup subsystem name
-	// with the value as the path.
-	CgroupPaths map[string]string `json:"cgroup_paths"`
-
-	// NamespacePaths are filepaths to the container's namespaces. Key is the namespace type
-	// with the value as the path.
-	NamespacePaths map[configs.NamespaceType]string `json:"namespace_paths"`
-
 	// Config is the container's configuration.
 	// Config is the container's configuration.
 	Config configs.Config `json:"config"`
 	Config configs.Config `json:"config"`
-
-	// Container's standard descriptors (std{in,out,err}), needed for checkpoint and restore
-	ExternalDescriptors []string `json:"external_descriptors,omitempty"`
 }
 }
 
 
 // A libcontainer container object.
 // A libcontainer container object.
 //
 //
 // Each container is thread-safe within the same process. Since a container can
 // 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
 // be destroyed by a separate process, any function may return that the container
-// was not found.
-type Container interface {
+// was not found. BaseContainer includes methods that are platform agnostic.
+type BaseContainer interface {
 	// Returns the ID of the container
 	// Returns the ID of the container
 	ID() string
 	ID() string
 
 
@@ -98,7 +88,7 @@ type Container interface {
 	// Systemerror - System error.
 	// Systemerror - System error.
 	Stats() (*Stats, error)
 	Stats() (*Stats, error)
 
 
-	// Set cgroup resources of container as configured
+	// Set resources of container as configured
 	//
 	//
 	// We can use this to change resources when containers are running.
 	// We can use this to change resources when containers are running.
 	//
 	//
@@ -116,18 +106,6 @@ type Container interface {
 	// Systemerror - System error.
 	// Systemerror - System error.
 	Start(process *Process) (err error)
 	Start(process *Process) (err error)
 
 
-	// Checkpoint checkpoints the running container's state to disk using the criu(8) utility.
-	//
-	// errors:
-	// Systemerror - System error.
-	Checkpoint(criuOpts *CriuOpts) error
-
-	// Restore restores the checkpointed container to a running state using the criu(8) utiity.
-	//
-	// errors:
-	// Systemerror - System error.
-	Restore(process *Process, criuOpts *CriuOpts) error
-
 	// Destroys the container after killing all running processes.
 	// Destroys the container after killing all running processes.
 	//
 	//
 	// Any event registrations are removed before the container is destroyed.
 	// Any event registrations are removed before the container is destroyed.
@@ -137,31 +115,6 @@ type Container interface {
 	// Systemerror - System error.
 	// Systemerror - System error.
 	Destroy() error
 	Destroy() 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:
-	// ContainerDestroyed - Container no longer exists,
-	// Systemerror - 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:
-	// ContainerDestroyed - Container no longer exists,
-	// Systemerror - System error.
-	Resume() error
-
-	// NotifyOOM returns a read-only channel signaling when the container receives an OOM notification.
-	//
-	// errors:
-	// Systemerror - System error.
-	NotifyOOM() (<-chan struct{}, error)
-
 	// Signal sends the provided signal code to the container's initial process.
 	// Signal sends the provided signal code to the container's initial process.
 	//
 	//
 	// errors:
 	// errors:

+ 112 - 9
vendor/src/github.com/opencontainers/runc/libcontainer/container_linux.go

@@ -9,6 +9,7 @@ import (
 	"os"
 	"os"
 	"os/exec"
 	"os/exec"
 	"path/filepath"
 	"path/filepath"
+	"reflect"
 	"strings"
 	"strings"
 	"sync"
 	"sync"
 	"syscall"
 	"syscall"
@@ -32,6 +33,73 @@ type linuxContainer struct {
 	initProcess   parentProcess
 	initProcess   parentProcess
 	criuPath      string
 	criuPath      string
 	m             sync.Mutex
 	m             sync.Mutex
+	criuVersion   int
+}
+
+// State represents a running container's state
+type State struct {
+	BaseState
+
+	// Platform specific fields below here
+
+	// Path to all the cgroups setup for a container. Key is cgroup subsystem name
+	// with the value as the path.
+	CgroupPaths map[string]string `json:"cgroup_paths"`
+
+	// NamespacePaths are filepaths to the container's namespaces. Key is the namespace type
+	// with the value as the path.
+	NamespacePaths map[configs.NamespaceType]string `json:"namespace_paths"`
+
+	// Container's standard descriptors (std{in,out,err}), needed for checkpoint and restore
+	ExternalDescriptors []string `json:"external_descriptors,omitempty"`
+}
+
+// A libcontainer container object.
+//
+// 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 {
+	BaseContainer
+
+	// Methods below here are platform specific
+
+	// Checkpoint checkpoints the running container's state to disk using the criu(8) utility.
+	//
+	// errors:
+	// Systemerror - System error.
+	Checkpoint(criuOpts *CriuOpts) error
+
+	// Restore restores the checkpointed container to a running state using the criu(8) utiity.
+	//
+	// errors:
+	// Systemerror - System error.
+	Restore(process *Process, criuOpts *CriuOpts) 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:
+	// ContainerDestroyed - Container no longer exists,
+	// Systemerror - 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:
+	// ContainerDestroyed - Container no longer exists,
+	// Systemerror - System error.
+	Resume() error
+
+	// NotifyOOM returns a read-only channel signaling when the container receives an OOM notification.
+	//
+	// errors:
+	// Systemerror - System error.
+	NotifyOOM() (<-chan struct{}, error)
 }
 }
 
 
 // ID returns the container's unique ID
 // ID returns the container's unique ID
@@ -111,10 +179,25 @@ func (c *linuxContainer) Start(process *Process) error {
 		}
 		}
 		return newSystemError(err)
 		return newSystemError(err)
 	}
 	}
-	process.ops = parent
 	if doInit {
 	if doInit {
 		c.updateState(parent)
 		c.updateState(parent)
 	}
 	}
+	if c.config.Hooks != nil {
+		s := configs.HookState{
+			Version: c.config.Version,
+			ID:      c.id,
+			Pid:     parent.pid(),
+			Root:    c.config.Rootfs,
+		}
+		for _, hook := range c.config.Hooks.Poststart {
+			if err := hook.Run(s); err != nil {
+				if err := parent.terminate(); err != nil {
+					logrus.Warn(err)
+				}
+				return newSystemError(err)
+			}
+		}
+	}
 	return nil
 	return nil
 }
 }
 
 
@@ -186,6 +269,7 @@ func (c *linuxContainer) newInitProcess(p *Process, cmd *exec.Cmd, parentPipe, c
 		manager:    c.cgroupManager,
 		manager:    c.cgroupManager,
 		config:     c.newInitConfig(p),
 		config:     c.newInitConfig(p),
 		container:  c,
 		container:  c,
+		process:    p,
 	}, nil
 	}, nil
 }
 }
 
 
@@ -204,6 +288,7 @@ func (c *linuxContainer) newSetnsProcess(p *Process, cmd *exec.Cmd, parentPipe,
 		childPipe:   childPipe,
 		childPipe:   childPipe,
 		parentPipe:  parentPipe,
 		parentPipe:  parentPipe,
 		config:      c.newInitConfig(p),
 		config:      c.newInitConfig(p),
+		process:     p,
 	}
 	}
 }
 }
 
 
@@ -337,7 +422,9 @@ func (c *linuxContainer) checkCriuVersion(min_version string) error {
 		}
 		}
 	}
 	}
 
 
-	if x*10000+y*100+z < versionReq {
+	c.criuVersion = x*10000 + y*100 + z
+
+	if c.criuVersion < versionReq {
 		return fmt.Errorf("CRIU version must be %s or higher", min_version)
 		return fmt.Errorf("CRIU version must be %s or higher", min_version)
 	}
 	}
 
 
@@ -665,6 +752,8 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *
 	defer criuServer.Close()
 	defer criuServer.Close()
 
 
 	args := []string{"swrk", "3"}
 	args := []string{"swrk", "3"}
+	logrus.Debugf("Using CRIU %d at: %s", c.criuVersion, c.criuPath)
+	logrus.Debugf("Using CRIU with following args: %s", args)
 	cmd := exec.Command(c.criuPath, args...)
 	cmd := exec.Command(c.criuPath, args...)
 	if process != nil {
 	if process != nil {
 		cmd.Stdin = process.Stdin
 		cmd.Stdin = process.Stdin
@@ -701,6 +790,18 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *
 		}
 		}
 	}
 	}
 
 
+	logrus.Debugf("Using CRIU in %s mode", req.GetType().String())
+	val := reflect.ValueOf(req.GetOpts())
+	v := reflect.Indirect(val)
+	for i := 0; i < v.NumField(); i++ {
+		st := v.Type()
+		name := st.Field(i).Name
+		if strings.HasPrefix(name, "XXX_") {
+			continue
+		}
+		value := val.MethodByName("Get" + name).Call([]reflect.Value{})
+		logrus.Debugf("CRIU option %s with value %v", name, value[0])
+	}
 	data, err := proto.Marshal(req)
 	data, err := proto.Marshal(req)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
@@ -899,13 +1000,15 @@ func (c *linuxContainer) currentState() (*State, error) {
 		return nil, newSystemError(err)
 		return nil, newSystemError(err)
 	}
 	}
 	state := &State{
 	state := &State{
-		ID:                   c.ID(),
-		Config:               *c.config,
-		InitProcessPid:       c.initProcess.pid(),
-		InitProcessStartTime: startTime,
-		CgroupPaths:          c.cgroupManager.GetPaths(),
-		NamespacePaths:       make(map[configs.NamespaceType]string),
-		ExternalDescriptors:  c.initProcess.externalDescriptors(),
+		BaseState: BaseState{
+			ID:                   c.ID(),
+			Config:               *c.config,
+			InitProcessPid:       c.initProcess.pid(),
+			InitProcessStartTime: startTime,
+		},
+		CgroupPaths:         c.cgroupManager.GetPaths(),
+		NamespacePaths:      make(map[configs.NamespaceType]string),
+		ExternalDescriptors: c.initProcess.externalDescriptors(),
 	}
 	}
 	for _, ns := range c.config.Namespaces {
 	for _, ns := range c.config.Namespaces {
 		state.NamespacePaths[ns.Type] = ns.GetPath(c.initProcess.pid())
 		state.NamespacePaths[ns.Type] = ns.GetPath(c.initProcess.pid())

+ 20 - 0
vendor/src/github.com/opencontainers/runc/libcontainer/container_windows.go

@@ -0,0 +1,20 @@
+package libcontainer
+
+// State represents a running container's state
+type State struct {
+	BaseState
+
+	// Platform specific fields below here
+}
+
+// A libcontainer container object.
+//
+// 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 {
+	BaseContainer
+
+	// Methods below here are platform specific
+
+}

+ 2 - 0
vendor/src/github.com/opencontainers/runc/libcontainer/criu_opts.go → vendor/src/github.com/opencontainers/runc/libcontainer/criu_opts_unix.go

@@ -1,3 +1,5 @@
+// +build linux freebsd
+
 package libcontainer
 package libcontainer
 
 
 // cgroup restoring strategy provided by criu
 // cgroup restoring strategy provided by criu

+ 6 - 0
vendor/src/github.com/opencontainers/runc/libcontainer/criu_opts_windows.go

@@ -0,0 +1,6 @@
+package libcontainer
+
+// TODO Windows: This can ultimately be entirely factored out as criu is
+// a Unix concept not relevant on Windows.
+type CriuOpts struct {
+}

+ 3 - 0
vendor/src/github.com/opencontainers/runc/libcontainer/devices/devices_unsupported.go

@@ -0,0 +1,3 @@
+// +build windows
+
+package devices

+ 0 - 16
vendor/src/github.com/opencontainers/runc/libcontainer/devices/devices_windows.go

@@ -1,16 +0,0 @@
-package devices
-
-import (
-	"github.com/opencontainers/runc/libcontainer/configs"
-)
-
-// TODO Windows. This can be factored out further - Devices are not supported
-// by Windows Containers.
-
-func DeviceFromPath(path, permissions string) (*configs.Device, error) {
-	return nil, nil
-}
-
-func HostDevices() ([]*configs.Device, error) {
-	return nil, nil
-}

+ 6 - 5
vendor/src/github.com/opencontainers/runc/libcontainer/factory_linux.go

@@ -159,7 +159,7 @@ func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, err
 	}
 	}
 	containerRoot := filepath.Join(l.Root, id)
 	containerRoot := filepath.Join(l.Root, id)
 	if _, err := os.Stat(containerRoot); err == nil {
 	if _, err := os.Stat(containerRoot); err == nil {
-		return nil, newGenericError(fmt.Errorf("Container with id exists: %v", id), IdInUse)
+		return nil, newGenericError(fmt.Errorf("container with id exists: %v", id), IdInUse)
 	} else if !os.IsNotExist(err) {
 	} else if !os.IsNotExist(err) {
 		return nil, newGenericError(err, SystemError)
 		return nil, newGenericError(err, SystemError)
 	}
 	}
@@ -210,9 +210,10 @@ func (l *LinuxFactory) Type() string {
 // StartInitialization loads a container by opening the pipe fd from the parent to read the configuration and state
 // StartInitialization loads a container by opening the pipe fd from the parent to read the configuration and state
 // This is a low level implementation detail of the reexec and should not be consumed externally
 // This is a low level implementation detail of the reexec and should not be consumed externally
 func (l *LinuxFactory) StartInitialization() (err error) {
 func (l *LinuxFactory) StartInitialization() (err error) {
-	pipefd, err := strconv.Atoi(os.Getenv("_LIBCONTAINER_INITPIPE"))
+	fdStr := os.Getenv("_LIBCONTAINER_INITPIPE")
+	pipefd, err := strconv.Atoi(fdStr)
 	if err != nil {
 	if err != nil {
-		return err
+		return fmt.Errorf("error converting env var _LIBCONTAINER_INITPIPE(%q) to an int: %s", fdStr, err)
 	}
 	}
 	var (
 	var (
 		pipe = os.NewFile(uintptr(pipefd), "pipe")
 		pipe = os.NewFile(uintptr(pipefd), "pipe")
@@ -260,10 +261,10 @@ func (l *LinuxFactory) loadState(root string) (*State, error) {
 
 
 func (l *LinuxFactory) validateID(id string) error {
 func (l *LinuxFactory) validateID(id string) error {
 	if !idRegex.MatchString(id) {
 	if !idRegex.MatchString(id) {
-		return newGenericError(fmt.Errorf("Invalid id format: %v", id), InvalidIdFormat)
+		return newGenericError(fmt.Errorf("invalid id format: %v", id), InvalidIdFormat)
 	}
 	}
 	if len(id) > maxIdLen {
 	if len(id) > maxIdLen {
-		return newGenericError(fmt.Errorf("Invalid id format: %v", id), InvalidIdFormat)
+		return newGenericError(fmt.Errorf("invalid id format: %v", id), InvalidIdFormat)
 	}
 	}
 	return nil
 	return nil
 }
 }

+ 5 - 3
vendor/src/github.com/opencontainers/runc/libcontainer/process_linux.go

@@ -47,6 +47,7 @@ type setnsProcess struct {
 	cgroupPaths map[string]string
 	cgroupPaths map[string]string
 	config      *initConfig
 	config      *initConfig
 	fds         []string
 	fds         []string
+	process     *Process
 }
 }
 
 
 func (p *setnsProcess) startTime() (string, error) {
 func (p *setnsProcess) startTime() (string, error) {
@@ -87,7 +88,6 @@ func (p *setnsProcess) start() (err error) {
 		p.wait()
 		p.wait()
 		return newSystemError(ierr)
 		return newSystemError(ierr)
 	}
 	}
-
 	return nil
 	return nil
 }
 }
 
 
@@ -115,13 +115,12 @@ func (p *setnsProcess) execSetns() error {
 		p.cmd.Wait()
 		p.cmd.Wait()
 		return newSystemError(err)
 		return newSystemError(err)
 	}
 	}
-
 	process, err := os.FindProcess(pid.Pid)
 	process, err := os.FindProcess(pid.Pid)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-
 	p.cmd.Process = process
 	p.cmd.Process = process
+	p.process.ops = p
 	return nil
 	return nil
 }
 }
 
 
@@ -165,6 +164,7 @@ type initProcess struct {
 	manager    cgroups.Manager
 	manager    cgroups.Manager
 	container  *linuxContainer
 	container  *linuxContainer
 	fds        []string
 	fds        []string
+	process    *Process
 }
 }
 
 
 func (p *initProcess) pid() int {
 func (p *initProcess) pid() int {
@@ -178,8 +178,10 @@ func (p *initProcess) externalDescriptors() []string {
 func (p *initProcess) start() (err error) {
 func (p *initProcess) start() (err error) {
 	defer p.parentPipe.Close()
 	defer p.parentPipe.Close()
 	err = p.cmd.Start()
 	err = p.cmd.Start()
+	p.process.ops = p
 	p.childPipe.Close()
 	p.childPipe.Close()
 	if err != nil {
 	if err != nil {
+		p.process.ops = nil
 		return newSystemError(err)
 		return newSystemError(err)
 	}
 	}
 	// Save the standard descriptor names before the container process
 	// Save the standard descriptor names before the container process

+ 18 - 14
vendor/src/github.com/opencontainers/runc/libcontainer/rootfs_linux.go

@@ -29,7 +29,7 @@ func setupRootfs(config *configs.Config, console *linuxConsole) (err error) {
 		return newSystemError(err)
 		return newSystemError(err)
 	}
 	}
 
 
-	setupDev := len(config.Devices) == 0
+	setupDev := len(config.Devices) != 0
 	for _, m := range config.Mounts {
 	for _, m := range config.Mounts {
 		for _, precmd := range m.PremountCmds {
 		for _, precmd := range m.PremountCmds {
 			if err := mountCmd(precmd); err != nil {
 			if err := mountCmd(precmd); err != nil {
@@ -46,7 +46,7 @@ func setupRootfs(config *configs.Config, console *linuxConsole) (err error) {
 			}
 			}
 		}
 		}
 	}
 	}
-	if !setupDev {
+	if setupDev {
 		if err := createDevices(config); err != nil {
 		if err := createDevices(config); err != nil {
 			return newSystemError(err)
 			return newSystemError(err)
 		}
 		}
@@ -68,7 +68,7 @@ func setupRootfs(config *configs.Config, console *linuxConsole) (err error) {
 	if err != nil {
 	if err != nil {
 		return newSystemError(err)
 		return newSystemError(err)
 	}
 	}
-	if !setupDev {
+	if setupDev {
 		if err := reOpenDevNull(); err != nil {
 		if err := reOpenDevNull(); err != nil {
 			return newSystemError(err)
 			return newSystemError(err)
 		}
 		}
@@ -290,8 +290,7 @@ func getCgroupMounts(m *configs.Mount) ([]*configs.Mount, error) {
 	return binds, nil
 	return binds, nil
 }
 }
 
 
-// checkMountDestination checks to ensure that the mount destination is not over the
-// top of /proc or /sys.
+// checkMountDestination checks to ensure that the mount destination is not over the top of /proc.
 // dest is required to be an abs path and have any symlinks resolved before calling this function.
 // dest is required to be an abs path and have any symlinks resolved before calling this function.
 func checkMountDestination(rootfs, dest string) error {
 func checkMountDestination(rootfs, dest string) error {
 	if filepath.Clean(rootfs) == filepath.Clean(dest) {
 	if filepath.Clean(rootfs) == filepath.Clean(dest) {
@@ -379,6 +378,17 @@ func createDevices(config *configs.Config) error {
 	return nil
 	return nil
 }
 }
 
 
+func bindMountDeviceNode(dest string, node *configs.Device) error {
+	f, err := os.Create(dest)
+	if err != nil && !os.IsExist(err) {
+		return err
+	}
+	if f != nil {
+		f.Close()
+	}
+	return syscall.Mount(node.Path, dest, "bind", syscall.MS_BIND, "")
+}
+
 // Creates the device node in the rootfs of the container.
 // Creates the device node in the rootfs of the container.
 func createDeviceNode(rootfs string, node *configs.Device, bind bool) error {
 func createDeviceNode(rootfs string, node *configs.Device, bind bool) error {
 	dest := filepath.Join(rootfs, node.Path)
 	dest := filepath.Join(rootfs, node.Path)
@@ -387,18 +397,13 @@ func createDeviceNode(rootfs string, node *configs.Device, bind bool) error {
 	}
 	}
 
 
 	if bind {
 	if bind {
-		f, err := os.Create(dest)
-		if err != nil && !os.IsExist(err) {
-			return err
-		}
-		if f != nil {
-			f.Close()
-		}
-		return syscall.Mount(node.Path, dest, "bind", syscall.MS_BIND, "")
+		return bindMountDeviceNode(dest, node)
 	}
 	}
 	if err := mknodDevice(dest, node); err != nil {
 	if err := mknodDevice(dest, node); err != nil {
 		if os.IsExist(err) {
 		if os.IsExist(err) {
 			return nil
 			return nil
+		} else if os.IsPermission(err) {
+			return bindMountDeviceNode(dest, node)
 		}
 		}
 		return err
 		return err
 	}
 	}
@@ -634,7 +639,6 @@ func remount(m *configs.Mount, rootfs string) error {
 	if !strings.HasPrefix(dest, rootfs) {
 	if !strings.HasPrefix(dest, rootfs) {
 		dest = filepath.Join(rootfs, dest)
 		dest = filepath.Join(rootfs, dest)
 	}
 	}
-
 	if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), ""); err != nil {
 	if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), ""); err != nil {
 		return err
 		return err
 	}
 	}

+ 46 - 28
vendor/src/github.com/opencontainers/runc/libcontainer/seccomp/config.go

@@ -6,29 +6,47 @@ import (
 	"github.com/opencontainers/runc/libcontainer/configs"
 	"github.com/opencontainers/runc/libcontainer/configs"
 )
 )
 
 
+var operators = map[string]configs.Operator{
+	"SCMP_CMP_NE":        configs.NotEqualTo,
+	"SCMP_CMP_LT":        configs.LessThan,
+	"SCMP_CMP_LE":        configs.LessThanOrEqualTo,
+	"SCMP_CMP_EQ":        configs.EqualTo,
+	"SCMP_CMP_GE":        configs.GreaterThanOrEqualTo,
+	"SCMP_CMP_GT":        configs.GreaterThan,
+	"SCMP_CMP_MASKED_EQ": configs.MaskEqualTo,
+}
+
+var actions = map[string]configs.Action{
+	"SCMP_ACT_KILL":  configs.Kill,
+	"SCMP_ACT_ERRNO": configs.Errno,
+	"SCMP_ACT_TRAP":  configs.Trap,
+	"SCMP_ACT_ALLOW": configs.Allow,
+	"SCMP_ACT_TRACE": configs.Trace,
+}
+
+var archs = map[string]string{
+	"SCMP_ARCH_X86":         "x86",
+	"SCMP_ARCH_X86_64":      "amd64",
+	"SCMP_ARCH_X32":         "x32",
+	"SCMP_ARCH_ARM":         "arm",
+	"SCMP_ARCH_AARCH64":     "arm64",
+	"SCMP_ARCH_MIPS":        "mips",
+	"SCMP_ARCH_MIPS64":      "mips64",
+	"SCMP_ARCH_MIPS64N32":   "mips64n32",
+	"SCMP_ARCH_MIPSEL":      "mipsel",
+	"SCMP_ARCH_MIPSEL64":    "mipsel64",
+	"SCMP_ARCH_MIPSEL64N32": "mipsel64n32",
+}
+
 // ConvertStringToOperator converts a string into a Seccomp comparison operator.
 // ConvertStringToOperator converts a string into a Seccomp comparison operator.
 // Comparison operators use the names they are assigned by Libseccomp's header.
 // Comparison operators use the names they are assigned by Libseccomp's header.
 // Attempting to convert a string that is not a valid operator results in an
 // Attempting to convert a string that is not a valid operator results in an
 // error.
 // error.
 func ConvertStringToOperator(in string) (configs.Operator, error) {
 func ConvertStringToOperator(in string) (configs.Operator, error) {
-	switch in {
-	case "SCMP_CMP_NE":
-		return configs.NotEqualTo, nil
-	case "SCMP_CMP_LT":
-		return configs.LessThan, nil
-	case "SCMP_CMP_LE":
-		return configs.LessThanOrEqualTo, nil
-	case "SCMP_CMP_EQ":
-		return configs.EqualTo, nil
-	case "SCMP_CMP_GE":
-		return configs.GreaterThan, nil
-	case "SCMP_CMP_GT":
-		return configs.GreaterThanOrEqualTo, nil
-	case "SCMP_CMP_MASKED_EQ":
-		return configs.MaskEqualTo, nil
-	default:
-		return 0, fmt.Errorf("string %s is not a valid operator for seccomp", in)
+	if op, ok := operators[in]; ok == true {
+		return op, nil
 	}
 	}
+	return 0, fmt.Errorf("string %s is not a valid operator for seccomp", in)
 }
 }
 
 
 // ConvertStringToAction converts a string into a Seccomp rule match action.
 // ConvertStringToAction converts a string into a Seccomp rule match action.
@@ -38,16 +56,16 @@ func ConvertStringToOperator(in string) (configs.Operator, error) {
 // Attempting to convert a string that is not a valid action results in an
 // Attempting to convert a string that is not a valid action results in an
 // error.
 // error.
 func ConvertStringToAction(in string) (configs.Action, error) {
 func ConvertStringToAction(in string) (configs.Action, error) {
-	switch in {
-	case "SCMP_ACT_KILL":
-		return configs.Kill, nil
-	case "SCMP_ACT_ERRNO":
-		return configs.Errno, nil
-	case "SCMP_ACT_TRAP":
-		return configs.Trap, nil
-	case "SCMP_ACT_ALLOW":
-		return configs.Allow, nil
-	default:
-		return 0, fmt.Errorf("string %s is not a valid action for seccomp", in)
+	if act, ok := actions[in]; ok == true {
+		return act, nil
+	}
+	return 0, fmt.Errorf("string %s is not a valid action for seccomp", in)
+}
+
+// ConvertStringToArch converts a string into a Seccomp comparison arch.
+func ConvertStringToArch(in string) (string, error) {
+	if arch, ok := archs[in]; ok == true {
+		return arch, nil
 	}
 	}
+	return "", fmt.Errorf("string %s is not a valid arch for seccomp", in)
 }
 }

+ 3 - 0
vendor/src/github.com/opencontainers/runc/libcontainer/seccomp/seccomp_linux.go

@@ -15,6 +15,7 @@ var (
 	actAllow = libseccomp.ActAllow
 	actAllow = libseccomp.ActAllow
 	actTrap  = libseccomp.ActTrap
 	actTrap  = libseccomp.ActTrap
 	actKill  = libseccomp.ActKill
 	actKill  = libseccomp.ActKill
+	actTrace = libseccomp.ActTrace.SetReturnCode(int16(syscall.EPERM))
 	actErrno = libseccomp.ActErrno.SetReturnCode(int16(syscall.EPERM))
 	actErrno = libseccomp.ActErrno.SetReturnCode(int16(syscall.EPERM))
 )
 )
 
 
@@ -83,6 +84,8 @@ func getAction(act configs.Action) (libseccomp.ScmpAction, error) {
 		return actTrap, nil
 		return actTrap, nil
 	case configs.Allow:
 	case configs.Allow:
 		return actAllow, nil
 		return actAllow, nil
+	case configs.Trace:
+		return actTrace, nil
 	default:
 	default:
 		return libseccomp.ActInvalid, fmt.Errorf("invalid action, cannot use in rule")
 		return libseccomp.ActInvalid, fmt.Errorf("invalid action, cannot use in rule")
 	}
 	}

+ 1 - 1
vendor/src/github.com/opencontainers/runc/libcontainer/utils/utils.go

@@ -36,7 +36,7 @@ func ResolveRootfs(uncleanRootfs string) (string, error) {
 }
 }
 
 
 // ExitStatus returns the correct exit status for a process based on if it
 // ExitStatus returns the correct exit status for a process based on if it
-// was signaled or existed cleanly.
+// was signaled or exited cleanly.
 func ExitStatus(status syscall.WaitStatus) int {
 func ExitStatus(status syscall.WaitStatus) int {
 	if status.Signaled() {
 	if status.Signaled() {
 		return exitSignalOffset + int(status.Signal())
 		return exitSignalOffset + int(status.Signal())

+ 4 - 2
vendor/src/github.com/syndtr/gocapability/capability/syscall_linux.go

@@ -86,6 +86,10 @@ func getVfsCap(path string, dest *vfscapData) (err error) {
 	}
 	}
 	r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_vfsXattrName)), uintptr(unsafe.Pointer(dest)), vfscapDataSizeV2, 0, 0)
 	r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_vfsXattrName)), uintptr(unsafe.Pointer(dest)), vfscapDataSizeV2, 0, 0)
 	if e1 != 0 {
 	if e1 != 0 {
+		if e1 == syscall.ENODATA {
+			dest.version = 2
+			return
+		}
 		err = e1
 		err = e1
 	}
 	}
 	switch dest.magic & vfsCapVerMask {
 	switch dest.magic & vfsCapVerMask {
@@ -128,8 +132,6 @@ func setVfsCap(path string, data *vfscapData) (err error) {
 		data.magic = vfsCapVer2
 		data.magic = vfsCapVer2
 		if data.effective[0] != 0 || data.effective[1] != 0 {
 		if data.effective[0] != 0 || data.effective[1] != 0 {
 			data.magic |= vfsCapFlageffective
 			data.magic |= vfsCapFlageffective
-			data.data[0].permitted |= data.effective[0]
-			data.data[1].permitted |= data.effective[1]
 		}
 		}
 		size = vfscapDataSizeV2
 		size = vfscapDataSizeV2
 	} else {
 	} else {