diff --git a/Makefile b/Makefile index 86507f82..4e508842 100644 --- a/Makefile +++ b/Makefile @@ -66,7 +66,7 @@ gosuper: go-builder test-gosuper: go-builder -docker rm --volumes -f resin_test_gosuper_$(JOB_NAME) || true - docker run --name resin_test_gosuper_$(JOB_NAME) -v /var/run/dbus:/mnt/root/run/dbus resin/go-supervisor-builder:$(SUPERVISOR_VERSION) bash -c "cd src/resin-supervisor/gosuper && ./test_formatting.sh && go test -v ./gosuper" + docker run --name resin_test_gosuper_$(JOB_NAME) -v /var/run/dbus:/mnt/root/run/dbus -e DBUS_SYSTEM_BUS_ADDRESS="unix:path=/mnt/root/run/dbus/system_bus_socket" resin/go-supervisor-builder:$(SUPERVISOR_VERSION) bash -c "cd src/resin-supervisor/gosuper && ./test_formatting.sh && go test -v ./gosuper" docker rm --volumes -f resin_test_gosuper_$(JOB_NAME) format-gosuper: go-builder diff --git a/entry.sh b/entry.sh index 0a099ea3..54c77990 100755 --- a/entry.sh +++ b/entry.sh @@ -22,6 +22,7 @@ mount -t tmpfs -o size=1m tmpfs /var/run/resin if [ -z "$GOSUPER_SOCKET" ]; then export GOSUPER_SOCKET=/var/run/resin/gosuper.sock fi +export DBUS_SYSTEM_BUS_ADDRESS="unix:path=/mnt/root/run/dbus/system_bus_socket" /usr/bin/supervisord -c /etc/supervisor/supervisord.conf diff --git a/gosuper/Godeps/Godeps.json b/gosuper/Godeps/Godeps.json index fb6cf6b2..99169304 100644 --- a/gosuper/Godeps/Godeps.json +++ b/gosuper/Godeps/Godeps.json @@ -5,6 +5,11 @@ "./..." ], "Deps": [ + { + "ImportPath": "github.com/coreos/go-systemd/login1", + "Comment": "v3-13-g392c689", + "Rev": "392c689e425689acb51976419a8d62878966511f" + }, { "ImportPath": "github.com/godbus/dbus", "Comment": "v2-14-g69f6e9a", diff --git a/gosuper/Godeps/_workspace/src/github.com/coreos/go-systemd/login1/dbus.go b/gosuper/Godeps/_workspace/src/github.com/coreos/go-systemd/login1/dbus.go new file mode 100644 index 00000000..05c5fc02 --- /dev/null +++ b/gosuper/Godeps/_workspace/src/github.com/coreos/go-systemd/login1/dbus.go @@ -0,0 +1,84 @@ +// 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 logind API. See http://www.freedesktop.org/wiki/Software/systemd/logind/ +package login1 + +import ( + "os" + "strconv" + + "resin-supervisor/gosuper/Godeps/_workspace/src/github.com/godbus/dbus" +) + +const ( + dbusInterface = "org.freedesktop.login1.Manager" + dbusPath = "/org/freedesktop/login1" +) + +// Conn is a connection to systemds dbus endpoint. +type Conn struct { + conn *dbus.Conn + object dbus.BusObject +} + +// New() establishes a connection to the system bus and authenticates. +func New() (*Conn, error) { + c := new(Conn) + + if err := c.initConnection(); err != nil { + return nil, err + } + + return c, nil +} + +func (c *Conn) initConnection() error { + var err error + c.conn, err = dbus.SystemBusPrivate() + if err != nil { + return err + } + + // Only use EXTERNAL method, and hardcode the uid (not username) + // to avoid a username lookup (which requires a dynamically linked + // libc) + methods := []dbus.Auth{dbus.AuthExternal(strconv.Itoa(os.Getuid()))} + + err = c.conn.Auth(methods) + if err != nil { + c.conn.Close() + return err + } + + err = c.conn.Hello() + if err != nil { + c.conn.Close() + return err + } + + c.object = c.conn.Object("org.freedesktop.login1", dbus.ObjectPath(dbusPath)) + + return nil +} + +// Reboot asks logind for a reboot optionally asking for auth. +func (c *Conn) Reboot(askForAuth bool) { + c.object.Call(dbusInterface+".Reboot", 0, askForAuth) +} + +// PowerOff asks logind for a power off optionally asking for auth. +func (c *Conn) PowerOff(askForAuth bool) { + c.object.Call(dbusInterface+".PowerOff", 0, askForAuth) +} diff --git a/gosuper/Godeps/_workspace/src/github.com/coreos/go-systemd/login1/dbus_test.go b/gosuper/Godeps/_workspace/src/github.com/coreos/go-systemd/login1/dbus_test.go new file mode 100644 index 00000000..d160f470 --- /dev/null +++ b/gosuper/Godeps/_workspace/src/github.com/coreos/go-systemd/login1/dbus_test.go @@ -0,0 +1,28 @@ +// 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 login1 + +import ( + "testing" +) + +// TestNew ensures that New() works without errors. +func TestNew(t *testing.T) { + _, err := New() + + if err != nil { + t.Fatal(err) + } +} diff --git a/gosuper/gosuper/api.go b/gosuper/gosuper/api.go index addb28a8..ff9b3eb8 100644 --- a/gosuper/gosuper/api.go +++ b/gosuper/gosuper/api.go @@ -96,7 +96,7 @@ func RebootHandler(writer http.ResponseWriter, request *http.Request) { sendResponse := responseSender(writer) sendResponse("OK", "", http.StatusAccepted) - systemd.Reboot() + systemd.Logind.Reboot(false) } func ShutdownHandler(writer http.ResponseWriter, request *http.Request) { @@ -104,5 +104,5 @@ func ShutdownHandler(writer http.ResponseWriter, request *http.Request) { sendResponse := responseSender(writer) sendResponse("OK", "", http.StatusAccepted) - systemd.Shutdown() + systemd.Logind.PowerOff(false) } diff --git a/gosuper/systemd/systemd.go b/gosuper/systemd/systemd.go index d27b4ac3..a9716c4a 100644 --- a/gosuper/systemd/systemd.go +++ b/gosuper/systemd/systemd.go @@ -2,33 +2,15 @@ package systemd import ( "log" - "os/exec" - "resin-supervisor/gosuper/Godeps/_workspace/src/github.com/godbus/dbus" + "resin-supervisor/gosuper/Godeps/_workspace/src/github.com/coreos/go-systemd/login1" ) -var Systemd dbus.BusObject +var Logind *login1.Conn func init() { - if conn, err := dbus.Dial("unix:path=/mnt/root/run/dbus/system_bus_socket"); err != nil { + var err error + if Logind, err = login1.New(); err != nil { log.Fatal("Failed to connect to host system bus") - } else { - Systemd = conn.Object("org.freedesktop.systemd1", "/org/freedesktop/systemd1") - } -} - -func Reboot() { - if err := exec.Command("sync").Run(); err != nil { - log.Println(err) - } else if call := Systemd.Call("org.freedesktop.systemd1.Reboot", 0); call.Err != nil { - log.Println(call.Err) - } -} - -func Shutdown() { - if err := exec.Command("sync").Run(); err != nil { - log.Println(err) - } else if call := Systemd.Call("org.freedesktop.systemd1.PowerOff", 0); call.Err != nil { - log.Println(call.Err) } }