Merge ~kzapalowicz/snappy-hwe-snaps/+git/udisks2:feature/automount-on-boot into ~snappy-hwe-team/snappy-hwe-snaps/+git/udisks2:master

Proposed by Konrad Zapałowicz
Status: Merged
Approved by: Simon Fels
Approved revision: 8c22719633a3b701b5f64f7eee24c021db798e2b
Merged at revision: 355f84ab9cb55529fe5a85dfaeb79444d132dd12
Proposed branch: ~kzapalowicz/snappy-hwe-snaps/+git/udisks2:feature/automount-on-boot
Merge into: ~snappy-hwe-team/snappy-hwe-snaps/+git/udisks2:master
Diff against target: 292 lines (+158/-69)
5 files modified
docs/reference/snap-configuration/automount.md (+3/-0)
tests/main/installation/task.yaml (+2/-2)
udisks2/udisks2.go (+85/-67)
udisks2/utils.go (+31/-0)
udisks2/utils_test.go (+37/-0)
Reviewer Review Type Date Requested Status
Simon Fels Approve
System Enablement Bot continuous-integration Approve
Review via email: mp+322761@code.launchpad.net

Description of the change

ciborium: wait till the GetManagedObjects interface is ready

At certain systems it has been observed that although the
org.freedesktop.UDisks2 name is registered the ObjectManager interface
is not immediately ready. As a result the "GetManagedObjects" call fails
and the cold-plugged usb devices not reported.

This commit implements behavior for ciborium to call GetManagedObjects
several times waiting for it to return successfully. It is assumed that
the org.freedesktop.UDisks2 name is acquired the interface show up.

To post a comment you must log in.
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Simon Fels (morphis) wrote :

Would be nice to have a test case for this.

review: Needs Fixing
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Simon Fels (morphis) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/docs/reference/snap-configuration/automount.md b/docs/reference/snap-configuration/automount.md
2index a400fcd..e825a5c 100644
3--- a/docs/reference/snap-configuration/automount.md
4+++ b/docs/reference/snap-configuration/automount.md
5@@ -35,6 +35,9 @@ If all requirements are fulfilled by a storage device or some of its partitions,
6 they are mounted in */media* in a directory specific for the *root* user. The path
7 generally follows this schema: */media/<user>/<storage device id/name>*
8
9+When enabled this feature will also mount any device plugged in before the boot that
10+fulfill the above rules.
11+
12 ## Enable Automount
13
14 The udisks2 snap provides a single configuration option which can be used to turn
15diff --git a/tests/main/installation/task.yaml b/tests/main/installation/task.yaml
16index 93a9e2c..e98f9a7 100644
17--- a/tests/main/installation/task.yaml
18+++ b/tests/main/installation/task.yaml
19@@ -13,6 +13,6 @@ execute: |
20 /snap/bin/udisks2.udisksctl status
21
22 # Ensure all necessary plugs/slots are connected
23- snap interfaces | grep -Pzq ":mount-observe +udisks2"
24+ snap interfaces | grep -Pzq ":mount-observe +[a-z,-]*udisks2"
25 snap interfaces | grep -Pzq "udisks2:service +udisks2:client"
26- snap interfaces | grep -Pzq ":network-bind +udisks2"
27+ snap interfaces | grep -Pzq ":network-bind +[a-z,-]*udisks2"
28diff --git a/udisks2/udisks2.go b/udisks2/udisks2.go
29index 5ab03be..ec8217c 100644
30--- a/udisks2/udisks2.go
31+++ b/udisks2/udisks2.go
32@@ -51,6 +51,7 @@ const (
33 dbusPropertiesInterface = "org.freedesktop.DBus.Properties"
34 dbusAddedSignal = "InterfacesAdded"
35 dbusRemovedSignal = "InterfacesRemoved"
36+ defaultMaximumWaitTime = 64
37 )
38
39 type MountEvent struct {
40@@ -208,77 +209,78 @@ func (u *UDisks2) mountpointsForPath(p dbus.ObjectPath) []string {
41
42 func (u *UDisks2) Init() (err error) {
43 d, err := newDispatcher(u.conn)
44- if err == nil {
45- u.dispatcher = d
46- u.jobs = newJobManager(d)
47- go func() {
48- for {
49- select {
50- case e := <-u.dispatcher.Additions:
51- if err := u.processAddEvent(&e); err != nil {
52- log.Print("Issues while processing ", e.Path, ": ", err)
53- }
54- case e := <-u.dispatcher.Removals:
55- if err := u.processRemoveEvent(e.Path, e.Interfaces); err != nil {
56- log.Println("Issues while processing remove event:", err)
57- }
58- case j := <-u.jobs.UnmountJobs:
59- if j.WasCompleted {
60- log.Println("Unmount job was finished for", j.Event.Path, "for paths", j.Paths)
61- for _, path := range j.Paths {
62- u.umountCompleted <- path
63- log.Println("Removing", path, "from", u.mountpoints)
64- delete(u.mountpoints, dbus.ObjectPath(path))
65- }
66- } else {
67- log.Print("Unmount job started.")
68+ if err != nil {
69+ return err
70+ }
71+
72+ u.dispatcher = d
73+ u.jobs = newJobManager(d)
74+ go func() {
75+ for {
76+ select {
77+ case e := <-u.dispatcher.Additions:
78+ if err := u.processAddEvent(&e); err != nil {
79+ log.Print("Issues while processing ", e.Path, ": ", err)
80+ }
81+ case e := <-u.dispatcher.Removals:
82+ if err := u.processRemoveEvent(e.Path, e.Interfaces); err != nil {
83+ log.Println("Issues while processing remove event:", err)
84+ }
85+ case j := <-u.jobs.UnmountJobs:
86+ if j.WasCompleted {
87+ log.Println("Unmount job was finished for", j.Event.Path, "for paths", j.Paths)
88+ for _, path := range j.Paths {
89+ u.umountCompleted <- path
90+ log.Println("Removing", path, "from", u.mountpoints)
91+ delete(u.mountpoints, dbus.ObjectPath(path))
92 }
93- case j := <-u.jobs.MountJobs:
94- if j.WasCompleted {
95- log.Println("Mount job was finished for", j.Event.Path, "for paths", j.Paths)
96- for _, path := range j.Paths {
97- // grab the mointpoints from the variant
98- mountpoints := u.mountpointsForPath(dbus.ObjectPath(path))
99- log.Println("Mount points are", mountpoints)
100- if len(mountpoints) > 0 {
101- p := dbus.ObjectPath(path)
102- mp := string(mountpoints[0])
103- u.mountpoints[p] = string(mp)
104- // update the drives
105- for _, d := range u.drives {
106- changed := d.SetMounted(p)
107- if changed {
108- e := MountEvent{d.Path, mp}
109- log.Println("New mount event", e)
110- go func() {
111- for _, t := range [...]int{1, 2, 3, 4, 5, 10} {
112- _, err := os.Stat(mp)
113- if err != nil {
114- log.Println("Mountpoint", mp, "not yet present. Wating", t, "seconds due to", err)
115- time.Sleep(time.Duration(t) * time.Second)
116- } else {
117- break
118- }
119+ } else {
120+ log.Print("Unmount job started.")
121+ }
122+ case j := <-u.jobs.MountJobs:
123+ if j.WasCompleted {
124+ log.Println("Mount job was finished for", j.Event.Path, "for paths", j.Paths)
125+ for _, path := range j.Paths {
126+ // grab the mointpoints from the variant
127+ mountpoints := u.mountpointsForPath(dbus.ObjectPath(path))
128+ log.Println("Mount points are", mountpoints)
129+ if len(mountpoints) > 0 {
130+ p := dbus.ObjectPath(path)
131+ mp := string(mountpoints[0])
132+ u.mountpoints[p] = string(mp)
133+ // update the drives
134+ for _, d := range u.drives {
135+ changed := d.SetMounted(p)
136+ if changed {
137+ e := MountEvent{d.Path, mp}
138+ log.Println("New mount event", e)
139+ go func() {
140+ for _, t := range [...]int{1, 2, 3, 4, 5, 10} {
141+ _, err := os.Stat(mp)
142+ if err != nil {
143+ log.Println("Mountpoint", mp, "not yet present. Wating", t, "seconds due to", err)
144+ time.Sleep(time.Duration(t) * time.Second)
145+ } else {
146+ break
147 }
148- log.Println("Sending new event to channel.")
149- u.mountCompleted <- e
150- }()
151- }
152+ }
153+ log.Println("Sending new event to channel.")
154+ u.mountCompleted <- e
155+ }()
156 }
157 }
158-
159 }
160- } else {
161- log.Print("Mount job started.")
162+
163 }
164+ } else {
165+ log.Print("Mount job started.")
166 }
167 }
168- }()
169- d.Init()
170- u.emitExistingDevices()
171- return nil
172- }
173- return err
174+ }
175+ }()
176+ d.Init()
177+ u.emitExistingDevices()
178+ return nil
179 }
180
181 func (u *UDisks2) connectToSignal(path dbus.ObjectPath, inter, member string) (*dbus.SignalWatch, error) {
182@@ -304,10 +306,26 @@ func (u *UDisks2) emitExistingDevices() {
183 u.startLock.Lock()
184 defer u.startLock.Unlock()
185 obj := u.conn.Object(dbusName, dbusObject)
186- reply, err := obj.Call(dbusObjectManagerInterface, "GetManagedObjects")
187- if err != nil {
188- log.Println("Cannot get initial state for devices:", err)
189- return
190+
191+ // At certain systems it has been observed that although the
192+ // org.freedesktop.UDisks2 name is registered the ObjectManager
193+ // interface is not immediately ready. As a result the
194+ // "GetManagedObjects" call fails and the cold-plugged usb devices
195+ // are not reported. The code below calls GetManagedObjects several
196+ // times waiting for it to return successfully. It is assumed that
197+ // once the org.freedesktop.UDisks2 name is acquired the interface
198+ // will show up.
199+ var reply *dbus.Message
200+ f := fibonacci()
201+ for i := f(); i < defaultMaximumWaitTime; i = f() {
202+ var err error
203+ reply, err = obj.Call(dbusObjectManagerInterface, "GetManagedObjects")
204+ if err != nil {
205+ log.Println("Cannot get initial state for devices:", err)
206+ time.Sleep(time.Duration(i) * time.Second)
207+ } else {
208+ break
209+ }
210 }
211
212 allDevices := make(map[dbus.ObjectPath]InterfacesAndProperties)
213diff --git a/udisks2/utils.go b/udisks2/utils.go
214new file mode 100644
215index 0000000..97f1053
216--- /dev/null
217+++ b/udisks2/utils.go
218@@ -0,0 +1,31 @@
219+/*
220+ * Copyright 2017 Canonical Ltd.
221+ *
222+ * Authors:
223+ * Konrad Zapalowicz <konrad.zapalowicz@canonical.com>
224+ *
225+ * ciborium is free software; you can redistribute it and/or modify
226+ * it under the terms of the GNU General Public License as published by
227+ * the Free Software Foundation; version 3.
228+ *
229+ * ciborium is distributed in the hope that it will be useful,
230+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
231+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
232+ * GNU General Public License for more details.
233+ *
234+ * You should have received a copy of the GNU General Public License
235+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
236+ */
237+
238+package udisks2
239+
240+// Returns a function that returns fibonacci sequence
241+// that starts from 1
242+func fibonacci() func() int {
243+ a, b := 1, 1
244+ return func() int {
245+ retval := a
246+ a, b = b, a+b
247+ return retval
248+ }
249+}
250diff --git a/udisks2/utils_test.go b/udisks2/utils_test.go
251new file mode 100644
252index 0000000..0b33a51
253--- /dev/null
254+++ b/udisks2/utils_test.go
255@@ -0,0 +1,37 @@
256+/*
257+ * Copyright 2017 Canonical Ltd.
258+ *
259+ * Authors:
260+ * Konrad Zapalowicz <konrad.zapalowicz@canonical.com>
261+ *
262+ * ciborium is free software; you can redistribute it and/or modify
263+ * it under the terms of the GNU General Public License as published by
264+ * the Free Software Foundation; version 3.
265+ *
266+ * ciborium is distributed in the hope that it will be useful,
267+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
268+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
269+ * GNU General Public License for more details.
270+ *
271+ * You should have received a copy of the GNU General Public License
272+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
273+ */
274+
275+package udisks2
276+
277+import (
278+ . "launchpad.net/gocheck"
279+)
280+
281+type UtilsTestSuite struct{}
282+
283+var _ = Suite(&UtilsTestSuite{})
284+
285+func (s *UtilsTestSuite) TestFibonacci(c *C) {
286+ fib := fibonacci()
287+ c.Assert(fib(), Equals, 1)
288+ c.Assert(fib(), Equals, 1)
289+ c.Assert(fib(), Equals, 2)
290+ c.Assert(fib(), Equals, 3)
291+ c.Assert(fib(), Equals, 5)
292+}

Subscribers

People subscribed via source and target branches