Merge pull request #166 from gitido/fixes

Go1.5 compatibility fix
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index b362fdc..e355c3e 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -14,8 +14,13 @@
 		},
 		{
 			"ImportPath": "github.com/coreos/go-systemd/dbus",
-			"Comment": "v2",
-			"Rev": "f743bc15d6bddd23662280b4ad20f7c874cdd5ad"
+			"Comment": "v3",
+			"Rev": "be94bc700879ae8217780e9d141789a2defa302b"
+		},
+		{
+			"ImportPath": "github.com/coreos/go-systemd/util",
+			"Comment": "v3",
+			"Rev": "be94bc700879ae8217780e9d141789a2defa302b"
 		},
 		{
 			"ImportPath": "github.com/docker/docker/pkg/mount",
@@ -48,7 +53,7 @@
 		},
 		{
 			"ImportPath": "github.com/opencontainers/specs",
-			"Rev": "08873003592da169f89ec7c671ed34e1a2333ef8"
+			"Rev": "5b31bb2b7771e5074a4eb14eca432da1ca5182d6"
 		},
 		{
 			"ImportPath": "github.com/syndtr/gocapability/capability",
diff --git a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/dbus.go b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/dbus.go
index 91d7112..625a32b 100644
--- a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/dbus.go
+++ b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/dbus.go
@@ -1,23 +1,22 @@
-/*
-Copyright 2013 CoreOS Inc.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 // Integration with the systemd D-Bus API.  See http://www.freedesktop.org/wiki/Software/systemd/dbus/
 package dbus
 
 import (
+	"fmt"
 	"os"
 	"strconv"
 	"strings"
@@ -26,24 +25,53 @@
 	"github.com/godbus/dbus"
 )
 
-const signalBuffer = 100
+const (
+	alpha        = `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`
+	num          = `0123456789`
+	alphanum     = alpha + num
+	signalBuffer = 100
+)
 
-// ObjectPath creates a dbus.ObjectPath using the rules that systemd uses for
-// serializing special characters.
-func ObjectPath(path string) dbus.ObjectPath {
-	path = strings.Replace(path, ".", "_2e", -1)
-	path = strings.Replace(path, "-", "_2d", -1)
-	path = strings.Replace(path, "@", "_40", -1)
-
-	return dbus.ObjectPath(path)
+// needsEscape checks whether a byte in a potential dbus ObjectPath needs to be escaped
+func needsEscape(i int, b byte) bool {
+	// Escape everything that is not a-z-A-Z-0-9
+	// Also escape 0-9 if it's the first character
+	return strings.IndexByte(alphanum, b) == -1 ||
+		(i == 0 && strings.IndexByte(num, b) != -1)
 }
 
-// Conn is a connection to systemds dbus endpoint.
+// PathBusEscape sanitizes a constituent string of a dbus ObjectPath using the
+// rules that systemd uses for serializing special characters.
+func PathBusEscape(path string) string {
+	// Special case the empty string
+	if len(path) == 0 {
+		return "_"
+	}
+	n := []byte{}
+	for i := 0; i < len(path); i++ {
+		c := path[i]
+		if needsEscape(i, c) {
+			e := fmt.Sprintf("_%x", c)
+			n = append(n, []byte(e)...)
+		} else {
+			n = append(n, c)
+		}
+	}
+	return string(n)
+}
+
+// Conn is a connection to systemd's dbus endpoint.
 type Conn struct {
-	sysconn     *dbus.Conn
-	sysobj      *dbus.Object
+	// sysconn/sysobj are only used to call dbus methods
+	sysconn *dbus.Conn
+	sysobj  *dbus.Object
+
+	// sigconn/sigobj are only used to receive dbus signals
+	sigconn *dbus.Conn
+	sigobj  *dbus.Object
+
 	jobListener struct {
-		jobs map[dbus.ObjectPath]chan string
+		jobs map[dbus.ObjectPath]chan<- string
 		sync.Mutex
 	}
 	subscriber struct {
@@ -53,26 +81,61 @@
 		ignore      map[dbus.ObjectPath]int64
 		cleanIgnore int64
 	}
-	dispatch map[string]func(dbus.Signal)
 }
 
-// New() establishes a connection to the system bus and authenticates.
+// New establishes a connection to the system bus and authenticates.
+// Callers should call Close() when done with the connection.
 func New() (*Conn, error) {
-	c := new(Conn)
+	return newConnection(dbus.SystemBusPrivate)
+}
 
-	if err := c.initConnection(); err != nil {
+// 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)
+}
+
+// Close closes an established connection
+func (c *Conn) Close() {
+	c.sysconn.Close()
+	c.sigconn.Close()
+}
+
+func newConnection(createBus func() (*dbus.Conn, error)) (*Conn, error) {
+	sysconn, err := dbusConnection(createBus)
+	if err != nil {
 		return nil, err
 	}
 
-	c.initJobs()
+	sigconn, err := dbusConnection(createBus)
+	if err != nil {
+		sysconn.Close()
+		return nil, err
+	}
+
+	c := &Conn{
+		sysconn: sysconn,
+		sysobj:  systemdObject(sysconn),
+		sigconn: sigconn,
+		sigobj:  systemdObject(sigconn),
+	}
+
+	c.subscriber.ignore = make(map[dbus.ObjectPath]int64)
+	c.jobListener.jobs = make(map[dbus.ObjectPath]chan<- string)
+
+	// Setup the listeners on jobs so that we can get completions
+	c.sigconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
+		"type='signal', interface='org.freedesktop.systemd1.Manager', member='JobRemoved'")
+
+	c.dispatch()
 	return c, nil
 }
 
-func (c *Conn) initConnection() error {
-	var err error
-	c.sysconn, err = dbus.SystemBusPrivate()
+func dbusConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error) {
+	conn, err := createBus()
 	if err != nil {
-		return err
+		return nil, err
 	}
 
 	// Only use EXTERNAL method, and hardcode the uid (not username)
@@ -80,25 +143,21 @@
 	// libc)
 	methods := []dbus.Auth{dbus.AuthExternal(strconv.Itoa(os.Getuid()))}
 
-	err = c.sysconn.Auth(methods)
+	err = conn.Auth(methods)
 	if err != nil {
-		c.sysconn.Close()
-		return err
+		conn.Close()
+		return nil, err
 	}
 
-	err = c.sysconn.Hello()
+	err = conn.Hello()
 	if err != nil {
-		c.sysconn.Close()
-		return err
+		conn.Close()
+		return nil, err
 	}
 
-	c.sysobj = c.sysconn.Object("org.freedesktop.systemd1", dbus.ObjectPath("/org/freedesktop/systemd1"))
+	return conn, nil
+}
 
-	// Setup the listeners on jobs so that we can get completions
-	c.sysconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
-		"type='signal', interface='org.freedesktop.systemd1.Manager', member='JobRemoved'")
-	c.initSubscription()
-	c.initDispatch()
-
-	return nil
+func systemdObject(conn *dbus.Conn) *dbus.Object {
+	return conn.Object("org.freedesktop.systemd1", dbus.ObjectPath("/org/freedesktop/systemd1"))
 }
diff --git a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/dbus_test.go b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/dbus_test.go
index 2e80f73..3ea131e 100644
--- a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/dbus_test.go
+++ b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/dbus_test.go
@@ -1,18 +1,16 @@
-/*
-Copyright 2013 CoreOS Inc.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 package dbus
 
@@ -20,15 +18,53 @@
 	"testing"
 )
 
-// TestObjectPath ensures path encoding of the systemd rules works.
-func TestObjectPath(t *testing.T) {
-	input := "/silly-path/to@a/unit..service"
-	output := ObjectPath(input)
-	expected := "/silly_2dpath/to_40a/unit_2e_2eservice"
-
-	if string(output) != expected {
-		t.Fatalf("Output '%s' did not match expected '%s'", output, expected)
+func TestNeedsEscape(t *testing.T) {
+	// Anything not 0-9a-zA-Z should always be escaped
+	for want, vals := range map[bool][]byte{
+		false: []byte{'a', 'b', 'z', 'A', 'Q', '1', '4', '9'},
+		true:  []byte{'#', '%', '$', '!', '.', '_', '-', '%', '\\'},
+	} {
+		for i := 1; i < 10; i++ {
+			for _, b := range vals {
+				got := needsEscape(i, b)
+				if got != want {
+					t.Errorf("needsEscape(%d, %c) returned %t, want %t", i, b, got, want)
+				}
+			}
+		}
 	}
+
+	// 0-9 in position 0 should be escaped
+	for want, vals := range map[bool][]byte{
+		false: []byte{'A', 'a', 'e', 'x', 'Q', 'Z'},
+		true:  []byte{'0', '4', '5', '9'},
+	} {
+		for _, b := range vals {
+			got := needsEscape(0, b)
+			if got != want {
+				t.Errorf("needsEscape(0, %c) returned %t, want %t", b, got, want)
+			}
+		}
+	}
+
+}
+
+func TestPathBusEscape(t *testing.T) {
+	for in, want := range map[string]string{
+		"":                   "_",
+		"foo.service":        "foo_2eservice",
+		"foobar":             "foobar",
+		"woof@woof.service":  "woof_40woof_2eservice",
+		"0123456":            "_30123456",
+		"account_db.service": "account_5fdb_2eservice",
+		"got-dashes":         "got_2ddashes",
+	} {
+		got := PathBusEscape(in)
+		if got != want {
+			t.Errorf("bad result for PathBusEscape(%s): got %q, want %q", in, got, want)
+		}
+	}
+
 }
 
 // TestNew ensures that New() works without errors.
diff --git a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/methods.go b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/methods.go
index a60de05..ab614c7 100644
--- a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/methods.go
+++ b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/methods.go
@@ -1,30 +1,27 @@
-/*
-Copyright 2013 CoreOS Inc.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 package dbus
 
 import (
 	"errors"
+	"path"
+	"strconv"
+
 	"github.com/godbus/dbus"
 )
 
-func (c *Conn) initJobs() {
-	c.jobListener.jobs = make(map[dbus.ObjectPath]chan string)
-}
-
 func (c *Conn) jobComplete(signal *dbus.Signal) {
 	var id uint32
 	var job dbus.ObjectPath
@@ -40,29 +37,29 @@
 	c.jobListener.Unlock()
 }
 
-func (c *Conn) startJob(job string, args ...interface{}) (<-chan string, error) {
-	c.jobListener.Lock()
-	defer c.jobListener.Unlock()
-
-	ch := make(chan string, 1)
-	var path dbus.ObjectPath
-	err := c.sysobj.Call(job, 0, args...).Store(&path)
-	if err != nil {
-		return nil, err
+func (c *Conn) startJob(ch chan<- string, job string, args ...interface{}) (int, error) {
+	if ch != nil {
+		c.jobListener.Lock()
+		defer c.jobListener.Unlock()
 	}
-	c.jobListener.jobs[path] = ch
-	return ch, nil
+
+	var p dbus.ObjectPath
+	err := c.sysobj.Call(job, 0, args...).Store(&p)
+	if err != nil {
+		return 0, err
+	}
+
+	if ch != nil {
+		c.jobListener.jobs[p] = ch
+	}
+
+	// ignore error since 0 is fine if conversion fails
+	jobID, _ := strconv.Atoi(path.Base(string(p)))
+
+	return jobID, nil
 }
 
-func (c *Conn) runJob(job string, args ...interface{}) (string, error) {
-	respCh, err := c.startJob(job, args...)
-	if err != nil {
-		return "", err
-	}
-	return <-respCh, nil
-}
-
-// StartUnit enqeues a start job and depending jobs, if any (unless otherwise
+// StartUnit enqueues a start job and depending jobs, if any (unless otherwise
 // specified by the mode string).
 //
 // Takes the unit to activate, plus a mode string. The mode needs to be one of
@@ -77,50 +74,58 @@
 // requirement dependencies. It is not recommended to make use of the latter
 // two options.
 //
-// Result string: one of done, canceled, timeout, failed, dependency, skipped.
+// If the provided channel is non-nil, a result string will be sent to it upon
+// job completion: one of done, canceled, timeout, failed, dependency, skipped.
 // done indicates successful execution of a job. canceled indicates that a job
 // has been canceled  before it finished execution. timeout indicates that the
 // job timeout was reached. failed indicates that the job failed. dependency
 // indicates that a job this job has been depending on failed and the job hence
 // has been removed too. skipped indicates that a job was skipped because it
 // didn't apply to the units current state.
-func (c *Conn) StartUnit(name string, mode string) (string, error) {
-	return c.runJob("org.freedesktop.systemd1.Manager.StartUnit", name, mode)
+//
+// If no error occurs, the ID of the underlying systemd job will be returned. There
+// does exist the possibility for no error to be returned, but for the returned job
+// ID to be 0. In this case, the actual underlying ID is not 0 and this datapoint
+// should not be considered authoritative.
+//
+// If an error does occur, it will be returned to the user alongside a job ID of 0.
+func (c *Conn) StartUnit(name string, mode string, ch chan<- string) (int, error) {
+	return c.startJob(ch, "org.freedesktop.systemd1.Manager.StartUnit", name, mode)
 }
 
 // StopUnit is similar to StartUnit but stops the specified unit rather
 // than starting it.
-func (c *Conn) StopUnit(name string, mode string) (string, error) {
-	return c.runJob("org.freedesktop.systemd1.Manager.StopUnit", name, mode)
+func (c *Conn) StopUnit(name string, mode string, ch chan<- string) (int, error) {
+	return c.startJob(ch, "org.freedesktop.systemd1.Manager.StopUnit", name, mode)
 }
 
 // ReloadUnit reloads a unit.  Reloading is done only if the unit is already running and fails otherwise.
-func (c *Conn) ReloadUnit(name string, mode string) (string, error) {
-	return c.runJob("org.freedesktop.systemd1.Manager.ReloadUnit", name, mode)
+func (c *Conn) ReloadUnit(name string, mode string, ch chan<- string) (int, error) {
+	return c.startJob(ch, "org.freedesktop.systemd1.Manager.ReloadUnit", name, mode)
 }
 
 // RestartUnit restarts a service.  If a service is restarted that isn't
 // running it will be started.
-func (c *Conn) RestartUnit(name string, mode string) (string, error) {
-	return c.runJob("org.freedesktop.systemd1.Manager.RestartUnit", name, mode)
+func (c *Conn) RestartUnit(name string, mode string, ch chan<- string) (int, error) {
+	return c.startJob(ch, "org.freedesktop.systemd1.Manager.RestartUnit", name, mode)
 }
 
 // TryRestartUnit is like RestartUnit, except that a service that isn't running
 // is not affected by the restart.
-func (c *Conn) TryRestartUnit(name string, mode string) (string, error) {
-	return c.runJob("org.freedesktop.systemd1.Manager.TryRestartUnit", name, mode)
+func (c *Conn) TryRestartUnit(name string, mode string, ch chan<- string) (int, error) {
+	return c.startJob(ch, "org.freedesktop.systemd1.Manager.TryRestartUnit", name, mode)
 }
 
 // ReloadOrRestart attempts a reload if the unit supports it and use a restart
 // otherwise.
-func (c *Conn) ReloadOrRestartUnit(name string, mode string) (string, error) {
-	return c.runJob("org.freedesktop.systemd1.Manager.ReloadOrRestartUnit", name, mode)
+func (c *Conn) ReloadOrRestartUnit(name string, mode string, ch chan<- string) (int, error) {
+	return c.startJob(ch, "org.freedesktop.systemd1.Manager.ReloadOrRestartUnit", name, mode)
 }
 
 // ReloadOrTryRestart attempts a reload if the unit supports it and use a "Try"
 // flavored restart otherwise.
-func (c *Conn) ReloadOrTryRestartUnit(name string, mode string) (string, error) {
-	return c.runJob("org.freedesktop.systemd1.Manager.ReloadOrTryRestartUnit", name, mode)
+func (c *Conn) ReloadOrTryRestartUnit(name string, mode string, ch chan<- string) (int, error) {
+	return c.startJob(ch, "org.freedesktop.systemd1.Manager.ReloadOrTryRestartUnit", name, mode)
 }
 
 // StartTransientUnit() may be used to create and start a transient unit, which
@@ -128,8 +133,8 @@
 // system is rebooted. name is the unit name including suffix, and must be
 // unique. mode is the same as in StartUnit(), properties contains properties
 // of the unit.
-func (c *Conn) StartTransientUnit(name string, mode string, properties ...Property) (string, error) {
-	return c.runJob("org.freedesktop.systemd1.Manager.StartTransientUnit", name, mode, properties, make([]PropertyCollection, 0))
+func (c *Conn) StartTransientUnit(name string, mode string, properties []Property, ch chan<- string) (int, error) {
+	return c.startJob(ch, "org.freedesktop.systemd1.Manager.StartTransientUnit", name, mode, properties, make([]PropertyCollection, 0))
 }
 
 // KillUnit takes the unit name and a UNIX signal number to send.  All of the unit's
@@ -138,12 +143,17 @@
 	c.sysobj.Call("org.freedesktop.systemd1.Manager.KillUnit", 0, name, "all", signal).Store()
 }
 
+// ResetFailedUnit resets the "failed" state of a specific unit.
+func (c *Conn) ResetFailedUnit(name string) error {
+	return c.sysobj.Call("org.freedesktop.systemd1.Manager.ResetFailedUnit", 0, name).Store()
+}
+
 // getProperties takes the unit name and returns all of its dbus object properties, for the given dbus interface
 func (c *Conn) getProperties(unit string, dbusInterface string) (map[string]interface{}, error) {
 	var err error
 	var props map[string]dbus.Variant
 
-	path := ObjectPath("/org/freedesktop/systemd1/unit/" + unit)
+	path := unitPath(unit)
 	if !path.IsValid() {
 		return nil, errors.New("invalid unit name: " + unit)
 	}
@@ -171,7 +181,7 @@
 	var err error
 	var prop dbus.Variant
 
-	path := ObjectPath("/org/freedesktop/systemd1/unit/" + unit)
+	path := unitPath(unit)
 	if !path.IsValid() {
 		return nil, errors.New("invalid unit name: " + unit)
 	}
@@ -208,7 +218,7 @@
 }
 
 func (c *Conn) GetUnitTypeProperty(unit string, unitType string, propertyName string) (*Property, error) {
-	return c.getProperty(unit, "org.freedesktop.systemd1." + unitType, propertyName)
+	return c.getProperty(unit, "org.freedesktop.systemd1."+unitType, propertyName)
 }
 
 // ListUnits returns an array with all currently loaded units. Note that
@@ -394,3 +404,7 @@
 func (c *Conn) Reload() error {
 	return c.sysobj.Call("org.freedesktop.systemd1.Manager.Reload", 0).Store()
 }
+
+func unitPath(name string) dbus.ObjectPath {
+	return dbus.ObjectPath("/org/freedesktop/systemd1/unit/" + PathBusEscape(name))
+}
diff --git a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/methods_test.go b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/methods_test.go
index 8c7ab93..c9f9ccd 100644
--- a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/methods_test.go
+++ b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/methods_test.go
@@ -1,18 +1,16 @@
-/*
-Copyright 2013 CoreOS Inc.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 package dbus
 
@@ -46,7 +44,7 @@
 
 func setupUnit(target string, conn *Conn, t *testing.T) {
 	// Blindly stop the unit in case it is running
-	conn.StopUnit(target, "replace")
+	conn.StopUnit(target, "replace", nil)
 
 	// Blindly remove the symlink in case it exists
 	targetRun := filepath.Join("/run/systemd/system/", target)
@@ -81,11 +79,13 @@
 	linkUnit(target, conn, t)
 
 	// 2. Start the unit
-	job, err := conn.StartUnit(target, "replace")
+	reschan := make(chan string)
+	_, err := conn.StartUnit(target, "replace", reschan)
 	if err != nil {
 		t.Fatal(err)
 	}
 
+	job := <-reschan
 	if job != "done" {
 		t.Fatal("Job is not done:", job)
 	}
@@ -108,11 +108,14 @@
 	}
 
 	// 3. Stop the unit
-	job, err = conn.StopUnit(target, "replace")
+	_, err = conn.StopUnit(target, "replace", reschan)
 	if err != nil {
 		t.Fatal(err)
 	}
 
+	// wait for StopUnit job to complete
+	<-reschan
+
 	units, err = conn.ListUnits()
 
 	unit = nil
@@ -260,11 +263,13 @@
 	target := fmt.Sprintf("testing-transient-%d.service", rand.Int())
 
 	// Start the unit
-	job, err := conn.StartTransientUnit(target, "replace", props...)
+	reschan := make(chan string)
+	_, err := conn.StartTransientUnit(target, "replace", props, reschan)
 	if err != nil {
 		t.Fatal(err)
 	}
 
+	job := <-reschan
 	if job != "done" {
 		t.Fatal("Job is not done:", job)
 	}
@@ -287,11 +292,14 @@
 	}
 
 	// 3. Stop the unit
-	job, err = conn.StopUnit(target, "replace")
+	_, err = conn.StopUnit(target, "replace", reschan)
 	if err != nil {
 		t.Fatal(err)
 	}
 
+	// wait for StopUnit job to complete
+	<-reschan
+
 	units, err = conn.ListUnits()
 
 	unit = nil
@@ -315,16 +323,21 @@
 
 	jobSize := len(conn.jobListener.jobs)
 
-	_, err := conn.StartUnit(target, "replace")
+	reschan := make(chan string)
+	_, err := conn.StartUnit(target, "replace", reschan)
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	_, err = conn.StopUnit(target, "replace")
+	<-reschan
+
+	_, err = conn.StopUnit(target, "replace", reschan)
 	if err != nil {
 		t.Fatal(err)
 	}
 
+	<-reschan
+
 	currentJobSize := len(conn.jobListener.jobs)
 	if jobSize != currentJobSize {
 		t.Fatal("JobListener jobs leaked")
diff --git a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/properties.go b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/properties.go
index a06ccda..7520011 100644
--- a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/properties.go
+++ b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/properties.go
@@ -1,18 +1,16 @@
-/*
-Copyright 2013 CoreOS Inc.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 package dbus
 
diff --git a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/set.go b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/set.go
index 45ad1fb..f92e6fb 100644
--- a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/set.go
+++ b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/set.go
@@ -1,3 +1,17 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package dbus
 
 type set struct {
@@ -17,17 +31,17 @@
 	return
 }
 
-func (s *set) Length() (int) {
+func (s *set) Length() int {
 	return len(s.data)
 }
 
 func (s *set) Values() (values []string) {
-	 for val, _ := range s.data {
+	for val, _ := range s.data {
 		values = append(values, val)
-	 }
-	 return
+	}
+	return
 }
 
-func newSet() (*set) {
-	return &set{make(map[string] bool)}
+func newSet() *set {
+	return &set{make(map[string]bool)}
 }
diff --git a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/set_test.go b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/set_test.go
index c4435f8..2f04096 100644
--- a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/set_test.go
+++ b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/set_test.go
@@ -1,3 +1,17 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package dbus
 
 import (
diff --git a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/subscription.go b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/subscription.go
index fcd29b6..9964514 100644
--- a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/subscription.go
+++ b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/subscription.go
@@ -1,18 +1,16 @@
-/*
-Copyright 2013 CoreOS Inc.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 package dbus
 
@@ -33,12 +31,12 @@
 // systemd will automatically stop sending signals so there is no need to
 // explicitly call Unsubscribe().
 func (c *Conn) Subscribe() error {
-	c.sysconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
+	c.sigconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
 		"type='signal',interface='org.freedesktop.systemd1.Manager',member='UnitNew'")
-	c.sysconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
+	c.sigconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
 		"type='signal',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged'")
 
-	err := c.sysobj.Call("org.freedesktop.systemd1.Manager.Subscribe", 0).Store()
+	err := c.sigobj.Call("org.freedesktop.systemd1.Manager.Subscribe", 0).Store()
 	if err != nil {
 		return err
 	}
@@ -48,7 +46,7 @@
 
 // Unsubscribe this connection from systemd dbus events.
 func (c *Conn) Unsubscribe() error {
-	err := c.sysobj.Call("org.freedesktop.systemd1.Manager.Unsubscribe", 0).Store()
+	err := c.sigobj.Call("org.freedesktop.systemd1.Manager.Unsubscribe", 0).Store()
 	if err != nil {
 		return err
 	}
@@ -56,14 +54,10 @@
 	return nil
 }
 
-func (c *Conn) initSubscription() {
-	c.subscriber.ignore = make(map[dbus.ObjectPath]int64)
-}
-
-func (c *Conn) initDispatch() {
+func (c *Conn) dispatch() {
 	ch := make(chan *dbus.Signal, signalBuffer)
 
-	c.sysconn.Signal(ch)
+	c.sigconn.Signal(ch)
 
 	go func() {
 		for {
@@ -72,24 +66,32 @@
 				return
 			}
 
+			if signal.Name == "org.freedesktop.systemd1.Manager.JobRemoved" {
+				c.jobComplete(signal)
+			}
+
+			if c.subscriber.updateCh == nil {
+				continue
+			}
+
+			var unitPath dbus.ObjectPath
 			switch signal.Name {
 			case "org.freedesktop.systemd1.Manager.JobRemoved":
-				c.jobComplete(signal)
-
 				unitName := signal.Body[2].(string)
-				var unitPath dbus.ObjectPath
 				c.sysobj.Call("org.freedesktop.systemd1.Manager.GetUnit", 0, unitName).Store(&unitPath)
-				if unitPath != dbus.ObjectPath("") {
-					c.sendSubStateUpdate(unitPath)
-				}
 			case "org.freedesktop.systemd1.Manager.UnitNew":
-				c.sendSubStateUpdate(signal.Body[1].(dbus.ObjectPath))
+				unitPath = signal.Body[1].(dbus.ObjectPath)
 			case "org.freedesktop.DBus.Properties.PropertiesChanged":
 				if signal.Body[0].(string) == "org.freedesktop.systemd1.Unit" {
-					// we only care about SubState updates, which are a Unit property
-					c.sendSubStateUpdate(signal.Path)
+					unitPath = signal.Path
 				}
 			}
+
+			if unitPath == dbus.ObjectPath("") {
+				continue
+			}
+
+			c.sendSubStateUpdate(unitPath)
 		}
 	}()
 }
@@ -103,7 +105,7 @@
 // SubscribeUnitsCustom is like SubscribeUnits but lets you specify the buffer
 // size of the channels, the comparison function for detecting changes and a filter
 // function for cutting down on the noise that your channel receives.
-func (c *Conn) SubscribeUnitsCustom(interval time.Duration, buffer int, isChanged func(*UnitStatus, *UnitStatus) bool, filterUnit func (string) bool) (<-chan map[string]*UnitStatus, <-chan error) {
+func (c *Conn) SubscribeUnitsCustom(interval time.Duration, buffer int, isChanged func(*UnitStatus, *UnitStatus) bool, filterUnit func(string) bool) (<-chan map[string]*UnitStatus, <-chan error) {
 	old := make(map[string]*UnitStatus)
 	statusChan := make(chan map[string]*UnitStatus, buffer)
 	errChan := make(chan error, buffer)
@@ -176,9 +178,6 @@
 func (c *Conn) sendSubStateUpdate(path dbus.ObjectPath) {
 	c.subscriber.Lock()
 	defer c.subscriber.Unlock()
-	if c.subscriber.updateCh == nil {
-		return
-	}
 
 	if c.shouldIgnore(path) {
 		return
diff --git a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/subscription_set.go b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/subscription_set.go
index 2625786..5b408d5 100644
--- a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/subscription_set.go
+++ b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/subscription_set.go
@@ -1,3 +1,17 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package dbus
 
 import (
@@ -11,7 +25,6 @@
 	conn *Conn
 }
 
-
 func (s *SubscriptionSet) filter(unit string) bool {
 	return !s.Contains(unit)
 }
@@ -21,12 +34,24 @@
 func (s *SubscriptionSet) Subscribe() (<-chan map[string]*UnitStatus, <-chan error) {
 	// TODO: Make fully evented by using systemd 209 with properties changed values
 	return s.conn.SubscribeUnitsCustom(time.Second, 0,
-		func(u1, u2 *UnitStatus) bool { return *u1 != *u2 },
+		mismatchUnitStatus,
 		func(unit string) bool { return s.filter(unit) },
 	)
 }
 
 // NewSubscriptionSet returns a new subscription set.
-func (conn *Conn) NewSubscriptionSet() (*SubscriptionSet) {
+func (conn *Conn) NewSubscriptionSet() *SubscriptionSet {
 	return &SubscriptionSet{newSet(), conn}
 }
+
+// mismatchUnitStatus returns true if the provided UnitStatus objects
+// are not equivalent. false is returned if the objects are equivalent.
+// Only the Name, Description and state-related fields are used in
+// the comparison.
+func mismatchUnitStatus(u1, u2 *UnitStatus) bool {
+	return u1.Name != u2.Name ||
+		u1.Description != u2.Description ||
+		u1.LoadState != u2.LoadState ||
+		u1.ActiveState != u2.ActiveState ||
+		u1.SubState != u2.SubState
+}
diff --git a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/subscription_set_test.go b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/subscription_set_test.go
index 4ecd153..53f75df 100644
--- a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/subscription_set_test.go
+++ b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/subscription_set_test.go
@@ -1,3 +1,17 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package dbus
 
 import (
@@ -27,11 +41,13 @@
 	setupUnit(target, conn, t)
 	linkUnit(target, conn, t)
 
-	job, err := conn.StartUnit(target, "replace")
+	reschan := make(chan string)
+	_, err = conn.StartUnit(target, "replace", reschan)
 	if err != nil {
 		t.Fatal(err)
 	}
 
+	job := <-reschan
 	if job != "done" {
 		t.Fatal("Couldn't start", target)
 	}
diff --git a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/subscription_test.go b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/subscription_test.go
index f2b5dfc..e50fc6f 100644
--- a/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/subscription_test.go
+++ b/Godeps/_workspace/src/github.com/coreos/go-systemd/dbus/subscription_test.go
@@ -1,3 +1,17 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package dbus
 
 import (
@@ -49,11 +63,13 @@
 	setupUnit(target, conn, t)
 	linkUnit(target, conn, t)
 
-	job, err := conn.StartUnit(target, "replace")
+	reschan := make(chan string)
+	_, err = conn.StartUnit(target, "replace", reschan)
 	if err != nil {
 		t.Fatal(err)
 	}
 
+	job := <-reschan
 	if job != "done" {
 		t.Fatal("Couldn't start", target)
 	}
@@ -87,5 +103,3 @@
 success:
 	return
 }
-
-
diff --git a/Godeps/_workspace/src/github.com/coreos/go-systemd/util/util.go b/Godeps/_workspace/src/github.com/coreos/go-systemd/util/util.go
new file mode 100644
index 0000000..33832a1
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/coreos/go-systemd/util/util.go
@@ -0,0 +1,33 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package util contains utility functions related to systemd that applications
+// can use to check things like whether systemd is running.
+package util
+
+import (
+	"os"
+)
+
+// IsRunningSystemd checks whether the host was booted with systemd as its init
+// system. This functions similar to systemd's `sd_booted(3)`: internally, it
+// checks whether /run/systemd/system/ exists and is a directory.
+// http://www.freedesktop.org/software/systemd/man/sd_booted.html
+func IsRunningSystemd() bool {
+	fi, err := os.Lstat("/run/systemd/system")
+	if err != nil {
+		return false
+	}
+	return fi.IsDir()
+}
diff --git a/Godeps/_workspace/src/github.com/opencontainers/specs/LICENSE b/Godeps/_workspace/src/github.com/opencontainers/specs/LICENSE
new file mode 100644
index 0000000..bdc4036
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/opencontainers/specs/LICENSE
@@ -0,0 +1,191 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   Copyright 2015 The Linux Foundation.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/Godeps/_workspace/src/github.com/opencontainers/specs/README.md b/Godeps/_workspace/src/github.com/opencontainers/specs/README.md
index a3ae958..f5e57d9 100644
--- a/Godeps/_workspace/src/github.com/opencontainers/specs/README.md
+++ b/Godeps/_workspace/src/github.com/opencontainers/specs/README.md
@@ -1,6 +1,6 @@
 # Open Container Specifications
 
-This project is where the Open Container Project Specifications are written. This is a work in progress. We should have a first draft by end of July 2015.
+This project is where the [Open Container Initiative](http://www.opencontainers.org/) Specifications are written. This is a work in progress. We should have a first draft by end of July 2015.
 
 Table of Contents
 
@@ -9,6 +9,14 @@
   - [Linux Specific Configuration](config-linux.md)
 - [Runtime and Lifecycle](runtime.md)
 
+## Use Cases
+
+To provide context for users the following section gives example use cases for each part of the spec.
+
+### Filesystem Bundle & Configuration
+
+- A user can create a root filesystem and configuration, with low-level OS and host specific details, and launch it as a container under an Open Container runtime.
+
 # The 5 principles of Standard Containers
 
 Define a unit of software delivery called a Standard Container. The goal of a Standard Container is to encapsulate a software component and all its dependencies in a format that is self-describing and portable, so that any compliant runtime can run it without extra dependencies, regardless of the underlying machine and the contents of the container.
@@ -43,3 +51,79 @@
 
 With Standard Containers we can put an end to that embarrassment, by making INDUSTRIAL-GRADE DELIVERY of software a reality.
 
+# Contributing
+
+Development happens on github for the spec.  Issues are used for bugs and actionable items and longer
+discussions can happen on the mailing list.  You can subscribe and join the mailing list on
+[google groups](https://groups.google.com/a/opencontainers.org/forum/#!forum/dev).
+
+The specification and code is licensed under the Apache 2.0 license found in 
+the `LICENSE` file of this repository.  
+
+## Weekly Call
+
+The contributors and maintainers of the project have a weekly meeting Wednesdays at 10:00 AM PST.
+Everyone is welcome to participate in the call.  The link to the call will be posted on the mailing
+list each week along with set topics for discussion.
+Minutes for the call will be posted to the mailing list for those who are unable to join the call.
+
+## Markdown style
+
+To keep consistency throughout the Markdown files in the Open Container spec all files should be formatted one sentence per line.
+This fixes two things: it makes diffing easier with git and it resolves fights about line wrapping length.
+For example, this paragraph will span three lines in the Markdown source.
+
+### Sign your work
+
+The sign-off is a simple line at the end of the explanation for the
+patch, which certifies that you wrote it or otherwise have the right to
+pass it on as an open-source patch.  The rules are pretty simple: if you
+can certify the below (from
+[developercertificate.org](http://developercertificate.org/)):
+
+```
+Developer Certificate of Origin
+Version 1.1
+
+Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
+660 York Street, Suite 102,
+San Francisco, CA 94110 USA
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+
+
+Developer's Certificate of Origin 1.1
+
+By making a contribution to this project, I certify that:
+
+(a) The contribution was created in whole or in part by me and I
+    have the right to submit it under the open source license
+    indicated in the file; or
+
+(b) The contribution is based upon previous work that, to the best
+    of my knowledge, is covered under an appropriate open source
+    license and I have the right under that license to submit that
+    work with modifications, whether created in whole or in part
+    by me, under the same open source license (unless I am
+    permitted to submit under a different license), as indicated
+    in the file; or
+
+(c) The contribution was provided directly to me by some other
+    person who certified (a), (b) or (c) and I have not modified
+    it.
+
+(d) I understand and agree that this project and the contribution
+    are public and that a record of the contribution (including all
+    personal information I submit with it, including my sign-off) is
+    maintained indefinitely and may be redistributed consistent with
+    this project or the open source license(s) involved.
+```
+
+then you just add a line to every git commit message:
+
+    Signed-off-by: Joe Smith <joe@gmail.com>
+
+using your real name (sorry, no pseudonyms or anonymous contributions.)
+
+You can add the sign off when creating the git commit via `git commit -s`.
diff --git a/Godeps/_workspace/src/github.com/opencontainers/specs/bundle.md b/Godeps/_workspace/src/github.com/opencontainers/specs/bundle.md
index 1948e48..ff6906f 100644
--- a/Godeps/_workspace/src/github.com/opencontainers/specs/bundle.md
+++ b/Godeps/_workspace/src/github.com/opencontainers/specs/bundle.md
@@ -21,7 +21,7 @@
 ```
 /
 !
--- config.json
+--- config.json
 !
 --- rootfs
 !
diff --git a/Godeps/_workspace/src/github.com/opencontainers/specs/config-linux.md b/Godeps/_workspace/src/github.com/opencontainers/specs/config-linux.md
index 765a0cb..1927dae 100644
--- a/Godeps/_workspace/src/github.com/opencontainers/specs/config-linux.md
+++ b/Godeps/_workspace/src/github.com/opencontainers/specs/config-linux.md
@@ -97,7 +97,7 @@
 sysctl allows kernel parameters to be modified at runtime for the container.
 For more information, see [the man page](http://man7.org/linux/man-pages/man8/sysctl.8.html)
 
-```
+```json
    "sysctl": {
         "net.ipv4.ip_forward": "1",
         "net.core.somaxconn": "256"
@@ -106,7 +106,7 @@
 
 ## Linux rlimits
 
-```
+```json
    "rlimits": [
         {
             "type": "RLIMIT_NPROC",
@@ -120,7 +120,7 @@
 
 ## Linux user namespace mappings
 
-```
+```json
     "uidMappings": [
         {
             "hostID": 1000,
@@ -137,7 +137,14 @@
     ]
 ```
 
-uid/gid mappings describe the user namespace mappings from the host to the container. *from* is the starting uid/gid on the host to be mapped to *to* which is the starting uid/gid in the container and *count* refers to the number of ids to be mapped. The Linux kernel has a limit of 5 such mappings that can be specified.
+uid/gid mappings describe the user namespace mappings from the host to the container. *hostID* is the starting uid/gid on the host to be mapped to *containerID* which is the starting uid/gid in the container and *size* refers to the number of ids to be mapped. The Linux kernel has a limit of 5 such mappings that can be specified.
+
+## Rootfs Mount Propagation
+rootfsPropagation sets the rootfs's mount propagation. Its value is either slave, private, or shared. [The kernel doc](https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt) has more information about mount propagation.
+
+```json
+    "rootfsPropagation": "slave",
+```
 
 ## Security
 
diff --git a/Godeps/_workspace/src/github.com/opencontainers/specs/config.md b/Godeps/_workspace/src/github.com/opencontainers/specs/config.md
index 6f5d4bb..f0adcb4 100644
--- a/Godeps/_workspace/src/github.com/opencontainers/specs/config.md
+++ b/Godeps/_workspace/src/github.com/opencontainers/specs/config.md
@@ -80,8 +80,8 @@
 "mounts": [
     {
         "type": "ntfs",
-        "source": "\\?\Volume\{2eca078d-5cbc-43d3-aff8-7e8511f60d0e}\",
-        "destination": "C:\Users\crosbymichael\My Fancy Mount Point\",
+        "source": "\\\\?\\Volume\\{2eca078d-5cbc-43d3-aff8-7e8511f60d0e}\\",
+        "destination": "C:\\Users\\crosbymichael\\My Fancy Mount Point\\",
         "options": ""
     }
 ]
diff --git a/Godeps/_workspace/src/github.com/opencontainers/specs/runtime.md b/Godeps/_workspace/src/github.com/opencontainers/specs/runtime.md
index c558308..dbd055f 100644
--- a/Godeps/_workspace/src/github.com/opencontainers/specs/runtime.md
+++ b/Godeps/_workspace/src/github.com/opencontainers/specs/runtime.md
@@ -12,6 +12,48 @@
 
 ### Stop (process)
 
-Not sure we need that from oc cli. Process is killed from the outside.
+Not sure we need that from runc cli. Process is killed from the outside.
 
-This event needs to be captured by oc to run onstop event handlers.
+This event needs to be captured by runc to run onstop event handlers.
+
+## Hooks
+Hooks allow one to run code before/after various lifecycle events of the container.
+The state of the container is passed to the hooks over stdin, so the hooks could get the information they need to do their work.
+
+Hook paths are absolute and are executed from the host's filesystem.
+
+### Pre-start
+The pre-start hooks are called after the container process is spawned, but before the user supplied command is executed.
+They are called after the container namespaces are created on Linux, so they provide an opportunity to customize the container.
+In Linux, for e.g., the network namespace could be configured in this hook.
+
+If a hook returns a non-zero exit code, then an error including the exit code and the stderr is returned to the caller and the container is torn down.
+
+### Post-stop
+The post-stop hooks are called after the container process is stopped. Cleanup or debugging could be performed in such a hook.
+If a hook returns a non-zero exit code, then an error is logged and the remaining hooks are executed.
+
+*Example*
+
+```json
+    "hooks" : {
+        "prestart": [
+            {
+                "path": "/usr/bin/fix-mounts",
+                "args": ["arg1", "arg2"],
+                "env":  [ "key1=value1"]
+            },
+            {
+                "path": "/usr/bin/setup-network"
+            }
+        ],
+        "poststop": [
+            {
+                "path": "/usr/sbin/cleanup.sh",
+                "args": ["-f"]
+            }
+        ]
+    }
+```
+
+`path` is required for a hook. `args` and `env` are optional.
diff --git a/Godeps/_workspace/src/github.com/opencontainers/specs/spec.go b/Godeps/_workspace/src/github.com/opencontainers/specs/spec.go
index 30b3c1b..2100cca 100644
--- a/Godeps/_workspace/src/github.com/opencontainers/specs/spec.go
+++ b/Godeps/_workspace/src/github.com/opencontainers/specs/spec.go
@@ -11,10 +11,20 @@
 	Process Process `json:"process"`
 	// Root is the root information for the container's filesystem.
 	Root Root `json:"root"`
-	// Hostname is the containers host name.
+	// Hostname is the container's host name.
 	Hostname string `json:"hostname"`
 	// Mounts profile configuration for adding mounts to the container's filesystem.
 	Mounts []Mount `json:"mounts"`
+	// Hooks are the commands run at various lifecycle events of the container.
+	Hooks Hooks `json:"hooks"`
+}
+
+type Hooks struct {
+	// Prestart is a list of hooks to be run before the container process is executed.
+	// On Linux, they are run after the container namespaces are created.
+	Prestart []Hook `json:"prestart"`
+	// Poststop is a list of hooks to be run after the container process exits.
+	Poststop []Hook `json:"poststop"`
 }
 
 // Mount specifies a mount for a container.
@@ -61,3 +71,10 @@
 	// Arch is the architecture
 	Arch string `json:"arch"`
 }
+
+// Hook specifies a command that is run at a particular event in the lifecycle of a container.
+type Hook struct {
+	Path string   `json:"path"`
+	Args []string `json:"args"`
+	Env  []string `json:"env"`
+}
diff --git a/Godeps/_workspace/src/github.com/opencontainers/specs/spec_linux.go b/Godeps/_workspace/src/github.com/opencontainers/specs/spec_linux.go
index f5f561b..3c82db4 100644
--- a/Godeps/_workspace/src/github.com/opencontainers/specs/spec_linux.go
+++ b/Godeps/_workspace/src/github.com/opencontainers/specs/spec_linux.go
@@ -2,101 +2,107 @@
 
 package specs
 
-// LinuxSpec is the full specification for linux containers.
+// LinuxSpec is the full specification for Linux containers
 type LinuxSpec struct {
 	Spec
-	// Linux is platform specific configuration for linux based containers.
+	// Linux is platform specific configuration for Linux based containers
 	Linux Linux `json:"linux"`
 }
 
-// Linux contains platform specific configuration for linux based containers.
+// Linux contains platform specific configuration for Linux based containers
 type Linux struct {
-	// UidMapping specifies user mappings for supporting user namespaces on linux.
-	UidMappings []IDMapping `json:"uidMappings"`
-	// UidMapping specifies group mappings for supporting user namespaces on linux.
-	GidMappings []IDMapping `json:"gidMappings"`
-	// Rlimits specifies rlimit options to apply to the container's process.
+	// UIDMapping specifies user mappings for supporting user namespaces on Linux
+	UIDMappings []IDMapping `json:"uidMappings"`
+	// GIDMapping specifies group mappings for supporting user namespaces on Linux
+	GIDMappings []IDMapping `json:"gidMappings"`
+	// Rlimits specifies rlimit options to apply to the container's process
 	Rlimits []Rlimit `json:"rlimits"`
-	// Sysctl are a set of key value pairs that are set for the container on start.
+	// Sysctl are a set of key value pairs that are set for the container on start
 	Sysctl map[string]string `json:"sysctl"`
 	// Resources contain cgroup information for handling resource constraints
-	// for the container.
+	// for the container
 	Resources Resources `json:"resources"`
-	// Namespaces contains the namespaces that are created and/or joined by the container.
+	// Namespaces contains the namespaces that are created and/or joined by the container
 	Namespaces []Namespace `json:"namespaces"`
-	// Capabilities are linux capabilities that are kept for the container.
+	// Capabilities are Linux capabilities that are kept for the container
 	Capabilities []string `json:"capabilities"`
-	// Devices are a list of device nodes that are created and enabled for the container.
+	// Devices are a list of device nodes that are created and enabled for the container
 	Devices []string `json:"devices"`
+	// RootfsPropagation is the rootfs mount propagation mode for the container
+	RootfsPropagation string `json:"rootfsPropagation"`
 }
 
-// User specifies linux specific user and group information for the container's
-// main process.
+// User specifies Linux specific user and group information for the container's
+// main process
 type User struct {
-	// Uid is the user id.
-	Uid int32 `json:"uid"`
-	// Gid is the group id.
-	Gid int32 `json:"gid"`
-	// AdditionalGids are additional group ids set the the container's process.
+	// Uid is the user id
+	UID int32 `json:"uid"`
+	// Gid is the group id
+	GID int32 `json:"gid"`
+	// AdditionalGids are additional group ids set for the container's process
 	AdditionalGids []int32 `json:"additionalGids"`
 }
 
-// Namespace is the configuration for a linux namespace.
+// Namespace is the configuration for a Linux namespace
 type Namespace struct {
-	// Type is the type of linux namespace.
+	// Type is the type of Linux namespace
 	Type string `json:"type"`
 	// Path is a path to an existing namespace persisted on disk that can be joined
-	// and is of the same type.
+	// and is of the same type
 	Path string `json:"path"`
 }
 
-// IDMapping specifies uid/gid mappings.
+// IDMapping specifies UID/GID mappings
 type IDMapping struct {
-	// HostID is the uid/gid of the host user or group.
+	// HostID is the UID/GID of the host user or group
 	HostID int32 `json:"hostID"`
-	// ContainerID is the uid/gid of the container's user or group.
+	// ContainerID is the UID/GID of the container's user or group
 	ContainerID int32 `json:"containerID"`
-	// Size is the length of the range of IDs mapped between the two namespaces.
+	// Size is the length of the range of IDs mapped between the two namespaces
 	Size int32 `json:"size"`
 }
 
-// Rlimit type and restrictions.
+// Rlimit type and restrictions
 type Rlimit struct {
-	// Type of the rlimit to set.
+	// Type of the rlimit to set
 	Type int `json:"type"`
-	// Hard is the hard limit for the specified type.
+	// Hard is the hard limit for the specified type
 	Hard uint64 `json:"hard"`
-	// Soft is the soft limit for the specified type.
+	// Soft is the soft limit for the specified type
 	Soft uint64 `json:"soft"`
 }
 
+// HugepageLimit structure corresponds to limiting kernel hugepages
 type HugepageLimit struct {
 	Pagesize string `json:"pageSize"`
 	Limit    int    `json:"limit"`
 }
 
+// InterfacePriority for network interfaces
 type InterfacePriority struct {
-	// Name is the name of the network interface.
+	// Name is the name of the network interface
 	Name string `json:"name"`
-	// Priority for the interface.
+	// Priority for the interface
 	Priority int64 `json:"priority"`
 }
 
+// BlockIO for Linux cgroup 'blockio' resource management
 type BlockIO struct {
-	// Specifies per cgroup weight, range is from 10 to 1000.
+	// Specifies per cgroup weight, range is from 10 to 1000
 	Weight int64 `json:"blkioWeight"`
-	// Weight per cgroup per device, can override BlkioWeight.
+	// Weight per cgroup per device, can override BlkioWeight
 	WeightDevice string `json:"blkioWeightDevice"`
-	// IO read rate limit per cgroup per device, bytes per second.
+	// IO read rate limit per cgroup per device, bytes per second
 	ThrottleReadBpsDevice string `json:"blkioThrottleReadBpsDevice"`
-	// IO write rate limit per cgroup per divice, bytes per second.
+	// IO write rate limit per cgroup per divice, bytes per second
 	ThrottleWriteBpsDevice string `json:"blkioThrottleWriteBpsDevice"`
-	// IO read rate limit per cgroup per device, IO per second.
+	// IO read rate limit per cgroup per device, IO per second
 	ThrottleReadIOpsDevice string `json:"blkioThrottleReadIopsDevice"`
-	// IO write rate limit per cgroup per device, IO per second.
+	// IO write rate limit per cgroup per device, IO per second
 	ThrottleWriteIOpsDevice string `json:"blkioThrottleWriteIopsDevice"`
 }
 
+// Memory for Linux cgroup 'memory' resource management
 type Memory struct {
 	// Memory limit (in bytes)
 	Limit int64 `json:"limit"`
@@ -106,45 +112,48 @@
 	Swap int64 `json:"swap"`
 	// Kernel memory limit (in bytes)
 	Kernel int64 `json:"kernel"`
-	// How aggressive the kernel will swap memory pages. Range from 0 to 100. Set -1 to use system default.
+	// How aggressive the kernel will swap memory pages. Range from 0 to 100. Set -1 to use system default
 	Swappiness int64 `json:"swappiness"`
 }
 
+// CPU for Linux cgroup 'cpu' resource management
 type CPU struct {
-	// CPU shares (relative weight vs. other cgroups with cpu shares).
+	// CPU shares (relative weight vs. other cgroups with cpu shares)
 	Shares int64 `json:"shares"`
-	// CPU hardcap limit (in usecs). Allowed cpu time in a given period.
+	// CPU hardcap limit (in usecs). Allowed cpu time in a given period
 	Quota int64 `json:"quota"`
-	// CPU period to be used for hardcapping (in usecs). 0 to use system default.
+	// CPU period to be used for hardcapping (in usecs). 0 to use system default
 	Period int64 `json:"period"`
-	// How many time CPU will use in realtime scheduling (in usecs).
+	// How many time CPU will use in realtime scheduling (in usecs)
 	RealtimeRuntime int64 `json:"realtimeRuntime"`
-	// CPU period to be used for realtime scheduling (in usecs).
+	// CPU period to be used for realtime scheduling (in usecs)
 	RealtimePeriod int64 `json:"realtimePeriod"`
-	// CPU to use within the cpuset.
+	// CPU to use within the cpuset
 	Cpus string `json:"cpus"`
-	// MEM to use within the cpuset.
+	// MEM to use within the cpuset
 	Mems string `json:"mems"`
 }
 
+// Network identification and priority configuration
 type Network struct {
-	// Set class identifier for container's network packets.
+	// Set class identifier for container's network packets
 	ClassID string `json:"classId"`
-	// Set priority of network traffic for container.
+	// Set priority of network traffic for container
 	Priorities []InterfacePriority `json:"priorities"`
 }
 
+// Resources has container runtime resource constraints
 type Resources struct {
-	// DisableOOMKiller disables the OOM killer for out of memory conditions.
+	// DisableOOMKiller disables the OOM killer for out of memory conditions
 	DisableOOMKiller bool `json:"disableOOMKiller"`
-	// Memory restriction configuration.
+	// Memory restriction configuration
 	Memory Memory `json:"memory"`
-	// CPU resource restriction configuration.
+	// CPU resource restriction configuration
 	CPU CPU `json:"cpu"`
-	// BlockIO restriction configuration.
+	// BlockIO restriction configuration
 	BlockIO BlockIO `json:"blockIO"`
 	// Hugetlb limit (in bytes)
 	HugepageLimits []HugepageLimit `json:"hugepageLimits"`
-	// Network restriction configuration.
+	// Network restriction configuration
 	Network Network `json:"network"`
 }
diff --git a/libcontainer/cgroups/systemd/apply_systemd.go b/libcontainer/cgroups/systemd/apply_systemd.go
index 1472ba3..7b523da 100644
--- a/libcontainer/cgroups/systemd/apply_systemd.go
+++ b/libcontainer/cgroups/systemd/apply_systemd.go
@@ -12,7 +12,8 @@
 	"sync"
 	"time"
 
-	systemd "github.com/coreos/go-systemd/dbus"
+	systemdDbus "github.com/coreos/go-systemd/dbus"
+	systemdUtil "github.com/coreos/go-systemd/util"
 	"github.com/godbus/dbus"
 	"github.com/opencontainers/runc/libcontainer/cgroups"
 	"github.com/opencontainers/runc/libcontainer/cgroups/fs"
@@ -52,21 +53,20 @@
 
 var (
 	connLock                        sync.Mutex
-	theConn                         *systemd.Conn
+	theConn                         *systemdDbus.Conn
 	hasStartTransientUnit           bool
 	hasTransientDefaultDependencies bool
 )
 
-func newProp(name string, units interface{}) systemd.Property {
-	return systemd.Property{
+func newProp(name string, units interface{}) systemdDbus.Property {
+	return systemdDbus.Property{
 		Name:  name,
 		Value: dbus.MakeVariant(units),
 	}
 }
 
 func UseSystemd() bool {
-	s, err := os.Stat("/run/systemd/system")
-	if err != nil || !s.IsDir() {
+	if !systemdUtil.IsRunningSystemd() {
 		return false
 	}
 
@@ -75,7 +75,7 @@
 
 	if theConn == nil {
 		var err error
-		theConn, err = systemd.New()
+		theConn, err = systemdDbus.New()
 		if err != nil {
 			return false
 		}
@@ -84,7 +84,7 @@
 		hasStartTransientUnit = true
 
 		// But if we get UnknownMethod error we don't
-		if _, err := theConn.StartTransientUnit("test.scope", "invalid"); err != nil {
+		if _, err := theConn.StartTransientUnit("test.scope", "invalid", nil, nil); err != nil {
 			if dbusError, ok := err.(dbus.Error); ok {
 				if dbusError.Name == "org.freedesktop.DBus.Error.UnknownMethod" {
 					hasStartTransientUnit = false
@@ -99,7 +99,7 @@
 		scope := fmt.Sprintf("libcontainer-%d-systemd-test-default-dependencies.scope", os.Getpid())
 		testScopeExists := true
 		for i := 0; i <= testScopeWait; i++ {
-			if _, err := theConn.StopUnit(scope, "replace"); err != nil {
+			if _, err := theConn.StopUnit(scope, "replace", nil); err != nil {
 				if dbusError, ok := err.(dbus.Error); ok {
 					if strings.Contains(dbusError.Name, "org.freedesktop.systemd1.NoSuchUnit") {
 						testScopeExists = false
@@ -118,7 +118,7 @@
 		// Assume StartTransientUnit on a scope allows DefaultDependencies
 		hasTransientDefaultDependencies = true
 		ddf := newProp("DefaultDependencies", false)
-		if _, err := theConn.StartTransientUnit(scope, "replace", ddf); err != nil {
+		if _, err := theConn.StartTransientUnit(scope, "replace", []systemdDbus.Property{ddf}, nil); err != nil {
 			if dbusError, ok := err.(dbus.Error); ok {
 				if strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.PropertyReadOnly") {
 					hasTransientDefaultDependencies = false
@@ -127,7 +127,7 @@
 		}
 
 		// Not critical because of the stop unit logic above.
-		theConn.StopUnit(scope, "replace")
+		theConn.StopUnit(scope, "replace", nil)
 	}
 	return hasStartTransientUnit
 }
@@ -147,7 +147,7 @@
 		c          = m.Cgroups
 		unitName   = getUnitName(c)
 		slice      = "system.slice"
-		properties []systemd.Property
+		properties []systemdDbus.Property
 	)
 
 	if c.Slice != "" {
@@ -155,8 +155,8 @@
 	}
 
 	properties = append(properties,
-		systemd.PropSlice(slice),
-		systemd.PropDescription("docker container "+c.Name),
+		systemdDbus.PropSlice(slice),
+		systemdDbus.PropDescription("docker container "+c.Name),
 		newProp("PIDs", []uint32{uint32(pid)}),
 	)
 
@@ -198,7 +198,7 @@
 		}
 	}
 
-	if _, err := theConn.StartTransientUnit(unitName, "replace", properties...); err != nil {
+	if _, err := theConn.StartTransientUnit(unitName, "replace", properties, nil); err != nil {
 		return err
 	}
 
@@ -269,7 +269,7 @@
 func (m *Manager) Destroy() error {
 	m.mu.Lock()
 	defer m.mu.Unlock()
-	theConn.StopUnit(getUnitName(m.Cgroups), "replace")
+	theConn.StopUnit(getUnitName(m.Cgroups), "replace", nil)
 	if err := cgroups.RemovePaths(m.Paths); err != nil {
 		return err
 	}
diff --git a/libcontainer/factory_linux.go b/libcontainer/factory_linux.go
index 5eb561f..0f7ba67 100644
--- a/libcontainer/factory_linux.go
+++ b/libcontainer/factory_linux.go
@@ -46,7 +46,7 @@
 			}
 			name = abs
 		}
-		l.InitPath = name
+		l.InitPath = "/proc/self/exe"
 		l.InitArgs = append([]string{name}, args[1:]...)
 		return nil
 	}
diff --git a/spec.go b/spec.go
index a70e858..2a025cd 100644
--- a/spec.go
+++ b/spec.go
@@ -316,7 +316,7 @@
 }
 
 func setupUserNamespace(spec *specs.LinuxSpec, config *configs.Config) error {
-	if len(spec.Linux.UidMappings) == 0 {
+	if len(spec.Linux.UIDMappings) == 0 {
 		return nil
 	}
 	config.Namespaces.Add(configs.NEWUSER, "")
@@ -327,10 +327,10 @@
 			Size:        int(m.Size),
 		}
 	}
-	for _, m := range spec.Linux.UidMappings {
+	for _, m := range spec.Linux.UIDMappings {
 		config.UidMappings = append(config.UidMappings, create(m))
 	}
-	for _, m := range spec.Linux.GidMappings {
+	for _, m := range spec.Linux.GIDMappings {
 		config.GidMappings = append(config.GidMappings, create(m))
 	}
 	rootUid, err := config.HostUID()
diff --git a/utils.go b/utils.go
index 9f59b0d..151705e 100644
--- a/utils.go
+++ b/utils.go
@@ -168,7 +168,7 @@
 		Args: p.Args,
 		Env:  p.Env,
 		// TODO: fix libcontainer's API to better support uid/gid in a typesafe way.
-		User:   fmt.Sprintf("%d:%d", p.User.Uid, p.User.Gid),
+		User:   fmt.Sprintf("%d:%d", p.User.UID, p.User.GID),
 		Cwd:    p.Cwd,
 		Stdin:  os.Stdin,
 		Stdout: os.Stdout,