Bugfix/lp1488114 import msg #14

Merged
merged 14 commits into from Oct 28, 2015
@@ -21,8 +21,19 @@ set -e
TEST=$1
NEEDS_REBOOT=/tmp/needs-reboot
+# We export the tests bin path so the snappy binary that might be compiled from
+# the branch is found.
export PATH=$(pwd)/_integration-tests/bin:$PATH
+# XXX sudo does not preserve the user PATH. A nicer way to solve this would be
+# to use an alias, but go exec.Command sets the full binary path.
+cat > $(pwd)/_integration-tests/bin/sudo <<EOF
+#!/bin/bash
+/usr/bin/sudo env PATH=$PATH "\$@"
+EOF
+
+chmod +x $(pwd)/_integration-tests/bin/sudo
+
# shift to remove the test binary name (first argument) and be able to pass the rest
# of them to it
shift
@@ -0,0 +1,56 @@
+// -*- Mode: Go; indent-tabs-mode: t -*-
+
+/*
+ * Copyright (C) 2015 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package tests
+
+import (
+ "os/exec"
+
+ "launchpad.net/snappy/_integration-tests/testutils/cli"
+ "launchpad.net/snappy/_integration-tests/testutils/common"
+
+ check "gopkg.in/check.v1"
+)
+
+var _ = check.Suite(&autopilotMsgSuite{})
+
+type autopilotMsgSuite struct {
+ common.SnappySuite
+}
+
+// Test that there is a proper message if the autopilot runs in the
+// background
+func (s *autopilotMsgSuite) TestAutoPilotMessageIsPrinted(c *check.C) {
+ cli.ExecCommand(c, "sudo", "systemctl", "start", "snappy-autopilot")
+
+ // do not pollute the other tests with the now installed hello-world
+ s.AddCleanup(func() {
+ common.RemoveSnap(c, "hello-world")
+ })
+
+ // FIXME: risk of race
+ // (i.e. systemctl start finishes before install runs)
+ snappyOutput, _ := exec.Command("sudo", "snappy", "install", "hello-world").CombinedOutput()
+
+ expected := "(?ms)" +
+ ".*" +
+ "^The snappy autopilot is updating your system.*\n" +
+ ".*"
+ c.Assert(string(snappyOutput), check.Matches, expected)
+}
@@ -52,7 +52,7 @@ func init() {
}
func (x *cmdActivate) Execute(args []string) error {
- return withMutex(x.doActivate)
+ return withMutexAndRetry(x.doActivate)
}
func (x *cmdActivate) doActivate() error {
@@ -39,7 +39,7 @@ func init() {
}
func (x *cmdBooted) Execute(args []string) error {
- return withMutex(x.doBooted)
+ return withMutexAndRetry(x.doBooted)
}
func (x *cmdBooted) doBooted() error {
@@ -38,7 +38,7 @@ func init() {
}
func (x *cmdGrubMigrate) Execute(args []string) error {
- return withMutex(x.doGrubMigrate)
+ return withMutexAndRetry(x.doGrubMigrate)
}
func (x *cmdGrubMigrate) doGrubMigrate() error {
@@ -51,7 +51,7 @@ func init() {
}
func (x *cmdHWAssign) Execute(args []string) error {
- return withMutex(x.doHWAssign)
+ return withMutexAndRetry(x.doHWAssign)
}
func (x *cmdHWAssign) doHWAssign() error {
@@ -76,7 +76,7 @@ func outputHWAccessForAll() error {
}
func (x *cmdHWInfo) Execute(args []string) error {
- return withMutex(x.doHWInfo)
+ return withMutexAndRetry(x.doHWInfo)
}
func (x *cmdHWInfo) doHWInfo() error {
@@ -51,7 +51,7 @@ func init() {
}
func (x *cmdHWUnassign) Execute(args []string) error {
- return withMutex(x.doHWUnassign)
+ return withMutexAndRetry(x.doHWUnassign)
}
func (x *cmdHWUnassign) doHWUnassign() error {
@@ -54,7 +54,7 @@ func init() {
}
func (x *cmdInstall) Execute(args []string) error {
- return withMutex(x.doInstall)
+ return withMutexAndRetry(x.doInstall)
}
func (x *cmdInstall) doInstall() error {
@@ -49,7 +49,7 @@ func init() {
}
func (x *cmdPurge) Execute(args []string) error {
- return withMutex(func() error {
+ return withMutexAndRetry(func() error {
return x.doPurge(args)
})
}
@@ -44,7 +44,7 @@ func init() {
}
func (x *cmdRemove) Execute(args []string) (err error) {
- return withMutex(func() error {
+ return withMutexAndRetry(func() error {
return x.doRemove(args)
})
}
@@ -53,7 +53,7 @@ func init() {
}
func (x *cmdRollback) Execute(args []string) (err error) {
- return withMutex(x.doRollback)
+ return withMutexAndRetry(x.doRollback)
}
func (x *cmdRollback) doRollback() error {
@@ -135,7 +135,7 @@ func (s *svcStatus) Execute(args []string) error {
}
func (s *svcLogs) Execute([]string) error {
- return withMutex(func() error {
+ return withMutexAndRetry(func() error {
logs, err := s.doExecute(doLogs)
if err != nil {
return err
@@ -150,35 +150,35 @@ func (s *svcLogs) Execute([]string) error {
}
func (s *svcStart) Execute(args []string) error {
- return withMutex(func() error {
+ return withMutexAndRetry(func() error {
_, err := s.doExecute(doStart)
return err
})
}
func (s *svcStop) Execute(args []string) error {
- return withMutex(func() error {
+ return withMutexAndRetry(func() error {
_, err := s.doExecute(doStop)
return err
})
}
func (s *svcRestart) Execute(args []string) error {
- return withMutex(func() error {
+ return withMutexAndRetry(func() error {
_, err := s.doExecute(doRestart)
return err
})
}
func (s *svcEnable) Execute(args []string) error {
- return withMutex(func() error {
+ return withMutexAndRetry(func() error {
_, err := s.doExecute(doEnable)
return err
})
}
func (s *svcDisable) Execute(args []string) error {
- return withMutex(func() error {
+ return withMutexAndRetry(func() error {
_, err := s.doExecute(doDisable)
return err
})
View
@@ -54,7 +54,7 @@ func init() {
func (x *cmdSet) Execute(args []string) (err error) {
x.args = args
- return withMutex(x.doSet)
+ return withMutexAndRetry(x.doSet)
}
func (x *cmdSet) doSet() (err error) {
@@ -56,7 +56,7 @@ const (
var shutdownMsg = i18n.G("snappy autopilot triggered a reboot to boot into an up to date system -- temprorarily disable the reboot by running 'sudo shutdown -c'")
func (x *cmdUpdate) Execute(args []string) (err error) {
- return withMutex(x.doUpdate)
+ return withMutexAndRetry(x.doUpdate)
}
func (x *cmdUpdate) doUpdate() error {
View
@@ -20,6 +20,12 @@
package main
import (
+ "fmt"
+ "os/exec"
+ "strings"
+ "time"
+
+ "github.com/ubuntu-core/snappy/i18n"
"github.com/ubuntu-core/snappy/logger"
"github.com/ubuntu-core/snappy/priv"
@@ -28,9 +34,48 @@ import (
const snappyLockFile = "/run/snappy.lock"
-// withMutex runs the given function with a filelock mutex
-func withMutex(f func() error) error {
- return priv.WithMutex(snappyLockFile, f)
+func isAutoPilotRunning() bool {
+ unitName := "snappy-autopilot"
+ bs, err := exec.Command("systemctl", "show", "--property=SubState", unitName).CombinedOutput()
+ if err != nil {
+ return false
+ }
+
+ return strings.TrimSpace(string(bs)) == "SubState=running"
+}
+
+// withMutexAndRetry runs the given function with a filelock mutex and provides
+// automatic re-try and helpful messages if the lock is already taken
+func withMutexAndRetry(f func() error) error {
+ for {
+ err := priv.WithMutex(snappyLockFile, f)
+ // if already locked, auto-retry
+ if err == priv.ErrAlreadyLocked {
+ var msg string
+ if isAutoPilotRunning() {
+ // FIXME: we could even do a
+ // journalctl -u snappy-autopilot
+ // here
+ msg = i18n.G(
+ `The snappy autopilot is updating your system in the background. This may
+take some minutes. Will try again in %d seconds...
+Press ctrl-c to cancel.
+`)
+ } else {
+ msg = i18n.G(
+ `Another snappy is running, will try again in %d seconds...
+Press ctrl-c to cancel.
+`)
+ }
+ // wait a wee bit
+ wait := 5
+ fmt.Printf(msg, wait)
+ time.Sleep(time.Duration(wait) * time.Second)
+ continue
+ }
+
+ return err
+ }
}
// addOptionDescription will try to find the given longName in the
View
@@ -7,7 +7,7 @@
msgid ""
msgstr "Project-Id-Version: snappy\n"
"Report-Msgid-Bugs-To: snappy-devel@lists.ubuntu.com\n"
- "POT-Creation-Date: 2015-10-15 15:53+0200\n"
+ "POT-Creation-Date: 2015-10-28 16:28+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -70,6 +70,11 @@ msgstr ""
msgid "Allows rollback of a snap to a previous installed version. Without any arguments, the previous installed version is selected. It is also possible to specify the version to rollback to as a additional argument.\n"
msgstr ""
+#, c-format
+msgid "Another snappy is running, will try again in %d seconds...\n"
+ "Press ctrl-c to cancel.\n"
+msgstr ""
+
msgid "Assign a hardware device to a package"
msgstr ""
@@ -293,6 +298,12 @@ msgstr ""
msgid "The package to rollback "
msgstr ""
+#, c-format
+msgid "The snappy autopilot is updating your system in the background. This may\n"
+ "take some minutes. Will try again in %d seconds...\n"
+ "Press ctrl-c to cancel.\n"
+msgstr ""
+
msgid "The version to rollback to"
msgstr ""