Merge ~kzapalowicz/snappy-hwe-snaps/+git/udisks2:feature/automount-on-boot into ~snappy-hwe-team/snappy-hwe-snaps/+git/udisks2:master
- Git
- lp:~kzapalowicz/snappy-hwe-snaps/+git/udisks2
- feature/automount-on-boot
- Merge into master
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) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Simon Fels | Approve | ||
System Enablement Bot | continuous-integration | Approve | |
Review via email: mp+322761@code.launchpad.net |
Commit message
Description of the change
ciborium: wait till the GetManagedObjects interface is ready
At certain systems it has been observed that although the
org.freedesktop
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
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:1ae44426336
https:/
Executed test runs:
FAILURE: https:/
None: https:/
FAILURE: https:/
None: https:/
Click here to trigger a rebuild:
https:/
Simon Fels (morphis) wrote : | # |
Would be nice to have a test case for this.
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:b51b77d54c6
https:/
Executed test runs:
FAILURE: https:/
None: https:/
FAILURE: https:/
None: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:9da139f1d92
https:/
Executed test runs:
FAILURE: https:/
None: https:/
FAILURE: https:/
None: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:02780daf296
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
SUCCESS: https:/
None: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3eb45037d49
https:/
Executed test runs:
FAILURE: https:/
None: https:/
FAILURE: https:/
None: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:0d582f33713
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
SUCCESS: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:8b2e056fe05
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
SUCCESS: https:/
None: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:8c22719633a
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
SUCCESS: https:/
None: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | diff --git a/docs/reference/snap-configuration/automount.md b/docs/reference/snap-configuration/automount.md |
2 | index 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 |
15 | diff --git a/tests/main/installation/task.yaml b/tests/main/installation/task.yaml |
16 | index 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" |
28 | diff --git a/udisks2/udisks2.go b/udisks2/udisks2.go |
29 | index 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) |
213 | diff --git a/udisks2/utils.go b/udisks2/utils.go |
214 | new file mode 100644 |
215 | index 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 | +} |
250 | diff --git a/udisks2/utils_test.go b/udisks2/utils_test.go |
251 | new file mode 100644 |
252 | index 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 | +} |
FAILED: Continuous integration, rev:1ae44426336 16fc7200e3baa7f 8d977b534a1a7b /jenkins. canonical. com/system- enablement/ job/generic- build-snap/ 1470/ /jenkins. canonical. com/system- enablement/ job/generic- build-snap- worker/ 1149/console /jenkins. canonical. com/system- enablement/ job/generic- update- snap-mp/ 1378/console /jenkins. canonical. com/system- enablement/ job/generic- test-snap/ 1637/console /jenkins. canonical. com/system- enablement/ job/generic- cleanup- snap/770/ console
https:/
Executed test runs:
FAILURE: https:/
None: https:/
FAILURE: https:/
None: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/system- enablement/ job/generic- build-snap/ 1470/rebuild
https:/