Преглед на файлове

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
 
 #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/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
 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/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)
 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/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 {
 	// sysconn/sysobj are only used to call dbus methods
 	sysconn *dbus.Conn
-	sysobj  *dbus.Object
+	sysobj  dbus.BusObject
 
 	// sigconn/sigobj are only used to receive dbus signals
 	sigconn *dbus.Conn
-	sigobj  *dbus.Object
+	sigobj  dbus.BusObject
 
 	jobListener struct {
 		jobs map[dbus.ObjectPath]chan<- string
@@ -86,14 +86,30 @@ type Conn struct {
 // New establishes a connection to the system bus and authenticates.
 // Callers should call Close() when done with the connection.
 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
 // authenticates. This can be used to connect to systemd user instances.
 // Callers should call Close() when done with the connection.
 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
@@ -103,12 +119,12 @@ func (c *Conn) Close() {
 }
 
 func newConnection(createBus func() (*dbus.Conn, error)) (*Conn, error) {
-	sysconn, err := dbusConnection(createBus)
+	sysconn, err := createBus()
 	if err != nil {
 		return nil, err
 	}
 
-	sigconn, err := dbusConnection(createBus)
+	sigconn, err := createBus()
 	if err != nil {
 		sysconn.Close()
 		return nil, err
@@ -132,7 +148,7 @@ func newConnection(createBus func() (*dbus.Conn, error)) (*Conn, error) {
 	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()
 	if err != nil {
 		return nil, err
@@ -149,8 +165,16 @@ func dbusConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error) {
 		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 {
+		return nil, err
+	}
+
+	if err = conn.Hello(); err != nil {
 		conn.Close()
 		return nil, err
 	}
@@ -158,6 +182,6 @@ func dbusConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error) {
 	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"))
 }

+ 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
 // 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
 
 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 {
 	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
 // significance: see the journalctl documentation
 // (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
 }
 
+// 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) {
 	if !validVarName(name) {
 		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
 *.a
 *.so
+bin/
 
 # Folders
 integration-tmp/
@@ -33,4 +34,4 @@ cmd/dnet/dnet
 .project
 .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
 build_image=libnetworkbuild
 dockerargs = --privileged -v $(shell pwd):/go/src/github.com/docker/libnetwork -w /go/src/github.com/docker/libnetwork
 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"
-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:
-	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
 
+all: ${build_image}.created build check integration-tests clean
+
+all-local: build-local check-local integration-tests-local clean
+
 build: ${build_image}.created
 	@echo "Building code... "
 	@${docker} ./wrapmake.sh build-local
 	@echo "Done building code"
 
 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
 	@${docker} ./wrapmake.sh check-local
@@ -71,27 +75,31 @@ run-tests:
 	done
 	@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:
 	-@goveralls -service circleci -coverprofile=coverage.coverprofile -repotoken $$COVERALLS_TOKEN
 
 # 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)
 		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
 		current.next = newSequence
 		mergeSequences(current)

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

@@ -1,12 +1,18 @@
 machine:
-    services:
-        - docker
+  services:
+    - docker
 
 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:
-    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"
 )
 
+type iptableCleanFunc func() error
+type iptablesCleanFuncs []iptableCleanFunc
+
 // configuration info for the "bridge" driver.
 type configuration struct {
 	EnableIPForwarding  bool
@@ -92,12 +95,13 @@ type bridgeEndpoint 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
 }
 
@@ -236,6 +240,10 @@ func parseErr(label, value, errString string) error {
 	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) {
 	n.Lock()
 	defer n.Unlock()
@@ -604,6 +612,10 @@ func (d *driver) createNetwork(config *networkConfiguration) error {
 			}
 			return err
 		}
+		network.registerIptCleanFunc(func() error {
+			nwList := d.getNetworks()
+			return network.isolateNetwork(nwList, false)
+		})
 		return nil
 	}
 
@@ -722,22 +734,6 @@ func (d *driver) DeleteNetwork(nid string) error {
 		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.
 	if !config.DefaultBridge {
 		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)
 }
 

+ 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 {
 		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()
 	if err != nil {
 		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 {
 		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 {
 		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())
 

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

@@ -159,7 +159,11 @@ func (ep *endpoint) Info() EndpointInfo {
 		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) {

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

@@ -27,7 +27,7 @@ const (
 // Conn is a connection to firewalld dbus endpoint.
 type Conn struct {
 	sysconn *dbus.Conn
-	sysobj  *dbus.Object
+	sysobj  dbus.BusObject
 	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
-func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode bool) error {
+func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode, enable bool) error {
 	if c.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",
 			"--dst-type", "LOCAL",
 			"-j", c.Name}
-		if !Exists(Nat, "PREROUTING", preroute...) {
+		if !Exists(Nat, "PREROUTING", preroute...) && enable {
 			if err := c.Prerouting(Append, preroute...); err != nil {
 				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{
 			"-m", "addrtype",
@@ -118,10 +122,14 @@ func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode bool) error {
 		if !hairpinMode {
 			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 {
 				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:
 		if bridgeName == "" {
@@ -131,13 +139,21 @@ func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode bool) error {
 		link := []string{
 			"-o", bridgeName,
 			"-j", c.Name}
-		if !Exists(Filter, "FORWARD", link...) {
+		if !Exists(Filter, "FORWARD", link...) && enable {
 			insert := append([]string{string(Insert), "FORWARD"}, link...)
 			if output, err := Raw(insert...); err != nil {
 				return err
 			} else if len(output) != 0 {
 				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

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

@@ -9,10 +9,8 @@ import (
 	"fmt"
 	"io"
 	"net"
-	"strings"
 
 	"github.com/docker/libnetwork/types"
-	"github.com/vishvananda/netlink"
 )
 
 var (
@@ -22,8 +20,6 @@ var (
 	ErrNetworkOverlaps = errors.New("requested network overlaps with existing network")
 	// ErrNoDefaultRoute preformatted error
 	ErrNoDefaultRoute = errors.New("no default route")
-
-	networkGetRoutesFct = netlink.RouteList
 )
 
 // 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
 }
 
-// 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
 func NetworkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
 	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
 }
-
-// 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...)
 
+	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 {
 		return nil, err
 	}

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

@@ -1,19 +1,6 @@
 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 {
 	ContainerID string
@@ -23,163 +10,3 @@ type setKeyData struct {
 func init() {
 	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.
 
 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
 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
 further notice.
 

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

@@ -2,7 +2,6 @@ package dbus
 
 import (
 	"errors"
-	"strings"
 )
 
 // Call represents a pending or completed method call.
@@ -35,113 +34,3 @@ func (c *Call) Store(retvalues ...interface{}) error {
 
 	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 {
 	transport
 
-	busObj *Object
+	busObj BusObject
 	unixFD bool
 	uuid   string
 
@@ -46,7 +46,7 @@ type Conn struct {
 	calls    map[uint32]*Call
 	callsLck sync.RWMutex
 
-	handlers    map[ObjectPath]map[string]interface{}
+	handlers    map[ObjectPath]map[string]exportWithMapping
 	handlersLck sync.RWMutex
 
 	out    chan *Message
@@ -157,7 +157,7 @@ func newConn(tr transport) (*Conn, error) {
 	conn.transport = tr
 	conn.calls = make(map[uint32]*Call)
 	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.serialUsed = map[uint32]bool{0: true}
 	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
 // administrative requests.
-func (conn *Conn) BusObject() *Object {
+func (conn *Conn) BusObject() BusObject {
 	return conn.busObj
 }
 
@@ -303,18 +303,33 @@ func (conn *Conn) inWorker() {
 				// as per http://dbus.freedesktop.org/doc/dbus-specification.html ,
 				// sender is optional for signals.
 				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{
 					Sender: sender,
@@ -360,7 +375,7 @@ func (conn *Conn) Names() []string {
 }
 
 // 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}
 }
 
@@ -554,7 +569,7 @@ type transport interface {
 }
 
 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) {
@@ -571,6 +586,7 @@ func getTransport(address string) (transport, error) {
 		f := transports[v[:i]]
 		if f == nil {
 			err = errors.New("dbus: invalid bus address (invalid or unsupported transport)")
+			continue
 		}
 		t, err = f(v[i+1:])
 		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.
 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.out = out
 	enc.order = order
+	enc.pos = offset
 	return enc
 }
 
 // Aligns the next output to be on a multiple of n. Panics on write errors.
 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 {
 			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.
 func (enc *encoder) binwrite(v interface{}) {
 	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 {
 			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
-		bufenc := newEncoder(&buf, enc.order)
+		bufenc := newEncoderAtOffset(&buf, offset, enc.order)
 
 		for i := 0; i < v.Len(); i++ {
 			bufenc.encode(v.Index(i), depth+1)
@@ -159,8 +183,13 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
 			panic(InvalidTypeError{v.Type()})
 		}
 		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
-		bufenc := newEncoder(&buf, enc.order)
+		bufenc := newEncoderAtOffset(&buf, offset, enc.order)
 		for _, k := range keys {
 			bufenc.align(8)
 			bufenc.encode(k, depth+2)

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

@@ -2,9 +2,9 @@ package dbus
 
 import (
 	"errors"
+	"fmt"
 	"reflect"
 	"strings"
-	"unicode"
 )
 
 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.
 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{}
 	}
-	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{}
 	}
 	t := m.Type()
@@ -43,6 +79,42 @@ func exportedMethod(v interface{}, name string) reflect.Value {
 	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
 // pre-implemented ones and searches for a corresponding handler if not).
 func (conn *Conn) handleCall(msg *Message) {
@@ -62,40 +134,35 @@ func (conn *Conn) handleCall(msg *Message) {
 		}
 		return
 	}
-	if len(name) == 0 || unicode.IsLower([]rune(name)[0]) {
+	if len(name) == 0 {
 		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
 	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)
 	} 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)
 			if m.IsValid() {
 				break
 			}
 		}
-		conn.handlersLck.RUnlock()
 	}
+
 	if !m.IsValid() {
 		conn.sendError(errmsgUnknownMethod, sender, serial)
 		return
 	}
+
 	t := m.Type()
 	vs := msg.Body
 	pointers := make([]interface{}, t.NumIn())
@@ -106,27 +173,36 @@ func (conn *Conn) handleCall(msg *Message) {
 		pointers[i] = val.Interface()
 		if tp == reflect.TypeOf((*Sender)(nil)).Elem() {
 			val.Elem().SetString(sender)
+		} else if tp == reflect.TypeOf((*Message)(nil)).Elem() {
+			val.Elem().Set(reflect.ValueOf(*msg))
 		} else {
 			decode = append(decode, pointers[i])
 		}
 	}
+
 	if len(decode) != len(vs) {
 		conn.sendError(errmsgInvalidArg, sender, serial)
 		return
 	}
+
 	if err := Store(vs, decode...); err != nil {
 		conn.sendError(errmsgInvalidArg, sender, serial)
 		return
 	}
+
+	// Extract parameters
 	params := make([]reflect.Value, len(pointers))
 	for i := 0; i < len(pointers); i++ {
 		params[i] = reflect.ValueOf(pointers[i]).Elem()
 	}
+
+	// Call method
 	ret := m.Call(params)
 	if em := ret[t.NumOut()-1].Interface().(*Error); em != nil {
 		conn.sendError(*em, sender, serial)
 		return
 	}
+
 	if msg.Flags&FlagNoReplyExpected == 0 {
 		reply := new(Message)
 		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
 // 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
 // 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.
 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() {
-		return errors.New("dbus: invalid path name")
+		return fmt.Errorf(`dbus: Invalid path name: "%s"`, path)
 	}
+
 	conn.handlersLck.Lock()
+	defer conn.handlersLck.Unlock()
+
+	// Remove a previous export if the interface is nil
 	if v == nil {
 		if _, ok := conn.handlers[path]; ok {
 			delete(conn.handlers[path], iface)
@@ -225,51 +346,39 @@ func (conn *Conn) Export(v interface{}, path ObjectPath, iface string) error {
 				delete(conn.handlers, path)
 			}
 		}
+
 		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 {
-		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
 }
 
-// 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) {
 	var r uint32
 	err := conn.busObj.Call("org.freedesktop.DBus.ReleaseName", 0, name).Store(&r)
 	if err != nil {
 		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
 }
 
-// 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) {
 	var r uint32
 	err := conn.busObj.Call("org.freedesktop.DBus.RequestName", 0, name, flags).Store(&r)
 	if err != nil {
 		return 0, err
 	}
-	if r == uint32(RequestNameReplyPrimaryOwner) {
-		conn.namesLck.Lock()
-		conn.names = append(conn.names, name)
-		conn.namesLck.Unlock()
-	}
 	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:
 	make install
 	make -C testdata
-	protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata:. proto3_proto/proto3.proto
+	make -C proto3_proto
 	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)
 		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
 }

+ 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 {
 		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)
-
-		case reflect.Slice:
+		} else {
 			for i := 0; i < f.Len(); i++ {
 				e := f.Index(i)
 				if e.IsNil() {
@@ -623,15 +621,6 @@ func setDefaults(v reflect.Value, recur, zeros bool) {
 				}
 				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
 }
 
+func ptrToStruct(t reflect.Type) bool {
+	return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
+}
+
 // t is a struct type.
 func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
 	sprop := GetProperties(t)
@@ -668,33 +661,9 @@ func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
 		}
 		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
 		}
 

+ 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.dec = (*Buffer).dec_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.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 
 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 
 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
 
 import (
+	"errors"
 	"fmt"
 	"io"
 	"io/ioutil"
@@ -16,30 +17,45 @@ import (
 )
 
 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"
 	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 {
+	// Name returns the name of the subsystem.
+	Name() string
 	// Returns the stats, as 'stats', corresponding to the cgroup under 'path'.
 	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(path string, cgroup *configs.Cgroup) error
 }
@@ -76,10 +92,11 @@ func getCgroupRoot() (string, error) {
 	return cgroupRoot, nil
 }
 
-type data struct {
+type cgroupData struct {
 	root   string
-	cgroup string
-	c      *configs.Cgroup
+	parent string
+	name   string
+	config *configs.Cgroup
 	pid    int
 }
 
@@ -101,21 +118,21 @@ func (m *Manager) Apply(pid int) (err error) {
 			cgroups.RemovePaths(paths)
 		}
 	}()
-	for name, sys := range subsystems {
+	for _, sys := range subsystems {
 		if err := sys.Apply(d); err != nil {
 			return err
 		}
 		// 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
 		// 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 cgroups.IsNotFound(err) {
 				continue
 			}
 			return err
 		}
-		paths[name] = p
+		paths[sys.Name()] = p
 	}
 	m.Paths = paths
 
@@ -150,29 +167,27 @@ func (m *Manager) GetStats() (*cgroups.Stats, error) {
 	defer m.mu.Unlock()
 	stats := cgroups.NewStats()
 	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
 		}
 		if err := sys.GetStats(path, stats); err != nil {
 			return nil, err
 		}
 	}
-
 	return stats, nil
 }
 
 func (m *Manager) Set(container *configs.Config) error {
 	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
 		}
 		if err := sys.Set(path, container.Cgroups); err != nil {
 			return err
 		}
 	}
-
 	return nil
 }
 
@@ -183,22 +198,21 @@ func (m *Manager) Freeze(state configs.FreezerState) error {
 	if err != nil {
 		return err
 	}
-
 	dir, err := d.path("freezer")
 	if err != nil {
 		return err
 	}
-
 	prevState := m.Cgroups.Freezer
 	m.Cgroups.Freezer = state
-
-	freezer := subsystems["freezer"]
+	freezer, err := subsystems.Get("freezer")
+	if err != nil {
+		return err
+	}
 	err = freezer.Set(dir, m.Cgroups)
 	if err != nil {
 		m.Cgroups.Freezer = prevState
 		return err
 	}
-
 	return nil
 }
 
@@ -216,30 +230,31 @@ func (m *Manager) GetPids() ([]int, error) {
 	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()
 	if err != nil {
 		return nil, err
 	}
 
-	cgroup := c.Name
-	if c.Parent != "" {
-		cgroup = filepath.Join(c.Parent, cgroup)
-	}
-
-	return &data{
+	return &cgroupData{
 		root:   root,
-		cgroup: cgroup,
-		c:      c,
+		parent: c.Parent,
+		name:   c.Name,
+		config: c,
 		pid:    pid,
 	}, 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)
 	if err != nil {
 		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)
 	if err != nil {
 		return "", err
@@ -247,27 +262,29 @@ func (raw *data) parent(subsystem, mountpoint, root string) (string, error) {
 	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)
 	// If we didn't mount the subsystem, there is no point we make the path.
 	if err != nil {
 		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 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 {
 		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)
 	if err != nil {
 		return "", err

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

@@ -17,13 +17,17 @@ import (
 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")
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 	}
 
-	if err := s.Set(dir, d.c); err != nil {
+	if err := s.Set(dir, d.config); err != nil {
 		return err
 	}
 
@@ -74,7 +78,7 @@ func (s *BlkioGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 }
 
-func (s *BlkioGroup) Remove(d *data) error {
+func (s *BlkioGroup) Remove(d *cgroupData) error {
 	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 {
 }
 
-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
 	// on a container basis
 	dir, err := d.join("cpu")
@@ -23,7 +27,7 @@ func (s *CpuGroup) Apply(d *data) error {
 		return err
 	}
 
-	if err := s.Set(dir, d.c); err != nil {
+	if err := s.Set(dir, d.config); err != nil {
 		return err
 	}
 
@@ -60,7 +64,7 @@ func (s *CpuGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 }
 
-func (s *CpuGroup) Remove(d *data) error {
+func (s *CpuGroup) Remove(d *cgroupData) error {
 	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 {
 }
 
-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
 	if _, err := d.join("cpuacct"); err != nil && !cgroups.IsNotFound(err) {
 		return err
@@ -37,7 +41,7 @@ func (s *CpuacctGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 }
 
-func (s *CpuacctGroup) Remove(d *data) error {
+func (s *CpuacctGroup) Remove(d *cgroupData) error {
 	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 {
 }
 
-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")
 	if err != nil && !cgroups.IsNotFound(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 {
@@ -38,7 +42,7 @@ func (s *CpusetGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 }
 
-func (s *CpusetGroup) Remove(d *data) error {
+func (s *CpusetGroup) Remove(d *cgroupData) error {
 	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 {
 		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
 	// s.ensureParent, cover these if we have our own
 	if err := s.Set(dir, cgroup); err != nil {
 		return err
 	}
+	// because we are not using d.join we need to place the pid into the procs file
+	// unlike the other subsystems
+	if err := writeFile(dir, "cgroup.procs", strconv.Itoa(pid)); err != nil {
+		return err
+	}
 
 	return nil
 }

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

@@ -10,7 +10,11 @@ import (
 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")
 	if err != nil {
 		// We will return error even it's `not found` error, devices
@@ -18,7 +22,7 @@ func (s *DevicesGroup) Apply(d *data) error {
 		return err
 	}
 
-	if err := s.Set(dir, d.c); err != nil {
+	if err := s.Set(dir, d.config); err != nil {
 		return err
 	}
 
@@ -52,7 +56,7 @@ func (s *DevicesGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 }
 
-func (s *DevicesGroup) Remove(d *data) error {
+func (s *DevicesGroup) Remove(d *cgroupData) error {
 	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 {
 }
 
-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")
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 	}
 
-	if err := s.Set(dir, d.c); err != nil {
+	if err := s.Set(dir, d.config); err != nil {
 		return err
 	}
 
@@ -53,7 +57,7 @@ func (s *FreezerGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 }
 
-func (s *FreezerGroup) Remove(d *data) error {
+func (s *FreezerGroup) Remove(d *cgroupData) error {
 	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 {
 }
 
-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")
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 	}
 
-	if err := s.Set(dir, d.c); err != nil {
+	if err := s.Set(dir, d.config); err != nil {
 		return err
 	}
 
@@ -37,7 +41,7 @@ func (s *HugetlbGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 }
 
-func (s *HugetlbGroup) Remove(d *data) error {
+func (s *HugetlbGroup) Remove(d *cgroupData) error {
 	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 {
 }
 
-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")
-	if err != nil {
-		if cgroups.IsNotFound(err) {
-			return nil
-		}
+	if err != nil && !cgroups.IsNotFound(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() {
@@ -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
 	// 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
 	}
 
@@ -88,7 +94,7 @@ func (s *MemoryGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 }
 
-func (s *MemoryGroup) Remove(d *data) error {
+func (s *MemoryGroup) Remove(d *cgroupData) error {
 	return removePath(d.path("memory"))
 }
 
@@ -132,6 +138,15 @@ func (s *MemoryGroup) GetStats(path string, stats *cgroups.Stats) error {
 	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) {
 	memoryData := cgroups.MemoryData{}
 

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

@@ -1,3 +1,5 @@
+// +build linux
+
 package fs
 
 import (
@@ -6,9 +8,14 @@ import (
 )
 
 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
 }
 
@@ -16,7 +23,7 @@ func (s *NameGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 }
 
-func (s *NameGroup) Remove(d *data) error {
+func (s *NameGroup) Remove(d *cgroupData) error {
 	return nil
 }
 

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

@@ -1,3 +1,5 @@
+// +build linux
+
 package fs
 
 import (
@@ -8,13 +10,17 @@ import (
 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")
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 	}
 
-	if err := s.Set(dir, d.c); err != nil {
+	if err := s.Set(dir, d.config); err != nil {
 		return err
 	}
 
@@ -31,7 +37,7 @@ func (s *NetClsGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 }
 
-func (s *NetClsGroup) Remove(d *data) error {
+func (s *NetClsGroup) Remove(d *cgroupData) error {
 	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
 
 import (
@@ -8,13 +10,17 @@ import (
 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")
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 	}
 
-	if err := s.Set(dir, d.c); err != nil {
+	if err := s.Set(dir, d.config); err != nil {
 		return err
 	}
 
@@ -31,7 +37,7 @@ func (s *NetPrioGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 }
 
-func (s *NetPrioGroup) Remove(d *data) error {
+func (s *NetPrioGroup) Remove(d *cgroupData) error {
 	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 {
 }
 
-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
 	if _, err := d.join("perf_event"); err != nil && !cgroups.IsNotFound(err) {
 		return err
@@ -22,7 +26,7 @@ func (s *PerfEventGroup) Set(path string, cgroup *configs.Cgroup) error {
 	return nil
 }
 
-func (s *PerfEventGroup) Remove(d *data) error {
+func (s *PerfEventGroup) Remove(d *cgroupData) error {
 	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:
 		value, err := parseUint(parts[1], 10, 64)
 		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
@@ -55,12 +55,17 @@ func getCgroupParamKeyValue(t string) (string, uint64, error) {
 
 // Gets a single uint64 value from the specified cgroup file.
 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 {
 		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

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

@@ -3,6 +3,7 @@
 package systemd
 
 import (
+	"errors"
 	"fmt"
 	"io/ioutil"
 	"os"
@@ -27,25 +28,40 @@ type Manager struct {
 }
 
 type subsystem interface {
+	// Name returns the name of the subsystem.
+	Name() string
 	// Returns the stats, as 'stats', corresponding to the cgroup under 'path'.
 	GetStats(path string, stats *cgroups.Stats) error
 	// Set the cgroup represented by cgroup.
 	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 (
@@ -249,8 +265,8 @@ func (m *Manager) Apply(pid int) error {
 	}
 
 	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 {
 			// Don't fail if a cgroup hierarchy was not found, just skip this subsystem
 			if cgroups.IsNotFound(err) {
@@ -258,7 +274,7 @@ func (m *Manager) Apply(pid int) error {
 			}
 			return err
 		}
-		paths[sysname] = subsystemPath
+		paths[s.Name()] = subsystemPath
 	}
 	m.Paths = paths
 
@@ -347,8 +363,10 @@ func joinFreezer(c *configs.Cgroup, pid int) error {
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 	}
-
-	freezer := subsystems["freezer"]
+	freezer, err := subsystems.Get("freezer")
+	if err != nil {
+		return err
+	}
 	return freezer.Set(path, c)
 }
 
@@ -357,8 +375,10 @@ func joinNetPrio(c *configs.Cgroup, pid int) error {
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 	}
-	netPrio := subsystems["net_prio"]
-
+	netPrio, err := subsystems.Get("net_prio")
+	if err != nil {
+		return err
+	}
 	return netPrio.Set(path, c)
 }
 
@@ -367,8 +387,10 @@ func joinNetCls(c *configs.Cgroup, pid int) error {
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 	}
-	netcls := subsystems["net_cls"]
-
+	netcls, err := subsystems.Get("net_cls")
+	if err != nil {
+		return err
+	}
 	return netcls.Set(path, c)
 }
 
@@ -396,17 +418,17 @@ func (m *Manager) Freeze(state configs.FreezerState) error {
 	if err != nil {
 		return err
 	}
-
 	prevState := m.Cgroups.Freezer
 	m.Cgroups.Freezer = state
-
-	freezer := subsystems["freezer"]
+	freezer, err := subsystems.Get("freezer")
+	if err != nil {
+		return err
+	}
 	err = freezer.Set(path, m.Cgroups)
 	if err != nil {
 		m.Cgroups.Freezer = prevState
 		return err
 	}
-
 	return nil
 }
 
@@ -423,8 +445,8 @@ func (m *Manager) GetStats() (*cgroups.Stats, error) {
 	defer m.mu.Unlock()
 	stats := cgroups.NewStats()
 	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
 		}
 		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 {
 	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
 		}
 		if err := sys.Set(path, container.Cgroups); err != nil {
@@ -471,8 +493,10 @@ func joinDevices(c *configs.Cgroup, pid int) error {
 	if err != nil {
 		return err
 	}
-
-	devices := subsystems["devices"]
+	devices, err := subsystems.Get("devices")
+	if err != nil {
+		return err
+	}
 	return devices.Set(path, c)
 }
 
@@ -600,8 +624,10 @@ func joinHugetlb(c *configs.Cgroup, pid int) error {
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 	}
-
-	hugetlb := subsystems["hugetlb"]
+	hugetlb, err := subsystems.Get("hugetlb")
+	if err != nil {
+		return err
+	}
 	return hugetlb.Set(path, c)
 }
 
@@ -610,7 +636,9 @@ func joinPerfEvent(c *configs.Cgroup, pid int) error {
 	if err != nil && !cgroups.IsNotFound(err) {
 		return err
 	}
-
-	perfEvent := subsystems["perf_event"]
+	perfEvent, err := subsystems.Get("perf_event")
+	if err != nil {
+		return err
+	}
 	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
 
 type FreezerState string
@@ -8,9 +10,6 @@ const (
 	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 {
 	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
 
 const (
-	Kill Action = iota - 4
+	Kill Action = iota + 1
 	Errno
 	Trap
 	Allow
+	Trace
 )
 
 // A comparison operator to be used when matching syscall arguments in Seccomp
 type Operator int
 
 const (
-	EqualTo Operator = iota
+	EqualTo Operator = iota + 1
 	NotEqualTo
 	GreaterThan
 	GreaterThanOrEqualTo
@@ -183,6 +184,9 @@ type Hooks struct {
 	// but before the user supplied command is executed from init.
 	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 []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
 
 // 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
 )
 
-// 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 string `json:"id"`
 
@@ -41,27 +42,16 @@ type State struct {
 	// InitProcessStartTime is the init process start time.
 	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 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.
 //
 // 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 {
+// was not found. BaseContainer includes methods that are platform agnostic.
+type BaseContainer interface {
 	// Returns the ID of the container
 	ID() string
 
@@ -98,7 +88,7 @@ type Container interface {
 	// Systemerror - System 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.
 	//
@@ -116,18 +106,6 @@ type Container interface {
 	// Systemerror - System 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.
 	//
 	// Any event registrations are removed before the container is destroyed.
@@ -137,31 +115,6 @@ type Container interface {
 	// Systemerror - System 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.
 	//
 	// errors:

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

@@ -9,6 +9,7 @@ import (
 	"os"
 	"os/exec"
 	"path/filepath"
+	"reflect"
 	"strings"
 	"sync"
 	"syscall"
@@ -32,6 +33,73 @@ type linuxContainer struct {
 	initProcess   parentProcess
 	criuPath      string
 	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
@@ -111,10 +179,25 @@ func (c *linuxContainer) Start(process *Process) error {
 		}
 		return newSystemError(err)
 	}
-	process.ops = parent
 	if doInit {
 		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
 }
 
@@ -186,6 +269,7 @@ func (c *linuxContainer) newInitProcess(p *Process, cmd *exec.Cmd, parentPipe, c
 		manager:    c.cgroupManager,
 		config:     c.newInitConfig(p),
 		container:  c,
+		process:    p,
 	}, nil
 }
 
@@ -204,6 +288,7 @@ func (c *linuxContainer) newSetnsProcess(p *Process, cmd *exec.Cmd, parentPipe,
 		childPipe:   childPipe,
 		parentPipe:  parentPipe,
 		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)
 	}
 
@@ -665,6 +752,8 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *
 	defer criuServer.Close()
 
 	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...)
 	if process != nil {
 		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)
 	if err != nil {
 		return err
@@ -899,13 +1000,15 @@ func (c *linuxContainer) currentState() (*State, error) {
 		return nil, newSystemError(err)
 	}
 	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 {
 		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
 
 // 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)
 	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) {
 		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
 // This is a low level implementation detail of the reexec and should not be consumed externally
 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 {
-		return err
+		return fmt.Errorf("error converting env var _LIBCONTAINER_INITPIPE(%q) to an int: %s", fdStr, err)
 	}
 	var (
 		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 {
 	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 {
-		return newGenericError(fmt.Errorf("Invalid id format: %v", id), InvalidIdFormat)
+		return newGenericError(fmt.Errorf("invalid id format: %v", id), InvalidIdFormat)
 	}
 	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
 	config      *initConfig
 	fds         []string
+	process     *Process
 }
 
 func (p *setnsProcess) startTime() (string, error) {
@@ -87,7 +88,6 @@ func (p *setnsProcess) start() (err error) {
 		p.wait()
 		return newSystemError(ierr)
 	}
-
 	return nil
 }
 
@@ -115,13 +115,12 @@ func (p *setnsProcess) execSetns() error {
 		p.cmd.Wait()
 		return newSystemError(err)
 	}
-
 	process, err := os.FindProcess(pid.Pid)
 	if err != nil {
 		return err
 	}
-
 	p.cmd.Process = process
+	p.process.ops = p
 	return nil
 }
 
@@ -165,6 +164,7 @@ type initProcess struct {
 	manager    cgroups.Manager
 	container  *linuxContainer
 	fds        []string
+	process    *Process
 }
 
 func (p *initProcess) pid() int {
@@ -178,8 +178,10 @@ func (p *initProcess) externalDescriptors() []string {
 func (p *initProcess) start() (err error) {
 	defer p.parentPipe.Close()
 	err = p.cmd.Start()
+	p.process.ops = p
 	p.childPipe.Close()
 	if err != nil {
+		p.process.ops = nil
 		return newSystemError(err)
 	}
 	// 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)
 	}
 
-	setupDev := len(config.Devices) == 0
+	setupDev := len(config.Devices) != 0
 	for _, m := range config.Mounts {
 		for _, precmd := range m.PremountCmds {
 			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 {
 			return newSystemError(err)
 		}
@@ -68,7 +68,7 @@ func setupRootfs(config *configs.Config, console *linuxConsole) (err error) {
 	if err != nil {
 		return newSystemError(err)
 	}
-	if !setupDev {
+	if setupDev {
 		if err := reOpenDevNull(); err != nil {
 			return newSystemError(err)
 		}
@@ -290,8 +290,7 @@ func getCgroupMounts(m *configs.Mount) ([]*configs.Mount, error) {
 	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.
 func checkMountDestination(rootfs, dest string) error {
 	if filepath.Clean(rootfs) == filepath.Clean(dest) {
@@ -379,6 +378,17 @@ func createDevices(config *configs.Config) error {
 	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.
 func createDeviceNode(rootfs string, node *configs.Device, bind bool) error {
 	dest := filepath.Join(rootfs, node.Path)
@@ -387,18 +397,13 @@ func createDeviceNode(rootfs string, node *configs.Device, bind bool) error {
 	}
 
 	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 os.IsExist(err) {
 			return nil
+		} else if os.IsPermission(err) {
+			return bindMountDeviceNode(dest, node)
 		}
 		return err
 	}
@@ -634,7 +639,6 @@ func remount(m *configs.Mount, rootfs string) error {
 	if !strings.HasPrefix(dest, rootfs) {
 		dest = filepath.Join(rootfs, dest)
 	}
-
 	if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), ""); err != nil {
 		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"
 )
 
+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.
 // 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
 // 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.
@@ -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
 // 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
 	actTrap  = libseccomp.ActTrap
 	actKill  = libseccomp.ActKill
+	actTrace = libseccomp.ActTrace.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
 	case configs.Allow:
 		return actAllow, nil
+	case configs.Trace:
+		return actTrace, nil
 	default:
 		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
-// was signaled or existed cleanly.
+// was signaled or exited cleanly.
 func ExitStatus(status syscall.WaitStatus) int {
 	if status.Signaled() {
 		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)
 	if e1 != 0 {
+		if e1 == syscall.ENODATA {
+			dest.version = 2
+			return
+		}
 		err = e1
 	}
 	switch dest.magic & vfsCapVerMask {
@@ -128,8 +132,6 @@ func setVfsCap(path string, data *vfscapData) (err error) {
 		data.magic = vfsCapVer2
 		if data.effective[0] != 0 || data.effective[1] != 0 {
 			data.magic |= vfsCapFlageffective
-			data.data[0].permitted |= data.effective[0]
-			data.data[1].permitted |= data.effective[1]
 		}
 		size = vfscapDataSizeV2
 	} else {