Merge lp:~larryprice/libertine/release-1.7.1 into lp:libertine/trunk
- release-1.7.1
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Christopher Townsend |
Approved revision: | 204 |
Merged at revision: | 201 |
Proposed branch: | lp:~larryprice/libertine/release-1.7.1 |
Merge into: | lp:libertine/trunk |
Diff against target: |
4695 lines (+1707/-1017) 62 files modified
CMakeLists.txt (+6/-0) debian/changelog (+37/-0) debian/control (+9/-11) debian/libertine-tools.install (+1/-2) debian/libertine-xmir-tools.install (+4/-0) debian/libertined.preinst (+1/-1) debian/libertined.prerm (+1/-1) debian/python3-libertine.install (+1/-2) liblibertine/libertined.cpp (+15/-10) pasted/pasted.cpp (+97/-43) pasted/pasted.h (+13/-5) python/libertine/ChrootContainer.py (+2/-2) python/libertine/ContainerControlClient.py (+14/-9) python/libertine/ContainersConfig.py (+52/-17) python/libertine/Libertine.py (+21/-15) python/libertine/LxcContainer.py (+7/-9) python/libertine/LxdContainer.py (+17/-16) python/libertine/service/constants.py (+27/-0) python/libertine/service/container.py (+38/-34) python/libertine/service/container_control.py (+29/-58) python/libertine/service/container_control_client.py (+75/-0) python/libertine/service/download.py (+35/-40) python/libertine/service/operations.py (+18/-62) python/libertine/service/operations_monitor.py (+93/-0) python/libertine/service/task_dispatcher.py (+8/-25) python/libertine/service/tasks/__init__.py (+2/-1) python/libertine/service/tasks/app_info_task.py (+5/-5) python/libertine/service/tasks/base_task.py (+39/-14) python/libertine/service/tasks/container_info_task.py (+4/-4) python/libertine/service/tasks/create_task.py (+14/-11) python/libertine/service/tasks/destroy_task.py (+10/-8) python/libertine/service/tasks/install_task.py (+10/-8) python/libertine/service/tasks/list_app_ids_task.py (+6/-6) python/libertine/service/tasks/list_task.py (+4/-3) python/libertine/service/tasks/remove_task.py (+9/-8) python/libertine/service/tasks/search_task.py (+4/-4) python/libertine/service/tasks/update_task.py (+11/-10) snap/plugins/x-libertine-deps.py (+2/-1) tests/integration/CMakeLists.txt (+21/-1) tests/integration/data/libertine/ContainersConfig.json (+19/-0) tests/integration/test_libertine_service.py (+41/-38) tests/integration/test_liblibertine.cpp (+145/-0) tests/unit/CMakeLists.txt (+2/-1) tests/unit/ContainerConfigListTests.cpp (+1/-0) tests/unit/service/CMakeLists.txt (+2/-1) tests/unit/service/tasks/test_app_info_task.py (+24/-26) tests/unit/service/tasks/test_container_info_task.py (+26/-27) tests/unit/service/tasks/test_create_task.py (+170/-176) tests/unit/service/tasks/test_destroy_task.py (+44/-46) tests/unit/service/tasks/test_install_task.py (+38/-41) tests/unit/service/tasks/test_list_app_ids_task.py (+23/-25) tests/unit/service/tasks/test_list_task.py (+15/-16) tests/unit/service/tasks/test_remove_task.py (+38/-41) tests/unit/service/tasks/test_search_task.py (+9/-9) tests/unit/service/tasks/test_update_task.py (+46/-46) tests/unit/service/test_container.py (+32/-31) tests/unit/service/test_operations_monitor.py (+146/-0) tests/unit/service/test_task_dispatcher.py (+6/-5) tools/libertine-container-manager (+41/-19) tools/libertine-launch (+12/-2) tools/libertine-lxd-setup (+37/-14) tools/libertined (+28/-7) |
To merge this branch: | bzr merge lp:~larryprice/libertine/release-1.7.1 |
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Christopher Townsend | Approve | ||
Review via email: mp+319854@code.launchpad.net |
Commit message
* When starting pasted, ensure DISPLAY is set and valid before continuing to
run. (LP: 1666472)
* Fix pasted to work with rootless Xmir. (LP: 1671257)
* Bump version to 1.7.1
* Gracefully handle creating a LibertineContainer object when the container
backend is unavailable.
* Update libertine xmir components to not depend on container backends.
(LP: 1671938)
* Catch all errors and gracefully shutdown libertined. (LP: 1671009)
* Fix method call from ContainerControl d-bus to interfaces.
* Update signal handlers in test_libertine_
* Inject client for accessing ContainerControl within containers.
* Rearchitect libertine service python backend for simpler access to running
tasks. (LP: 1669091)
* Ignore completions from dependencies during snapcraft build.
* LXD needs to forward host environment to container when running arbitrary
commands.
* Add client object to list_app_ids_task to avoid making reentrant service
calls.
* Take advantage of new network subcommand during lxd init on newer
installs.
* Prevent installing empty package names and appropriately update status for
unstopped containers.
* Modifications to make test_libertine_
* Add a '-x' option to pkill so it only kills the libertined process(es)
and nothing else. (LP: 1676005)
* Remove hard-coded dependency on libraries.
* Reopen the database file after every failure to grab the lock.
(LP: 1662655)
Description of the change
Release libertine 1.7.1 with packaging/
- 199. By Larry Price
-
* When starting pasted, ensure DISPLAY is set and valid before continuing to
run. (LP: #1666472)
* Fix pasted to work with rootless Xmir. (LP: #1671257)
* LXD needs to forward host environment to container when running arbitrary
commands.
* Add client object to list_app_ids_task to avoid making reentrant service
calls.
* Take advantage of new network subcommand during lxd init on newer
installs.
* Prevent installing empty package names and appropriately update status for
unstopped containers. - 200. By Larry Price
-
Only depend on libertine-
xmir-tools on the appropriate architectures - 201. By Larry Price
-
Path does not exist issue
- 202. By Larry Price
-
Merge with lp:libertine/trunk
- 203. By Larry Price
-
Merge in test_libertine_
service stabilization changes - 204. By Larry Price
-
Allow libertine-
xmir-tools to build on any architecture
- 205. By Larry Price
-
Merge lp:libertine
- 206. By Larry Price
- 207. By Larry Price
-
Update changelog
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2017-03-06 17:36:14 +0000 |
3 | +++ CMakeLists.txt 2017-03-31 20:05:48 +0000 |
4 | @@ -30,6 +30,12 @@ |
5 | pkg_check_modules(PYTHON3 REQUIRED python3) |
6 | include_directories(${PYTHON3_INCLUDE_DIRS}) |
7 | |
8 | +pkg_check_modules(DBUSTEST REQUIRED dbustest-1>=14.04.0) |
9 | +include_directories(${DBUSTEST_INCLUDE_DIRS}) |
10 | + |
11 | +pkg_check_modules(GIO2 REQUIRED gio-2.0 gio-unix-2.0) |
12 | +include_directories(${GIO2_INCLUDE_DIRS}) |
13 | + |
14 | set(CMAKE_AUTOMOC ON) |
15 | |
16 | set(LIBERTINE_COMMON libertine-common) |
17 | |
18 | === modified file 'debian/changelog' |
19 | --- debian/changelog 2017-03-20 15:34:36 +0000 |
20 | +++ debian/changelog 2017-03-31 20:05:48 +0000 |
21 | @@ -1,3 +1,40 @@ |
22 | +libertine (1.7.1-0ubuntu1) UNRELEASED; urgency=medium |
23 | + |
24 | + [ Chris Townsend ] |
25 | + * When starting pasted, ensure DISPLAY is set and valid before continuing to |
26 | + run. (LP: #1666472) |
27 | + * Fix pasted to work with rootless Xmir. (LP: #1671257) |
28 | + * Add a '-x' option to pkill so it only kills the libertined process(es) |
29 | + and nothing else. (LP: #1676005) |
30 | + * Remove hard-coded dependency on libraries. |
31 | + |
32 | + [ Larry Price ] |
33 | + * Bump version to 1.7.1 |
34 | + * Gracefully handle creating a LibertineContainer object when the container |
35 | + backend is unavailable. |
36 | + * Update libertine xmir components to not depend on container backends. |
37 | + (LP: #1671938) |
38 | + * Catch all errors and gracefully shutdown libertined. (LP: #1671009) |
39 | + * Fix method call from ContainerControl d-bus to interfaces. |
40 | + * Update signal handlers in test_libertine_service to reflect new API. |
41 | + * Inject client for accessing ContainerControl within containers. |
42 | + * Rearchitect libertine service python backend for simpler access to running |
43 | + tasks. (LP: #1669091) |
44 | + * Ignore completions from dependencies during snapcraft build. |
45 | + * LXD needs to forward host environment to container when running arbitrary |
46 | + commands. |
47 | + * Add client object to list_app_ids_task to avoid making reentrant service |
48 | + calls. |
49 | + * Take advantage of new network subcommand during lxd init on newer |
50 | + installs. |
51 | + * Prevent installing empty package names and appropriately update status for |
52 | + unstopped containers. |
53 | + * Modifications to make test_libertine_service more stable. |
54 | + * Reopen the database file after every failure to grab the lock. |
55 | + (LP: #1662655) |
56 | + |
57 | + -- Larry Price <larry.price@canonical.com> Tue, 14 Mar 2017 11:35:33 -0400 |
58 | + |
59 | libertine (1.7+17.04.20170320.1-0ubuntu1) zesty; urgency=medium |
60 | |
61 | * No change rebuild |
62 | |
63 | === modified file 'debian/control' |
64 | --- debian/control 2017-03-13 14:01:08 +0000 |
65 | +++ debian/control 2017-03-31 20:05:48 +0000 |
66 | @@ -9,6 +9,7 @@ |
67 | gobject-introspection, |
68 | intltool, |
69 | libcontent-hub-dev (>= 0.2), |
70 | + libdbustest1-dev (>= 14.04.0), |
71 | libgirepository1.0-dev, |
72 | libglib2.0-dev, |
73 | libgtest-dev, |
74 | @@ -61,7 +62,6 @@ |
75 | Depends: libertine-qt-common, |
76 | libertine-tools, |
77 | python3-libertine-lxd, |
78 | - libsystemsettings1, |
79 | ${misc:Depends}, |
80 | ${shlibs:Depends} |
81 | Enhances: ubuntu-system-settings |
82 | @@ -74,7 +74,7 @@ |
83 | Architecture: any |
84 | Depends: qml-module-qtquick2, |
85 | qml-module-qtquick-dialogs, |
86 | - qtdeclarative5-ubuntu-ui-toolkit-plugin, |
87 | + qtdeclarative5-ubuntu-ui-toolkit-plugin | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles, |
88 | ${misc:Depends}, |
89 | ${shlibs:Depends} |
90 | Description: common files for qt-based libertine applications |
91 | @@ -84,13 +84,14 @@ |
92 | |
93 | Package: libertine-tools |
94 | Architecture: any |
95 | -Depends: libglib2.0-bin, |
96 | +Depends: libertine-xmir-tools (>= 1.7.1) [amd64 armhf arm64 i386], |
97 | + libglib2.0-bin, |
98 | python3-dbus, |
99 | python3-libertine, |
100 | ${misc:Depends}, |
101 | ${python3:Depends}, |
102 | ${shlibs:Depends} |
103 | -Recommends: libertine-xmir-tools (>= 1.4.3) |
104 | +Recommends: python3-libertine-lxd |
105 | Breaks: libertine-demo |
106 | Replaces: libertine-demo |
107 | Description: CLI tools for running deb-packaged X11 apps on Ubuntu Personal |
108 | @@ -98,17 +99,14 @@ |
109 | the Ubuntu Personal sandbox for legacy Deb-packaged X11 applicatons. |
110 | |
111 | Package: libertine-xmir-tools |
112 | -Architecture: amd64 armhf arm64 i386 |
113 | -Depends: libcontent-hub0, |
114 | - libqt5core5a, |
115 | - libqt5gui5, |
116 | - libqt5widgets5, |
117 | +Architecture: any |
118 | +Depends: python3-libertine, |
119 | xmir [amd64 armhf arm64 i386], |
120 | ${misc:Depends}, |
121 | ${python3:Depends}, |
122 | ${shlibs:Depends} |
123 | -Breaks: libertine-tools (<< 1.4.3) |
124 | -Replaces: libertine-tools (<< 1.4.3) |
125 | +Breaks: libertine-tools (<< 1.7.1) |
126 | +Replaces: libertine-tools (<< 1.7.1) |
127 | Description: helper apps for using and interacting with Xmir |
128 | Helper applications for using and interacting with Xmir such as launching |
129 | Xmir and allowing copy and paste. |
130 | |
131 | === modified file 'debian/libertine-tools.install' |
132 | --- debian/libertine-tools.install 2017-01-20 18:43:08 +0000 |
133 | +++ debian/libertine-tools.install 2017-03-31 20:05:48 +0000 |
134 | @@ -1,4 +1,3 @@ |
135 | usr/bin/libertine-container-manager |
136 | -usr/bin/libertine-launch |
137 | usr/share/bash-completion/completions/libertine-container-manager |
138 | -usr/share/man |
139 | +usr/share/man/*/libertine-container-manager.1 |
140 | |
141 | === modified file 'debian/libertine-xmir-tools.install' |
142 | --- debian/libertine-xmir-tools.install 2016-10-26 20:48:08 +0000 |
143 | +++ debian/libertine-xmir-tools.install 2017-03-31 20:05:48 +0000 |
144 | @@ -1,3 +1,7 @@ |
145 | +usr/bin/libertine-launch |
146 | usr/bin/libertine-xmir |
147 | usr/bin/pasted |
148 | +usr/lib/python*/*/libertine/launcher |
149 | +usr/share/man/*/libertine-launch.1 |
150 | +usr/share/man/*/libertine-xmir.1 |
151 | usr/share/upstart/sessions/libertine-xmir.conf |
152 | |
153 | === modified file 'debian/libertined.preinst' |
154 | --- debian/libertined.preinst 2017-03-06 16:15:27 +0000 |
155 | +++ debian/libertined.preinst 2017-03-31 20:05:48 +0000 |
156 | @@ -16,7 +16,7 @@ |
157 | |
158 | if [ "$1" = "upgrade" ]; then |
159 | echo "Shutting down the libertined service..." |
160 | - pkill libertined |
161 | + pkill -x libertined |
162 | fi |
163 | |
164 | #DEBHELPER# |
165 | |
166 | === modified file 'debian/libertined.prerm' |
167 | --- debian/libertined.prerm 2017-03-06 16:15:27 +0000 |
168 | +++ debian/libertined.prerm 2017-03-31 20:05:48 +0000 |
169 | @@ -16,7 +16,7 @@ |
170 | |
171 | if [ "$1" = "remove" ]; then |
172 | echo "Shutting down the libertined service..." |
173 | - pkill libertined |
174 | + pkill -x libertined |
175 | fi |
176 | |
177 | #DEBHELPER# |
178 | |
179 | === modified file 'debian/python3-libertine.install' |
180 | --- debian/python3-libertine.install 2017-02-15 21:12:37 +0000 |
181 | +++ debian/python3-libertine.install 2017-03-31 20:05:48 +0000 |
182 | @@ -1,7 +1,6 @@ |
183 | -usr/lib/python*/*/libertine/Client.py |
184 | +usr/lib/python*/*/libertine/ContainerControlClient.py |
185 | usr/lib/python*/*/libertine/ContainersConfig.py |
186 | usr/lib/python*/*/libertine/HostInfo.py |
187 | usr/lib/python*/*/libertine/Libertine.py |
188 | usr/lib/python*/*/libertine/__init__.py |
189 | -usr/lib/python*/*/libertine/launcher |
190 | usr/lib/python*/*/libertine/utils.py |
191 | |
192 | === modified file 'liblibertine/libertined.cpp' |
193 | --- liblibertine/libertined.cpp 2017-02-23 21:08:28 +0000 |
194 | +++ liblibertine/libertined.cpp 2017-03-31 20:05:48 +0000 |
195 | @@ -25,12 +25,16 @@ |
196 | #include <QJsonArray> |
197 | #include <QJsonObject> |
198 | |
199 | + |
200 | namespace |
201 | { |
202 | -constexpr auto SERVICE_INTERFACE = "com.canonical.libertine.Service"; |
203 | -constexpr auto PROGRESS_INTERFACE = "com.canonical.libertine.Service.Progress"; |
204 | -constexpr auto SESSION_DBUS_ENV_VAR = "DBUS_SESSION_BUS_ADDRESS"; |
205 | -constexpr auto SERVICE_NAME = "libertined"; |
206 | +constexpr auto SERVICE_INTERFACE = "com.canonical.libertine.Service"; |
207 | +constexpr auto OPERATIONS_INTERFACE = "com.canonical.libertine.Service.Operations"; |
208 | +constexpr auto OPERATIONS_OBJECT = "/com/canonical/libertine/Service/Operations"; |
209 | +constexpr auto OPERATIONS_MONITOR_INTERFACE = "com.canonical.libertine.Service.OperationsMonitor"; |
210 | +constexpr auto OPERATIONS_MONITOR_OBJECT = "/com/canonical/libertine/Service/OperationsMonitor"; |
211 | +constexpr auto SESSION_DBUS_ENV_VAR = "DBUS_SESSION_BUS_ADDRESS"; |
212 | +constexpr auto SERVICE_NAME = "libertined"; |
213 | |
214 | |
215 | class SessionBus |
216 | @@ -69,7 +73,7 @@ |
217 | static bool |
218 | isRunning(QDBusConnection const& bus, QString const& path) |
219 | { |
220 | - auto args = dbusCall(bus, PROGRESS_INTERFACE, path, "running", QVariantList()); |
221 | + auto args = dbusCall(bus, OPERATIONS_MONITOR_INTERFACE, OPERATIONS_MONITOR_OBJECT, "running", QVariantList{path}); |
222 | |
223 | if (args.isEmpty()) |
224 | { |
225 | @@ -83,12 +87,12 @@ |
226 | static QString |
227 | result(QDBusConnection const& bus, QString const& path) |
228 | { |
229 | - auto args = dbusCall(bus, PROGRESS_INTERFACE, path, "result"); |
230 | + auto args = dbusCall(bus, OPERATIONS_MONITOR_INTERFACE, OPERATIONS_MONITOR_OBJECT, "result", QVariantList{path}); |
231 | |
232 | if (args.isEmpty()) |
233 | { |
234 | qWarning() << "lastError - no arguments?"; |
235 | - return ""; |
236 | + return QString(); |
237 | } |
238 | |
239 | return args.first().toString(); |
240 | @@ -97,12 +101,12 @@ |
241 | static QString |
242 | lastError(QDBusConnection const& bus, QString const& path) |
243 | { |
244 | - auto args = dbusCall(bus, PROGRESS_INTERFACE, path, "last_error"); |
245 | + auto args = dbusCall(bus, OPERATIONS_MONITOR_INTERFACE, OPERATIONS_MONITOR_OBJECT, "last_error", QVariantList{path}); |
246 | |
247 | if (args.isEmpty()) |
248 | { |
249 | qWarning() << "lastError - no arguments?"; |
250 | - return ""; |
251 | + return QString(); |
252 | } |
253 | |
254 | return args.first().toString(); |
255 | @@ -111,7 +115,7 @@ |
256 | static QString |
257 | call(QDBusConnection const& bus, QString const& method, QVariantList const& args) |
258 | { |
259 | - auto results = dbusCall(bus, SERVICE_INTERFACE, "/Manager", method, args); |
260 | + auto results = dbusCall(bus, OPERATIONS_INTERFACE, OPERATIONS_OBJECT, method, args); |
261 | |
262 | if (results.isEmpty()) |
263 | { |
264 | @@ -158,6 +162,7 @@ |
265 | } |
266 | } |
267 | |
268 | + |
269 | QJsonArray |
270 | libertined_list() |
271 | { |
272 | |
273 | === modified file 'pasted/pasted.cpp' |
274 | --- pasted/pasted.cpp 2016-09-12 17:59:56 +0000 |
275 | +++ pasted/pasted.cpp 2017-03-31 20:05:48 +0000 |
276 | @@ -36,9 +36,8 @@ |
277 | constexpr auto UNITY_FOCUSINFO_METHOD = "isSurfaceFocused"; |
278 | |
279 | |
280 | -static QString getPersistentSurfaceId() |
281 | +static QString getPersistentSurfaceId(Display *dpy, const Window& id) |
282 | { |
283 | - Display *dpy = XOpenDisplay(NULL); |
284 | Atom prop = XInternAtom(dpy, MIR_WM_PERSISTENT_ID, 0), |
285 | type; // unused |
286 | int form, // unused |
287 | @@ -48,7 +47,7 @@ |
288 | unsigned char *data = nullptr; |
289 | QString persistentSurfaceId; |
290 | |
291 | - status = XGetWindowProperty(dpy, XDefaultRootWindow(dpy), prop, 0, 1024, 0, |
292 | + status = XGetWindowProperty(dpy, id, prop, 0, 1024, 0, |
293 | XA_STRING, &type, &form, &len, &remain, &data); |
294 | |
295 | if (status) |
296 | @@ -60,56 +59,109 @@ |
297 | persistentSurfaceId = (const char *)data; |
298 | } |
299 | |
300 | - XCloseDisplay(dpy); |
301 | XFree(data); |
302 | |
303 | return persistentSurfaceId; |
304 | } |
305 | |
306 | + |
307 | +Display *checkXServer() |
308 | +{ |
309 | + char *display = getenv("DISPLAY"); |
310 | + |
311 | + if (display == nullptr) |
312 | + { |
313 | + qCritical() << "DISPLAY environment variable not set!"; |
314 | + exit(-1); |
315 | + } |
316 | + |
317 | + Display *dpy = XOpenDisplay(display); |
318 | + if (dpy == nullptr) |
319 | + { |
320 | + qCritical() << "Xmir is not running on DISPLAY" << display << "!"; |
321 | + exit(-1); |
322 | + } |
323 | + |
324 | + return dpy; |
325 | +} |
326 | + |
327 | } //anonymous namespace |
328 | |
329 | |
330 | +XEventWorker:: |
331 | +XEventWorker(Display *dpy) |
332 | +: dpy_(dpy) |
333 | +{ |
334 | + unityFocus_ = new QDBusInterface(UNITY_FOCUSINFO_SERVICE, |
335 | + UNITY_FOCUSINFO_PATH, |
336 | + UNITY_FOCUSINFO_INTERFACE, |
337 | + QDBusConnection::sessionBus(), |
338 | + this); |
339 | +} |
340 | + |
341 | + |
342 | +XEventWorker:: |
343 | +~XEventWorker() |
344 | +{ |
345 | + XCloseDisplay(dpy_); |
346 | +} |
347 | + |
348 | + |
349 | +bool XEventWorker:: |
350 | +isSurfaceFocused(const Window& focus_window) |
351 | +{ |
352 | + surfaceId_ = getPersistentSurfaceId(dpy_, focus_window); |
353 | + |
354 | + QDBusReply<bool> isFocused = unityFocus_->call(UNITY_FOCUSINFO_METHOD, surfaceId_); |
355 | + |
356 | + return isFocused; |
357 | +} |
358 | + |
359 | + |
360 | void XEventWorker:: |
361 | checkForAppFocus() |
362 | { |
363 | bool hasFocus = false; |
364 | + int focus_state; |
365 | + Window focus_window; |
366 | + |
367 | + XGetInputFocus(dpy_, &focus_window, &focus_state); |
368 | + |
369 | + if (focus_window > PointerRoot) |
370 | + { |
371 | + if (isSurfaceFocused(focus_window)) |
372 | + { |
373 | + focusChanged(surfaceId_); |
374 | + hasFocus = true; |
375 | + } |
376 | + } |
377 | + |
378 | + XSelectInput(dpy_, XDefaultRootWindow(dpy_), FocusChangeMask); |
379 | + |
380 | + bool focused = false; |
381 | XEvent event; |
382 | |
383 | - QDBusInterface *unityFocus = new QDBusInterface(UNITY_FOCUSINFO_SERVICE, |
384 | - UNITY_FOCUSINFO_PATH, |
385 | - UNITY_FOCUSINFO_INTERFACE, |
386 | - QDBusConnection::sessionBus(), |
387 | - this); |
388 | - |
389 | - QString surfaceId = getPersistentSurfaceId(); |
390 | - |
391 | - QDBusReply<bool> isFocused = unityFocus->call(UNITY_FOCUSINFO_METHOD, surfaceId); |
392 | - |
393 | - if (isFocused == true) |
394 | - { |
395 | - focusChanged(); |
396 | - hasFocus = true; |
397 | - } |
398 | - |
399 | - Display *dpy = XOpenDisplay(NULL); |
400 | - XSelectInput(dpy, XDefaultRootWindow(dpy), FocusChangeMask); |
401 | - |
402 | while (1) |
403 | { |
404 | - XNextEvent(dpy, &event); |
405 | - |
406 | - isFocused = unityFocus->call(UNITY_FOCUSINFO_METHOD, surfaceId); |
407 | - |
408 | - if (hasFocus == false && isFocused == true) |
409 | - { |
410 | - qDebug() << "Surface is focused"; |
411 | - focusChanged(); |
412 | - hasFocus = true; |
413 | - } |
414 | - else if (hasFocus == true && isFocused == false) |
415 | - { |
416 | - qDebug() << "Surface lost focus"; |
417 | - hasFocus = false; |
418 | + XNextEvent(dpy_, &event); |
419 | + |
420 | + XGetInputFocus(dpy_, &focus_window, &focus_state); |
421 | + |
422 | + if (focus_window > PointerRoot) |
423 | + { |
424 | + focused = isSurfaceFocused(focus_window); |
425 | + |
426 | + if (hasFocus == false && focused == true) |
427 | + { |
428 | + qDebug() << "Surface is focused"; |
429 | + focusChanged(surfaceId_); |
430 | + hasFocus = true; |
431 | + } |
432 | + else if (hasFocus == true && focused == false) |
433 | + { |
434 | + qDebug() << "Surface lost focus"; |
435 | + hasFocus = false; |
436 | + } |
437 | } |
438 | } |
439 | } |
440 | @@ -230,19 +282,19 @@ |
441 | |
442 | |
443 | void Pasted:: |
444 | -setPersistentSurfaceId() |
445 | +setPersistentSurfaceId(const QString& surfaceId) |
446 | { |
447 | - if (persistentSurfaceId_.isEmpty()) |
448 | + if (persistentSurfaceId_ != surfaceId) |
449 | { |
450 | - persistentSurfaceId_ = getPersistentSurfaceId(); |
451 | + persistentSurfaceId_ = surfaceId; |
452 | } |
453 | } |
454 | |
455 | |
456 | void Pasted:: |
457 | -appFocused() |
458 | +appFocused(const QString& surfaceId) |
459 | { |
460 | - setPersistentSurfaceId(); |
461 | + setPersistentSurfaceId(surfaceId); |
462 | handleContentHubPasteboard(); |
463 | } |
464 | |
465 | @@ -252,10 +304,12 @@ |
466 | { |
467 | qSetMessagePattern(QString("%{appname}: %{message}")); |
468 | |
469 | + Display *dpy = checkXServer(); |
470 | + |
471 | Pasted pasted(argc, argv); |
472 | |
473 | QThread t; |
474 | - XEventWorker worker; |
475 | + XEventWorker worker(dpy); |
476 | |
477 | worker.moveToThread(&t); |
478 | |
479 | |
480 | === modified file 'pasted/pasted.h' |
481 | --- pasted/pasted.h 2016-09-12 17:59:56 +0000 |
482 | +++ pasted/pasted.h 2017-03-31 20:05:48 +0000 |
483 | @@ -39,14 +39,22 @@ |
484 | Q_OBJECT |
485 | |
486 | public: |
487 | - XEventWorker() = default; |
488 | - virtual ~XEventWorker() = default; |
489 | + XEventWorker(Display *dpy); |
490 | + virtual ~XEventWorker(); |
491 | + |
492 | + private: |
493 | + bool isSurfaceFocused(const Window& focus_window); |
494 | |
495 | signals: |
496 | - void focusChanged(); |
497 | + void focusChanged(const QString& surfaceId); |
498 | |
499 | public slots: |
500 | void checkForAppFocus(); |
501 | + |
502 | + private: |
503 | + Display *dpy_; |
504 | + QDBusInterface *unityFocus_; |
505 | + QString surfaceId_; |
506 | }; |
507 | |
508 | |
509 | @@ -60,13 +68,13 @@ |
510 | virtual ~Pasted() = default; |
511 | |
512 | public slots: |
513 | - void appFocused(); |
514 | + void appFocused(const QString& surfaceId); |
515 | |
516 | private: |
517 | void updateLastMimeData(const QMimeData *source); |
518 | void updateXMimeData(const QMimeData *source); |
519 | void handleContentHubPasteboard(); |
520 | - void setPersistentSurfaceId(); |
521 | + void setPersistentSurfaceId(const QString& surfaceId); |
522 | |
523 | static bool compareMimeData(const QMimeData *a, const QMimeData *b); |
524 | static void copyMimeData(QMimeData& target, const QMimeData *source); |
525 | |
526 | === modified file 'python/libertine/ChrootContainer.py' |
527 | --- python/libertine/ChrootContainer.py 2017-02-27 20:47:21 +0000 |
528 | +++ python/libertine/ChrootContainer.py 2017-03-31 20:05:48 +0000 |
529 | @@ -47,8 +47,8 @@ |
530 | A concrete container type implemented using a plain old chroot. |
531 | """ |
532 | |
533 | - def __init__(self, container_id, config): |
534 | - super().__init__(container_id, 'chroot', config) |
535 | + def __init__(self, container_id, config, service): |
536 | + super().__init__(container_id, 'chroot', config, service) |
537 | # FIXME: Disabling seccomp is a temporary measure until we fully understand why we need |
538 | # it or figure out when we need it. |
539 | os.environ['PROOT_NO_SECCOMP'] = '1' |
540 | |
541 | === renamed file 'python/libertine/Client.py' => 'python/libertine/ContainerControlClient.py' |
542 | --- python/libertine/Client.py 2017-02-24 14:56:36 +0000 |
543 | +++ python/libertine/ContainerControlClient.py 2017-03-31 20:05:48 +0000 |
544 | @@ -19,19 +19,24 @@ |
545 | from . import utils |
546 | |
547 | |
548 | -class Client(object): |
549 | +class ContainerControlClient(object): |
550 | + """ |
551 | + A client for ContainerControl using D-BUS, to be used in clients |
552 | + external to the libertine service. |
553 | + """ |
554 | def __init__(self): |
555 | self._get_manager() |
556 | |
557 | def _get_manager(self): |
558 | - self._manager = None |
559 | + self._control = None |
560 | |
561 | try: |
562 | - from .service.manager import LIBERTINE_MANAGER_NAME, LIBERTINE_MANAGER_OBJECT |
563 | + from .service import constants |
564 | + |
565 | if utils.set_session_dbus_env_var(): |
566 | bus = dbus.SessionBus() |
567 | - self._manager = bus.get_object(LIBERTINE_MANAGER_NAME, LIBERTINE_MANAGER_OBJECT) |
568 | - self._interface = LIBERTINE_MANAGER_NAME |
569 | + self._control = bus.get_object(constants.SERVICE_NAME, constants.CONTAINER_CONTROL_OBJECT) |
570 | + self._interface = constants.CONTAINER_CONTROL_INTERFACE |
571 | except ImportError as e: |
572 | utils.get_logger().warning("Libertine service libraries not installed.") |
573 | except dbus.exceptions.DBusException as e: |
574 | @@ -51,11 +56,11 @@ |
575 | |
576 | @property |
577 | def valid(self): |
578 | - return self._manager is not None |
579 | + return self._control is not None |
580 | |
581 | def container_operation_start(self, id): |
582 | retries = 0 |
583 | - while not self._do_operation(lambda: self._manager.get_dbus_method('container_operation_start', self._interface)(id)): |
584 | + while not self._do_operation(lambda: self._control.get_dbus_method('start', self._interface)(id)): |
585 | retries += 1 |
586 | if retries > 5: |
587 | return False |
588 | @@ -64,7 +69,7 @@ |
589 | return True |
590 | |
591 | def container_operation_finished(self, id, app_name, pid): |
592 | - return self._do_operation(lambda: self._manager.get_dbus_method("container_operation_finished", self._interface)(id, app_name, pid)) |
593 | + return self._do_operation(lambda: self._control.get_dbus_method('finished', self._interface)(id, app_name, pid)) |
594 | |
595 | def container_stopped(self, id): |
596 | - return self._do_operation(lambda: self._manager.get_dbus_method('container_stopped', self._interface)(id)) |
597 | + return self._do_operation(lambda: self._control.get_dbus_method('stopped', self._interface)(id)) |
598 | |
599 | === modified file 'python/libertine/ContainersConfig.py' |
600 | --- python/libertine/ContainersConfig.py 2017-02-23 21:08:28 +0000 |
601 | +++ python/libertine/ContainersConfig.py 2017-03-31 20:05:48 +0000 |
602 | @@ -14,42 +14,77 @@ |
603 | |
604 | import fcntl |
605 | import json |
606 | -import libertine.utils |
607 | import os |
608 | import sys |
609 | +import errno |
610 | +import time |
611 | + |
612 | from hashlib import md5 |
613 | -from libertine.HostInfo import HostInfo |
614 | +from . import utils, HostInfo |
615 | + |
616 | +class _ContainersConfigFile(object): |
617 | + def __init__(self, readonly=True): |
618 | + self._readonly = readonly |
619 | + |
620 | + if readonly: |
621 | + self._flags = 'r' |
622 | + else: |
623 | + self._flags = 'w' |
624 | + |
625 | + self._fd = None |
626 | + |
627 | + def __enter__(self): |
628 | + container_config_file = utils.get_libertine_database_file_path() |
629 | + if self._readonly and (not os.path.exists(container_config_file) or |
630 | + os.path.getsize(container_config_file) == 0): |
631 | + return None |
632 | + |
633 | + retries = 0 |
634 | + while retries < 100: |
635 | + try: |
636 | + fd = open(container_config_file, self._flags) |
637 | + fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) |
638 | + |
639 | + self._fd = fd |
640 | + return self._fd |
641 | + except IOError as e: |
642 | + if e.errno != errno.EAGAIN: |
643 | + raise |
644 | + else: |
645 | + fd.close() |
646 | + retries += 1 |
647 | + time.sleep(0.05) |
648 | + |
649 | + def __exit__(self, *args): |
650 | + if self._fd: |
651 | + self._fd.close() |
652 | |
653 | |
654 | def read_container_config_file(): |
655 | container_list = {} |
656 | - container_config_file = libertine.utils.get_libertine_database_file_path() |
657 | - |
658 | - if (os.path.exists(container_config_file) and |
659 | - os.path.getsize(container_config_file) != 0): |
660 | - with open(container_config_file, 'r') as fd: |
661 | - fcntl.flock(fd, fcntl.LOCK_EX) |
662 | + with _ContainersConfigFile() as fd: |
663 | + if fd is not None: |
664 | container_list = json.load(fd) |
665 | |
666 | return container_list |
667 | |
668 | |
669 | def write_container_config_file(container_list): |
670 | - container_config_file = libertine.utils.get_libertine_database_file_path() |
671 | + container_config_file = utils.get_libertine_database_file_path() |
672 | |
673 | # Add a warning to adventurous users advising against mucking with this file |
674 | if container_list is not None: |
675 | container_list["_warning"] = "This file is automatically generated by Libertine and should not be manually edited." |
676 | |
677 | - with open(container_config_file, 'w') as fd: |
678 | - fcntl.flock(fd, fcntl.LOCK_EX) |
679 | - json.dump(container_list, fd, sort_keys=True, indent=4) |
680 | - fd.write('\n') |
681 | + with _ContainersConfigFile(False) as fd: |
682 | + if fd: |
683 | + json.dump(container_list, fd, sort_keys=True, indent=4) |
684 | + fd.write('\n') |
685 | |
686 | |
687 | def container_config_hash(): |
688 | checksum = md5() |
689 | - container_config_file = libertine.utils.get_libertine_database_file_path() |
690 | + container_config_file = utils.get_libertine_database_file_path() |
691 | if (os.path.exists(container_config_file) and os.path.getsize(container_config_file) != 0): |
692 | with open(container_config_file, "rb") as fd: |
693 | fcntl.flock(fd, fcntl.LOCK_EX) |
694 | @@ -214,12 +249,12 @@ |
695 | |
696 | def check_container_id(self, container_id): |
697 | if container_id and not self.container_exists(container_id): |
698 | - libertine.utils.get_logger().error("Container id \'%s\' does not exist." % container_id) |
699 | + utils.get_logger().error("Container id '{container_id}' does not exist.".format(container_id=container_id)) |
700 | sys.exit(1) |
701 | elif not container_id: |
702 | container_id = self.get_default_container_id() |
703 | if container_id is None: |
704 | - libertine.utils.get_logger().error("No default container available.") |
705 | + utils.get_logger().error("No default container available.") |
706 | sys.exit(1) |
707 | |
708 | return container_id |
709 | @@ -263,7 +298,7 @@ |
710 | |
711 | def delete_container(self, container_id): |
712 | if not self.container_list: |
713 | - libertine.utils.get_logger().error("Unable to delete container. No containers defined.") |
714 | + utils.get_logger().error("Unable to delete container. No containers defined.") |
715 | sys.exit(1) |
716 | |
717 | container = self._get_container_entry(container_id) |
718 | |
719 | === modified file 'python/libertine/Libertine.py' |
720 | --- python/libertine/Libertine.py 2017-03-03 15:34:16 +0000 |
721 | +++ python/libertine/Libertine.py 2017-03-31 20:05:48 +0000 |
722 | @@ -17,7 +17,7 @@ |
723 | import os |
724 | import shutil |
725 | |
726 | -from . import utils |
727 | +from . import utils, ContainerControlClient |
728 | from libertine.ContainersConfig import ContainersConfig |
729 | from libertine.HostInfo import HostInfo |
730 | |
731 | @@ -79,10 +79,11 @@ |
732 | |
733 | :param container_id: The machine-readable container name. |
734 | """ |
735 | - def __init__(self, container_id, container_type, config): |
736 | + def __init__(self, container_id, container_type, config, service): |
737 | self.container_type = container_type |
738 | self.container_id = container_id |
739 | self._config = config |
740 | + self._service = service |
741 | self._app_name = '' |
742 | self._pid = 0 |
743 | self.root_path = utils.get_libertine_container_rootfs_path(self.container_id) |
744 | @@ -332,8 +333,8 @@ |
745 | """ |
746 | A concrete mock container type. Used for unit testing. |
747 | """ |
748 | - def __init__(self, container_id, config): |
749 | - super().__init__(container_id, 'mock', config) |
750 | + def __init__(self, container_id, config, service): |
751 | + super().__init__(container_id, 'mock', config, service) |
752 | |
753 | def create_libertine_container(self, password=None, multiarch=False): |
754 | return True |
755 | @@ -386,7 +387,7 @@ |
756 | A sandbox for DEB-packaged X11-based applications. |
757 | """ |
758 | |
759 | - def __init__(self, container_id, containers_config=None): |
760 | + def __init__(self, container_id, containers_config=None, service=None): |
761 | """ |
762 | Initializes the container object. |
763 | |
764 | @@ -394,23 +395,22 @@ |
765 | """ |
766 | super().__init__() |
767 | |
768 | - if containers_config is None: |
769 | - containers_config = ContainersConfig() |
770 | - self.containers_config = containers_config |
771 | + self.containers_config = containers_config or ContainersConfig() |
772 | + service = service or ContainerControlClient.ContainerControlClient() |
773 | |
774 | container_type = self.containers_config.get_container_type(container_id) |
775 | |
776 | if container_type == "lxc": |
777 | from libertine.LxcContainer import LibertineLXC |
778 | - self.container = LibertineLXC(container_id, self.containers_config) |
779 | + self.container = LibertineLXC(container_id, self.containers_config, service) |
780 | elif container_type == "lxd": |
781 | from libertine.LxdContainer import LibertineLXD |
782 | - self.container = LibertineLXD(container_id, self.containers_config) |
783 | + self.container = LibertineLXD(container_id, self.containers_config, service) |
784 | elif container_type == "chroot": |
785 | from libertine.ChrootContainer import LibertineChroot |
786 | - self.container = LibertineChroot(container_id, self.containers_config) |
787 | + self.container = LibertineChroot(container_id, self.containers_config, service) |
788 | elif container_type == "mock": |
789 | - self.container = LibertineMock(container_id, self.containers_config) |
790 | + self.container = LibertineMock(container_id, self.containers_config, service) |
791 | else: |
792 | raise RuntimeError("Unsupported container type %s" % container_type) |
793 | |
794 | @@ -463,7 +463,10 @@ |
795 | try: |
796 | with ContainerRunning(self.container): |
797 | self.containers_config.update_container_install_status(self.container_id, "installing packages") |
798 | - return self.container.install_package(package_name, no_dialog, update_cache) |
799 | + retval = self.container.install_package(package_name, no_dialog, update_cache) |
800 | + |
801 | + self.containers_config.update_container_install_status(self.container_id, "running") |
802 | + return retval |
803 | except RuntimeError as e: |
804 | return handle_runtime_error(e) |
805 | |
806 | @@ -479,7 +482,10 @@ |
807 | os.environ['DEBIAN_FRONTEND'] = 'teletype' |
808 | |
809 | self.containers_config.update_container_install_status(self.container_id, "removing packages") |
810 | - return self.container.remove_package(package_name) |
811 | + retval = self.container.remove_package(package_name) |
812 | + |
813 | + self.containers_config.update_container_install_status(self.container_id, "running") |
814 | + return retval |
815 | except RuntimeError as e: |
816 | return handle_runtime_error(e) |
817 | |
818 | @@ -547,7 +553,7 @@ |
819 | for root, dirs, files in os.walk(apps_dir): |
820 | app_ids.extend(["{}_{}_0.0".format(self.container_id, f[:-8]) for f in files if f.endswith(".desktop")]) |
821 | |
822 | - return app_ids |
823 | + return sorted(app_ids) |
824 | |
825 | def exec_command(self, exec_line): |
826 | """ |
827 | |
828 | === modified file 'python/libertine/LxcContainer.py' |
829 | --- python/libertine/LxcContainer.py 2017-03-03 15:34:16 +0000 |
830 | +++ python/libertine/LxcContainer.py 2017-03-31 20:05:48 +0000 |
831 | @@ -23,7 +23,7 @@ |
832 | import tempfile |
833 | |
834 | from .Libertine import BaseContainer |
835 | -from . import utils, HostInfo, Client |
836 | +from . import utils, HostInfo |
837 | |
838 | |
839 | home_path = os.environ['HOME'] |
840 | @@ -157,14 +157,12 @@ |
841 | A concrete container type implemented using an LXC container. |
842 | """ |
843 | |
844 | - def __init__(self, container_id, config): |
845 | - super().__init__(container_id, 'lxc', config) |
846 | + def __init__(self, container_id, config, service): |
847 | + super().__init__(container_id, 'lxc', config, service) |
848 | self.container = lxc_container(container_id) |
849 | self.host_info = HostInfo.HostInfo() |
850 | self._freeze_on_stop = config.get_freeze_on_stop(self.container_id) |
851 | |
852 | - self._manager = Client.Client() |
853 | - |
854 | def _setup_pulse(self): |
855 | pulse_socket_path = os.path.join(utils.get_libertine_runtime_dir(), 'pulse_socket') |
856 | |
857 | @@ -213,7 +211,7 @@ |
858 | return fd.read().strip('\n') != self.host_info.get_host_timezone() |
859 | |
860 | def start_container(self): |
861 | - if not self._manager.container_operation_start(self.container_id): |
862 | + if not self._service.container_operation_start(self.container_id): |
863 | return False |
864 | |
865 | if self.container.state == 'RUNNING': |
866 | @@ -236,11 +234,11 @@ |
867 | stopped = False |
868 | self._config.refresh_database() |
869 | |
870 | - if self._manager.container_operation_finished(self.container_id, self._app_name, self._pid): |
871 | + if self._service.container_operation_finished(self.container_id, self._app_name, self._pid): |
872 | self._config.update_container_install_status(self.container_id, self._get_stop_type_string(self._freeze_on_stop)) |
873 | |
874 | if lxc_stop(self.container, self._freeze_on_stop): |
875 | - stopped = self._manager.container_stopped(self.container_id) |
876 | + stopped = self._service.container_stopped(self.container_id) |
877 | |
878 | self._config.update_container_install_status(self.container_id, self.container.state.lower()) |
879 | |
880 | @@ -397,7 +395,7 @@ |
881 | os.environ.update(environ) |
882 | |
883 | if not self.start_container(): |
884 | - self._manager.container_stopped(self.container_id) |
885 | + self._service.container_stopped(self.container_id) |
886 | return |
887 | |
888 | self._app_name = app_exec_line[0] |
889 | |
890 | === modified file 'python/libertine/LxdContainer.py' |
891 | --- python/libertine/LxdContainer.py 2017-03-03 15:34:16 +0000 |
892 | +++ python/libertine/LxdContainer.py 2017-03-31 20:05:48 +0000 |
893 | @@ -22,7 +22,7 @@ |
894 | import subprocess |
895 | import time |
896 | |
897 | -from . import Libertine, utils, HostInfo, Client |
898 | +from . import Libertine, utils, HostInfo |
899 | |
900 | |
901 | def _get_devices_map(): |
902 | @@ -62,10 +62,11 @@ |
903 | |
904 | def _setup_lxd(): |
905 | if utils.is_snap_environment(): |
906 | - utils.get_logger().warning("Running in snap environment, skipping automatic lxd setup.") |
907 | + utils.get_logger().warning("Snapped libertine detected, you may need to run `sudo lxd init` manually.") |
908 | return True |
909 | |
910 | - utils.get_logger().info("Running LXD setup.") |
911 | + utils.get_logger().debug("Running LXD setup.") |
912 | + |
913 | import pexpect |
914 | child = pexpect.spawnu('sudo libertine-lxd-setup {}'.format(os.environ['USER']), env={'TERM': 'dumb'}) |
915 | |
916 | @@ -74,6 +75,7 @@ |
917 | # The following are required for lxd=2.0.x |
918 | '.+\[yes/no\].*', |
919 | '.+\(e.g. (?P<example>[a-z0-9\.:]+)\).+']) |
920 | + |
921 | if index == 0: |
922 | child.sendline() |
923 | elif index == 1: |
924 | @@ -383,8 +385,8 @@ |
925 | |
926 | |
927 | class LibertineLXD(Libertine.BaseContainer): |
928 | - def __init__(self, name, config): |
929 | - super().__init__(name, 'lxd', config) |
930 | + def __init__(self, name, config, service): |
931 | + super().__init__(name, 'lxd', config, service) |
932 | self._host_info = HostInfo.HostInfo() |
933 | self._container = None |
934 | self._freeze_on_stop = config.get_freeze_on_stop(self.container_id) |
935 | @@ -392,15 +394,14 @@ |
936 | if not _setup_lxd(): |
937 | raise Exception("Failed to setup lxd.") |
938 | |
939 | - self._client = pylxd.Client() |
940 | - self._manager = Client.Client() |
941 | + self._lxd_client = pylxd.Client() |
942 | |
943 | def create_libertine_container(self, password=None, multiarch=False): |
944 | if self._try_get_container(): |
945 | utils.get_logger().error("Container already exists") |
946 | return False |
947 | |
948 | - update_libertine_profile(self._client) |
949 | + update_libertine_profile(self._lxd_client) |
950 | |
951 | utils.get_logger().info("Creating container '%s' with distro '%s'" % (self.container_id, self.installed_release)) |
952 | create = subprocess.Popen(shlex.split('lxc launch ubuntu-daily:{distro} {id} --profile ' |
953 | @@ -498,13 +499,13 @@ |
954 | return _lxc_args(self.container_id, command, environ) |
955 | |
956 | def run_in_container(self, command): |
957 | - return subprocess.Popen(self._lxc_args(command)).wait() |
958 | + return subprocess.Popen(self._lxc_args(command, os.environ.copy())).wait() |
959 | |
960 | def start_container(self, home=env_home_path()): |
961 | if not self._try_get_container(): |
962 | return False |
963 | |
964 | - if not self._manager.container_operation_start(self.container_id): |
965 | + if not self._service.container_operation_start(self.container_id): |
966 | return False |
967 | |
968 | if self._container.status == 'Running': |
969 | @@ -513,12 +514,12 @@ |
970 | requires_remount = self._container.status == 'Stopped' |
971 | |
972 | if requires_remount: |
973 | - update_libertine_profile(self._client) |
974 | + update_libertine_profile(self._lxd_client) |
975 | update_bind_mounts(self._container, self._config, home) |
976 | |
977 | self._config.update_container_install_status(self.container_id, "starting") |
978 | if not lxd_start(self._container): |
979 | - self._manager.container_stopped() |
980 | + self._service.container_stopped() |
981 | self._config.update_container_install_status(self.container_id, self._container.status.lower()) |
982 | return False |
983 | |
984 | @@ -539,11 +540,11 @@ |
985 | stopped = False |
986 | self._config.refresh_database() |
987 | |
988 | - if self._manager.container_operation_finished(self.container_id, self._app_name, self._pid): |
989 | + if self._service.container_operation_finished(self.container_id, self._app_name, self._pid): |
990 | self._config.update_container_install_status(self.container_id, self._get_stop_type_string(self._freeze_on_stop)) |
991 | - |
992 | + |
993 | if lxd_stop(self._container, freeze_on_stop=self._freeze_on_stop): |
994 | - stopped = self._manager.container_stopped(self.container_id) |
995 | + stopped = self._service.container_stopped(self.container_id) |
996 | |
997 | self._config.update_container_install_status(self.container_id, self._container.status.lower()) |
998 | |
999 | @@ -598,6 +599,6 @@ |
1000 | |
1001 | def _try_get_container(self): |
1002 | if self._container is None: |
1003 | - self._container = lxd_container(self._client, self.container_id) |
1004 | + self._container = lxd_container(self._lxd_client, self.container_id) |
1005 | |
1006 | return self._container is not None |
1007 | |
1008 | === added file 'python/libertine/service/constants.py' |
1009 | --- python/libertine/service/constants.py 1970-01-01 00:00:00 +0000 |
1010 | +++ python/libertine/service/constants.py 2017-03-31 20:05:48 +0000 |
1011 | @@ -0,0 +1,27 @@ |
1012 | +# Copyright 2017 Canonical Ltd. |
1013 | +# |
1014 | +# This program is free software: you can redistribute it and/or modify |
1015 | +# it under the terms of the GNU General Public License as published by |
1016 | +# the Free Software Foundation; version 3 of the License. |
1017 | +# |
1018 | +# This program is distributed in the hope that it will be useful, |
1019 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1020 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1021 | +# GNU General Public License for more details. |
1022 | +# |
1023 | +# You should have received a copy of the GNU General Public License |
1024 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1025 | + |
1026 | +SERVICE_NAME = "com.canonical.libertine.Service" |
1027 | + |
1028 | +OPERATIONS_INTERFACE = "com.canonical.libertine.Service.Operations" |
1029 | +OPERATIONS_OBJECT = "/com/canonical/libertine/Service/Operations" |
1030 | + |
1031 | +DOWNLOAD_INTERFACE = "com.canonical.applications.Service.Download" |
1032 | +DOWNLOAD_OBJECT = "/com/canonical/libertine/Service/Download/%s" |
1033 | + |
1034 | +OPERATIONS_MONITOR_INTERFACE = "com.canonical.libertine.Service.OperationsMonitor" |
1035 | +OPERATIONS_MONITOR_OBJECT = "/com/canonical/libertine/Service/OperationsMonitor" |
1036 | + |
1037 | +CONTAINER_CONTROL_INTERFACE = "com.canonical.libertine.Service.ContainerControl" |
1038 | +CONTAINER_CONTROL_OBJECT = "/com/canonical/libertine/Service/ContainerControl" |
1039 | |
1040 | === modified file 'python/libertine/service/container.py' |
1041 | --- python/libertine/service/container.py 2017-02-07 12:35:48 +0000 |
1042 | +++ python/libertine/service/container.py 2017-03-31 20:05:48 +0000 |
1043 | @@ -22,11 +22,13 @@ |
1044 | |
1045 | |
1046 | class Container(object): |
1047 | - def __init__(self, container_id, config, connection, callback): |
1048 | + def __init__(self, container_id, config, monitor, client, callback): |
1049 | self._id = container_id |
1050 | - self._connection = connection |
1051 | + self._config = config |
1052 | + self._monitor = monitor |
1053 | + self._client = client |
1054 | self._callback = callback |
1055 | - self._config = config |
1056 | + |
1057 | self._lock = Lock() |
1058 | self._tasks = [] |
1059 | |
1060 | @@ -53,31 +55,6 @@ |
1061 | def tasks(self): |
1062 | return [task.id for task in self._tasks if task.running] |
1063 | |
1064 | - def search(self, query): |
1065 | - utils.get_logger().debug("search container '%s' for package '%s'" % (self.id, query)) |
1066 | - |
1067 | - if utils.is_snap_environment(): |
1068 | - raise Exception("This operation is not currently supported within the snap") |
1069 | - |
1070 | - task = SearchTask(self.id, self._cache, query, self._connection, self._cleanup_task) |
1071 | - self._tasks.append(task) |
1072 | - task.start() |
1073 | - |
1074 | - return task.id |
1075 | - |
1076 | - def app_info(self, package_name): |
1077 | - utils.get_logger().debug("get info for package '%s' in container '%s'" % (package_name, self.id)) |
1078 | - |
1079 | - if utils.is_snap_environment(): |
1080 | - raise Exception("This operation is not currently supported within the snap") |
1081 | - |
1082 | - related_task_ids = [t.id for t in self._tasks if t.package == package_name and t.running] |
1083 | - task = AppInfoTask(self.id, self._cache, package_name, related_task_ids, self._config, self._connection, self._cleanup_task) |
1084 | - |
1085 | - self._tasks.append(task) |
1086 | - task.start() |
1087 | - return task.id |
1088 | - |
1089 | def install(self, package_name): |
1090 | utils.get_logger().debug("Install package '%s' from container '%s'" % (package_name, self.id)) |
1091 | |
1092 | @@ -86,7 +63,7 @@ |
1093 | utils.get_logger().debug("Install already in progress for '%s':'%s'" % (package_name, self.id)) |
1094 | return tasks[0].id |
1095 | |
1096 | - task = InstallTask(package_name, self.id, self._config, self._lock, self._connection, self._cleanup_task) |
1097 | + task = InstallTask(package_name, self.id, self._config, self._lock, self._monitor, self._client, self._cleanup_task) |
1098 | self._tasks.append(task) |
1099 | task.start() |
1100 | return task.id |
1101 | @@ -99,7 +76,7 @@ |
1102 | utils.get_logger().debug("Remove already in progress for '%s':'%s'" % (package_name, self.id)) |
1103 | return tasks[0].id |
1104 | |
1105 | - task = RemoveTask(package_name, self.id, self._config, self._lock, self._connection, self._cleanup_task) |
1106 | + task = RemoveTask(package_name, self.id, self._config, self._lock, self._monitor, self._client, self._cleanup_task) |
1107 | self._tasks.append(task) |
1108 | task.start() |
1109 | return task.id |
1110 | @@ -113,7 +90,7 @@ |
1111 | return tasks[0].id |
1112 | |
1113 | task = CreateTask(self.id, container_name, distro, container_type, enable_multiarch, |
1114 | - self._config, self._lock, self._connection, self._cleanup_task) |
1115 | + self._config, self._lock, self._monitor, self._client, self._cleanup_task) |
1116 | self._tasks.append(task) |
1117 | task.start() |
1118 | return task.id |
1119 | @@ -126,7 +103,7 @@ |
1120 | utils.get_logger().debug("Destroy already in progress for '%s'" % self.id) |
1121 | return tasks[0].id |
1122 | |
1123 | - task = DestroyTask(self.id, self._config, self._lock, self._connection, self._cleanup_task) |
1124 | + task = DestroyTask(self.id, self._config, self._lock, self._monitor, self._client, self._cleanup_task) |
1125 | self._tasks.append(task) |
1126 | task.start() |
1127 | return task.id |
1128 | @@ -139,15 +116,42 @@ |
1129 | utils.get_logger().debug("Update already in progress for '%s'" % self.id) |
1130 | return tasks[0].id |
1131 | |
1132 | - task = UpdateTask(self.id, self._config, self._lock, self._connection, self._cleanup_task) |
1133 | + task = UpdateTask(self.id, self._config, self._lock, self._monitor, self._client, self._cleanup_task) |
1134 | self._tasks.append(task) |
1135 | task.start() |
1136 | return task.id |
1137 | |
1138 | + # Tasks which don't require starting/stopping the container |
1139 | + |
1140 | def list_app_ids(self): |
1141 | utils.get_logger().debug("List all app ids in container '%s'" % self.id) |
1142 | |
1143 | - task = ListAppIdsTask(self.id, self._config, self._connection, self._cleanup_task) |
1144 | + task = ListAppIdsTask(self.id, self._config, self._monitor, self._client, self._cleanup_task) |
1145 | + |
1146 | + self._tasks.append(task) |
1147 | + task.start() |
1148 | + return task.id |
1149 | + |
1150 | + def search(self, query): |
1151 | + utils.get_logger().debug("search container '%s' for package '%s'" % (self.id, query)) |
1152 | + |
1153 | + if utils.is_snap_environment(): |
1154 | + raise Exception("This operation is not currently supported within the snap") |
1155 | + |
1156 | + task = SearchTask(self.id, self._cache, query, self._monitor, self._cleanup_task) |
1157 | + self._tasks.append(task) |
1158 | + task.start() |
1159 | + |
1160 | + return task.id |
1161 | + |
1162 | + def app_info(self, package_name): |
1163 | + utils.get_logger().debug("get info for package '%s' in container '%s'" % (package_name, self.id)) |
1164 | + |
1165 | + if utils.is_snap_environment(): |
1166 | + raise Exception("This operation is not currently supported within the snap") |
1167 | + |
1168 | + related_task_ids = [t.id for t in self._tasks if t.package == package_name and t.running] |
1169 | + task = AppInfoTask(self.id, self._cache, package_name, related_task_ids, self._config, self._monitor, self._cleanup_task) |
1170 | |
1171 | self._tasks.append(task) |
1172 | task.start() |
1173 | |
1174 | === renamed file 'python/libertine/service/operations_state.py' => 'python/libertine/service/container_control.py' |
1175 | --- python/libertine/service/operations_state.py 2017-02-23 15:25:17 +0000 |
1176 | +++ python/libertine/service/container_control.py 2017-03-31 20:05:48 +0000 |
1177 | @@ -12,64 +12,35 @@ |
1178 | # You should have received a copy of the GNU General Public License |
1179 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
1180 | |
1181 | -import libertine.ContainersConfig |
1182 | -import psutil |
1183 | - |
1184 | -from collections import Counter |
1185 | + |
1186 | +import dbus |
1187 | + |
1188 | +from . import constants |
1189 | from libertine import utils |
1190 | |
1191 | |
1192 | -class OperationsState(object): |
1193 | - def __init__(self): |
1194 | - self._get_running_apps_per_container() |
1195 | - |
1196 | - def _get_running_apps_per_container(self): |
1197 | - self._invalid_apps = dict() |
1198 | - self._operations = Counter() |
1199 | - config = libertine.ContainersConfig.ContainersConfig() |
1200 | - |
1201 | - for container in config.get_containers(): |
1202 | - running_apps = config.get_running_apps(container).copy() |
1203 | - |
1204 | - for app in running_apps: |
1205 | - try: |
1206 | - proc = psutil.Process(app['pid']) |
1207 | - if app['appExecName'] in proc.cmdline(): |
1208 | - self._operations[container] += 1 |
1209 | - else: |
1210 | - raise |
1211 | - except: |
1212 | - utils.get_logger().error("Container app {} is not valid.".format(app['appExecName'])) |
1213 | - if container not in self._invalid_apps: |
1214 | - self._invalid_apps[container] = [{app['appExecName'], app['pid']}] |
1215 | - else: |
1216 | - self._invalid_apps[container].append({app['appExecName'], app['pid']}) |
1217 | - config.delete_running_app(container, app) |
1218 | - continue |
1219 | - |
1220 | - def operation_start(self, container): |
1221 | - if self._operations[container] == -1: |
1222 | - return False |
1223 | - |
1224 | - self._operations[container] += 1 |
1225 | - |
1226 | - return True |
1227 | - |
1228 | - def operation_finished(self, container, app_name, pid): |
1229 | - if container in self._invalid_apps and {app_name, pid} in self._invalid_apps[container]: |
1230 | - self._invalid_apps[container].remove({app_name, pid}) |
1231 | - if not self._invalid_apps[container]: |
1232 | - del self._invalid_apps[container] |
1233 | - else: |
1234 | - self._operations[container] -= 1 |
1235 | - |
1236 | - if self._operations[container] == 0: |
1237 | - self._operations[container] = -1 |
1238 | - return True |
1239 | - |
1240 | - return False |
1241 | - |
1242 | - def operation_stopped(self, container): |
1243 | - del self._operations[container] |
1244 | - |
1245 | - return True |
1246 | +class ContainerControl(dbus.service.Object): |
1247 | + def __init__(self, connection, client): |
1248 | + dbus.service.Object.__init__(self, conn=connection, object_path=constants.CONTAINER_CONTROL_OBJECT) |
1249 | + self._client = client |
1250 | + |
1251 | + @dbus.service.method(constants.CONTAINER_CONTROL_INTERFACE, |
1252 | + in_signature='s', |
1253 | + out_signature='b') |
1254 | + def start(self, container): |
1255 | + utils.get_logger().debug("start({})".format(container)) |
1256 | + return self._client.container_operation_start(container) |
1257 | + |
1258 | + @dbus.service.method(constants.CONTAINER_CONTROL_INTERFACE, |
1259 | + in_signature='ssi', |
1260 | + out_signature='b') |
1261 | + def finished(self, container, app_name, pid): |
1262 | + utils.get_logger().debug("finished({})".format(container)) |
1263 | + return self._client.container_operation_finished(container, app_name, pid) |
1264 | + |
1265 | + @dbus.service.method(constants.CONTAINER_CONTROL_INTERFACE, |
1266 | + in_signature='s', |
1267 | + out_signature='b') |
1268 | + def stopped(self, container): |
1269 | + utils.get_logger().debug("stopped({})".format(container)) |
1270 | + return self._client.container_stopped(container) |
1271 | |
1272 | === added file 'python/libertine/service/container_control_client.py' |
1273 | --- python/libertine/service/container_control_client.py 1970-01-01 00:00:00 +0000 |
1274 | +++ python/libertine/service/container_control_client.py 2017-03-31 20:05:48 +0000 |
1275 | @@ -0,0 +1,75 @@ |
1276 | +# Copyright 2017 Canonical Ltd. |
1277 | +# |
1278 | +# This program is free software: you can redistribute it and/or modify |
1279 | +# it under the terms of the GNU General Public License as published by |
1280 | +# the Free Software Foundation; version 3 of the License. |
1281 | +# |
1282 | +# This program is distributed in the hope that it will be useful, |
1283 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1284 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1285 | +# GNU General Public License for more details. |
1286 | +# |
1287 | +# You should have received a copy of the GNU General Public License |
1288 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1289 | + |
1290 | + |
1291 | +import libertine.ContainersConfig |
1292 | +import psutil |
1293 | + |
1294 | +from collections import Counter |
1295 | +from libertine import utils |
1296 | + |
1297 | + |
1298 | +class ContainerControlClient(object): |
1299 | + def __init__(self): |
1300 | + self._get_running_apps_per_container() |
1301 | + |
1302 | + def _get_running_apps_per_container(self): |
1303 | + self._invalid_apps = dict() |
1304 | + self._operations = Counter() |
1305 | + config = libertine.ContainersConfig.ContainersConfig() |
1306 | + |
1307 | + for container in config.get_containers(): |
1308 | + running_apps = config.get_running_apps(container).copy() |
1309 | + |
1310 | + for app in running_apps: |
1311 | + try: |
1312 | + proc = psutil.Process(app['pid']) |
1313 | + if app['appExecName'] in proc.cmdline(): |
1314 | + self._operations[container] += 1 |
1315 | + else: |
1316 | + raise |
1317 | + except: |
1318 | + utils.get_logger().error("Container app {} is not valid.".format(app['appExecName'])) |
1319 | + if container not in self._invalid_apps: |
1320 | + self._invalid_apps[container] = [{app['appExecName'], app['pid']}] |
1321 | + else: |
1322 | + self._invalid_apps[container].append({app['appExecName'], app['pid']}) |
1323 | + config.delete_running_app(container, app) |
1324 | + continue |
1325 | + |
1326 | + def container_operation_start(self, container): |
1327 | + if self._operations[container] == -1: |
1328 | + return False |
1329 | + |
1330 | + self._operations[container] += 1 |
1331 | + |
1332 | + return True |
1333 | + |
1334 | + def container_operation_finished(self, container, app_name, pid): |
1335 | + if container in self._invalid_apps and {app_name, pid} in self._invalid_apps[container]: |
1336 | + self._invalid_apps[container].remove({app_name, pid}) |
1337 | + if not self._invalid_apps[container]: |
1338 | + del self._invalid_apps[container] |
1339 | + else: |
1340 | + self._operations[container] -= 1 |
1341 | + |
1342 | + if self._operations[container] == 0: |
1343 | + self._operations[container] = -1 |
1344 | + return True |
1345 | + |
1346 | + return False |
1347 | + |
1348 | + def container_stopped(self, container): |
1349 | + del self._operations[container] |
1350 | + return True |
1351 | |
1352 | === renamed file 'python/libertine/service/progress.py' => 'python/libertine/service/download.py' |
1353 | --- python/libertine/service/progress.py 2017-01-24 18:00:57 +0000 |
1354 | +++ python/libertine/service/download.py 2017-03-31 20:05:48 +0000 |
1355 | @@ -1,4 +1,4 @@ |
1356 | -# Copyright 2016-2017 Canonical Ltd. |
1357 | +# Copyright 2017 Canonical Ltd. |
1358 | # |
1359 | # This program is free software: you can redistribute it and/or modify |
1360 | # it under the terms of the GNU General Public License as published by |
1361 | @@ -12,73 +12,68 @@ |
1362 | # You should have received a copy of the GNU General Public License |
1363 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
1364 | |
1365 | + |
1366 | import dbus.service |
1367 | import threading |
1368 | + |
1369 | +from . import constants |
1370 | from libertine import utils |
1371 | from time import time |
1372 | |
1373 | -DOWNLOAD_INTERFACE = "com.canonical.applications.Download" |
1374 | -PROGRESS_INTERFACE = "com.canonical.libertine.Service.Progress" |
1375 | |
1376 | -class Progress(dbus.service.Object): |
1377 | - def __init__(self, connection): |
1378 | - utils.get_logger().debug("creating a Progress object") |
1379 | +class Download(dbus.service.Object): |
1380 | + def __init__(self, connection, id): |
1381 | self._finished = False |
1382 | - self._result = [] |
1383 | + self._result = '' |
1384 | self._error = '' |
1385 | - dbus.service.Object.__init__(self, conn=connection, object_path=("/Progress/%s" % hex(int(time()*10000000))[2:])) |
1386 | - |
1387 | - # self.emit_processing() # Disabled until something requires the Download interface |
1388 | - |
1389 | - @property |
1390 | - def id(self): |
1391 | - return self._object_path |
1392 | - |
1393 | + dbus.service.Object.__init__(self, conn=connection, object_path=(constants.DOWNLOAD_OBJECT % id)) |
1394 | + |
1395 | + # Disabled until something requires the Download interface |
1396 | + # self.emit_processing() |
1397 | + |
1398 | + # This is currently how services using the Ubuntu SDK to show progress |
1399 | + # determine whether or not an operation is running. |
1400 | def emit_processing(self): |
1401 | if not self.done: |
1402 | self.processing(self.id) |
1403 | threading.Timer(0.5, self.emit_processing).start() |
1404 | |
1405 | @property |
1406 | + def id(self): |
1407 | + return self._object_path |
1408 | + |
1409 | + @property |
1410 | def done(self): |
1411 | return self._finished |
1412 | |
1413 | - @dbus.service.signal(DOWNLOAD_INTERFACE) |
1414 | + @property |
1415 | + def result(self): |
1416 | + return self._result.strip() |
1417 | + |
1418 | + @property |
1419 | + def last_error(self): |
1420 | + return self._error |
1421 | + |
1422 | + def data(self, message): |
1423 | + self._result += message + '\n' |
1424 | + |
1425 | + # Signals to satisfy the download interface |
1426 | + |
1427 | + @dbus.service.signal(constants.DOWNLOAD_INTERFACE, signature='o') |
1428 | def processing(self, path): |
1429 | utils.get_logger().debug("emit processing('%s')" % path) |
1430 | |
1431 | - @dbus.service.signal(DOWNLOAD_INTERFACE) |
1432 | + @dbus.service.signal(constants.DOWNLOAD_INTERFACE, signature='o') |
1433 | def finished(self, path): |
1434 | utils.get_logger().debug("emit finished('%s')" % path) |
1435 | self._finished = True |
1436 | |
1437 | - @dbus.service.signal(DOWNLOAD_INTERFACE) |
1438 | + @dbus.service.signal(constants.DOWNLOAD_INTERFACE) |
1439 | def progress(self, received, total): |
1440 | utils.get_logger().debug("emit progress(%d, %d)" % (received, total)) |
1441 | |
1442 | - @dbus.service.signal(DOWNLOAD_INTERFACE) |
1443 | + @dbus.service.signal(constants.DOWNLOAD_INTERFACE, signature='s') |
1444 | def error(self, message): |
1445 | utils.get_logger().error("emit error(%s)" % message) |
1446 | self._error = message |
1447 | self._finished = True |
1448 | - |
1449 | - @dbus.service.signal(PROGRESS_INTERFACE) |
1450 | - def data(self, message): |
1451 | - utils.get_logger().debug("emit data(%s)" % message) |
1452 | - self._result.append(message) |
1453 | - |
1454 | - @dbus.service.method(PROGRESS_INTERFACE, out_signature='b') |
1455 | - def running(self): |
1456 | - utils.get_logger().debug(not self.done) |
1457 | - return not self.done |
1458 | - |
1459 | - @dbus.service.method(PROGRESS_INTERFACE, out_signature='s') |
1460 | - def result(self): |
1461 | - full_result = "\n".join(self._result) |
1462 | - utils.get_logger().debug(full_result) |
1463 | - return full_result |
1464 | - |
1465 | - @dbus.service.method(PROGRESS_INTERFACE, out_signature='s') |
1466 | - def last_error(self): |
1467 | - utils.get_logger().debug(self._error) |
1468 | - return self._error |
1469 | |
1470 | === renamed file 'python/libertine/service/manager.py' => 'python/libertine/service/operations.py' |
1471 | --- python/libertine/service/manager.py 2017-02-21 18:20:21 +0000 |
1472 | +++ python/libertine/service/operations.py 2017-03-31 20:05:48 +0000 |
1473 | @@ -12,69 +12,51 @@ |
1474 | # You should have received a copy of the GNU General Public License |
1475 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
1476 | |
1477 | + |
1478 | import dbus |
1479 | import dbus.service |
1480 | -import libertine.service.task_dispatcher |
1481 | -import libertine.service.operations_state |
1482 | -from dbus.mainloop.glib import DBusGMainLoop |
1483 | -from libertine.service import container |
1484 | + |
1485 | +from . import constants, operations_monitor, task_dispatcher |
1486 | from libertine import utils |
1487 | |
1488 | |
1489 | -LIBERTINE_MANAGER_NAME = "com.canonical.libertine.Service" |
1490 | -LIBERTINE_MANAGER_INTERFACE = LIBERTINE_MANAGER_NAME |
1491 | -LIBERTINE_MANAGER_OBJECT = "/Manager" |
1492 | - |
1493 | - |
1494 | -class Manager(dbus.service.Object): |
1495 | - def __init__(self): |
1496 | - utils.get_logger().debug("creating service") |
1497 | - DBusGMainLoop(set_as_default=True) |
1498 | - self._operations_state = libertine.service.operations_state.OperationsState() |
1499 | - |
1500 | - try: |
1501 | - bus_name = dbus.service.BusName(LIBERTINE_MANAGER_NAME, |
1502 | - bus=dbus.SessionBus(), |
1503 | - do_not_queue=True) |
1504 | - except dbus.exceptions.NameExistsException: |
1505 | - utils.get_logger().warning("service is already running") |
1506 | - raise |
1507 | - |
1508 | - super().__init__(bus_name, LIBERTINE_MANAGER_OBJECT) |
1509 | - |
1510 | - self._dispatcher = libertine.service.task_dispatcher.TaskDispatcher(self.connection) |
1511 | +class Operations(dbus.service.Object): |
1512 | + def __init__(self, bus_name, client): |
1513 | + super().__init__(bus_name, constants.OPERATIONS_OBJECT) |
1514 | + |
1515 | + self._dispatcher = task_dispatcher.TaskDispatcher(operations_monitor.OperationsMonitor(self.connection), client) |
1516 | |
1517 | # Information |
1518 | |
1519 | - @dbus.service.method(LIBERTINE_MANAGER_INTERFACE, |
1520 | + @dbus.service.method(constants.OPERATIONS_INTERFACE, |
1521 | in_signature='ss', |
1522 | out_signature='o') |
1523 | def search(self, container_id, search_string): |
1524 | utils.get_logger().debug("search('{}', '{}') called".format(container_id, search_string)) |
1525 | return self._dispatcher.search(container_id, search_string) |
1526 | |
1527 | - @dbus.service.method(LIBERTINE_MANAGER_INTERFACE, |
1528 | + @dbus.service.method(constants.OPERATIONS_INTERFACE, |
1529 | in_signature='ss', |
1530 | out_signature='o') |
1531 | def app_info(self, container_id, app_id): |
1532 | utils.get_logger().debug("app_info('{}', '{}') called".format(container_id, app_id)) |
1533 | return self._dispatcher.app_info(container_id, app_id) |
1534 | |
1535 | - @dbus.service.method(LIBERTINE_MANAGER_INTERFACE, |
1536 | + @dbus.service.method(constants.OPERATIONS_INTERFACE, |
1537 | in_signature='s', |
1538 | out_signature='o') |
1539 | def container_info(self, container_id): |
1540 | utils.get_logger().debug("container_info('{}')".format(container_id)) |
1541 | return self._dispatcher.container_info(container_id) |
1542 | |
1543 | - @dbus.service.method(LIBERTINE_MANAGER_INTERFACE, |
1544 | + @dbus.service.method(constants.OPERATIONS_INTERFACE, |
1545 | in_signature='s', |
1546 | out_signature='o') |
1547 | def list_app_ids(self, container_id): |
1548 | utils.get_logger().debug("list_app_ids('{}')".format(container_id)) |
1549 | return self._dispatcher.list_app_ids(container_id) |
1550 | |
1551 | - @dbus.service.method(LIBERTINE_MANAGER_INTERFACE, |
1552 | + @dbus.service.method(constants.OPERATIONS_INTERFACE, |
1553 | out_signature='o') |
1554 | def list(self): |
1555 | utils.get_logger().debug("list()") |
1556 | @@ -82,63 +64,37 @@ |
1557 | |
1558 | # Operations |
1559 | |
1560 | - @dbus.service.method(LIBERTINE_MANAGER_INTERFACE, |
1561 | + @dbus.service.method(constants.OPERATIONS_INTERFACE, |
1562 | in_signature='ssssb', |
1563 | out_signature='o') |
1564 | def create(self, container_id, container_name='', distro='', container_type='', enable_multiarch=False): |
1565 | utils.get_logger().debug("create('{}', '{}', '{}', '{}', '{}')".format(container_id, container_name, distro, container_type, enable_multiarch)) |
1566 | return self._dispatcher.create(container_id, container_name, distro, container_type, enable_multiarch) |
1567 | |
1568 | - @dbus.service.method(LIBERTINE_MANAGER_INTERFACE, |
1569 | + @dbus.service.method(constants.OPERATIONS_INTERFACE, |
1570 | in_signature='s', |
1571 | out_signature='o') |
1572 | def destroy(self, container_id): |
1573 | utils.get_logger().debug("destroy('{}')".format(container_id)) |
1574 | return self._dispatcher.destroy(container_id) |
1575 | |
1576 | - @dbus.service.method(LIBERTINE_MANAGER_INTERFACE, |
1577 | + @dbus.service.method(constants.OPERATIONS_INTERFACE, |
1578 | in_signature='s', |
1579 | out_signature='o') |
1580 | def update(self, container_id): |
1581 | utils.get_logger().debug("update('{}')".format(container_id)) |
1582 | return self._dispatcher.update(container_id) |
1583 | |
1584 | - @dbus.service.method(LIBERTINE_MANAGER_INTERFACE, |
1585 | + @dbus.service.method(constants.OPERATIONS_INTERFACE, |
1586 | in_signature='ss', |
1587 | out_signature='o') |
1588 | def install(self, container_id, package_name): |
1589 | utils.get_logger().debug("install('%s', '%s')" % (container_id, package_name)) |
1590 | return self._dispatcher.install(container_id, package_name) |
1591 | |
1592 | - @dbus.service.method(LIBERTINE_MANAGER_INTERFACE, |
1593 | + @dbus.service.method(constants.OPERATIONS_INTERFACE, |
1594 | in_signature='ss', |
1595 | out_signature='o') |
1596 | def remove(self, container_id, package_name): |
1597 | utils.get_logger().debug("remove('%s', '%s')" % (container_id, package_name)) |
1598 | return self._dispatcher.remove(container_id, package_name) |
1599 | - |
1600 | - # Container Lifecycle |
1601 | - |
1602 | - @dbus.service.method(LIBERTINE_MANAGER_INTERFACE, |
1603 | - in_signature='s', |
1604 | - out_signature='b') |
1605 | - def container_operation_start(self, container): |
1606 | - utils.get_logger().debug("container_operation_start({})".format(container)) |
1607 | - |
1608 | - return self._operations_state.operation_start(container) |
1609 | - |
1610 | - @dbus.service.method(LIBERTINE_MANAGER_INTERFACE, |
1611 | - in_signature='ssi', |
1612 | - out_signature='b') |
1613 | - def container_operation_finished(self, container, app_name='', pid=0): |
1614 | - utils.get_logger().debug("container_operation_finished({})".format(container)) |
1615 | - |
1616 | - return self._operations_state.operation_finished(container, app_name, pid) |
1617 | - |
1618 | - @dbus.service.method(LIBERTINE_MANAGER_INTERFACE, |
1619 | - in_signature='s', |
1620 | - out_signature='b') |
1621 | - def container_stopped(self, container): |
1622 | - utils.get_logger().debug("container_stopped({})".format(container)) |
1623 | - |
1624 | - return self._operations_state.operation_stopped(container) |
1625 | |
1626 | === added file 'python/libertine/service/operations_monitor.py' |
1627 | --- python/libertine/service/operations_monitor.py 1970-01-01 00:00:00 +0000 |
1628 | +++ python/libertine/service/operations_monitor.py 2017-03-31 20:05:48 +0000 |
1629 | @@ -0,0 +1,93 @@ |
1630 | +# Copyright 2017 Canonical Ltd. |
1631 | +# |
1632 | +# This program is free software: you can redistribute it and/or modify |
1633 | +# it under the terms of the GNU General Public License as published by |
1634 | +# the Free Software Foundation; version 3 of the License. |
1635 | +# |
1636 | +# This program is distributed in the hope that it will be useful, |
1637 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1638 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1639 | +# GNU General Public License for more details. |
1640 | +# |
1641 | +# You should have received a copy of the GNU General Public License |
1642 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1643 | + |
1644 | + |
1645 | +import dbus.service |
1646 | +import threading |
1647 | +import uuid |
1648 | + |
1649 | +from . import constants, download |
1650 | +from libertine import utils |
1651 | +from time import time |
1652 | + |
1653 | + |
1654 | +class OperationsMonitor(dbus.service.Object): |
1655 | + def __init__(self, connection): |
1656 | + self._operations = [] |
1657 | + dbus.service.Object.__init__(self, conn=connection, object_path=constants.OPERATIONS_MONITOR_OBJECT) |
1658 | + |
1659 | + def new_operation(self): |
1660 | + self._operations.append(download.Download(self.connection, str(uuid.uuid4().fields[-1]))) |
1661 | + return self._operations[-1].id |
1662 | + |
1663 | + def remove_from_connection(self, path): |
1664 | + operation = self._operation(path) |
1665 | + self._operations.remove(operation) |
1666 | + operation.remove_from_connection() |
1667 | + |
1668 | + def done(self, path): |
1669 | + op = self._operation(path) |
1670 | + if op: |
1671 | + return op.done |
1672 | + else: |
1673 | + return False |
1674 | + |
1675 | + def _operation(self, path): |
1676 | + operations = [op for op in self._operations if op.id == path] |
1677 | + if not operations: |
1678 | + return None |
1679 | + |
1680 | + return operations[0] |
1681 | + |
1682 | + @dbus.service.signal(constants.OPERATIONS_MONITOR_INTERFACE, signature='o') |
1683 | + def finished(self, path): |
1684 | + op = self._operation(path) |
1685 | + if op: |
1686 | + op.finished(path) |
1687 | + |
1688 | + @dbus.service.signal(constants.OPERATIONS_MONITOR_INTERFACE, signature='os') |
1689 | + def error(self, path, message): |
1690 | + op = self._operation(path) |
1691 | + if op: |
1692 | + op.error(message) |
1693 | + |
1694 | + @dbus.service.signal(constants.OPERATIONS_MONITOR_INTERFACE, signature='os') |
1695 | + def data(self, path, message): |
1696 | + op = self._operation(path) |
1697 | + if op: |
1698 | + op.data(message) |
1699 | + |
1700 | + @dbus.service.method(constants.OPERATIONS_MONITOR_INTERFACE, in_signature='o', out_signature='b') |
1701 | + def running(self, path): |
1702 | + op = self._operation(path) |
1703 | + if op: |
1704 | + return not op.done |
1705 | + else: |
1706 | + return False |
1707 | + |
1708 | + @dbus.service.method(constants.OPERATIONS_MONITOR_INTERFACE, in_signature='o', out_signature='s') |
1709 | + def result(self, path): |
1710 | + op = self._operation(path) |
1711 | + if op: |
1712 | + return op.result |
1713 | + else: |
1714 | + return '' |
1715 | + |
1716 | + @dbus.service.method(constants.OPERATIONS_MONITOR_INTERFACE, in_signature='o', out_signature='s') |
1717 | + def last_error(self, path): |
1718 | + op = self._operation(path) |
1719 | + if op: |
1720 | + return op.last_error |
1721 | + else: |
1722 | + return '' |
1723 | |
1724 | === modified file 'python/libertine/service/task_dispatcher.py' |
1725 | --- python/libertine/service/task_dispatcher.py 2017-02-23 20:47:39 +0000 |
1726 | +++ python/libertine/service/task_dispatcher.py 2017-03-31 20:05:48 +0000 |
1727 | @@ -16,22 +16,13 @@ |
1728 | import libertine.ContainersConfig |
1729 | from libertine.service.container import Container |
1730 | from libertine.service.tasks import * |
1731 | -from threading import Lock |
1732 | from libertine import utils |
1733 | |
1734 | |
1735 | -# Decorator to refresh database before making a call |
1736 | -def _refresh_config(func): |
1737 | - def wrapper(*args, **kwargs): |
1738 | - args[0]._config.refresh_database() |
1739 | - return func(*args, **kwargs) |
1740 | - |
1741 | - return wrapper |
1742 | - |
1743 | - |
1744 | class TaskDispatcher(object): |
1745 | - def __init__(self, connection): |
1746 | - self._connection = connection |
1747 | + def __init__(self, monitor, client): |
1748 | + self._monitor = monitor |
1749 | + self._client = client |
1750 | self._config = libertine.ContainersConfig.ContainersConfig() |
1751 | self._containerless_tasks = [] |
1752 | self._tasks = [] |
1753 | @@ -49,11 +40,13 @@ |
1754 | |
1755 | def _find_or_create_container(self, container_id): |
1756 | utils.get_logger().debug("finding or creating container '%s'" % container_id) |
1757 | + |
1758 | container = self._find_container(container_id) |
1759 | if container is not None: |
1760 | utils.get_logger().debug("using existing container '%s'" % container_id) |
1761 | return container |
1762 | - container = Container(container_id, self._config, self._connection, self._cleanup_container) |
1763 | + |
1764 | + container = Container(container_id, self._config, self._monitor, self._client, self._cleanup_container) |
1765 | self._containers.append(container) |
1766 | |
1767 | return container |
1768 | @@ -65,49 +58,40 @@ |
1769 | |
1770 | # Tasks (usually) run within a container |
1771 | |
1772 | - @_refresh_config |
1773 | def search(self, container_id, query): |
1774 | utils.get_logger().debug("dispatching search in container '%s' for package '%s'" % (container_id, query)) |
1775 | return self._find_or_create_container(container_id).search(query) |
1776 | |
1777 | - @_refresh_config |
1778 | def app_info(self, container_id, app_id): |
1779 | utils.get_logger().debug("dispatching app_info in container '%s' for package '%s'" % (container_id, app_id)) |
1780 | return self._find_or_create_container(container_id).app_info(app_id) |
1781 | |
1782 | - @_refresh_config |
1783 | def install(self, container_id, package_name): |
1784 | utils.get_logger().debug("dispatching install of package '%s' from container '%s'" % (package_name, container_id)) |
1785 | return self._find_or_create_container(container_id).install(package_name) |
1786 | |
1787 | - @_refresh_config |
1788 | def remove(self, container_id, package_name): |
1789 | utils.get_logger().debug("dispatching remove of package '%s' from container '%s'" % (package_name, container_id)) |
1790 | return self._find_or_create_container(container_id).remove(package_name) |
1791 | |
1792 | - @_refresh_config |
1793 | def create(self, container_id, container_name, distro, container_type, enable_multiarch): |
1794 | utils.get_logger().debug("dispatching create of container '%s'" % container_id) |
1795 | return self._find_or_create_container(container_id).create(container_name, distro, container_type, enable_multiarch) |
1796 | |
1797 | - @_refresh_config |
1798 | def destroy(self, container_id): |
1799 | utils.get_logger().debug("dispatching destroy container '%s'" % container_id) |
1800 | return self._find_or_create_container(container_id).destroy() |
1801 | |
1802 | - @_refresh_config |
1803 | def update(self, container_id): |
1804 | utils.get_logger().debug("dispatching update container '%s'" % container_id) |
1805 | return self._find_or_create_container(container_id).update() |
1806 | |
1807 | - @_refresh_config |
1808 | def list_app_ids(self, container_id): |
1809 | utils.get_logger().debug("dispatching list apps ids in container '%s'" % container_id) |
1810 | return self._find_or_create_container(container_id).list_app_ids() |
1811 | |
1812 | # Containerless Tasks |
1813 | |
1814 | - @_refresh_config |
1815 | def container_info(self, container_id): |
1816 | utils.get_logger().debug("dispatching get info for container '%s'" % container_id) |
1817 | |
1818 | @@ -115,17 +99,16 @@ |
1819 | container = self._find_container(container_id) |
1820 | if container is not None: |
1821 | related_task_ids = container.tasks |
1822 | - task = ContainerInfoTask(container_id, related_task_ids, self._config, self._connection, self._cleanup_task) |
1823 | + task = ContainerInfoTask(container_id, related_task_ids, self._config, self._monitor, self._cleanup_task) |
1824 | self._tasks.append(task) |
1825 | task.start() |
1826 | |
1827 | return task.id |
1828 | |
1829 | - @_refresh_config |
1830 | def list(self): |
1831 | utils.get_logger().debug("dispatching list all containers") |
1832 | |
1833 | - task = ListTask(self._config, self._connection, self._cleanup_task) |
1834 | + task = ListTask(self._config, self._monitor, self._cleanup_task) |
1835 | self._tasks.append(task) |
1836 | task.start() |
1837 | |
1838 | |
1839 | === modified file 'python/libertine/service/tasks/__init__.py' |
1840 | --- python/libertine/service/tasks/__init__.py 2017-02-07 12:35:48 +0000 |
1841 | +++ python/libertine/service/tasks/__init__.py 2017-03-31 20:05:48 +0000 |
1842 | @@ -12,7 +12,7 @@ |
1843 | # You should have received a copy of the GNU General Public License along |
1844 | # with this program. If not, see <http://www.gnu.org/licenses/>. |
1845 | |
1846 | -from .base_task import BaseTask |
1847 | +from .base_task import BaseTask, ContainerBaseTask |
1848 | from .app_info_task import AppInfoTask |
1849 | from .container_info_task import ContainerInfoTask |
1850 | from .create_task import CreateTask |
1851 | @@ -27,6 +27,7 @@ |
1852 | __all__ = [ |
1853 | 'AppInfoTask', |
1854 | 'BaseTask', |
1855 | + 'ContainerBaseTask', |
1856 | 'ContainerInfoTask', |
1857 | 'CreateTask', |
1858 | 'DestroyTask', |
1859 | |
1860 | === modified file 'python/libertine/service/tasks/app_info_task.py' |
1861 | --- python/libertine/service/tasks/app_info_task.py 2016-11-01 17:38:38 +0000 |
1862 | +++ python/libertine/service/tasks/app_info_task.py 2017-03-31 20:05:48 +0000 |
1863 | @@ -1,4 +1,4 @@ |
1864 | -# Copyright 2016 Canonical Ltd. |
1865 | +# Copyright 2016-2017 Canonical Ltd. |
1866 | # |
1867 | # This program is free software: you can redistribute it and/or modify |
1868 | # it under the terms of the GNU General Public License as published by |
1869 | @@ -18,8 +18,8 @@ |
1870 | |
1871 | |
1872 | class AppInfoTask(BaseTask): |
1873 | - def __init__(self, container_id, cache, app_id, tasks, config, connection, callback): |
1874 | - super().__init__(lock=None, container_id=container_id, config=config, connection=connection, callback=callback) |
1875 | + def __init__(self, container_id, cache, app_id, tasks, config, monitor, callback): |
1876 | + super().__init__(lock=None, container_id=container_id, config=config, monitor=monitor, callback=callback) |
1877 | self._cache = cache |
1878 | self._app_id = app_id |
1879 | self._tasks = tasks |
1880 | @@ -27,9 +27,9 @@ |
1881 | def _run(self): |
1882 | app = self._cache.app_info(self._app_id) |
1883 | if app == {}: |
1884 | - self._progress.error("Could not find app info for '%s' in container '%s'" % (self._app_id, self._container)) |
1885 | + self._error("Could not find app info for '%s' in container '%s'" % (self._app_id, self._container)) |
1886 | return |
1887 | |
1888 | app['status'] = self._config.get_package_install_status(self._container, app['package']) or '' |
1889 | app['task_ids'] = self._tasks |
1890 | - self._progress.data(str(app)) |
1891 | + self._data(str(app)) |
1892 | |
1893 | === modified file 'python/libertine/service/tasks/base_task.py' |
1894 | --- python/libertine/service/tasks/base_task.py 2017-02-17 17:39:13 +0000 |
1895 | +++ python/libertine/service/tasks/base_task.py 2017-03-31 20:05:48 +0000 |
1896 | @@ -12,8 +12,9 @@ |
1897 | # You should have received a copy of the GNU General Public License |
1898 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
1899 | |
1900 | -import libertine.service.progress |
1901 | + |
1902 | import threading |
1903 | + |
1904 | from abc import ABCMeta, abstractmethod |
1905 | |
1906 | |
1907 | @@ -24,24 +25,21 @@ |
1908 | in a separate thread. Override _before to implement pre-execution actions |
1909 | without locking; if _before returns False, _run will not be executed. |
1910 | """ |
1911 | - def __init__(self, lock, container_id, config, connection, callback): |
1912 | + def __init__(self, lock, container_id, config, monitor, callback): |
1913 | self._lock = lock |
1914 | self._container = container_id |
1915 | self._config = config |
1916 | self._callback = callback |
1917 | - self._connection = connection |
1918 | - self._progress = None |
1919 | - self._instant_callback = False |
1920 | + self._monitor = monitor |
1921 | + self._operation_id = None |
1922 | + self._instant_callback = False # for testing |
1923 | |
1924 | def matches(self, container, klass): |
1925 | return self._container == container and self.__class__ == klass |
1926 | |
1927 | @property |
1928 | def id(self): |
1929 | - if self._progress is not None: |
1930 | - return self._progress.id |
1931 | - else: |
1932 | - return None |
1933 | + return self._operation_id |
1934 | |
1935 | @property |
1936 | def container(self): |
1937 | @@ -53,40 +51,67 @@ |
1938 | |
1939 | @property |
1940 | def running(self): |
1941 | - return not self._progress.done |
1942 | + return not self._monitor.done(self._operation_id) |
1943 | |
1944 | def _delayed_callback(self): |
1945 | if self._instant_callback: |
1946 | self._callback(self) |
1947 | else: |
1948 | - threading.Timer(10, lambda: (self._progress.remove_from_connection(), self._callback(self))).start() |
1949 | + threading.Timer(10, lambda: (self._monitor.remove_from_connection(self._operation_id), self._callback(self))).start() |
1950 | |
1951 | def start(self): |
1952 | - self._progress = libertine.service.progress.Progress(self._connection) |
1953 | + self._operation_id = self._monitor.new_operation() |
1954 | thread = threading.Thread(target=self.run) |
1955 | thread.start() |
1956 | return thread |
1957 | |
1958 | def run(self): |
1959 | + self._refresh_database() |
1960 | + |
1961 | if not self._before(): |
1962 | - self._progress.finished(self.container) |
1963 | + self._monitor.finished(self._operation_id) |
1964 | self._delayed_callback() |
1965 | return |
1966 | |
1967 | if self._lock is not None: |
1968 | with self._lock: |
1969 | + self._refresh_database(False) |
1970 | self._run() |
1971 | else: |
1972 | + self._refresh_database() |
1973 | self._run() |
1974 | |
1975 | if self.running: |
1976 | - self._progress.finished(self.container) |
1977 | + self._finished() |
1978 | |
1979 | self._delayed_callback() |
1980 | |
1981 | + def _refresh_database(self, require_lock=True): |
1982 | + if self._config: |
1983 | + if require_lock and self._lock is not None: |
1984 | + with self._lock: |
1985 | + self._config.refresh_database() |
1986 | + else: |
1987 | + self._config.refresh_database() |
1988 | + |
1989 | @abstractmethod |
1990 | def _run(self): |
1991 | pass |
1992 | |
1993 | def _before(self): |
1994 | return True |
1995 | + |
1996 | + def _data(self, message): |
1997 | + self._monitor.data(self._operation_id, message) |
1998 | + |
1999 | + def _finished(self): |
2000 | + self._monitor.finished(self._operation_id) |
2001 | + |
2002 | + def _error(self, message): |
2003 | + self._monitor.error(self._operation_id, message) |
2004 | + |
2005 | + |
2006 | +class ContainerBaseTask(BaseTask): |
2007 | + def __init__(self, lock, container_id, config, monitor, client, callback): |
2008 | + super().__init__(lock=lock, container_id=container_id, config=config, monitor=monitor, callback=callback) |
2009 | + self._client = client |
2010 | |
2011 | === modified file 'python/libertine/service/tasks/container_info_task.py' |
2012 | --- python/libertine/service/tasks/container_info_task.py 2017-01-18 20:08:47 +0000 |
2013 | +++ python/libertine/service/tasks/container_info_task.py 2017-03-31 20:05:48 +0000 |
2014 | @@ -20,8 +20,8 @@ |
2015 | |
2016 | |
2017 | class ContainerInfoTask(BaseTask): |
2018 | - def __init__(self, container_id, tasks, config, connection, callback): |
2019 | - super().__init__(lock=None, container_id=container_id, config=config, connection=connection, callback=callback) |
2020 | + def __init__(self, container_id, tasks, config, monitor, callback): |
2021 | + super().__init__(lock=None, container_id=container_id, config=config, monitor=monitor, callback=callback) |
2022 | self._tasks = tasks |
2023 | |
2024 | def _run(self): |
2025 | @@ -35,11 +35,11 @@ |
2026 | container['root'] = utils.get_libertine_container_rootfs_path(self._container) |
2027 | container['home'] = utils.get_libertine_container_home_dir(self._container) |
2028 | |
2029 | - self._progress.data(json.dumps(container)) |
2030 | + self._data(json.dumps(container)) |
2031 | |
2032 | def _before(self): |
2033 | if not self._config.container_exists(self._container): |
2034 | - self._progress.error("Container '%s' does not exist, ignoring info request" % self._container) |
2035 | + self._error("Container '%s' does not exist, ignoring info request" % self._container) |
2036 | return False |
2037 | |
2038 | return True |
2039 | |
2040 | === modified file 'python/libertine/service/tasks/create_task.py' |
2041 | --- python/libertine/service/tasks/create_task.py 2017-02-24 15:05:33 +0000 |
2042 | +++ python/libertine/service/tasks/create_task.py 2017-03-31 20:05:48 +0000 |
2043 | @@ -1,4 +1,4 @@ |
2044 | -# Copyright 2016 Canonical Ltd. |
2045 | +# Copyright 2016-2017 Canonical Ltd. |
2046 | # |
2047 | # This program is free software: you can redistribute it and/or modify |
2048 | # it under the terms of the GNU General Public License as published by |
2049 | @@ -13,14 +13,16 @@ |
2050 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
2051 | |
2052 | |
2053 | -from .base_task import BaseTask |
2054 | +from .base_task import ContainerBaseTask |
2055 | from libertine import LibertineContainer, utils |
2056 | from libertine.HostInfo import HostInfo |
2057 | |
2058 | |
2059 | -class CreateTask(BaseTask): |
2060 | - def __init__(self, container_id, container_name, distro, container_type, enable_multiarch, config, lock, connection, callback): |
2061 | - super().__init__(lock=lock, container_id=container_id, config=config, connection=connection, callback=callback) |
2062 | +class CreateTask(ContainerBaseTask): |
2063 | + def __init__(self, container_id, container_name, distro, container_type, enable_multiarch, |
2064 | + config, lock, monitor, client, callback): |
2065 | + super().__init__(lock=lock, container_id=container_id, config=config, |
2066 | + monitor=monitor, client=client, callback=callback) |
2067 | self._name = container_name |
2068 | self._distro = distro |
2069 | self._type = container_type |
2070 | @@ -30,35 +32,36 @@ |
2071 | utils.get_logger().debug("Creating container '%s'" % self._container) |
2072 | |
2073 | try: |
2074 | - container = LibertineContainer(self._container, self._config) |
2075 | + container = LibertineContainer(self._container, self._config, self._client) |
2076 | |
2077 | if not container.create_libertine_container(password='', multiarch=self._multiarch): |
2078 | self._config.delete_container(self._container) |
2079 | - self._progress.error("Creating container '%s' failed" % self._container) |
2080 | + self._error("Creating container '%s' failed" % self._container) |
2081 | else: |
2082 | self._config.update_container_install_status(self._container, "ready") |
2083 | + self._finished() |
2084 | except RuntimeError as e: |
2085 | - self._progress.error(str(e)) |
2086 | self._config.delete_container(self._container) |
2087 | + self._error(str(e)) |
2088 | |
2089 | def _before(self): |
2090 | utils.get_logger().debug("CreateTask::_before") |
2091 | if self._config.container_exists(self._container): |
2092 | - self._progress.error("Container '%s' already exists" % self._container) |
2093 | + self._error("Container '%s' already exists" % self._container) |
2094 | return False |
2095 | |
2096 | info = HostInfo() |
2097 | if not self._distro: |
2098 | self._distro = info.get_host_distro_release() |
2099 | elif not info.is_distro_valid(self._distro): |
2100 | - self._progress.error("Invalid distro '%s'." % self._distro) |
2101 | + self._error("Invalid distro '%s'." % self._distro) |
2102 | return False |
2103 | |
2104 | if not self._type: |
2105 | self._type = info.select_container_type_by_kernel() |
2106 | elif (self._type == 'lxd' and not info.has_lxd_support()) or \ |
2107 | (self._type == 'lxc' and not info.has_lxc_support()): |
2108 | - self._progress.error("System kernel does not support %s type containers. " |
2109 | + self._error("System kernel does not support %s type containers. " |
2110 | "Please either use chroot or leave empty." % self._type) |
2111 | return False |
2112 | |
2113 | |
2114 | === modified file 'python/libertine/service/tasks/destroy_task.py' |
2115 | --- python/libertine/service/tasks/destroy_task.py 2016-11-01 17:38:38 +0000 |
2116 | +++ python/libertine/service/tasks/destroy_task.py 2017-03-31 20:05:48 +0000 |
2117 | @@ -1,4 +1,4 @@ |
2118 | -# Copyright 2016 Canonical Ltd. |
2119 | +# Copyright 2016-2017 Canonical Ltd. |
2120 | # |
2121 | # This program is free software: you can redistribute it and/or modify |
2122 | # it under the terms of the GNU General Public License as published by |
2123 | @@ -13,29 +13,31 @@ |
2124 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
2125 | |
2126 | |
2127 | -from .base_task import BaseTask |
2128 | +from .base_task import ContainerBaseTask |
2129 | from libertine import LibertineContainer, utils |
2130 | |
2131 | |
2132 | -class DestroyTask(BaseTask): |
2133 | - def __init__(self, container_id, config, lock, connection, callback): |
2134 | - super().__init__(lock=lock, container_id=container_id, config=config, connection=connection, callback=callback) |
2135 | +class DestroyTask(ContainerBaseTask): |
2136 | + def __init__(self, container_id, config, lock, monitor, client, callback): |
2137 | + super().__init__(lock=lock, container_id=container_id, config=config, |
2138 | + monitor=monitor, client=client, callback=callback) |
2139 | |
2140 | def _run(self): |
2141 | utils.get_logger().debug("Destroying container '%s'" % self._container) |
2142 | |
2143 | - container = LibertineContainer(self._container, self._config) |
2144 | + container = LibertineContainer(self._container, self._config, self._client) |
2145 | if not container.destroy_libertine_container(): |
2146 | - self._progress.error("Destroying container '%s' failed" % self._container) |
2147 | + self._error("Destroying container '%s' failed" % self._container) |
2148 | self._config.update_container_install_status(self._container, "ready") |
2149 | return |
2150 | |
2151 | self._config.delete_container(self._container) |
2152 | + self._finished() |
2153 | |
2154 | def _before(self): |
2155 | utils.get_logger().debug("CreateTask::_before") |
2156 | if self._config._get_value_by_key(self._container, 'installStatus') != 'ready': |
2157 | - self._progress.error("Container '%s' does not exist" % self._container) |
2158 | + self._error("Container '%s' does not exist" % self._container) |
2159 | return False |
2160 | |
2161 | self._config.update_container_install_status(self._container, 'removing') |
2162 | |
2163 | === modified file 'python/libertine/service/tasks/install_task.py' |
2164 | --- python/libertine/service/tasks/install_task.py 2016-11-08 15:45:54 +0000 |
2165 | +++ python/libertine/service/tasks/install_task.py 2017-03-31 20:05:48 +0000 |
2166 | @@ -1,4 +1,4 @@ |
2167 | -# Copyright 2016 Canonical Ltd. |
2168 | +# Copyright 2016-2017 Canonical Ltd. |
2169 | # |
2170 | # This program is free software: you can redistribute it and/or modify |
2171 | # it under the terms of the GNU General Public License as published by |
2172 | @@ -13,13 +13,14 @@ |
2173 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
2174 | |
2175 | |
2176 | -from .base_task import BaseTask |
2177 | +from .base_task import ContainerBaseTask |
2178 | from libertine import LibertineContainer, utils |
2179 | |
2180 | |
2181 | -class InstallTask(BaseTask): |
2182 | - def __init__(self, package_name, container_id, config, lock, connection, callback): |
2183 | - super().__init__(lock=lock, container_id=container_id, config=config, connection=connection, callback=callback) |
2184 | +class InstallTask(ContainerBaseTask): |
2185 | + def __init__(self, package_name, container_id, config, lock, monitor, client, callback): |
2186 | + super().__init__(lock=lock, container_id=container_id, config=config, |
2187 | + monitor=monitor, client=client, callback=callback) |
2188 | self._package = package_name |
2189 | |
2190 | def matches(self, package, klass): |
2191 | @@ -31,17 +32,18 @@ |
2192 | |
2193 | def _run(self): |
2194 | utils.get_logger().debug("Installing package '%s'" % self._package) |
2195 | - container = LibertineContainer(self._container, self._config) |
2196 | + container = LibertineContainer(self._container, self._config, self._client) |
2197 | if container.install_package(self._package): |
2198 | self._config.update_package_install_status(self._container, self._package, "installed") |
2199 | + self._finished() |
2200 | else: |
2201 | self._config.delete_package(self._container, self._package) |
2202 | - self._progress.error("Package installation failed for '%s'" % self._package) |
2203 | + self._error("Package installation failed for '%s'" % self._package) |
2204 | |
2205 | def _before(self): |
2206 | utils.get_logger().debug("InstallTask::_before") |
2207 | if self._config.package_exists(self._container, self._package): |
2208 | - self._progress.error("Package '%s' already exists, skipping install" % self._package) |
2209 | + self._error("Package '%s' already exists, skipping install" % self._package) |
2210 | return False |
2211 | else: |
2212 | self._config.add_new_package(self._container, self._package) |
2213 | |
2214 | === modified file 'python/libertine/service/tasks/list_app_ids_task.py' |
2215 | --- python/libertine/service/tasks/list_app_ids_task.py 2017-01-20 15:20:13 +0000 |
2216 | +++ python/libertine/service/tasks/list_app_ids_task.py 2017-03-31 20:05:48 +0000 |
2217 | @@ -14,22 +14,22 @@ |
2218 | |
2219 | |
2220 | import json |
2221 | -from .base_task import BaseTask |
2222 | +from .base_task import ContainerBaseTask |
2223 | from libertine import LibertineContainer, utils |
2224 | import time |
2225 | |
2226 | |
2227 | -class ListAppIdsTask(BaseTask): |
2228 | - def __init__(self, container_id, config, connection, callback): |
2229 | - super().__init__(lock=None, container_id=container_id, config=config, connection=connection, callback=callback) |
2230 | +class ListAppIdsTask(ContainerBaseTask): |
2231 | + def __init__(self, container_id, config, monitor, client, callback): |
2232 | + super().__init__(lock=None, container_id=container_id, config=config, monitor=monitor, client=client, callback=callback) |
2233 | |
2234 | def _run(self): |
2235 | utils.get_logger().debug("Listing app ids from container '%s'" % self._container) |
2236 | - self._progress.data(json.dumps(LibertineContainer(self._container, self._config).list_app_ids())) |
2237 | + self._data(json.dumps(LibertineContainer(self._container, self._config, self._client).list_app_ids())) |
2238 | |
2239 | def _before(self): |
2240 | if not self._config.container_exists(self._container): |
2241 | - self._progress.error("Container '%s' does not exist, skipping list" % self._container) |
2242 | + self._error("Container '%s' does not exist, skipping list" % self._container) |
2243 | return False |
2244 | |
2245 | return True |
2246 | |
2247 | === modified file 'python/libertine/service/tasks/list_task.py' |
2248 | --- python/libertine/service/tasks/list_task.py 2017-01-18 20:08:47 +0000 |
2249 | +++ python/libertine/service/tasks/list_task.py 2017-03-31 20:05:48 +0000 |
2250 | @@ -20,8 +20,9 @@ |
2251 | |
2252 | |
2253 | class ListTask(BaseTask): |
2254 | - def __init__(self, config, connection, callback): |
2255 | - super().__init__(lock=None, container_id=None, config=config, connection=connection, callback=callback) |
2256 | + def __init__(self, config, monitor, callback): |
2257 | + super().__init__(lock=None, container_id=None, config=config, monitor=monitor, callback=callback) |
2258 | |
2259 | def _run(self): |
2260 | - self._progress.data(json.dumps(self._config.get_containers())) |
2261 | + self._data(json.dumps(self._config.get_containers())) |
2262 | + self._finished() |
2263 | |
2264 | === modified file 'python/libertine/service/tasks/remove_task.py' |
2265 | --- python/libertine/service/tasks/remove_task.py 2016-11-08 15:45:54 +0000 |
2266 | +++ python/libertine/service/tasks/remove_task.py 2017-03-31 20:05:48 +0000 |
2267 | @@ -1,4 +1,4 @@ |
2268 | -# Copyright 2016 Canonical Ltd. |
2269 | +# Copyright 2016-2017 Canonical Ltd. |
2270 | # |
2271 | # This program is free software: you can redistribute it and/or modify |
2272 | # it under the terms of the GNU General Public License as published by |
2273 | @@ -13,13 +13,13 @@ |
2274 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
2275 | |
2276 | |
2277 | -from .base_task import BaseTask |
2278 | +from .base_task import ContainerBaseTask |
2279 | from libertine import LibertineContainer, utils |
2280 | |
2281 | |
2282 | -class RemoveTask(BaseTask): |
2283 | - def __init__(self, package_name, container_id, config, lock, connection, callback): |
2284 | - super().__init__(lock=lock, container_id=container_id, config=config, connection=connection, callback=callback) |
2285 | +class RemoveTask(ContainerBaseTask): |
2286 | + def __init__(self, package_name, container_id, config, lock, monitor, client, callback): |
2287 | + super().__init__(lock=lock, container_id=container_id, config=config, monitor=monitor, client=client, callback=callback) |
2288 | self._package = package_name |
2289 | |
2290 | def matches(self, package, klass): |
2291 | @@ -31,12 +31,13 @@ |
2292 | |
2293 | def _run(self): |
2294 | utils.get_logger().debug("Removing package '%s'" % self._package) |
2295 | - container = LibertineContainer(self._container, self._config) |
2296 | + container = LibertineContainer(self._container, self._config, self._client) |
2297 | if container.remove_package(self._package): |
2298 | self._config.delete_package(self._container, self._package) |
2299 | + self._finished() |
2300 | else: |
2301 | self._config.update_package_install_status(self._container, self._package, 'installed') |
2302 | - self._progress.error("Package removal failed for '%s'" % self._package) |
2303 | + self._error("Package removal failed for '%s'" % self._package) |
2304 | |
2305 | def _before(self): |
2306 | utils.get_logger().debug("RemoveTask::_before") |
2307 | @@ -44,5 +45,5 @@ |
2308 | self._config.update_package_install_status(self._container, self._package, "removing") |
2309 | return True |
2310 | else: |
2311 | - self._progress.error("Package '%s' not installed, skipping remove" % self._package) |
2312 | + self._error("Package '%s' not installed, skipping remove" % self._package) |
2313 | return False |
2314 | |
2315 | === modified file 'python/libertine/service/tasks/search_task.py' |
2316 | --- python/libertine/service/tasks/search_task.py 2016-11-01 19:49:32 +0000 |
2317 | +++ python/libertine/service/tasks/search_task.py 2017-03-31 20:05:48 +0000 |
2318 | @@ -1,4 +1,4 @@ |
2319 | -# Copyright 2016 Canonical Ltd. |
2320 | +# Copyright 2016-2017 Canonical Ltd. |
2321 | # |
2322 | # This program is free software: you can redistribute it and/or modify |
2323 | # it under the terms of the GNU General Public License as published by |
2324 | @@ -18,10 +18,10 @@ |
2325 | |
2326 | |
2327 | class SearchTask(BaseTask): |
2328 | - def __init__(self, container_id, cache, query, connection, callback): |
2329 | - super().__init__(lock=None, container_id=container_id, config=None, connection=connection, callback=callback) |
2330 | + def __init__(self, container_id, cache, query, monitor, callback): |
2331 | + super().__init__(lock=None, container_id=container_id, config=None, monitor=monitor, callback=callback) |
2332 | self._cache = cache |
2333 | self._query = query |
2334 | |
2335 | def _run(self): |
2336 | - self._progress.data(str(self._cache.search(self._query))) |
2337 | + self._data(str(self._cache.search(self._query))) |
2338 | |
2339 | === modified file 'python/libertine/service/tasks/update_task.py' |
2340 | --- python/libertine/service/tasks/update_task.py 2016-11-08 15:37:58 +0000 |
2341 | +++ python/libertine/service/tasks/update_task.py 2017-03-31 20:05:48 +0000 |
2342 | @@ -1,4 +1,4 @@ |
2343 | -# Copyright 2016 Canonical Ltd. |
2344 | +# Copyright 2016-2017 Canonical Ltd. |
2345 | # |
2346 | # This program is free software: you can redistribute it and/or modify |
2347 | # it under the terms of the GNU General Public License as published by |
2348 | @@ -13,27 +13,28 @@ |
2349 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
2350 | |
2351 | |
2352 | -from .base_task import BaseTask |
2353 | +from .base_task import ContainerBaseTask |
2354 | from libertine import LibertineContainer, utils |
2355 | |
2356 | |
2357 | -class UpdateTask(BaseTask): |
2358 | - def __init__(self, container_id, config, lock, connection, callback): |
2359 | - super().__init__(lock=lock, container_id=container_id, config=config, connection=connection, callback=callback) |
2360 | +class UpdateTask(ContainerBaseTask): |
2361 | + def __init__(self, container_id, config, lock, monitor, client, callback): |
2362 | + super().__init__(lock=lock, container_id=container_id, config=config, |
2363 | + monitor=monitor, client=client, callback=callback) |
2364 | |
2365 | def _run(self): |
2366 | utils.get_logger().debug("Updating container '%s'" % self._container) |
2367 | - container = LibertineContainer(self._container, self._config) |
2368 | + container = LibertineContainer(self._container, self._config, self._client) |
2369 | self._config.update_container_install_status(self._container, "updating") |
2370 | if not container.update_libertine_container(): |
2371 | - self._progress.error("Failed to update container '%s'" % self._container) |
2372 | + self._error("Failed to update container '%s'" % self._container) |
2373 | |
2374 | self._config.update_container_install_status(self._container, "ready") |
2375 | |
2376 | def _before(self): |
2377 | utils.get_logger().debug("UpdateTask::_before") |
2378 | if not self._config.container_exists(self._container): |
2379 | - self._progress.error("Container '%s' does not exist, skipping update" % self._container) |
2380 | + self._error("Container '%s' does not exist, skipping update" % self._container) |
2381 | return False |
2382 | - else: |
2383 | - return True |
2384 | + |
2385 | + return True |
2386 | |
2387 | === modified file 'snap/plugins/x-libertine-deps.py' |
2388 | --- snap/plugins/x-libertine-deps.py 2017-02-14 19:17:30 +0000 |
2389 | +++ snap/plugins/x-libertine-deps.py 2017-03-31 20:05:48 +0000 |
2390 | @@ -145,7 +145,8 @@ |
2391 | '-usr/lib/{}/liblibertine.so*'.format(self._arch), |
2392 | '-usr/bin/libertine*', |
2393 | '-etc/sudoers.d/libertine*', |
2394 | - '-usr/lib/python3/dist-packages/libertine' |
2395 | + '-usr/lib/python3/dist-packages/libertine', |
2396 | + '-usr/share/bash-completion/completions/*' |
2397 | ]) |
2398 | |
2399 | def build(self): |
2400 | |
2401 | === modified file 'snap/snap-runner.wrapper' (properties changed: -x to +x) |
2402 | === modified file 'tests/integration/CMakeLists.txt' |
2403 | --- tests/integration/CMakeLists.txt 2017-03-06 15:33:12 +0000 |
2404 | +++ tests/integration/CMakeLists.txt 2017-03-31 20:05:48 +0000 |
2405 | @@ -1,4 +1,24 @@ |
2406 | add_test(test_libertine_service dbus-run-session -- /usr/bin/python3 ${CMAKE_CURRENT_SOURCE_DIR}/test_libertine_service.py) |
2407 | set_tests_properties(test_libertine_service |
2408 | PROPERTIES ENVIRONMENT |
2409 | - "PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR}:${CMAKE_SOURCE_DIR}/python;LIBERTINE_DATA_DIR=${CMAKE_CURRENT_SOURCE_DIR};PATH=${CMAKE_SOURCE_DIR}/tools:$ENV{PATH};") |
2410 | + "LIBERTINE_DEBUG=2;PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR}:${CMAKE_SOURCE_DIR}/python;;PATH=${CMAKE_SOURCE_DIR}/tools:$ENV{PATH};XDG_DATA_HOME=/tmp") |
2411 | + |
2412 | +add_executable( |
2413 | + test_liblibertine |
2414 | + test_liblibertine.cpp |
2415 | +) |
2416 | + |
2417 | +target_link_libraries( |
2418 | + test_liblibertine |
2419 | + ${LIBERTINE_CORE} |
2420 | + gtest gtest_main |
2421 | + ${DBUSTEST_LIBRARIES} |
2422 | + ${GIO2_LIBRARIES} |
2423 | + Qt5::Core |
2424 | +) |
2425 | + |
2426 | +add_test(test_liblibertine test_liblibertine) |
2427 | + |
2428 | +set_tests_properties(test_liblibertine |
2429 | + PROPERTIES ENVIRONMENT |
2430 | + "PYTHONPATH=${CMAKE_SOURCE_DIR}/python;PATH=${CMAKE_SOURCE_DIR}/tools:$ENV{PATH};XDG_DATA_HOME=${CMAKE_CURRENT_SOURCE_DIR}/data;XDG_CACHE_HOME=${CMAKE_CURRENT_SOURCE_DIR}/data") |
2431 | |
2432 | === added directory 'tests/integration/data' |
2433 | === added directory 'tests/integration/data/libertine' |
2434 | === added directory 'tests/integration/data/libertine-container' |
2435 | === added directory 'tests/integration/data/libertine-container/padme' |
2436 | === added directory 'tests/integration/data/libertine-container/padme/rootfs' |
2437 | === added directory 'tests/integration/data/libertine-container/padme/rootfs/usr' |
2438 | === added directory 'tests/integration/data/libertine-container/padme/rootfs/usr/share' |
2439 | === added directory 'tests/integration/data/libertine-container/padme/rootfs/usr/share/applications' |
2440 | === added file 'tests/integration/data/libertine-container/padme/rootfs/usr/share/applications/dagobah.desktop' |
2441 | === added file 'tests/integration/data/libertine-container/padme/rootfs/usr/share/applications/tatooine.desktop' |
2442 | === added directory 'tests/integration/data/libertine-container/user-data' |
2443 | === added directory 'tests/integration/data/libertine-container/user-data/padme' |
2444 | === added file 'tests/integration/data/libertine/ContainersConfig.json' |
2445 | --- tests/integration/data/libertine/ContainersConfig.json 1970-01-01 00:00:00 +0000 |
2446 | +++ tests/integration/data/libertine/ContainersConfig.json 2017-03-31 20:05:48 +0000 |
2447 | @@ -0,0 +1,19 @@ |
2448 | +{ |
2449 | + "containerList": [ |
2450 | + { |
2451 | + "id": "jarjar", |
2452 | + "name": "JarJar Binks", |
2453 | + "type": "mock" |
2454 | + }, |
2455 | + { |
2456 | + "id": "padme", |
2457 | + "name": "Padme Amedala", |
2458 | + "type": "mock" |
2459 | + }, |
2460 | + { |
2461 | + "id": "anakin", |
2462 | + "name": "Anakin Skywalker", |
2463 | + "type": "mock" |
2464 | + } |
2465 | + ] |
2466 | +} |
2467 | |
2468 | === modified file 'tests/integration/test_libertine_service.py' |
2469 | --- tests/integration/test_libertine_service.py 2017-03-06 15:33:12 +0000 |
2470 | +++ tests/integration/test_libertine_service.py 2017-03-31 20:05:48 +0000 |
2471 | @@ -26,7 +26,7 @@ |
2472 | |
2473 | from gi.repository import GLib |
2474 | from libertine import utils |
2475 | -from libertine.service import tasks, apt |
2476 | +from libertine.service import tasks, apt, constants |
2477 | from libertine.ContainersConfig import ContainersConfig |
2478 | from subprocess import Popen, PIPE |
2479 | from unittest import TestCase |
2480 | @@ -42,18 +42,14 @@ |
2481 | def setUpClass(cls): |
2482 | cls._tempdir = tempfile.TemporaryDirectory() |
2483 | |
2484 | - environ = os.environ.copy() |
2485 | - environ['XDG_DATA_HOME'] = cls._tempdir.name |
2486 | - |
2487 | - cls._process = pexpect.spawnu('libertined --debug', env=environ) |
2488 | + os.environ['XDG_DATA_HOME'] = cls._tempdir.name |
2489 | + cls._process = pexpect.spawnu('libertined --debug', env=os.environ.copy()) |
2490 | cls._process.logfile = sys.stdout |
2491 | |
2492 | # give libertined enough time to start the whole process |
2493 | - verbosity = environ.get('LIBERTINE_DEBUG', '1') |
2494 | - if verbosity == '1': |
2495 | - cls._process.expect(['.+\n', pexpect.TIMEOUT], timeout=1) |
2496 | - elif environ['LIBERTINE_DEBUG'] == '2': |
2497 | - cls._process.expect(['.+\n.+\n.+\n', pexpect.TIMEOUT], timeout=1) |
2498 | + verbosity = os.environ.get('LIBERTINE_DEBUG', '1') |
2499 | + if verbosity != '0': |
2500 | + cls._process.expect(['libertined ready', pexpect.TIMEOUT], timeout=5) |
2501 | |
2502 | dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) |
2503 | cls._loop = GLib.MainLoop() |
2504 | @@ -68,14 +64,25 @@ |
2505 | cls._tempdir.cleanup() |
2506 | |
2507 | def setUp(self): |
2508 | + os.environ['XDG_DATA_HOME'] = TestLibertineService._tempdir.name |
2509 | self.error = None |
2510 | self.result = None |
2511 | self.event = threading.Event() |
2512 | + self.signals = [] |
2513 | |
2514 | for retries in range(1, 11): |
2515 | try: |
2516 | self._bus = dbus.SessionBus() |
2517 | - self._libertined = self._bus.get_object('com.canonical.libertine.Service', '/Manager') |
2518 | + self.path = None |
2519 | + |
2520 | + self._libertined = self._bus.get_object(constants.SERVICE_NAME, constants.OPERATIONS_OBJECT) |
2521 | + |
2522 | + self.signals.append(self._bus.add_signal_receiver(path=constants.OPERATIONS_MONITOR_OBJECT, handler_function=self._finished_handler, |
2523 | + dbus_interface=constants.OPERATIONS_MONITOR_INTERFACE, signal_name='finished')) |
2524 | + self.signals.append(self._bus.add_signal_receiver(path=constants.OPERATIONS_MONITOR_OBJECT, handler_function=self._data_handler, |
2525 | + dbus_interface=constants.OPERATIONS_MONITOR_INTERFACE, signal_name='data')) |
2526 | + self.signals.append(self._bus.add_signal_receiver(path=constants.OPERATIONS_MONITOR_OBJECT, handler_function=self._error_handler, |
2527 | + dbus_interface=constants.OPERATIONS_MONITOR_INTERFACE, signal_name='error')) |
2528 | break |
2529 | except dbus.DBusException as e: |
2530 | print("Service not available (attempt %i/10). Exception: %s" % (retries, str(e))) |
2531 | @@ -85,39 +92,35 @@ |
2532 | except Exception as e: |
2533 | self.fail('Exception occurred during connection: %s' % str(e)) |
2534 | |
2535 | + def tearDown(self): |
2536 | + for signal in self.signals: |
2537 | + signal.remove() |
2538 | + |
2539 | def _finished_handler(self, path): |
2540 | - self.event.set() |
2541 | - |
2542 | - def _data_handler(self, message): |
2543 | - self.result = message |
2544 | - |
2545 | - def _error_handler(self, message): |
2546 | - self.error = message |
2547 | - self.event.set() |
2548 | + if self.path == path: |
2549 | + self.event.set() |
2550 | + |
2551 | + def _data_handler(self, path, message): |
2552 | + if self.path == path: |
2553 | + self.result = message |
2554 | + |
2555 | + def _error_handler(self, path, message): |
2556 | + if self.path == path: |
2557 | + self.error = message |
2558 | + self.event.set() |
2559 | |
2560 | def _send(self, func): |
2561 | self.event.clear() |
2562 | self.result = None |
2563 | |
2564 | - obj_path = func() |
2565 | - signals = [] |
2566 | - signals.append(self._bus.add_signal_receiver(path=obj_path, handler_function=self._finished_handler, |
2567 | - dbus_interface='com.canonical.applications.Download', signal_name='finished')) |
2568 | - signals.append(self._bus.add_signal_receiver(path=obj_path, handler_function=self._data_handler, |
2569 | - dbus_interface='com.canonical.libertine.Service.Progress', signal_name='data')) |
2570 | - signals.append(self._bus.add_signal_receiver(path=obj_path, handler_function=self._error_handler, |
2571 | - dbus_interface='com.canonical.applications.Download', signal_name='error')) |
2572 | - |
2573 | - task = self._bus.get_object('com.canonical.libertine.Service', obj_path) |
2574 | - if task.running(): |
2575 | - self.event.wait(5) |
2576 | - self.assertIsNone(self.error) |
2577 | - |
2578 | - self.assertEqual('', task.get_dbus_method('last_error', 'com.canonical.libertine.Service.Progress')()) |
2579 | - self.result = task.get_dbus_method('result', 'com.canonical.libertine.Service.Progress')() |
2580 | - |
2581 | - for signal in signals: |
2582 | - self._bus._clean_up_signal_match(signal) |
2583 | + monitor = self._bus.get_object(constants.SERVICE_NAME, constants.OPERATIONS_MONITOR_OBJECT) |
2584 | + self.path = func() |
2585 | + |
2586 | + while monitor.running(self.path): |
2587 | + self.event.wait(.1) |
2588 | + |
2589 | + self.assertEqual('', monitor.last_error(self.path)) |
2590 | + self.result = monitor.result(self.path) |
2591 | |
2592 | return self.result |
2593 | |
2594 | |
2595 | === added file 'tests/integration/test_liblibertine.cpp' |
2596 | --- tests/integration/test_liblibertine.cpp 1970-01-01 00:00:00 +0000 |
2597 | +++ tests/integration/test_liblibertine.cpp 2017-03-31 20:05:48 +0000 |
2598 | @@ -0,0 +1,145 @@ |
2599 | +/* |
2600 | + * Copyright 2017 Canonical Ltd. |
2601 | + * |
2602 | + * This program is free software: you can redistribute it and/or modify it under |
2603 | + * the terms of the GNU General Public License, version 3, as published by the |
2604 | + * Free Software Foundation. |
2605 | + * |
2606 | + * This program is distributed in the hope that it will be useful, |
2607 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2608 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2609 | + * GNU General Public License for more details. |
2610 | + * |
2611 | + * You should have received a copy of the GNU General Public License |
2612 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2613 | + */ |
2614 | + |
2615 | +#include "liblibertine/libertine.h" |
2616 | +#include <cstdlib> |
2617 | +#include <gio/gio.h> |
2618 | +#include <gtest/gtest.h> |
2619 | +#include <libdbustest/dbus-test.h> |
2620 | +#include <memory> |
2621 | +#include <QtCore/QByteArray> |
2622 | +#include <QtCore/QJsonDocument> |
2623 | +#include <QtCore/QJsonParseError> |
2624 | + |
2625 | +class LiblibertineTest : public ::testing::Test |
2626 | +{ |
2627 | +protected: |
2628 | + static void SetUpTestCase() |
2629 | + { |
2630 | + process = dbus_test_process_new("libertined"); |
2631 | + dbus_test_process_append_param(process, "--debug"); |
2632 | + |
2633 | + dbus_test_task_set_bus(DBUS_TEST_TASK(process), DBUS_TEST_SERVICE_BUS_SESSION); |
2634 | + dbus_test_task_set_name(DBUS_TEST_TASK(process), "libertine"); |
2635 | + dbus_test_task_set_return(DBUS_TEST_TASK(process), DBUS_TEST_TASK_RETURN_IGNORE); |
2636 | + dbus_test_task_set_wait_finished(DBUS_TEST_TASK(process), FALSE); |
2637 | + |
2638 | + wait = dbus_test_task_new(); |
2639 | + dbus_test_task_set_wait_for(wait, "com.canonical.libertine.Service"); |
2640 | + |
2641 | + service = dbus_test_service_new(nullptr); |
2642 | + dbus_test_service_add_task(service, DBUS_TEST_TASK(process)); |
2643 | + dbus_test_service_add_task(service, wait); |
2644 | + |
2645 | + dbus_test_service_start_tasks(service); |
2646 | + |
2647 | + bus = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr); |
2648 | + g_dbus_connection_set_exit_on_close(bus, FALSE); |
2649 | + g_object_add_weak_pointer(G_OBJECT(bus), (gpointer*)&bus); |
2650 | + } |
2651 | + |
2652 | + static void TearDownTestCase() |
2653 | + { |
2654 | + g_clear_object(&process); |
2655 | + g_clear_object(&wait); |
2656 | + |
2657 | + g_clear_object(&service); |
2658 | + g_object_unref(bus); |
2659 | + } |
2660 | + |
2661 | +private: |
2662 | + static DbusTestProcess* process; |
2663 | + static DbusTestTask* wait; |
2664 | + static DbusTestService* service; |
2665 | + static GDBusConnection* bus; |
2666 | +}; |
2667 | + |
2668 | + |
2669 | +DbusTestProcess* LiblibertineTest::process = nullptr; |
2670 | +DbusTestTask* LiblibertineTest::wait = nullptr; |
2671 | +DbusTestService* LiblibertineTest::service = nullptr; |
2672 | +GDBusConnection* LiblibertineTest::bus = nullptr; |
2673 | + |
2674 | + |
2675 | +TEST_F(LiblibertineTest, libertine_list_containers) |
2676 | +{ |
2677 | + auto scontainers = std::shared_ptr<gchar*>(libertine_list_containers(), g_strfreev); |
2678 | + auto containers = scontainers.get(); |
2679 | + |
2680 | + ASSERT_NE(containers[0], nullptr); |
2681 | + EXPECT_STREQ(containers[0], "jarjar"); |
2682 | + |
2683 | + ASSERT_NE(containers[1], nullptr); |
2684 | + EXPECT_STREQ(containers[1], "padme"); |
2685 | + |
2686 | + ASSERT_NE(containers[2], nullptr); |
2687 | + EXPECT_STREQ(containers[2], "anakin"); |
2688 | + |
2689 | + ASSERT_EQ(containers[3], nullptr); |
2690 | +} |
2691 | + |
2692 | + |
2693 | +TEST_F(LiblibertineTest, libertine_list_app_ids) |
2694 | +{ |
2695 | + auto sapps = std::shared_ptr<gchar*>(libertine_list_apps_for_container("padme"), g_strfreev); |
2696 | + auto apps = sapps.get(); |
2697 | + |
2698 | + ASSERT_NE(apps[0], nullptr); |
2699 | + EXPECT_STREQ(apps[0], "padme_dagobah_0.0"); |
2700 | + |
2701 | + ASSERT_NE(apps[1], nullptr); |
2702 | + EXPECT_STREQ(apps[1], "padme_tatooine_0.0"); |
2703 | + |
2704 | + ASSERT_EQ(apps[2], nullptr); |
2705 | +} |
2706 | + |
2707 | + |
2708 | +TEST_F(LiblibertineTest, libertine_container_name) |
2709 | +{ |
2710 | + auto actual = libertine_container_name("padme"); |
2711 | + EXPECT_STREQ("Padme Amedala", actual); |
2712 | + g_free(actual); |
2713 | +} |
2714 | + |
2715 | + |
2716 | +TEST_F(LiblibertineTest, libertine_container_path) |
2717 | +{ |
2718 | + auto actual = libertine_container_path("padme"); |
2719 | + auto expected = QString(getenv("XDG_CACHE_HOME")) + "/libertine-container/padme/rootfs"; |
2720 | + EXPECT_STREQ(expected.toUtf8(), actual); |
2721 | + g_free(actual); |
2722 | +} |
2723 | + |
2724 | + |
2725 | +TEST_F(LiblibertineTest, libertine_container_path_returns_empty) |
2726 | +{ |
2727 | + EXPECT_EQ(nullptr, libertine_container_path("jarjar")); |
2728 | +} |
2729 | + |
2730 | + |
2731 | +TEST_F(LiblibertineTest, libertine_container_home_path) |
2732 | +{ |
2733 | + auto actual = libertine_container_home_path("padme"); |
2734 | + auto expected = QString(getenv("XDG_DATA_HOME")) + "/libertine-container/user-data/padme"; |
2735 | + EXPECT_STREQ(expected.toUtf8(), actual); |
2736 | + g_free(actual); |
2737 | +} |
2738 | + |
2739 | + |
2740 | +TEST_F(LiblibertineTest, libertine_container_home_path_returns_empty) |
2741 | +{ |
2742 | + EXPECT_EQ(nullptr, libertine_container_home_path("jarjar")); |
2743 | +} |
2744 | |
2745 | === modified file 'tests/unit/CMakeLists.txt' |
2746 | --- tests/unit/CMakeLists.txt 2017-02-13 21:41:36 +0000 |
2747 | +++ tests/unit/CMakeLists.txt 2017-03-31 20:05:48 +0000 |
2748 | @@ -8,9 +8,10 @@ |
2749 | ContainerConfigListTests.cpp |
2750 | ContainersConfigTests.cpp |
2751 | ) |
2752 | + |
2753 | target_link_libraries( |
2754 | test_container_config |
2755 | - libertine-common |
2756 | + ${LIBERTINE_COMMON} |
2757 | gtest gtest_main |
2758 | Qt5::Core |
2759 | ) |
2760 | |
2761 | === modified file 'tests/unit/ContainerConfigListTests.cpp' |
2762 | --- tests/unit/ContainerConfigListTests.cpp 2017-02-08 14:57:34 +0000 |
2763 | +++ tests/unit/ContainerConfigListTests.cpp 2017-03-31 20:05:48 +0000 |
2764 | @@ -34,6 +34,7 @@ |
2765 | EXPECT_EQ(container_configs.size(), 0); |
2766 | } |
2767 | |
2768 | + |
2769 | /** Verify constructing a ContainerConfig from JSON DTRT. */ |
2770 | TEST(LibertineContainerConfigList, constructFromJson) |
2771 | { |
2772 | |
2773 | === modified file 'tests/unit/service/CMakeLists.txt' |
2774 | --- tests/unit/service/CMakeLists.txt 2016-11-04 13:49:40 +0000 |
2775 | +++ tests/unit/service/CMakeLists.txt 2017-03-31 20:05:48 +0000 |
2776 | @@ -1,5 +1,5 @@ |
2777 | function(create_service_unit_test test_name) |
2778 | - add_test(${test_name} /usr/bin/python3 -m testtools.run ${test_name}) |
2779 | + add_test(${test_name} /usr/bin/python3 ${CMAKE_CURRENT_SOURCE_DIR}/${test_name}.py) |
2780 | set_tests_properties(${test_name} |
2781 | PROPERTIES ENVIRONMENT |
2782 | "GI_TYPELIB_PATH=${CMAKE_BINARY_DIR}/liblibertine;LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/liblibertine:${LD_LIBRARY_PATH};PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR}:${CMAKE_SOURCE_DIR}/python;LIBERTINE_DATA_DIR=${CMAKE_CURRENT_SOURCE_DIR}") |
2783 | @@ -8,5 +8,6 @@ |
2784 | create_service_unit_test(test_container) |
2785 | create_service_unit_test(test_apt) |
2786 | create_service_unit_test(test_task_dispatcher) |
2787 | +create_service_unit_test(test_operations_monitor) |
2788 | |
2789 | add_subdirectory(tasks) |
2790 | |
2791 | === modified file 'tests/unit/service/tasks/test_app_info_task.py' |
2792 | --- tests/unit/service/tasks/test_app_info_task.py 2016-11-07 18:51:17 +0000 |
2793 | +++ tests/unit/service/tasks/test_app_info_task.py 2017-03-31 20:05:48 +0000 |
2794 | @@ -1,4 +1,4 @@ |
2795 | -# Copyright 2016 Canonical Ltd. |
2796 | +# Copyright 2016-2017 Canonical Ltd. |
2797 | # |
2798 | # This program is free software: you can redistribute it and/or modify it |
2799 | # under the terms of the GNU General Public License version 3, as published |
2800 | @@ -15,7 +15,7 @@ |
2801 | |
2802 | import unittest.mock |
2803 | from unittest import TestCase |
2804 | -from libertine.service import tasks, apt |
2805 | +from libertine.service import tasks, apt, operations_monitor |
2806 | from libertine.ContainersConfig import ContainersConfig |
2807 | |
2808 | |
2809 | @@ -23,39 +23,37 @@ |
2810 | def setUp(self): |
2811 | self.config = unittest.mock.create_autospec(ContainersConfig) |
2812 | self.cache = unittest.mock.create_autospec(apt.AptCache) |
2813 | - self.connection = unittest.mock.Mock() |
2814 | + self.monitor = unittest.mock.create_autospec(operations_monitor.OperationsMonitor) |
2815 | + self.monitor.new_operation.return_value = "/com/canonical/libertine/Service/Download/123456" |
2816 | |
2817 | def test_app_not_found_causes_error(self): |
2818 | self.called_with = None |
2819 | def callback(t): |
2820 | self.called_with = t |
2821 | |
2822 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
2823 | - progress = MockProgress.return_value |
2824 | - self.cache.app_info.return_value = {} |
2825 | - task = tasks.AppInfoTask('palpatine', self.cache, 'lightside', [1, 2], self.config, self.connection, callback) |
2826 | - task._instant_callback = True |
2827 | - task.start().join() |
2828 | - |
2829 | - progress.error.assert_called_once_with('Could not find app info for \'lightside\' in container \'palpatine\'') |
2830 | - |
2831 | - self.assertEqual(task, self.called_with) |
2832 | + self.cache.app_info.return_value = {} |
2833 | + task = tasks.AppInfoTask('palpatine', self.cache, 'lightside', [1, 2], self.config, self.monitor, callback) |
2834 | + task._instant_callback = True |
2835 | + task.start().join() |
2836 | + |
2837 | + self.monitor.error.assert_called_once_with(self.monitor.new_operation.return_value, 'Could not find app info for \'lightside\' in container \'palpatine\'') |
2838 | + |
2839 | + self.assertEqual(task, self.called_with) |
2840 | |
2841 | def test_success_sends_data(self): |
2842 | self.called_with = None |
2843 | def callback(t): |
2844 | self.called_with = t |
2845 | |
2846 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
2847 | - progress = MockProgress.return_value |
2848 | - progress.done = False |
2849 | - |
2850 | - self.cache.app_info.return_value = {'package': 'darkside-common'} |
2851 | - self.config.get_package_install_status.return_value = 'installed' |
2852 | - task = tasks.AppInfoTask('palpatine', self.cache, 'darkside', [1, 2, 3], self.config, self.connection, callback) |
2853 | - task._instant_callback = True |
2854 | - task.start().join() |
2855 | - |
2856 | - progress.data.assert_called_once_with(str({'package': 'darkside-common', 'status': 'installed', 'task_ids': [1, 2, 3]})) |
2857 | - |
2858 | - self.assertEqual(task, self.called_with) |
2859 | + self.monitor.done.return_value = False |
2860 | + |
2861 | + self.cache.app_info.return_value = {'package': 'darkside-common'} |
2862 | + self.config.get_package_install_status.return_value = 'installed' |
2863 | + task = tasks.AppInfoTask('palpatine', self.cache, 'darkside', [1, 2, 3], self.config, self.monitor, callback) |
2864 | + task._instant_callback = True |
2865 | + task.start().join() |
2866 | + |
2867 | + self.monitor.data.assert_called_once_with(self.monitor.new_operation.return_value, str({'package': 'darkside-common', 'status': 'installed', 'task_ids': [1, 2, 3]})) |
2868 | + self.monitor.finished.assert_called_once_with(self.monitor.new_operation.return_value) |
2869 | + |
2870 | + self.assertEqual(task, self.called_with) |
2871 | |
2872 | === modified file 'tests/unit/service/tasks/test_container_info_task.py' |
2873 | --- tests/unit/service/tasks/test_container_info_task.py 2017-01-27 16:42:22 +0000 |
2874 | +++ tests/unit/service/tasks/test_container_info_task.py 2017-03-31 20:05:48 +0000 |
2875 | @@ -1,4 +1,4 @@ |
2876 | -# Copyright 2016 Canonical Ltd. |
2877 | +# Copyright 2016-2017 Canonical Ltd. |
2878 | # |
2879 | # This program is free software: you can redistribute it and/or modify it |
2880 | # under the terms of the GNU General Public License version 3, as published |
2881 | @@ -17,40 +17,39 @@ |
2882 | import unittest.mock |
2883 | from unittest import TestCase |
2884 | from libertine import utils |
2885 | -from libertine.service import tasks |
2886 | +from libertine.service import tasks, operations_monitor |
2887 | from libertine.ContainersConfig import ContainersConfig |
2888 | |
2889 | |
2890 | class TestContainerInfoTask(TestCase): |
2891 | def setUp(self): |
2892 | - self.config = unittest.mock.create_autospec(ContainersConfig) |
2893 | - self.connection = unittest.mock.Mock() |
2894 | + self.config = unittest.mock.create_autospec(ContainersConfig) |
2895 | + self.monitor = unittest.mock.create_autospec(operations_monitor.OperationsMonitor) |
2896 | + self.monitor.new_operation.return_value = "/com/canonical/libertine/Service/Download/123456" |
2897 | |
2898 | def test_success_sends_data(self): |
2899 | self.called_with = None |
2900 | def callback(t): |
2901 | self.called_with = t |
2902 | |
2903 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
2904 | - progress = MockProgress.return_value |
2905 | - progress.done = False |
2906 | - |
2907 | - self.config.get_container_install_status.return_value = 'ready' |
2908 | - self.config.get_container_name.return_value = 'Palpatine' |
2909 | - task = tasks.ContainerInfoTask('palpatine', [1, 2, 3], self.config, self.connection, callback) |
2910 | - task._instant_callback = True |
2911 | - task.start().join() |
2912 | - |
2913 | - progress.data.assert_called_once_with(unittest.mock.ANY) |
2914 | - args, kwargs = progress.data.call_args |
2915 | - self.assertEqual({'id': 'palpatine', |
2916 | - 'status': 'ready', |
2917 | - 'task_ids': [1, 2, 3], |
2918 | - 'name': 'Palpatine', |
2919 | - 'root': utils.get_libertine_container_rootfs_path('palpatine'), |
2920 | - 'home': utils.get_libertine_container_home_dir('palpatine')}, |
2921 | - ast.literal_eval(args[0])) |
2922 | - |
2923 | - progress.finished.assert_called_once_with('palpatine') |
2924 | - |
2925 | - self.assertEqual(task, self.called_with) |
2926 | + self.monitor.done.return_value = False |
2927 | + |
2928 | + self.config.get_container_install_status.return_value = 'ready' |
2929 | + self.config.get_container_name.return_value = 'Palpatine' |
2930 | + task = tasks.ContainerInfoTask('palpatine', [1, 2, 3], self.config, self.monitor, callback) |
2931 | + task._instant_callback = True |
2932 | + task.start().join() |
2933 | + |
2934 | + self.monitor.data.assert_called_once_with(self.monitor.new_operation.return_value, unittest.mock.ANY) |
2935 | + args, kwargs = self.monitor.data.call_args |
2936 | + self.assertEqual({'id': 'palpatine', |
2937 | + 'status': 'ready', |
2938 | + 'task_ids': [1, 2, 3], |
2939 | + 'name': 'Palpatine', |
2940 | + 'root': utils.get_libertine_container_rootfs_path('palpatine'), |
2941 | + 'home': utils.get_libertine_container_home_dir('palpatine')}, |
2942 | + ast.literal_eval(args[1])) |
2943 | + |
2944 | + self.monitor.finished.assert_called_once_with(self.monitor.new_operation.return_value) |
2945 | + |
2946 | + self.assertEqual(task, self.called_with) |
2947 | |
2948 | === modified file 'tests/unit/service/tasks/test_create_task.py' |
2949 | --- tests/unit/service/tasks/test_create_task.py 2016-11-07 18:51:17 +0000 |
2950 | +++ tests/unit/service/tasks/test_create_task.py 2017-03-31 20:05:48 +0000 |
2951 | @@ -1,4 +1,4 @@ |
2952 | -# Copyright 2016 Canonical Ltd. |
2953 | +# Copyright 2016-2017 Canonical Ltd. |
2954 | # |
2955 | # This program is free software: you can redistribute it and/or modify it |
2956 | # under the terms of the GNU General Public License version 3, as published |
2957 | @@ -15,15 +15,18 @@ |
2958 | |
2959 | import unittest.mock |
2960 | from unittest import TestCase |
2961 | -from libertine.service import tasks |
2962 | +from libertine.service import tasks, operations_monitor |
2963 | from libertine.ContainersConfig import ContainersConfig |
2964 | |
2965 | |
2966 | class TestCreateTask(TestCase): |
2967 | def setUp(self): |
2968 | - self.config = unittest.mock.create_autospec(ContainersConfig) |
2969 | - self.connection = unittest.mock.Mock() |
2970 | - self.lock = unittest.mock.MagicMock() |
2971 | + self.config = unittest.mock.create_autospec(ContainersConfig) |
2972 | + self.lock = unittest.mock.MagicMock() |
2973 | + self.client = unittest.mock.Mock() |
2974 | + self.monitor = unittest.mock.create_autospec(operations_monitor.OperationsMonitor) |
2975 | + |
2976 | + self.monitor.new_operation.return_value = "/com/canonical/libertine/Service/Download/123456" |
2977 | self.called_with = None |
2978 | |
2979 | def callback(self, task): |
2980 | @@ -31,204 +34,195 @@ |
2981 | |
2982 | def test_success_creates_lxc_container(self): |
2983 | self.config.container_exists.return_value = False |
2984 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
2985 | - progress = MockProgress.return_value |
2986 | - progress.done = False |
2987 | - task = tasks.CreateTask('palpatine', 'Emperor Palpatine', 'zesty', 'lxc', False, self.config, self.lock, self.connection, self.callback) |
2988 | - task._instant_callback = True |
2989 | - |
2990 | - with unittest.mock.patch('libertine.service.tasks.create_task.HostInfo') as MockHostInfo: |
2991 | - MockHostInfo.return_value.is_distro_valid.return_value = True |
2992 | - MockHostInfo.return_value.has_lxc_support.return_value = True |
2993 | - |
2994 | - with unittest.mock.patch('libertine.service.tasks.create_task.LibertineContainer') as MockContainer: |
2995 | - MockContainer.return_value.create_libertine_container.return_value = True |
2996 | - task.start().join() |
2997 | - |
2998 | - progress.finished.assert_called_once_with('palpatine') |
2999 | - self.config.add_new_container.assert_called_once_with('palpatine', 'Emperor Palpatine', 'lxc', 'zesty') |
3000 | - self.config.update_container_install_status.assert_has_calls([ |
3001 | - unittest.mock.call('palpatine', 'installing'), |
3002 | - unittest.mock.call('palpatine', 'ready') |
3003 | - ], any_order=True) |
3004 | - self.assertEqual(task, self.called_with) |
3005 | + self.monitor.done.return_value = False |
3006 | + task = tasks.CreateTask('palpatine', 'Emperor Palpatine', 'zesty', 'lxc', False, |
3007 | + self.config, self.lock, self.monitor, self.client, self.callback) |
3008 | + task._instant_callback = True |
3009 | + |
3010 | + with unittest.mock.patch('libertine.service.tasks.create_task.HostInfo') as MockHostInfo: |
3011 | + MockHostInfo.return_value.is_distro_valid.return_value = True |
3012 | + MockHostInfo.return_value.has_lxc_support.return_value = True |
3013 | + |
3014 | + with unittest.mock.patch('libertine.service.tasks.create_task.LibertineContainer') as MockContainer: |
3015 | + MockContainer.return_value.create_libertine_container.return_value = True |
3016 | + task.start().join() |
3017 | + |
3018 | + self.monitor.finished.assert_called_once_with(self.monitor.new_operation.return_value) |
3019 | + self.config.add_new_container.assert_called_once_with('palpatine', 'Emperor Palpatine', 'lxc', 'zesty') |
3020 | + self.config.update_container_install_status.assert_has_calls([ |
3021 | + unittest.mock.call('palpatine', 'installing'), |
3022 | + unittest.mock.call('palpatine', 'ready') |
3023 | + ], any_order=True) |
3024 | + self.assertEqual(task, self.called_with) |
3025 | |
3026 | def test_success_creates_chroot_container(self): |
3027 | self.config.container_exists.return_value = False |
3028 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3029 | - progress = MockProgress.return_value |
3030 | - progress.done = False |
3031 | - task = tasks.CreateTask('palpatine', 'Emperor Palpatine', 'zesty', 'chroot', False, self.config, self.lock, self.connection, self.callback) |
3032 | - task._instant_callback = True |
3033 | - |
3034 | - with unittest.mock.patch('libertine.service.tasks.create_task.HostInfo') as MockHostInfo: |
3035 | - MockHostInfo.return_value.is_distro_valid.return_value = True |
3036 | - |
3037 | - with unittest.mock.patch('libertine.service.tasks.create_task.LibertineContainer') as MockContainer: |
3038 | - MockContainer.return_value.create_libertine_container.return_value = True |
3039 | - task.start().join() |
3040 | - |
3041 | - progress.finished.assert_called_once_with('palpatine') |
3042 | - self.config.add_new_container.assert_called_once_with('palpatine', 'Emperor Palpatine', 'chroot', 'zesty') |
3043 | - self.config.update_container_install_status.assert_has_calls([ |
3044 | - unittest.mock.call('palpatine', 'installing'), |
3045 | - unittest.mock.call('palpatine', 'ready') |
3046 | - ], any_order=True) |
3047 | - self.assertEqual(task, self.called_with) |
3048 | + self.monitor.done.return_value = False |
3049 | + task = tasks.CreateTask('palpatine', 'Emperor Palpatine', 'zesty', 'chroot', False, |
3050 | + self.config, self.lock, self.monitor, self.client, self.callback) |
3051 | + task._instant_callback = True |
3052 | + |
3053 | + with unittest.mock.patch('libertine.service.tasks.create_task.HostInfo') as MockHostInfo: |
3054 | + MockHostInfo.return_value.is_distro_valid.return_value = True |
3055 | + |
3056 | + with unittest.mock.patch('libertine.service.tasks.create_task.LibertineContainer') as MockContainer: |
3057 | + MockContainer.return_value.create_libertine_container.return_value = True |
3058 | + task.start().join() |
3059 | + |
3060 | + self.monitor.finished.assert_called_once_with(self.monitor.new_operation.return_value) |
3061 | + self.config.add_new_container.assert_called_once_with('palpatine', 'Emperor Palpatine', 'chroot', 'zesty') |
3062 | + self.config.update_container_install_status.assert_has_calls([ |
3063 | + unittest.mock.call('palpatine', 'installing'), |
3064 | + unittest.mock.call('palpatine', 'ready') |
3065 | + ], any_order=True) |
3066 | + self.assertEqual(task, self.called_with) |
3067 | |
3068 | def test_container_runtime_error_sends_error(self): |
3069 | self.config.container_exists.return_value = False |
3070 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3071 | - progress = MockProgress.return_value |
3072 | - task = tasks.CreateTask('palpatine', 'Emperor Palpatine', 'zesty', 'lxc', False, self.config, self.lock, self.connection, self.callback) |
3073 | - task._instant_callback = True |
3074 | - |
3075 | - with unittest.mock.patch('libertine.service.tasks.create_task.HostInfo') as MockHostInfo: |
3076 | - MockHostInfo.return_value.is_distro_valid.return_value = True |
3077 | - MockHostInfo.return_value.has_lxc_support.return_value = True |
3078 | - |
3079 | - with unittest.mock.patch('libertine.service.tasks.create_task.LibertineContainer') as MockContainer: |
3080 | - MockContainer.return_value.create_libertine_container.side_effect = RuntimeError('a great disturbance') |
3081 | - task.start().join() |
3082 | - |
3083 | - progress.error.assert_called_once_with('a great disturbance') |
3084 | - |
3085 | - self.config.add_new_container.assert_called_once_with('palpatine', 'Emperor Palpatine', 'lxc', 'zesty') |
3086 | - self.config.update_container_install_status.assert_called_once_with('palpatine', 'installing') |
3087 | - self.config.delete_container.assert_called_once_with('palpatine') |
3088 | - |
3089 | - self.assertEqual(task, self.called_with) |
3090 | + task = tasks.CreateTask('palpatine', 'Emperor Palpatine', 'zesty', 'lxc', False, |
3091 | + self.config, self.lock, self.monitor, self.client, self.callback) |
3092 | + task._instant_callback = True |
3093 | + |
3094 | + with unittest.mock.patch('libertine.service.tasks.create_task.HostInfo') as MockHostInfo: |
3095 | + MockHostInfo.return_value.is_distro_valid.return_value = True |
3096 | + MockHostInfo.return_value.has_lxc_support.return_value = True |
3097 | + |
3098 | + with unittest.mock.patch('libertine.service.tasks.create_task.LibertineContainer') as MockContainer: |
3099 | + MockContainer.return_value.create_libertine_container.side_effect = RuntimeError('a great disturbance') |
3100 | + task.start().join() |
3101 | + |
3102 | + self.monitor.error.assert_called_once_with(self.monitor.new_operation.return_value, 'a great disturbance') |
3103 | + |
3104 | + self.config.add_new_container.assert_called_once_with('palpatine', 'Emperor Palpatine', 'lxc', 'zesty') |
3105 | + self.config.update_container_install_status.assert_called_once_with('palpatine', 'installing') |
3106 | + self.config.delete_container.assert_called_once_with('palpatine') |
3107 | + |
3108 | + self.assertEqual(task, self.called_with) |
3109 | |
3110 | def test_failed_container_exists_sends_error(self): |
3111 | self.config.container_exists.return_value = True |
3112 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3113 | - progress = MockProgress.return_value |
3114 | - task = tasks.CreateTask('palpatine', 'Emperor Palpatine', 'zesty', 'lxc', False, self.config, self.lock, self.connection, self.callback) |
3115 | - task._instant_callback = True |
3116 | - task.start().join() |
3117 | + task = tasks.CreateTask('palpatine', 'Emperor Palpatine', 'zesty', 'lxc', False, |
3118 | + self.config, self.lock, self.monitor, self.client, self.callback) |
3119 | + task._instant_callback = True |
3120 | + task.start().join() |
3121 | |
3122 | - progress.error.assert_called_once_with('Container \'palpatine\' already exists') |
3123 | - self.assertEqual(task, self.called_with) |
3124 | + self.monitor.error.assert_called_once_with(self.monitor.new_operation.return_value, 'Container \'palpatine\' already exists') |
3125 | + self.assertEqual(task, self.called_with) |
3126 | |
3127 | def test_container_invalid_distro_error_sends_error(self): |
3128 | self.config.container_exists.return_value = False |
3129 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3130 | - progress = MockProgress.return_value |
3131 | - with unittest.mock.patch('libertine.service.tasks.create_task.HostInfo') as MockHostInfo: |
3132 | - MockHostInfo.return_value.is_distro_valid.return_value = False |
3133 | - task = tasks.CreateTask('palpatine', 'Emperor Palpatine', 'vesty', 'lxc', False, self.config, self.lock, self.connection, self.callback) |
3134 | - task._instant_callback = True |
3135 | - task.start().join() |
3136 | + with unittest.mock.patch('libertine.service.tasks.create_task.HostInfo') as MockHostInfo: |
3137 | + MockHostInfo.return_value.is_distro_valid.return_value = False |
3138 | + task = tasks.CreateTask('palpatine', 'Emperor Palpatine', 'vesty', 'lxc', False, |
3139 | + self.config, self.lock, self.monitor, self.client, self.callback) |
3140 | + task._instant_callback = True |
3141 | + task.start().join() |
3142 | |
3143 | - progress.error.assert_called_once_with('Invalid distro \'vesty\'.') |
3144 | - self.assertEqual(task, self.called_with) |
3145 | + self.monitor.error.assert_called_once_with(self.monitor.new_operation.return_value, 'Invalid distro \'vesty\'.') |
3146 | + self.assertEqual(task, self.called_with) |
3147 | |
3148 | def test_container_improper_lxc_error_sends_error(self): |
3149 | self.config.container_exists.return_value = False |
3150 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3151 | - progress = MockProgress.return_value |
3152 | - with unittest.mock.patch('libertine.service.tasks.create_task.HostInfo') as MockHostInfo: |
3153 | - MockHostInfo.return_value.is_distro_valid.return_value = True |
3154 | - MockHostInfo.return_value.has_lxc_support.return_value = False |
3155 | - task = tasks.CreateTask('palpatine', 'Emperor Palpatine', 'zesty', 'lxc', False, self.config, self.lock, self.connection, self.callback) |
3156 | - task._instant_callback = True |
3157 | - task.start().join() |
3158 | + with unittest.mock.patch('libertine.service.tasks.create_task.HostInfo') as MockHostInfo: |
3159 | + MockHostInfo.return_value.is_distro_valid.return_value = True |
3160 | + MockHostInfo.return_value.has_lxc_support.return_value = False |
3161 | + task = tasks.CreateTask('palpatine', 'Emperor Palpatine', 'zesty', 'lxc', False, |
3162 | + self.config, self.lock, self.monitor, self.client, self.callback) |
3163 | + task._instant_callback = True |
3164 | + task.start().join() |
3165 | |
3166 | - progress.error.assert_called_once_with('System kernel does not support lxc type containers. Please either use chroot or leave empty.') |
3167 | - self.assertEqual(task, self.called_with) |
3168 | + self.monitor.error.assert_called_once_with(self.monitor.new_operation.return_value, \ |
3169 | + 'System kernel does not support lxc type containers. Please either use chroot or leave empty.') |
3170 | + self.assertEqual(task, self.called_with) |
3171 | |
3172 | def test_sets_generic_name_when_empty(self): |
3173 | self.config.container_exists.return_value = False |
3174 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3175 | - progress = MockProgress.return_value |
3176 | - progress.done = False |
3177 | - task = tasks.CreateTask('palpatine', None, 'zesty', 'chroot', False, self.config, self.lock, self.connection, self.callback) |
3178 | - task._instant_callback = True |
3179 | - |
3180 | - with unittest.mock.patch('libertine.service.tasks.create_task.HostInfo') as MockHostInfo: |
3181 | - MockHostInfo.return_value.is_distro_valid.return_value = True |
3182 | - MockHostInfo.return_value.get_distro_codename.return_value = 'Zesty Zapus 17.04' |
3183 | - |
3184 | - with unittest.mock.patch('libertine.service.tasks.create_task.LibertineContainer') as MockContainer: |
3185 | - MockContainer.return_value.create_libertine_container.return_value = True |
3186 | - task.start().join() |
3187 | - |
3188 | - progress.finished.assert_called_once_with('palpatine') |
3189 | - self.config.add_new_container.assert_called_once_with('palpatine', 'Ubuntu \'Zesty Zapus 17.04\'', 'chroot', 'zesty') |
3190 | - self.config.update_container_install_status.assert_has_calls([ |
3191 | - unittest.mock.call('palpatine', 'installing'), |
3192 | - unittest.mock.call('palpatine', 'ready') |
3193 | - ], any_order=True) |
3194 | - self.assertEqual(task, self.called_with) |
3195 | + self.monitor.done.return_value = False |
3196 | + task = tasks.CreateTask('palpatine', None, 'zesty', 'chroot', False, self.config, |
3197 | + self.lock, self.monitor, self.client, self.callback) |
3198 | + task._instant_callback = True |
3199 | + |
3200 | + with unittest.mock.patch('libertine.service.tasks.create_task.HostInfo') as MockHostInfo: |
3201 | + MockHostInfo.return_value.is_distro_valid.return_value = True |
3202 | + MockHostInfo.return_value.get_distro_codename.return_value = 'Zesty Zapus 17.04' |
3203 | + |
3204 | + with unittest.mock.patch('libertine.service.tasks.create_task.LibertineContainer') as MockContainer: |
3205 | + MockContainer.return_value.create_libertine_container.return_value = True |
3206 | + task.start().join() |
3207 | + |
3208 | + self.monitor.finished.assert_called_once_with(self.monitor.new_operation.return_value) |
3209 | + self.config.add_new_container.assert_called_once_with('palpatine', 'Ubuntu \'Zesty Zapus 17.04\'', 'chroot', 'zesty') |
3210 | + self.config.update_container_install_status.assert_has_calls([ |
3211 | + unittest.mock.call('palpatine', 'installing'), |
3212 | + unittest.mock.call('palpatine', 'ready') |
3213 | + ], any_order=True) |
3214 | + self.assertEqual(task, self.called_with) |
3215 | |
3216 | def test_sets_multiarch(self): |
3217 | self.config.container_exists.return_value = False |
3218 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3219 | - progress = MockProgress.return_value |
3220 | - progress.done = False |
3221 | - task = tasks.CreateTask('palpatine', 'Emperor Palpatine', 'zesty', 'chroot', True, self.config, self.lock, self.connection, self.callback) |
3222 | - task._instant_callback = True |
3223 | - |
3224 | - with unittest.mock.patch('libertine.service.tasks.create_task.HostInfo') as MockHostInfo: |
3225 | - MockHostInfo.return_value.is_distro_valid.return_value = True |
3226 | - |
3227 | - with unittest.mock.patch('libertine.service.tasks.create_task.LibertineContainer') as MockContainer: |
3228 | - MockContainer.return_value.create_libertine_container.return_value = True |
3229 | - task.start().join() |
3230 | - |
3231 | - progress.finished.assert_called_once_with('palpatine') |
3232 | - self.config.add_new_container.assert_called_once_with('palpatine', 'Emperor Palpatine', 'chroot', 'zesty') |
3233 | - self.config.update_container_multiarch_support.assert_called_once_with('palpatine', 'enabled') |
3234 | - self.config.update_container_install_status.assert_has_calls([ |
3235 | - unittest.mock.call('palpatine', 'installing'), |
3236 | - unittest.mock.call('palpatine', 'ready') |
3237 | - ], any_order=True) |
3238 | - self.assertEqual(task, self.called_with) |
3239 | + self.monitor.done.return_value = False |
3240 | + task = tasks.CreateTask('palpatine', 'Emperor Palpatine', 'zesty', 'chroot', True, |
3241 | + self.config, self.lock, self.monitor, self.client, self.callback) |
3242 | + task._instant_callback = True |
3243 | + |
3244 | + with unittest.mock.patch('libertine.service.tasks.create_task.HostInfo') as MockHostInfo: |
3245 | + MockHostInfo.return_value.is_distro_valid.return_value = True |
3246 | + |
3247 | + with unittest.mock.patch('libertine.service.tasks.create_task.LibertineContainer') as MockContainer: |
3248 | + MockContainer.return_value.create_libertine_container.return_value = True |
3249 | + task.start().join() |
3250 | + |
3251 | + self.monitor.finished.assert_called_once_with(self.monitor.new_operation.return_value) |
3252 | + self.config.add_new_container.assert_called_once_with('palpatine', 'Emperor Palpatine', 'chroot', 'zesty') |
3253 | + self.config.update_container_multiarch_support.assert_called_once_with('palpatine', 'enabled') |
3254 | + self.config.update_container_install_status.assert_has_calls([ |
3255 | + unittest.mock.call('palpatine', 'installing'), |
3256 | + unittest.mock.call('palpatine', 'ready') |
3257 | + ], any_order=True) |
3258 | + self.assertEqual(task, self.called_with) |
3259 | |
3260 | def test_sets_default_type(self): |
3261 | self.config.container_exists.return_value = False |
3262 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3263 | - progress = MockProgress.return_value |
3264 | - progress.done = False |
3265 | - task = tasks.CreateTask('palpatine', 'Emperor Palpatine', 'zesty', None, False, self.config, self.lock, self.connection, self.callback) |
3266 | - task._instant_callback = True |
3267 | - |
3268 | - with unittest.mock.patch('libertine.service.tasks.create_task.HostInfo') as MockHostInfo: |
3269 | - MockHostInfo.return_value.is_distro_valid.return_value = True |
3270 | - MockHostInfo.return_value.select_container_type_by_kernel.return_value = 'lxc' |
3271 | - |
3272 | - with unittest.mock.patch('libertine.service.tasks.create_task.LibertineContainer') as MockContainer: |
3273 | - MockContainer.return_value.create_libertine_container.return_value = True |
3274 | - task.start().join() |
3275 | - |
3276 | - progress.finished.assert_called_once_with('palpatine') |
3277 | - self.config.add_new_container.assert_called_once_with('palpatine', 'Emperor Palpatine', 'lxc', 'zesty') |
3278 | - self.config.update_container_install_status.assert_has_calls([ |
3279 | - unittest.mock.call('palpatine', 'installing'), |
3280 | - unittest.mock.call('palpatine', 'ready') |
3281 | - ], any_order=True) |
3282 | - self.assertEqual(task, self.called_with) |
3283 | + self.monitor.done.return_value = False |
3284 | + task = tasks.CreateTask('palpatine', 'Emperor Palpatine', 'zesty', None, False, |
3285 | + self.config, self.lock, self.monitor, self.client, self.callback) |
3286 | + task._instant_callback = True |
3287 | + |
3288 | + with unittest.mock.patch('libertine.service.tasks.create_task.HostInfo') as MockHostInfo: |
3289 | + MockHostInfo.return_value.is_distro_valid.return_value = True |
3290 | + MockHostInfo.return_value.select_container_type_by_kernel.return_value = 'lxc' |
3291 | + |
3292 | + with unittest.mock.patch('libertine.service.tasks.create_task.LibertineContainer') as MockContainer: |
3293 | + MockContainer.return_value.create_libertine_container.return_value = True |
3294 | + task.start().join() |
3295 | + |
3296 | + self.monitor.finished.assert_called_once_with(self.monitor.new_operation.return_value) |
3297 | + self.config.add_new_container.assert_called_once_with('palpatine', 'Emperor Palpatine', 'lxc', 'zesty') |
3298 | + self.config.update_container_install_status.assert_has_calls([ |
3299 | + unittest.mock.call('palpatine', 'installing'), |
3300 | + unittest.mock.call('palpatine', 'ready') |
3301 | + ], any_order=True) |
3302 | + self.assertEqual(task, self.called_with) |
3303 | |
3304 | def test_sets_default_distro(self): |
3305 | self.config.container_exists.return_value = False |
3306 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3307 | - progress = MockProgress.return_value |
3308 | - progress.done = False |
3309 | - task = tasks.CreateTask('palpatine', 'Emperor Palpatine', None, 'lxc', False, self.config, self.lock, self.connection, self.callback) |
3310 | - task._instant_callback = True |
3311 | - |
3312 | - with unittest.mock.patch('libertine.service.tasks.create_task.HostInfo') as MockHostInfo: |
3313 | - MockHostInfo.return_value.has_lxc_support.return_value = True |
3314 | - MockHostInfo.return_value.get_host_distro_release.return_value = 'zesty' |
3315 | - |
3316 | - with unittest.mock.patch('libertine.service.tasks.create_task.LibertineContainer') as MockContainer: |
3317 | - MockContainer.return_value.create_libertine_container.return_value = True |
3318 | - task.start().join() |
3319 | - |
3320 | - progress.finished.assert_called_once_with('palpatine') |
3321 | - self.config.add_new_container.assert_called_once_with('palpatine', 'Emperor Palpatine', 'lxc', 'zesty') |
3322 | - self.config.update_container_install_status.assert_has_calls([ |
3323 | - unittest.mock.call('palpatine', 'installing'), |
3324 | - unittest.mock.call('palpatine', 'ready') |
3325 | - ], any_order=True) |
3326 | - self.assertEqual(task, self.called_with) |
3327 | + self.monitor.done.return_value = False |
3328 | + task = tasks.CreateTask('palpatine', 'Emperor Palpatine', None, 'lxc', False, |
3329 | + self.config, self.lock, self.monitor, self.client, self.callback) |
3330 | + task._instant_callback = True |
3331 | + |
3332 | + with unittest.mock.patch('libertine.service.tasks.create_task.HostInfo') as MockHostInfo: |
3333 | + MockHostInfo.return_value.has_lxc_support.return_value = True |
3334 | + MockHostInfo.return_value.get_host_distro_release.return_value = 'zesty' |
3335 | + |
3336 | + with unittest.mock.patch('libertine.service.tasks.create_task.LibertineContainer') as MockContainer: |
3337 | + MockContainer.return_value.create_libertine_container.return_value = True |
3338 | + task.start().join() |
3339 | + |
3340 | + self.monitor.finished.assert_called_once_with(self.monitor.new_operation.return_value) |
3341 | + self.config.add_new_container.assert_called_once_with('palpatine', 'Emperor Palpatine', 'lxc', 'zesty') |
3342 | + self.config.update_container_install_status.assert_has_calls([ |
3343 | + unittest.mock.call('palpatine', 'installing'), |
3344 | + unittest.mock.call('palpatine', 'ready') |
3345 | + ], any_order=True) |
3346 | + self.assertEqual(task, self.called_with) |
3347 | |
3348 | === modified file 'tests/unit/service/tasks/test_destroy_task.py' |
3349 | --- tests/unit/service/tasks/test_destroy_task.py 2016-11-07 18:51:17 +0000 |
3350 | +++ tests/unit/service/tasks/test_destroy_task.py 2017-03-31 20:05:48 +0000 |
3351 | @@ -1,4 +1,4 @@ |
3352 | -# Copyright 2016 Canonical Ltd. |
3353 | +# Copyright 2016-2017 Canonical Ltd. |
3354 | # |
3355 | # This program is free software: you can redistribute it and/or modify it |
3356 | # under the terms of the GNU General Public License version 3, as published |
3357 | @@ -15,15 +15,18 @@ |
3358 | |
3359 | import unittest.mock |
3360 | from unittest import TestCase |
3361 | -from libertine.service import tasks |
3362 | +from libertine.service import tasks, operations_monitor |
3363 | from libertine.ContainersConfig import ContainersConfig |
3364 | |
3365 | |
3366 | class TestDestroyTask(TestCase): |
3367 | def setUp(self): |
3368 | - self.config = unittest.mock.create_autospec(ContainersConfig) |
3369 | - self.connection = unittest.mock.Mock() |
3370 | - self.lock = unittest.mock.MagicMock() |
3371 | + self.config = unittest.mock.create_autospec(ContainersConfig) |
3372 | + self.lock = unittest.mock.MagicMock() |
3373 | + self.client = unittest.mock.Mock() |
3374 | + self.monitor = unittest.mock.create_autospec(operations_monitor.OperationsMonitor) |
3375 | + |
3376 | + self.monitor.new_operation.return_value = "/com/canonical/libertine/Service/Download/123456" |
3377 | self.called_with = None |
3378 | |
3379 | def callback(self, task): |
3380 | @@ -31,50 +34,45 @@ |
3381 | |
3382 | def test_sends_error_on_non_ready_container(self): |
3383 | self.config._get_value_by_key.return_value = '' |
3384 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3385 | - progress = MockProgress.return_value |
3386 | - progress.done = False |
3387 | - task = tasks.DestroyTask('palpatine', self.config, self.lock, self.connection, self.callback) |
3388 | - task._instant_callback = True |
3389 | - |
3390 | - with unittest.mock.patch('libertine.service.tasks.destroy_task.LibertineContainer') as MockContainer: |
3391 | - MockContainer.return_value.destroy_libertine_container.return_value = True |
3392 | - task.start().join() |
3393 | - |
3394 | - progress.error.assert_called_once_with('Container \'palpatine\' does not exist') |
3395 | - self.assertEqual(task, self.called_with) |
3396 | + self.monitor.done.return_value = False |
3397 | + task = tasks.DestroyTask('palpatine', self.config, self.lock, self.monitor, self.client, self.callback) |
3398 | + task._instant_callback = True |
3399 | + |
3400 | + with unittest.mock.patch('libertine.service.tasks.destroy_task.LibertineContainer') as MockContainer: |
3401 | + MockContainer.return_value.destroy_libertine_container.return_value = True |
3402 | + task.start().join() |
3403 | + |
3404 | + self.monitor.error.assert_called_once_with(self.monitor.new_operation.return_value, 'Container \'palpatine\' does not exist') |
3405 | + self.assertEqual(task, self.called_with) |
3406 | |
3407 | def test_sends_error_on_failed_destroy(self): |
3408 | self.config._get_value_by_key.return_value = 'ready' |
3409 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3410 | - progress = MockProgress.return_value |
3411 | - task = tasks.DestroyTask('palpatine', self.config, self.lock, self.connection, self.callback) |
3412 | - task._instant_callback = True |
3413 | - |
3414 | - with unittest.mock.patch('libertine.service.tasks.destroy_task.LibertineContainer') as MockContainer: |
3415 | - MockContainer.return_value.destroy_libertine_container.return_value = False |
3416 | - task.start().join() |
3417 | - |
3418 | - progress.error.assert_called_once_with('Destroying container \'palpatine\' failed') |
3419 | - self.config.update_container_install_status.assert_has_calls([ |
3420 | - unittest.mock.call('palpatine', 'removing'), |
3421 | - unittest.mock.call('palpatine', 'ready') |
3422 | - ], any_order=True) |
3423 | - self.assertEqual(task, self.called_with) |
3424 | + task = tasks.DestroyTask('palpatine', self.config, self.lock, self.monitor, self.client, self.callback) |
3425 | + task._instant_callback = True |
3426 | + |
3427 | + with unittest.mock.patch('libertine.service.tasks.destroy_task.LibertineContainer') as MockContainer: |
3428 | + MockContainer.return_value.destroy_libertine_container.return_value = False |
3429 | + task.start().join() |
3430 | + |
3431 | + self.monitor.error.assert_called_once_with(self.monitor.new_operation.return_value, 'Destroying container \'palpatine\' failed') |
3432 | + self.config.update_container_install_status.assert_has_calls([ |
3433 | + unittest.mock.call('palpatine', 'removing'), |
3434 | + unittest.mock.call('palpatine', 'ready') |
3435 | + ], any_order=True) |
3436 | + |
3437 | + self.assertEqual(task, self.called_with) |
3438 | |
3439 | def test_successfully_destroys(self): |
3440 | self.config._get_value_by_key.return_value = 'ready' |
3441 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3442 | - progress = MockProgress.return_value |
3443 | - progress.done = False |
3444 | - task = tasks.DestroyTask('palpatine', self.config, self.lock, self.connection, self.callback) |
3445 | - task._instant_callback = True |
3446 | - |
3447 | - with unittest.mock.patch('libertine.service.tasks.destroy_task.LibertineContainer') as MockContainer: |
3448 | - MockContainer.return_value.destroy_libertine_container.return_value = True |
3449 | - task.start().join() |
3450 | - |
3451 | - progress.finished.assert_called_once_with('palpatine') |
3452 | - self.config.update_container_install_status.assert_called_once_with('palpatine', 'removing') |
3453 | - self.config.delete_container.assert_called_once_with('palpatine') |
3454 | - self.assertEqual(task, self.called_with) |
3455 | + self.monitor.done.return_value = False |
3456 | + task = tasks.DestroyTask('palpatine', self.config, self.lock, self.monitor, self.client, self.callback) |
3457 | + task._instant_callback = True |
3458 | + |
3459 | + with unittest.mock.patch('libertine.service.tasks.destroy_task.LibertineContainer') as MockContainer: |
3460 | + MockContainer.return_value.destroy_libertine_container.return_value = True |
3461 | + task.start().join() |
3462 | + |
3463 | + self.monitor.finished.assert_called_once_with(self.monitor.new_operation.return_value) |
3464 | + self.config.update_container_install_status.assert_called_once_with('palpatine', 'removing') |
3465 | + self.config.delete_container.assert_called_once_with('palpatine') |
3466 | + self.assertEqual(task, self.called_with) |
3467 | |
3468 | === modified file 'tests/unit/service/tasks/test_install_task.py' |
3469 | --- tests/unit/service/tasks/test_install_task.py 2016-11-08 15:20:20 +0000 |
3470 | +++ tests/unit/service/tasks/test_install_task.py 2017-03-31 20:05:48 +0000 |
3471 | @@ -1,4 +1,4 @@ |
3472 | -# Copyright 2016 Canonical Ltd. |
3473 | +# Copyright 2016-2017 Canonical Ltd. |
3474 | # |
3475 | # This program is free software: you can redistribute it and/or modify it |
3476 | # under the terms of the GNU General Public License version 3, as published |
3477 | @@ -15,15 +15,18 @@ |
3478 | |
3479 | import unittest.mock |
3480 | from unittest import TestCase |
3481 | -from libertine.service import tasks |
3482 | +from libertine.service import tasks, operations_monitor |
3483 | from libertine.ContainersConfig import ContainersConfig |
3484 | |
3485 | |
3486 | class TestInstallTask(TestCase): |
3487 | def setUp(self): |
3488 | - self.config = unittest.mock.create_autospec(ContainersConfig) |
3489 | - self.connection = unittest.mock.Mock() |
3490 | - self.lock = unittest.mock.MagicMock() |
3491 | + self.config = unittest.mock.create_autospec(ContainersConfig) |
3492 | + self.lock = unittest.mock.MagicMock() |
3493 | + self.client = unittest.mock.Mock() |
3494 | + self.monitor = unittest.mock.create_autospec(operations_monitor.OperationsMonitor) |
3495 | + |
3496 | + self.monitor.new_operation.return_value = "/com/canonical/libertine/Service/Download/123456" |
3497 | self.called_with = None |
3498 | |
3499 | def callback(self, task): |
3500 | @@ -31,46 +34,40 @@ |
3501 | |
3502 | def test_sends_error_on_existing_package(self): |
3503 | self.config.package_exists.return_value = True |
3504 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3505 | - progress = MockProgress.return_value |
3506 | - task = tasks.InstallTask('darkside-common', 'palpatine', self.config, self.lock, self.connection, self.callback) |
3507 | - task._instant_callback = True |
3508 | - task.start().join() |
3509 | + task = tasks.InstallTask('darkside-common', 'palpatine', self.config, self.lock, self.monitor, self.client, self.callback) |
3510 | + task._instant_callback = True |
3511 | + task.start().join() |
3512 | |
3513 | - progress.error.assert_called_once_with('Package \'darkside-common\' already exists, skipping install') |
3514 | - self.assertEqual(task, self.called_with) |
3515 | + self.monitor.error.assert_called_once_with(self.monitor.new_operation.return_value, 'Package \'darkside-common\' already exists, skipping install') |
3516 | + self.assertEqual(task, self.called_with) |
3517 | |
3518 | def test_sends_error_on_failed_install(self): |
3519 | self.config.package_exists.return_value = False |
3520 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3521 | - progress = MockProgress.return_value |
3522 | - task = tasks.InstallTask('darkside-common', 'palpatine', self.config, self.lock, self.connection, self.callback) |
3523 | - task._instant_callback = True |
3524 | - |
3525 | - with unittest.mock.patch('libertine.service.tasks.install_task.LibertineContainer') as MockContainer: |
3526 | - MockContainer.return_value.install_package.return_value = False |
3527 | - task.start().join() |
3528 | - |
3529 | - progress.error.assert_called_once_with("Package installation failed for 'darkside-common'") |
3530 | - self.config.update_package_install_status.assert_called_once_with('palpatine', 'darkside-common', 'installing') |
3531 | - self.config.delete_package.assert_called_once_with('palpatine', 'darkside-common') |
3532 | - self.assertEqual(task, self.called_with) |
3533 | + task = tasks.InstallTask('darkside-common', 'palpatine', self.config, self.lock, self.monitor, self.client, self.callback) |
3534 | + task._instant_callback = True |
3535 | + |
3536 | + with unittest.mock.patch('libertine.service.tasks.install_task.LibertineContainer') as MockContainer: |
3537 | + MockContainer.return_value.install_package.return_value = False |
3538 | + task.start().join() |
3539 | + |
3540 | + self.monitor.error.assert_called_once_with(self.monitor.new_operation.return_value, "Package installation failed for 'darkside-common'") |
3541 | + self.config.update_package_install_status.assert_called_once_with('palpatine', 'darkside-common', 'installing') |
3542 | + self.config.delete_package.assert_called_once_with('palpatine', 'darkside-common') |
3543 | + self.assertEqual(task, self.called_with) |
3544 | |
3545 | def test_successfully_install(self): |
3546 | self.config.package_exists.return_value = False |
3547 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3548 | - progress = MockProgress.return_value |
3549 | - progress.done = False |
3550 | - task = tasks.InstallTask('darkside-common', 'palpatine', self.config, self.lock, self.connection, self.callback) |
3551 | - task._instant_callback = True |
3552 | - |
3553 | - with unittest.mock.patch('libertine.service.tasks.install_task.LibertineContainer') as MockContainer: |
3554 | - MockContainer.return_value.install_package.return_value = True |
3555 | - task.start().join() |
3556 | - |
3557 | - progress.finished.assert_called_once_with('palpatine') |
3558 | - self.config.update_package_install_status.assert_has_calls([ |
3559 | - unittest.mock.call('palpatine', 'darkside-common', 'installing'), |
3560 | - unittest.mock.call('palpatine', 'darkside-common', 'installed') |
3561 | - ], any_order=True) |
3562 | - self.assertEqual(task, self.called_with) |
3563 | + self.monitor.done.return_value = False |
3564 | + task = tasks.InstallTask('darkside-common', 'palpatine', self.config, self.lock, self.monitor, self.client, self.callback) |
3565 | + task._instant_callback = True |
3566 | + |
3567 | + with unittest.mock.patch('libertine.service.tasks.install_task.LibertineContainer') as MockContainer: |
3568 | + MockContainer.return_value.install_package.return_value = True |
3569 | + task.start().join() |
3570 | + |
3571 | + self.monitor.finished.assert_called_once_with(self.monitor.new_operation.return_value) |
3572 | + self.config.update_package_install_status.assert_has_calls([ |
3573 | + unittest.mock.call('palpatine', 'darkside-common', 'installing'), |
3574 | + unittest.mock.call('palpatine', 'darkside-common', 'installed') |
3575 | + ], any_order=True) |
3576 | + self.assertEqual(task, self.called_with) |
3577 | |
3578 | === modified file 'tests/unit/service/tasks/test_list_app_ids_task.py' |
3579 | --- tests/unit/service/tasks/test_list_app_ids_task.py 2017-02-07 12:35:48 +0000 |
3580 | +++ tests/unit/service/tasks/test_list_app_ids_task.py 2017-03-31 20:05:48 +0000 |
3581 | @@ -15,15 +15,17 @@ |
3582 | import json |
3583 | import unittest.mock |
3584 | from unittest import TestCase |
3585 | -from libertine.service import tasks |
3586 | +from libertine.service import tasks, operations_monitor |
3587 | from libertine.ContainersConfig import ContainersConfig |
3588 | |
3589 | |
3590 | class TestListAppIdsTask(TestCase): |
3591 | def setUp(self): |
3592 | self.config = unittest.mock.create_autospec(ContainersConfig) |
3593 | - self.connection = unittest.mock.Mock() |
3594 | self.lock = unittest.mock.MagicMock() |
3595 | + self.monitor = unittest.mock.create_autospec(operations_monitor.OperationsMonitor) |
3596 | + |
3597 | + self.monitor.new_operation.return_value = "/com/canonical/libertine/Service/Download/123456" |
3598 | self.called_with = None |
3599 | |
3600 | def callback(self, task): |
3601 | @@ -31,29 +33,25 @@ |
3602 | |
3603 | def test_sends_error_on_non_existent_container(self): |
3604 | self.config.container_exists.return_value = False |
3605 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3606 | - progress = MockProgress.return_value |
3607 | - task = tasks.ListAppIdsTask('palpatine', self.config, self.connection, self.callback) |
3608 | - task._instant_callback = True |
3609 | - |
3610 | - with unittest.mock.patch('libertine.service.tasks.list_app_ids_task.LibertineContainer') as MockContainer: |
3611 | - task.start().join() |
3612 | - |
3613 | - progress.error.assert_called_once_with('Container \'palpatine\' does not exist, skipping list') |
3614 | - self.assertEqual(task, self.called_with) |
3615 | + task = tasks.ListAppIdsTask('palpatine', self.config, self.monitor, self.callback) |
3616 | + task._instant_callback = True |
3617 | + |
3618 | + with unittest.mock.patch('libertine.service.tasks.list_app_ids_task.LibertineContainer') as MockContainer: |
3619 | + task.start().join() |
3620 | + |
3621 | + self.monitor.error.assert_called_once_with(self.monitor.new_operation.return_value, 'Container \'palpatine\' does not exist, skipping list') |
3622 | + self.assertEqual(task, self.called_with) |
3623 | |
3624 | def test_successfully_lists_apps(self): |
3625 | self.config.container_exists.return_value = True |
3626 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3627 | - progress = MockProgress.return_value |
3628 | - progress.done = False |
3629 | - task = tasks.ListAppIdsTask('palpatine', self.config, self.connection, self.callback) |
3630 | - task._instant_callback = True |
3631 | - |
3632 | - with unittest.mock.patch('libertine.service.tasks.list_app_ids_task.LibertineContainer') as MockContainer: |
3633 | - MockContainer.return_value.list_app_ids.return_value = '["palpatine_gedit_0.0","palpatine_xterm_0.0"]' |
3634 | - task.start().join() |
3635 | - |
3636 | - progress.finished.assert_called_once_with('palpatine') |
3637 | - progress.data.assert_called_once_with(json.dumps('["palpatine_gedit_0.0","palpatine_xterm_0.0"]')) |
3638 | - self.assertEqual(task, self.called_with) |
3639 | + self.monitor.done.return_value = False |
3640 | + task = tasks.ListAppIdsTask('palpatine', self.config, self.monitor, self.callback) |
3641 | + task._instant_callback = True |
3642 | + |
3643 | + with unittest.mock.patch('libertine.service.tasks.list_app_ids_task.LibertineContainer') as MockContainer: |
3644 | + MockContainer.return_value.list_app_ids.return_value = '["palpatine_gedit_0.0","palpatine_xterm_0.0"]' |
3645 | + task.start().join() |
3646 | + |
3647 | + self.monitor.finished.assert_called_once_with(self.monitor.new_operation.return_value) |
3648 | + self.monitor.data.assert_called_once_with(self.monitor.new_operation.return_value, json.dumps('["palpatine_gedit_0.0","palpatine_xterm_0.0"]')) |
3649 | + self.assertEqual(task, self.called_with) |
3650 | |
3651 | === modified file 'tests/unit/service/tasks/test_list_task.py' |
3652 | --- tests/unit/service/tasks/test_list_task.py 2017-01-24 18:00:57 +0000 |
3653 | +++ tests/unit/service/tasks/test_list_task.py 2017-03-31 20:05:48 +0000 |
3654 | @@ -17,31 +17,30 @@ |
3655 | import unittest.mock |
3656 | |
3657 | from unittest import TestCase |
3658 | -from libertine.service import tasks |
3659 | +from libertine.service import tasks, operations_monitor |
3660 | from libertine.ContainersConfig import ContainersConfig |
3661 | |
3662 | |
3663 | class TestListTask(TestCase): |
3664 | def setUp(self): |
3665 | self.config = unittest.mock.create_autospec(ContainersConfig) |
3666 | - self.connection = unittest.mock.Mock() |
3667 | + self.monitor = unittest.mock.create_autospec(operations_monitor.OperationsMonitor) |
3668 | + self.monitor.new_operation.return_value = "/com/canonical/libertine/Service/Download/123456" |
3669 | |
3670 | def test_success_sends_data(self): |
3671 | self.called_with = None |
3672 | def callback(t): |
3673 | self.called_with = t |
3674 | |
3675 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3676 | - progress = MockProgress.return_value |
3677 | - progress.done = False |
3678 | - |
3679 | - task = tasks.ListTask(self.config, self.connection, callback) |
3680 | - task._instant_callback = True |
3681 | - |
3682 | - self.config.get_containers.return_value = ['palatine', 'vader', 'maul'] |
3683 | - task.start().join() |
3684 | - |
3685 | - progress.data.assert_called_once_with(json.dumps(['palatine', 'vader', 'maul'])) |
3686 | - progress.finished.assert_called_once_with('') |
3687 | - |
3688 | - self.assertEqual(task, self.called_with) |
3689 | + self.monitor.done.return_value = False |
3690 | + |
3691 | + task = tasks.ListTask(self.config, self.monitor, callback) |
3692 | + task._instant_callback = True |
3693 | + |
3694 | + self.config.get_containers.return_value = ['palatine', 'vader', 'maul'] |
3695 | + task.start().join() |
3696 | + |
3697 | + self.monitor.data.assert_called_once_with(self.monitor.new_operation.return_value, json.dumps(['palatine', 'vader', 'maul'])) |
3698 | + self.monitor.finished.assert_called_once_with(self.monitor.new_operation.return_value) |
3699 | + |
3700 | + self.assertEqual(task, self.called_with) |
3701 | |
3702 | === modified file 'tests/unit/service/tasks/test_remove_task.py' |
3703 | --- tests/unit/service/tasks/test_remove_task.py 2016-11-08 15:20:20 +0000 |
3704 | +++ tests/unit/service/tasks/test_remove_task.py 2017-03-31 20:05:48 +0000 |
3705 | @@ -1,4 +1,4 @@ |
3706 | -# Copyright 2016 Canonical Ltd. |
3707 | +# Copyright 2016-2017 Canonical Ltd. |
3708 | # |
3709 | # This program is free software: you can redistribute it and/or modify it |
3710 | # under the terms of the GNU General Public License version 3, as published |
3711 | @@ -15,15 +15,18 @@ |
3712 | |
3713 | import unittest.mock |
3714 | from unittest import TestCase |
3715 | -from libertine.service import tasks |
3716 | +from libertine.service import tasks, operations_monitor |
3717 | from libertine.ContainersConfig import ContainersConfig |
3718 | |
3719 | |
3720 | class TestRemoveTask(TestCase): |
3721 | def setUp(self): |
3722 | - self.config = unittest.mock.create_autospec(ContainersConfig) |
3723 | - self.connection = unittest.mock.Mock() |
3724 | - self.lock = unittest.mock.MagicMock() |
3725 | + self.config = unittest.mock.create_autospec(ContainersConfig) |
3726 | + self.lock = unittest.mock.MagicMock() |
3727 | + self.client = unittest.mock.Mock() |
3728 | + self.monitor = unittest.mock.create_autospec(operations_monitor.OperationsMonitor) |
3729 | + |
3730 | + self.monitor.new_operation.return_value = "/com/canonical/libertine/Service/Download/123456" |
3731 | self.called_with = None |
3732 | |
3733 | def callback(self, task): |
3734 | @@ -31,46 +34,40 @@ |
3735 | |
3736 | def test_sends_error_on_non_installed_package(self): |
3737 | self.config.get_package_install_status.return_value = 'installing' |
3738 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3739 | - progress = MockProgress.return_value |
3740 | - task = tasks.RemoveTask('darkside-common', 'palpatine', self.config, self.lock, self.connection, self.callback) |
3741 | - task._instant_callback = True |
3742 | - task.start().join() |
3743 | + task = tasks.RemoveTask('darkside-common', 'palpatine', self.config, self.lock, self.monitor, self.client, self.callback) |
3744 | + task._instant_callback = True |
3745 | + task.start().join() |
3746 | |
3747 | - progress.error.assert_called_once_with('Package \'darkside-common\' not installed, skipping remove') |
3748 | - self.assertEqual(task, self.called_with) |
3749 | + self.monitor.error.assert_called_once_with(self.monitor.new_operation.return_value, 'Package \'darkside-common\' not installed, skipping remove') |
3750 | + self.assertEqual(task, self.called_with) |
3751 | |
3752 | def test_sends_error_on_failed_install(self): |
3753 | self.config.get_package_install_status.return_value = 'installed' |
3754 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3755 | - progress = MockProgress.return_value |
3756 | - task = tasks.RemoveTask('darkside-common', 'palpatine', self.config, self.lock, self.connection, self.callback) |
3757 | - task._instant_callback = True |
3758 | - |
3759 | - with unittest.mock.patch('libertine.service.tasks.remove_task.LibertineContainer') as MockContainer: |
3760 | - MockContainer.return_value.remove_package.return_value = False |
3761 | - task.start().join() |
3762 | - |
3763 | - progress.error.assert_called_once_with("Package removal failed for 'darkside-common'") |
3764 | - self.config.update_package_install_status.assert_has_calls([ |
3765 | - unittest.mock.call('palpatine', 'darkside-common', 'removing'), |
3766 | - unittest.mock.call('palpatine', 'darkside-common', 'installed') |
3767 | - ], any_order=True) |
3768 | - self.assertEqual(task, self.called_with) |
3769 | + task = tasks.RemoveTask('darkside-common', 'palpatine', self.config, self.lock, self.monitor, self.client, self.callback) |
3770 | + task._instant_callback = True |
3771 | + |
3772 | + with unittest.mock.patch('libertine.service.tasks.remove_task.LibertineContainer') as MockContainer: |
3773 | + MockContainer.return_value.remove_package.return_value = False |
3774 | + task.start().join() |
3775 | + |
3776 | + self.monitor.error.assert_called_once_with(self.monitor.new_operation.return_value, "Package removal failed for 'darkside-common'") |
3777 | + self.config.update_package_install_status.assert_has_calls([ |
3778 | + unittest.mock.call('palpatine', 'darkside-common', 'removing'), |
3779 | + unittest.mock.call('palpatine', 'darkside-common', 'installed') |
3780 | + ], any_order=True) |
3781 | + self.assertEqual(task, self.called_with) |
3782 | |
3783 | def test_successfully_install(self): |
3784 | self.config.get_package_install_status.return_value = 'installed' |
3785 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3786 | - progress = MockProgress.return_value |
3787 | - progress.done = False |
3788 | - task = tasks.RemoveTask('darkside-common', 'palpatine', self.config, self.lock, self.connection, self.callback) |
3789 | - task._instant_callback = True |
3790 | - |
3791 | - with unittest.mock.patch('libertine.service.tasks.remove_task.LibertineContainer') as MockContainer: |
3792 | - MockContainer.return_value.remove_package.return_value = True |
3793 | - task.start().join() |
3794 | - |
3795 | - progress.finished.assert_called_once_with('palpatine') |
3796 | - self.config.update_package_install_status.assert_called_once_with('palpatine', 'darkside-common', 'removing') |
3797 | - self.config.delete_package.assert_called_once_with('palpatine', 'darkside-common') |
3798 | - self.assertEqual(task, self.called_with) |
3799 | + self.monitor.done.return_value = False |
3800 | + task = tasks.RemoveTask('darkside-common', 'palpatine', self.config, self.lock, self.monitor, self.client, self.callback) |
3801 | + task._instant_callback = True |
3802 | + |
3803 | + with unittest.mock.patch('libertine.service.tasks.remove_task.LibertineContainer') as MockContainer: |
3804 | + MockContainer.return_value.remove_package.return_value = True |
3805 | + task.start().join() |
3806 | + |
3807 | + self.monitor.finished.assert_called_once_with(self.monitor.new_operation.return_value) |
3808 | + self.config.update_package_install_status.assert_called_once_with('palpatine', 'darkside-common', 'removing') |
3809 | + self.config.delete_package.assert_called_once_with('palpatine', 'darkside-common') |
3810 | + self.assertEqual(task, self.called_with) |
3811 | |
3812 | === modified file 'tests/unit/service/tasks/test_search_task.py' |
3813 | --- tests/unit/service/tasks/test_search_task.py 2016-11-07 18:51:17 +0000 |
3814 | +++ tests/unit/service/tasks/test_search_task.py 2017-03-31 20:05:48 +0000 |
3815 | @@ -1,4 +1,4 @@ |
3816 | -# Copyright 2016 Canonical Ltd. |
3817 | +# Copyright 2016-2017 Canonical Ltd. |
3818 | # |
3819 | # This program is free software: you can redistribute it and/or modify it |
3820 | # under the terms of the GNU General Public License version 3, as published |
3821 | @@ -15,29 +15,29 @@ |
3822 | |
3823 | import unittest.mock |
3824 | from unittest import TestCase |
3825 | -from libertine.service import tasks, apt |
3826 | +from libertine.service import tasks, apt, operations_monitor |
3827 | |
3828 | |
3829 | class TestSearchTask(TestCase): |
3830 | def setUp(self): |
3831 | - self.connection = unittest.mock.Mock() |
3832 | self.lock = unittest.mock.MagicMock() |
3833 | self.cache = unittest.mock.create_autospec(apt.AptCache) |
3834 | + self.monitor = unittest.mock.create_autospec(operations_monitor.OperationsMonitor) |
3835 | + |
3836 | + self.monitor.new_operation.return_value = "/com/canonical/libertine/Service/Download/123456" |
3837 | self.called_with = None |
3838 | |
3839 | def callback(self, task): |
3840 | self.called_with = task |
3841 | |
3842 | def test_successfully_lists_apps(self): |
3843 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3844 | - progress = MockProgress.return_value |
3845 | - progress.done = False |
3846 | - task = tasks.SearchTask('palpatine', self.cache, 'jarjar', self.connection, self.callback) |
3847 | + self.monitor.done.return_value = False |
3848 | + task = tasks.SearchTask('palpatine', self.cache, 'jarjar', self.monitor, self.callback) |
3849 | task._instant_callback = True |
3850 | |
3851 | self.cache.search.return_value = ['jarjar', 'sidius'] |
3852 | task.start().join() |
3853 | |
3854 | - progress.finished.assert_called_once_with('palpatine') |
3855 | - progress.data.assert_called_once_with(str(['jarjar', 'sidius'])) |
3856 | + self.monitor.finished.assert_called_once_with(self.monitor.new_operation.return_value) |
3857 | + self.monitor.data.assert_called_once_with(self.monitor.new_operation.return_value, str(['jarjar', 'sidius'])) |
3858 | self.assertEqual(task, self.called_with) |
3859 | |
3860 | === modified file 'tests/unit/service/tasks/test_update_task.py' |
3861 | --- tests/unit/service/tasks/test_update_task.py 2016-11-08 15:20:20 +0000 |
3862 | +++ tests/unit/service/tasks/test_update_task.py 2017-03-31 20:05:48 +0000 |
3863 | @@ -1,4 +1,4 @@ |
3864 | -# Copyright 2016 Canonical Ltd. |
3865 | +# Copyright 2016-2017 Canonical Ltd. |
3866 | # |
3867 | # This program is free software: you can redistribute it and/or modify it |
3868 | # under the terms of the GNU General Public License version 3, as published |
3869 | @@ -15,15 +15,18 @@ |
3870 | |
3871 | import unittest.mock |
3872 | from unittest import TestCase |
3873 | -from libertine.service import tasks |
3874 | +from libertine.service import tasks, operations_monitor |
3875 | from libertine.ContainersConfig import ContainersConfig |
3876 | |
3877 | |
3878 | class TestUpdateTask(TestCase): |
3879 | def setUp(self): |
3880 | - self.config = unittest.mock.create_autospec(ContainersConfig) |
3881 | - self.connection = unittest.mock.Mock() |
3882 | - self.lock = unittest.mock.MagicMock() |
3883 | + self.config = unittest.mock.create_autospec(ContainersConfig) |
3884 | + self.lock = unittest.mock.MagicMock() |
3885 | + self.client = unittest.mock.Mock() |
3886 | + self.monitor = unittest.mock.create_autospec(operations_monitor.OperationsMonitor) |
3887 | + |
3888 | + self.monitor.new_operation.return_value = "/com/canonical/libertine/Service/Download/123456" |
3889 | self.called_with = None |
3890 | |
3891 | def callback(self, task): |
3892 | @@ -31,50 +34,47 @@ |
3893 | |
3894 | def test_sends_error_on_non_existent_container(self): |
3895 | self.config.container_exists.return_value = False |
3896 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3897 | - progress = MockProgress.return_value |
3898 | - task = tasks.UpdateTask('palpatine', self.config, self.lock, self.connection, self.callback) |
3899 | - task._instant_callback = True |
3900 | - |
3901 | - with unittest.mock.patch('libertine.service.tasks.update_task.LibertineContainer') as MockContainer: |
3902 | - task.start().join() |
3903 | - |
3904 | - progress.error.assert_called_once_with('Container \'palpatine\' does not exist, skipping update') |
3905 | - self.assertEqual(task, self.called_with) |
3906 | + task = tasks.UpdateTask('palpatine', self.config, self.lock, self.monitor, self.client, self.callback) |
3907 | + task._instant_callback = True |
3908 | + |
3909 | + with unittest.mock.patch('libertine.service.tasks.update_task.LibertineContainer') as MockContainer: |
3910 | + task.start().join() |
3911 | + |
3912 | + self.monitor.error.assert_called_once_with(self.monitor.new_operation.return_value, 'Container \'palpatine\' does not exist, skipping update') |
3913 | + |
3914 | + self.assertEqual(task, self.called_with) |
3915 | |
3916 | def test_sends_error_on_failed_update(self): |
3917 | self.config.container_exists.return_value = True |
3918 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3919 | - progress = MockProgress.return_value |
3920 | - task = tasks.UpdateTask('palpatine', self.config, self.lock, self.connection, self.callback) |
3921 | - task._instant_callback = True |
3922 | - |
3923 | - with unittest.mock.patch('libertine.service.tasks.update_task.LibertineContainer') as MockContainer: |
3924 | - MockContainer.return_value.update_libertine_container.return_value = False |
3925 | - task.start().join() |
3926 | - |
3927 | - progress.error.assert_called_once_with('Failed to update container \'palpatine\'') |
3928 | - self.config.update_container_install_status.assert_has_calls([ |
3929 | - unittest.mock.call('palpatine', 'updating'), |
3930 | - unittest.mock.call('palpatine', 'ready') |
3931 | - ], any_order=True) |
3932 | - self.assertEqual(task, self.called_with) |
3933 | + task = tasks.UpdateTask('palpatine', self.config, self.lock, self.monitor, self.client, self.callback) |
3934 | + task._instant_callback = True |
3935 | + |
3936 | + with unittest.mock.patch('libertine.service.tasks.update_task.LibertineContainer') as MockContainer: |
3937 | + MockContainer.return_value.update_libertine_container.return_value = False |
3938 | + task.start().join() |
3939 | + |
3940 | + self.monitor.error.assert_called_once_with(self.monitor.new_operation.return_value, 'Failed to update container \'palpatine\'') |
3941 | + self.config.update_container_install_status.assert_has_calls([ |
3942 | + unittest.mock.call('palpatine', 'updating'), |
3943 | + unittest.mock.call('palpatine', 'ready') |
3944 | + ], any_order=True) |
3945 | + |
3946 | + self.assertEqual(task, self.called_with) |
3947 | |
3948 | def test_successfully_updates(self): |
3949 | self.config.container_exists.return_value = True |
3950 | - with unittest.mock.patch('libertine.service.tasks.base_task.libertine.service.progress.Progress') as MockProgress: |
3951 | - progress = MockProgress.return_value |
3952 | - progress.done = False |
3953 | - task = tasks.UpdateTask('palpatine', self.config, self.lock, self.connection, self.callback) |
3954 | - task._instant_callback = True |
3955 | - |
3956 | - with unittest.mock.patch('libertine.service.tasks.update_task.LibertineContainer') as MockContainer: |
3957 | - MockContainer.return_value.update_libertine_container.return_value = True |
3958 | - task.start().join() |
3959 | - |
3960 | - progress.finished.assert_called_once_with('palpatine') |
3961 | - self.config.update_container_install_status.assert_has_calls([ |
3962 | - unittest.mock.call('palpatine', 'updating'), |
3963 | - unittest.mock.call('palpatine', 'ready') |
3964 | - ], any_order=True) |
3965 | - self.assertEqual(task, self.called_with) |
3966 | + self.monitor.done.return_value = False |
3967 | + task = tasks.UpdateTask('palpatine', self.config, self.lock, self.monitor, self.client, self.callback) |
3968 | + task._instant_callback = True |
3969 | + |
3970 | + with unittest.mock.patch('libertine.service.tasks.update_task.LibertineContainer') as MockContainer: |
3971 | + MockContainer.return_value.update_libertine_container.return_value = True |
3972 | + task.start().join() |
3973 | + |
3974 | + self.monitor.finished.assert_called_once_with(self.monitor.new_operation.return_value) |
3975 | + self.config.update_container_install_status.assert_has_calls([ |
3976 | + unittest.mock.call('palpatine', 'updating'), |
3977 | + unittest.mock.call('palpatine', 'ready') |
3978 | + ], any_order=True) |
3979 | + |
3980 | + self.assertEqual(task, self.called_with) |
3981 | |
3982 | === modified file 'tests/unit/service/test_container.py' |
3983 | --- tests/unit/service/test_container.py 2017-02-07 12:35:48 +0000 |
3984 | +++ tests/unit/service/test_container.py 2017-03-31 20:05:48 +0000 |
3985 | @@ -20,31 +20,32 @@ |
3986 | |
3987 | class TestContainer(TestCase): |
3988 | def setUp(self): |
3989 | - self._connection = unittest.mock.Mock() |
3990 | + self._monitor = unittest.mock.Mock() |
3991 | self._config = unittest.mock.Mock() |
3992 | + self._client = unittest.mock.Mock() |
3993 | |
3994 | def test_search_creates_search_task(self): |
3995 | with unittest.mock.patch('libertine.service.container.apt.AptCache') as MockCache: |
3996 | cache = MockCache.return_value |
3997 | - c = container.Container('palpatine', self._config, self._connection, lambda task: task) |
3998 | + c = container.Container('palpatine', self._config, self._monitor, self._client, lambda task: task) |
3999 | with unittest.mock.patch('libertine.service.container.SearchTask') as MockSearchTask: |
4000 | c.search('darkseid') |
4001 | - MockSearchTask.assert_called_once_with('palpatine', cache, 'darkseid', self._connection, unittest.mock.ANY) |
4002 | + MockSearchTask.assert_called_once_with('palpatine', cache, 'darkseid', self._monitor, unittest.mock.ANY) |
4003 | MockSearchTask.return_value.start.assert_called_once_with() |
4004 | |
4005 | def test_app_info_creates_app_info_task(self): |
4006 | with unittest.mock.patch('libertine.service.container.apt.AptCache') as MockCache: |
4007 | cache = MockCache.return_value |
4008 | - c = container.Container('palpatine', self._config, self._connection, lambda task: task) |
4009 | + c = container.Container('palpatine', self._config, self._monitor, self._client, lambda task: task) |
4010 | with unittest.mock.patch('libertine.service.container.AppInfoTask') as MockAppInfoTask: |
4011 | c.app_info('force') |
4012 | - MockAppInfoTask.assert_called_once_with('palpatine', cache, 'force', [], self._config, self._connection, unittest.mock.ANY) |
4013 | + MockAppInfoTask.assert_called_once_with('palpatine', cache, 'force', [], self._config, self._monitor, unittest.mock.ANY) |
4014 | MockAppInfoTask.return_value.start.assert_called_once_with() |
4015 | |
4016 | def test_app_info_gets_related_task_info(self): |
4017 | with unittest.mock.patch('libertine.service.container.apt.AptCache') as MockCache: |
4018 | cache = MockCache.return_value |
4019 | - c = container.Container('palpatine', self._config, self._connection, lambda task: task) |
4020 | + c = container.Container('palpatine', self._config, self._monitor, self._client, lambda task: task) |
4021 | with unittest.mock.patch('libertine.service.container.InstallTask') as MockInstallTask: |
4022 | MockInstallTask.return_value.package = 'darkside' |
4023 | MockInstallTask.return_value.matches.return_value = False |
4024 | @@ -55,111 +56,111 @@ |
4025 | with unittest.mock.patch('libertine.service.container.AppInfoTask') as MockAppInfoTask: |
4026 | c.app_info('darkside') |
4027 | MockAppInfoTask.assert_called_once_with('palpatine', cache, 'darkside', [install_task_id, remove_task_id], |
4028 | - self._config, self._connection, unittest.mock.ANY) |
4029 | + self._config, self._monitor, unittest.mock.ANY) |
4030 | |
4031 | def test_install_creates_install_task(self): |
4032 | with unittest.mock.patch('libertine.service.container.apt.AptCache') as MockCache: |
4033 | - c = container.Container('palpatine', self._config, self._connection, lambda task: task) |
4034 | + c = container.Container('palpatine', self._config, self._monitor, self._client, lambda task: task) |
4035 | with unittest.mock.patch('libertine.service.container.InstallTask') as MockInstallTask: |
4036 | c.install('force') |
4037 | - MockInstallTask.assert_called_once_with('force', 'palpatine', self._config, unittest.mock.ANY, self._connection, unittest.mock.ANY) |
4038 | + MockInstallTask.assert_called_once_with('force', 'palpatine', self._config, unittest.mock.ANY, self._monitor, self._client, unittest.mock.ANY) |
4039 | MockInstallTask.return_value.start.assert_called_once_with() |
4040 | |
4041 | def test_install_only_calls_once_when_unfinished(self): |
4042 | with unittest.mock.patch('libertine.service.container.apt.AptCache') as MockCache: |
4043 | - c = container.Container('palpatine', self._config, self._connection, lambda task: task) |
4044 | + c = container.Container('palpatine', self._config, self._monitor, self._client, lambda task: task) |
4045 | with unittest.mock.patch('libertine.service.container.InstallTask') as MockInstallTask: |
4046 | c.install('darkside') |
4047 | c.install('darkside') |
4048 | c.install('darkside') |
4049 | - MockInstallTask.assert_called_once_with('darkside', 'palpatine', self._config, unittest.mock.ANY, self._connection, unittest.mock.ANY) |
4050 | + MockInstallTask.assert_called_once_with('darkside', 'palpatine', self._config, unittest.mock.ANY, self._monitor, self._client, unittest.mock.ANY) |
4051 | MockInstallTask.return_value.start.assert_called_once_with() |
4052 | |
4053 | def test_remove_creates_remove_task(self): |
4054 | with unittest.mock.patch('libertine.service.container.apt.AptCache') as MockCache: |
4055 | - c = container.Container('palpatine', self._config, self._connection, lambda task: task) |
4056 | + c = container.Container('palpatine', self._config, self._monitor, self._client, lambda task: task) |
4057 | with unittest.mock.patch('libertine.service.container.RemoveTask') as MockRemoveTask: |
4058 | c.remove('force') |
4059 | - MockRemoveTask.assert_called_once_with('force', 'palpatine', self._config, unittest.mock.ANY, self._connection, unittest.mock.ANY) |
4060 | + MockRemoveTask.assert_called_once_with('force', 'palpatine', self._config, unittest.mock.ANY, self._monitor, self._client, unittest.mock.ANY) |
4061 | MockRemoveTask.return_value.start.assert_called_once_with() |
4062 | |
4063 | def test_remove_only_calls_once_when_unfinished(self): |
4064 | with unittest.mock.patch('libertine.service.container.apt.AptCache') as MockCache: |
4065 | - c = container.Container('palpatine', self._config, self._connection, lambda task: task) |
4066 | + c = container.Container('palpatine', self._config, self._monitor, self._client, lambda task: task) |
4067 | with unittest.mock.patch('libertine.service.container.RemoveTask') as MockRemoveTask: |
4068 | c.remove('darkside') |
4069 | c.remove('darkside') |
4070 | c.remove('darkside') |
4071 | - MockRemoveTask.assert_called_once_with('darkside', 'palpatine', self._config, unittest.mock.ANY, self._connection, unittest.mock.ANY) |
4072 | + MockRemoveTask.assert_called_once_with('darkside', 'palpatine', self._config, unittest.mock.ANY, self._monitor, self._client, unittest.mock.ANY) |
4073 | MockRemoveTask.return_value.start.assert_called_once_with() |
4074 | |
4075 | def test_create_creates_create_task(self): |
4076 | with unittest.mock.patch('libertine.service.container.apt.AptCache') as MockCache: |
4077 | - c = container.Container('palpatine', self._config, self._connection, lambda task: task) |
4078 | + c = container.Container('palpatine', self._config, self._monitor, self._client, lambda task: task) |
4079 | with unittest.mock.patch('libertine.service.container.CreateTask') as MockCreateTask: |
4080 | c.create('Emperor Palpatine', 'zesty', 'lxd', False) |
4081 | MockCreateTask.assert_called_once_with('palpatine', 'Emperor Palpatine', 'zesty', 'lxd', False, |
4082 | - self._config, unittest.mock.ANY, self._connection, unittest.mock.ANY) |
4083 | + self._config, unittest.mock.ANY, self._monitor, self._client, unittest.mock.ANY) |
4084 | MockCreateTask.return_value.start.assert_called_once_with() |
4085 | |
4086 | def test_create_only_calls_once_when_unfinished(self): |
4087 | with unittest.mock.patch('libertine.service.container.apt.AptCache') as MockCache: |
4088 | - c = container.Container('palpatine', self._config, self._connection, lambda task: task) |
4089 | + c = container.Container('palpatine', self._config, self._monitor, self._client, lambda task: task) |
4090 | with unittest.mock.patch('libertine.service.container.CreateTask') as MockCreateTask: |
4091 | c.create('Emperor Palpatine', 'zesty', 'lxd', False) |
4092 | c.create('Emperor Palpatine', 'zesty', 'lxd', False) |
4093 | c.create('Emperor Palpatine', 'zesty', 'lxd', False) |
4094 | MockCreateTask.assert_called_once_with('palpatine', 'Emperor Palpatine', 'zesty', 'lxd', False, |
4095 | - self._config, unittest.mock.ANY, self._connection, unittest.mock.ANY) |
4096 | + self._config, unittest.mock.ANY, self._monitor, self._client, unittest.mock.ANY) |
4097 | MockCreateTask.return_value.start.assert_called_once_with() |
4098 | |
4099 | def test_destroy_creates_destroy_task(self): |
4100 | with unittest.mock.patch('libertine.service.container.apt.AptCache') as MockCache: |
4101 | - c = container.Container('palpatine', self._config, self._connection, lambda task: task) |
4102 | + c = container.Container('palpatine', self._config, self._monitor, self._client, lambda task: task) |
4103 | with unittest.mock.patch('libertine.service.container.DestroyTask') as MockDestroyTask: |
4104 | c.destroy() |
4105 | - MockDestroyTask.assert_called_once_with('palpatine', self._config, unittest.mock.ANY, self._connection, unittest.mock.ANY) |
4106 | + MockDestroyTask.assert_called_once_with('palpatine', self._config, unittest.mock.ANY, self._monitor, self._client, unittest.mock.ANY) |
4107 | MockDestroyTask.return_value.start.assert_called_once_with() |
4108 | |
4109 | def test_destroy_only_calls_once_when_unfinished(self): |
4110 | with unittest.mock.patch('libertine.service.container.apt.AptCache') as MockCache: |
4111 | - c = container.Container('palpatine', self._config, self._connection, lambda task: task) |
4112 | + c = container.Container('palpatine', self._config, self._monitor, self._client, lambda task: task) |
4113 | with unittest.mock.patch('libertine.service.container.DestroyTask') as MockDestroyTask: |
4114 | c.destroy() |
4115 | c.destroy() |
4116 | c.destroy() |
4117 | - MockDestroyTask.assert_called_once_with('palpatine', self._config, unittest.mock.ANY, self._connection, unittest.mock.ANY) |
4118 | + MockDestroyTask.assert_called_once_with('palpatine', self._config, unittest.mock.ANY, self._monitor, self._client, unittest.mock.ANY) |
4119 | MockDestroyTask.return_value.start.assert_called_once_with() |
4120 | |
4121 | def test_update_creates_update_task(self): |
4122 | with unittest.mock.patch('libertine.service.container.apt.AptCache') as MockCache: |
4123 | - c = container.Container('palpatine', self._config, self._connection, lambda task: task) |
4124 | + c = container.Container('palpatine', self._config, self._monitor, self._client, lambda task: task) |
4125 | with unittest.mock.patch('libertine.service.container.UpdateTask') as MockUpdateTask: |
4126 | c.update() |
4127 | - MockUpdateTask.assert_called_once_with('palpatine', self._config, unittest.mock.ANY, self._connection, unittest.mock.ANY) |
4128 | + MockUpdateTask.assert_called_once_with('palpatine', self._config, unittest.mock.ANY, self._monitor, self._client, unittest.mock.ANY) |
4129 | MockUpdateTask.return_value.start.assert_called_once_with() |
4130 | |
4131 | def test_update_only_calls_once_when_unfinished(self): |
4132 | with unittest.mock.patch('libertine.service.container.apt.AptCache') as MockCache: |
4133 | - c = container.Container('palpatine', self._config, self._connection, lambda task: task) |
4134 | + c = container.Container('palpatine', self._config, self._monitor, self._client, lambda task: task) |
4135 | with unittest.mock.patch('libertine.service.container.UpdateTask') as MockUpdateTask: |
4136 | c.update() |
4137 | c.update() |
4138 | c.update() |
4139 | - MockUpdateTask.assert_called_once_with('palpatine', self._config, unittest.mock.ANY, self._connection, unittest.mock.ANY) |
4140 | + MockUpdateTask.assert_called_once_with('palpatine', self._config, unittest.mock.ANY, self._monitor, self._client, unittest.mock.ANY) |
4141 | MockUpdateTask.return_value.start.assert_called_once_with() |
4142 | |
4143 | def test_list_app_ids_creates_list_app_ids_task(self): |
4144 | with unittest.mock.patch('libertine.service.container.apt.AptCache') as MockCache: |
4145 | - c = container.Container('palpatine', self._config, self._connection, lambda task: task) |
4146 | + c = container.Container('palpatine', self._config, self._monitor, self._client, lambda task: task) |
4147 | with unittest.mock.patch('libertine.service.container.ListAppIdsTask') as MockListAppIdsTask: |
4148 | c.list_app_ids() |
4149 | - MockListAppIdsTask.assert_called_once_with('palpatine', self._config, self._connection, unittest.mock.ANY) |
4150 | + MockListAppIdsTask.assert_called_once_with('palpatine', self._config, self._monitor, self._client, unittest.mock.ANY) |
4151 | MockListAppIdsTask.return_value.start.assert_called_once_with() |
4152 | |
4153 | def test_removes_task_during_callback(self): |
4154 | with unittest.mock.patch('libertine.service.container.apt.AptCache') as MockCache: |
4155 | - c = container.Container('palpatine', self._config, self._connection, lambda task: task) |
4156 | + c = container.Container('palpatine', self._config, self._monitor, self._client, lambda task: task) |
4157 | with unittest.mock.patch('libertine.service.container.InstallTask') as MockInstallTask: |
4158 | MockInstallTask.return_value.package = 'force' |
4159 | c.install('force') |
4160 | @@ -176,7 +177,7 @@ |
4161 | self._container_id = None |
4162 | def callback(container): |
4163 | self._container_id = container.id |
4164 | - c = container.Container('palpatine', self._config, self._connection, callback) |
4165 | + c = container.Container('palpatine', self._config, self._monitor, self._client, callback) |
4166 | with unittest.mock.patch('libertine.service.container.InstallTask') as MockInstallTask: |
4167 | c.install('force') |
4168 | name, args, kwargs = MockInstallTask.mock_calls[0] |
4169 | |
4170 | === added file 'tests/unit/service/test_operations_monitor.py' |
4171 | --- tests/unit/service/test_operations_monitor.py 1970-01-01 00:00:00 +0000 |
4172 | +++ tests/unit/service/test_operations_monitor.py 2017-03-31 20:05:48 +0000 |
4173 | @@ -0,0 +1,146 @@ |
4174 | +# Copyright 2017 Canonical Ltd. |
4175 | +# |
4176 | +# This program is free software: you can redistribute it and/or modify it |
4177 | +# under the terms of the GNU General Public License version 3, as published |
4178 | +# by the Free Software Foundation. |
4179 | +# |
4180 | +# This program is distributed in the hope that it will be useful, but |
4181 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
4182 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
4183 | +# PURPOSE. See the GNU General Public License for more details. |
4184 | +# |
4185 | +# You should have received a copy of the GNU General Public License along |
4186 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
4187 | + |
4188 | +import unittest.mock |
4189 | +from unittest import TestCase |
4190 | +from libertine.service import operations_monitor, download |
4191 | + |
4192 | + |
4193 | +class TestOperationsMonitor(TestCase): |
4194 | + def setUp(self): |
4195 | + self._connection = unittest.mock.Mock() |
4196 | + |
4197 | + def test_new_operation_returns_some_id(self): |
4198 | + with unittest.mock.patch('dbus.service.Object'): |
4199 | + monitor = operations_monitor.OperationsMonitor(self._connection) |
4200 | + monitor._connection = self._connection |
4201 | + |
4202 | + with unittest.mock.patch('libertine.service.operations_monitor.download.Download') as MockDownload: |
4203 | + self.assertIsNotNone(monitor.new_operation()) |
4204 | + |
4205 | + def test_remove_connection(self): |
4206 | + with unittest.mock.patch('dbus.service.Object'): |
4207 | + monitor = operations_monitor.OperationsMonitor(self._connection) |
4208 | + monitor._connection = self._connection |
4209 | + |
4210 | + with unittest.mock.patch('libertine.service.operations_monitor.download.Download') as MockDownload: |
4211 | + monitor.remove_from_connection(monitor.new_operation()) |
4212 | + MockDownload.return_value.remove_from_connection.assert_called_once_with() |
4213 | + |
4214 | + def test_returns_done_for_operation(self): |
4215 | + with unittest.mock.patch('dbus.service.Object'): |
4216 | + monitor = operations_monitor.OperationsMonitor(self._connection) |
4217 | + monitor._connection = self._connection |
4218 | + |
4219 | + with unittest.mock.patch('libertine.service.operations_monitor.download.Download') as MockDownload: |
4220 | + MockDownload.return_value.done = True |
4221 | + self.assertTrue(monitor.done(monitor.new_operation())) |
4222 | + |
4223 | + MockDownload.return_value.done = False |
4224 | + self.assertFalse(monitor.done(monitor.new_operation())) |
4225 | + |
4226 | + # non-existent operation |
4227 | + self.assertFalse(monitor.done("123456")) |
4228 | + |
4229 | + def test_running_returns_download_state(self): |
4230 | + with unittest.mock.patch('dbus.service.Object'): |
4231 | + monitor = operations_monitor.OperationsMonitor(self._connection) |
4232 | + monitor._connection = self._connection |
4233 | + |
4234 | + with unittest.mock.patch('libertine.service.operations_monitor.download.Download') as MockDownload: |
4235 | + MockDownload.return_value.done = True |
4236 | + self.assertFalse(monitor.running(monitor.new_operation())) |
4237 | + |
4238 | + MockDownload.return_value.done = False |
4239 | + self.assertTrue(monitor.running(monitor.new_operation())) |
4240 | + |
4241 | + # non-existent operation |
4242 | + self.assertFalse(monitor.running("123456")) |
4243 | + |
4244 | + def test_result_returns_download_results(self): |
4245 | + with unittest.mock.patch('dbus.service.Object'): |
4246 | + monitor = operations_monitor.OperationsMonitor(self._connection) |
4247 | + monitor._connection = self._connection |
4248 | + |
4249 | + with unittest.mock.patch('libertine.service.operations_monitor.download.Download') as MockDownload: |
4250 | + MockDownload.return_value.result = "pokemongus" |
4251 | + self.assertEqual("pokemongus", monitor.result(monitor.new_operation())) |
4252 | + |
4253 | + # non-existent operation |
4254 | + self.assertEqual("", monitor.result("123456")) |
4255 | + |
4256 | + def test_last_error_returns_download_last_errors(self): |
4257 | + with unittest.mock.patch('dbus.service.Object'): |
4258 | + monitor = operations_monitor.OperationsMonitor(self._connection) |
4259 | + monitor._connection = self._connection |
4260 | + |
4261 | + with unittest.mock.patch('libertine.service.operations_monitor.download.Download') as MockDownload: |
4262 | + MockDownload.return_value.last_error = "pokemongus" |
4263 | + self.assertEqual("pokemongus", monitor.last_error(monitor.new_operation())) |
4264 | + |
4265 | + # non-existent operation |
4266 | + self.assertEqual("", monitor.last_error("123456")) |
4267 | + |
4268 | + def test_forwards_finished(self): |
4269 | + with unittest.mock.patch('dbus.service.Object'): |
4270 | + monitor = operations_monitor.OperationsMonitor(self._connection) |
4271 | + monitor._connection = self._connection |
4272 | + monitor._locations = [] |
4273 | + |
4274 | + with unittest.mock.patch('libertine.service.operations_monitor.download.Download') as MockDownload: |
4275 | + path = monitor.new_operation() |
4276 | + monitor.finished(path) |
4277 | + MockDownload.return_value.finished.assert_called_once_with(path) |
4278 | + |
4279 | + # test does not crash on empty |
4280 | + MockDownload.reset_mock() |
4281 | + monitor.finished("some/junk") |
4282 | + MockDownload.return_value.finished.assert_not_called() |
4283 | + |
4284 | + def test_forwards_error(self): |
4285 | + with unittest.mock.patch('dbus.service.Object'): |
4286 | + monitor = operations_monitor.OperationsMonitor(self._connection) |
4287 | + monitor._connection = self._connection |
4288 | + monitor._locations = [] |
4289 | + |
4290 | + with unittest.mock.patch('libertine.service.operations_monitor.download.Download') as MockDownload: |
4291 | + path = monitor.new_operation() |
4292 | + monitor.error(path, "something messed up") |
4293 | + MockDownload.return_value.error.assert_called_once_with("something messed up") |
4294 | + |
4295 | + # test does not crash on empty |
4296 | + MockDownload.reset_mock() |
4297 | + monitor.error("some/junk", "something messed up") |
4298 | + MockDownload.return_value.error.assert_not_called() |
4299 | + |
4300 | + def test_forwards_data(self): |
4301 | + with unittest.mock.patch('dbus.service.Object'): |
4302 | + monitor = operations_monitor.OperationsMonitor(self._connection) |
4303 | + monitor._connection = self._connection |
4304 | + monitor._locations = [] |
4305 | + |
4306 | + with unittest.mock.patch('libertine.service.operations_monitor.download.Download') as MockDownload: |
4307 | + path = monitor.new_operation() |
4308 | + monitor.data(path, "some of that gud data") |
4309 | + MockDownload.return_value.data.assert_called_once_with("some of that gud data") |
4310 | + |
4311 | + # test does not crash on empty |
4312 | + MockDownload.reset_mock() |
4313 | + monitor.data("some/junk", "some of that gud data") |
4314 | + MockDownload.return_value.data.assert_not_called() |
4315 | + |
4316 | + |
4317 | + |
4318 | +if __name__ == '__main__': |
4319 | + unittest.main() |
4320 | |
4321 | === modified file 'tests/unit/service/test_task_dispatcher.py' |
4322 | --- tests/unit/service/test_task_dispatcher.py 2017-02-07 12:35:48 +0000 |
4323 | +++ tests/unit/service/test_task_dispatcher.py 2017-03-31 20:05:48 +0000 |
4324 | @@ -20,9 +20,10 @@ |
4325 | class TestTaskDispatcher(TestCase): |
4326 | def setUp(self): |
4327 | self._connection = unittest.mock.Mock() |
4328 | + self._client = unittest.mock.Mock() |
4329 | self._config_patcher = unittest.mock.patch('libertine.service.task_dispatcher.libertine.ContainersConfig.ContainersConfig') |
4330 | self._config_patcher.start() |
4331 | - self._dispatcher = task_dispatcher.TaskDispatcher(self._connection) |
4332 | + self._dispatcher = task_dispatcher.TaskDispatcher(self._connection, self._client) |
4333 | |
4334 | def tearDown(self): |
4335 | self._config_patcher.stop() |
4336 | @@ -90,20 +91,20 @@ |
4337 | self._dispatcher.list_app_ids('palpatine') |
4338 | self._dispatcher.list_app_ids('palpatine') |
4339 | self._dispatcher.list_app_ids('palpatine') |
4340 | - MockContainer.assert_called_once_with('palpatine', unittest.mock.ANY, self._connection, unittest.mock.ANY) |
4341 | + MockContainer.assert_called_once_with('palpatine', unittest.mock.ANY, self._connection, self._client, unittest.mock.ANY) |
4342 | |
4343 | def test_container_callback_removes_container(self): |
4344 | with unittest.mock.patch('libertine.service.task_dispatcher.Container') as MockContainer: |
4345 | c = MockContainer.return_value |
4346 | c.id = 'palpatine' |
4347 | self._dispatcher.list_app_ids('palpatine') |
4348 | - MockContainer.assert_called_once_with('palpatine', unittest.mock.ANY, self._connection, unittest.mock.ANY) |
4349 | + MockContainer.assert_called_once_with('palpatine', unittest.mock.ANY, self._connection, self._client, unittest.mock.ANY) |
4350 | name, args, kwargs = MockContainer.mock_calls[0] |
4351 | args[len(args)-1](MockContainer.return_value) |
4352 | self._dispatcher.list_app_ids('palpatine') |
4353 | MockContainer.assert_has_calls([ # verify container constructed twice |
4354 | - unittest.mock.call('palpatine', unittest.mock.ANY, self._connection, unittest.mock.ANY), |
4355 | - unittest.mock.call('palpatine', unittest.mock.ANY, self._connection, unittest.mock.ANY) |
4356 | + unittest.mock.call('palpatine', unittest.mock.ANY, self._connection, self._client, unittest.mock.ANY), |
4357 | + unittest.mock.call('palpatine', unittest.mock.ANY, self._connection, self._client, unittest.mock.ANY) |
4358 | ], any_order=True) |
4359 | |
4360 | def test_container_info_creates_container_info_task(self): |
4361 | |
4362 | === modified file 'tools/libertine-container-manager' |
4363 | --- tools/libertine-container-manager 2017-03-03 18:34:34 +0000 |
4364 | +++ tools/libertine-container-manager 2017-03-31 20:05:48 +0000 |
4365 | @@ -24,6 +24,10 @@ |
4366 | import sys |
4367 | import re |
4368 | |
4369 | +import gettext |
4370 | +gettext.textdomain('libertine') |
4371 | +_ = gettext.gettext |
4372 | + |
4373 | from libertine import ContainerRunning, LibertineContainer |
4374 | from libertine.ContainersConfig import ContainersConfig |
4375 | from libertine.HostInfo import HostInfo |
4376 | @@ -35,6 +39,16 @@ |
4377 | self.containers_config = ContainersConfig() |
4378 | self.host_info = HostInfo() |
4379 | |
4380 | + |
4381 | + def _container(self, container_id): |
4382 | + try: |
4383 | + return LibertineContainer(container_id, self.containers_config) |
4384 | + except ImportError as e: |
4385 | + container_type = self.containers_config.get_container_type(container_id) |
4386 | + libertine.utils.get_logger().error(_("Backend for container '{id}' not installed. Install " |
4387 | + "'python3-libertine-{type}' and try again.").format(id=container_id, type=container_type)) |
4388 | + sys.exit(1) |
4389 | + |
4390 | def _get_updated_locale(self, container_id): |
4391 | host_locale = self.host_info.get_host_locale() |
4392 | |
4393 | @@ -99,16 +113,18 @@ |
4394 | |
4395 | try: |
4396 | self.containers_config.update_container_locale(args.id, self.host_info.get_host_locale()) |
4397 | - container = LibertineContainer(args.id) |
4398 | - self.containers_config.update_container_install_status(args.id, "installing") |
4399 | - if not container.create_libertine_container(password, args.multiarch): |
4400 | - libertine.utils.get_logger().error("Failed to create container") |
4401 | - self.containers_config.delete_container(args.id) |
4402 | - sys.exit(1) |
4403 | + container = LibertineContainer(args.id, self.containers_config) |
4404 | + try: |
4405 | + self.containers_config.update_container_install_status(args.id, "installing") |
4406 | + if not container.create_libertine_container(password, args.multiarch): |
4407 | + libertine.utils.get_logger().error("Failed to create container") |
4408 | + self.containers_config.delete_container(args.id) |
4409 | + sys.exit(1) |
4410 | + except Exception as e: |
4411 | + container.destroy_libertine_container(force=True) |
4412 | + raise |
4413 | except Exception as e: |
4414 | libertine.utils.get_logger().error("Failed to create container: '{}'".format(str(e))) |
4415 | - if container: |
4416 | - container.destroy_libertine_container(force=True) |
4417 | |
4418 | self.containers_config.delete_container(args.id) |
4419 | sys.exit(1) |
4420 | @@ -130,7 +146,7 @@ |
4421 | |
4422 | def destroy(self, args): |
4423 | container_id = self.containers_config.check_container_id(args.id) |
4424 | - container = LibertineContainer(container_id, self.containers_config) |
4425 | + container = self._container(container_id) |
4426 | |
4427 | self.destroy_container(container, args.force) |
4428 | |
4429 | @@ -138,11 +154,14 @@ |
4430 | |
4431 | def install_package(self, args): |
4432 | container_id = self.containers_config.check_container_id(args.id) |
4433 | - container = LibertineContainer(container_id, self.containers_config) |
4434 | + container = self._container(container_id) |
4435 | failure = False |
4436 | |
4437 | with ContainerRunning(container.container): |
4438 | for i, pkg in enumerate(args.package): |
4439 | + if not pkg: |
4440 | + continue |
4441 | + |
4442 | is_debian_package = pkg.endswith('.deb') |
4443 | |
4444 | if is_debian_package: |
4445 | @@ -193,11 +212,14 @@ |
4446 | |
4447 | def remove_package(self, args): |
4448 | container_id = self.containers_config.check_container_id(args.id) |
4449 | - container = LibertineContainer(container_id) |
4450 | + container = self._container(container_id) |
4451 | failure = False |
4452 | |
4453 | with ContainerRunning(container.container): |
4454 | for pkg in args.package: |
4455 | + if not pkg: |
4456 | + continue |
4457 | + |
4458 | if self.containers_config.get_package_install_status(container_id, pkg) != 'installed': |
4459 | libertine.utils.get_logger().error("Package \'%s\' is not installed." % pkg) |
4460 | failure = True |
4461 | @@ -216,8 +238,8 @@ |
4462 | |
4463 | def search_cache(self, args): |
4464 | container_id = self.containers_config.check_container_id(args.id) |
4465 | + container = self._container(container_id) |
4466 | |
4467 | - container = LibertineContainer(container_id) |
4468 | if container.search_package_cache(args.search_string) is not 0: |
4469 | libertine.utils.get_logger().error("Search for '{}' in container '{}' exited with non-zero status" |
4470 | .format(args.id, args.search_string)) |
4471 | @@ -225,10 +247,10 @@ |
4472 | |
4473 | def update(self, args): |
4474 | container_id = self.containers_config.check_container_id(args.id) |
4475 | + container = self._container(container_id) |
4476 | + |
4477 | new_locale = self._get_updated_locale(container_id) |
4478 | |
4479 | - container = LibertineContainer(container_id) |
4480 | - |
4481 | if not container.update_libertine_container(new_locale): |
4482 | sys.exit(1) |
4483 | |
4484 | @@ -242,7 +264,7 @@ |
4485 | def list_apps(self, args): |
4486 | container_id = self.containers_config.check_container_id(args.id) |
4487 | |
4488 | - app_ids = LibertineContainer(container_id).list_app_ids() |
4489 | + app_ids = self._container(container_id).list_app_ids() |
4490 | if args.json: |
4491 | print(json.dumps(app_ids)) |
4492 | else: |
4493 | @@ -252,7 +274,7 @@ |
4494 | def exec(self, args): |
4495 | container_id = self.containers_config.check_container_id(args.id) |
4496 | |
4497 | - container = LibertineContainer(container_id) |
4498 | + container = self._container(container_id) |
4499 | |
4500 | if not container.exec_command(args.command): |
4501 | sys.exit(1) |
4502 | @@ -269,7 +291,7 @@ |
4503 | |
4504 | def configure(self, args): |
4505 | container_id = self.containers_config.check_container_id(args.id) |
4506 | - container = LibertineContainer(container_id) |
4507 | + container = self._container(container_id) |
4508 | |
4509 | if args.multiarch and self.host_info.get_host_architecture() == 'amd64': |
4510 | multiarch = 'disabled' |
4511 | @@ -377,7 +399,7 @@ |
4512 | def fix_integrity(self, args): |
4513 | if 'containerList' in self.containers_config.container_list: |
4514 | for container in self.containers_config.container_list['containerList']: |
4515 | - libertine_container = LibertineContainer(container['id']) |
4516 | + libertine_container = self._container(container['id']) |
4517 | |
4518 | if 'installStatus' not in container or container['installStatus'] == 'removing': |
4519 | self.destroy_container(libertine_container) |
4520 | @@ -411,7 +433,7 @@ |
4521 | libertine.utils.get_logger().error("The restart subcommand is only valid for LXC and LXD type containers.") |
4522 | sys.exit(1) |
4523 | |
4524 | - container = LibertineContainer(container_id) |
4525 | + container = self._container(container_id) |
4526 | |
4527 | container.restart_libertine_container() |
4528 | |
4529 | |
4530 | === modified file 'tools/libertine-launch' |
4531 | --- tools/libertine-launch 2017-02-23 18:18:29 +0000 |
4532 | +++ tools/libertine-launch 2017-03-31 20:05:48 +0000 |
4533 | @@ -19,6 +19,10 @@ |
4534 | import os |
4535 | import sys |
4536 | |
4537 | +import gettext |
4538 | +gettext.textdomain('libertine') |
4539 | +_ = gettext.gettext |
4540 | + |
4541 | from libertine import launcher |
4542 | |
4543 | def main(): |
4544 | @@ -30,8 +34,14 @@ |
4545 | utils.get_logger().error("No container with id '%s'" % config.container_id) |
4546 | sys.exit(1) |
4547 | |
4548 | - from libertine import LibertineContainer |
4549 | - container = LibertineContainer(container_id=config.container_id) |
4550 | + try: |
4551 | + from libertine import LibertineContainer |
4552 | + container = LibertineContainer(container_id=config.container_id) |
4553 | + except ImportError as e: |
4554 | + container_type = self.containers_config.get_container_type(container_id) |
4555 | + libertine.utils.get_logger().error(_("Backend for container '{id}' not installed. Install " |
4556 | + "'python3-libertine-{type}' and try again.").format(id=config.container_id, type=container_type)) |
4557 | + sys.exit(1) |
4558 | else: |
4559 | from libertine import NoContainer |
4560 | |
4561 | |
4562 | === modified file 'tools/libertine-lxd-setup' |
4563 | --- tools/libertine-lxd-setup 2017-01-06 15:32:00 +0000 |
4564 | +++ tools/libertine-lxd-setup 2017-03-31 20:05:48 +0000 |
4565 | @@ -20,20 +20,43 @@ |
4566 | echo ${idmap} | tee -a /etc/subuid /etc/subgid |
4567 | fi |
4568 | |
4569 | -# find the right lxc command |
4570 | -lxc=`which lxc` |
4571 | -if [ -z "${lxc}" ]; then |
4572 | - if [ -n `which lxd.lxc` ]; then |
4573 | - lxc=`which lxd.lxc` |
4574 | - else |
4575 | - echo "No lxc command found on this system." |
4576 | - exit 1 |
4577 | - fi |
4578 | -fi |
4579 | - |
4580 | -# Run lxd init if there are no containers already on the system |
4581 | -if [ 2 -ge `${lxc} list | grep -e "^+" | wc -l` ]; then |
4582 | - lxd init |
4583 | + |
4584 | +lxc profile device list default | grep "nic\|disk" > /dev/null |
4585 | +requires_init=$? |
4586 | +version=`lxd --version` |
4587 | +if [ ${version%%.*} -lt 2 -o ${version#*.} -lt 3 ]; then |
4588 | + if [ "$requires_init" -ne "0" ]; then |
4589 | + # Running lxd init without args to force the caller to pick the options |
4590 | + lxd init |
4591 | + fi |
4592 | +else |
4593 | + if [ "$requires_init" -ne "0" ]; then |
4594 | + # Running lxd init with auto flag to choose most of the right options |
4595 | + lxd init --auto |
4596 | + fi |
4597 | + |
4598 | + # networking |
4599 | + ifconfig lxdbr0 > /dev/null |
4600 | + bridge_exists=$? |
4601 | + |
4602 | + lxc network show lxdbr0 > /dev/null |
4603 | + network_exists=$? |
4604 | + |
4605 | + # no managed network, no bridge means we need to create a managed network |
4606 | + if [ "$bridge_exists" -ne "0" ]; then |
4607 | + if [ "$network_exists" -ne "0" ]; then |
4608 | + lxc network create lxdbr0 |
4609 | + |
4610 | + network_name=`lxc profile device get default eth0 parent` |
4611 | + if [ "$network_name" != "lxdbr0" ]; then |
4612 | + lxc network attach-profile lxdbr0 default eth0 |
4613 | + fi |
4614 | + else |
4615 | + # a managed network and no bridge means the bridge should be recreated |
4616 | + # when we restart the lxd service |
4617 | + service lxd restart |
4618 | + fi |
4619 | + fi |
4620 | fi |
4621 | |
4622 | mkdir -p /home/$USERNAME/.config/lxc |
4623 | |
4624 | === modified file 'tools/libertined' |
4625 | --- tools/libertined 2017-02-15 21:12:37 +0000 |
4626 | +++ tools/libertined 2017-03-31 20:05:48 +0000 |
4627 | @@ -1,7 +1,7 @@ |
4628 | #!/usr/bin/python3 |
4629 | # -*- coding: utf-8 -*- |
4630 | |
4631 | -# Copyright 2016 Canonical Ltd. |
4632 | +# Copyright 2016-2017 Canonical Ltd. |
4633 | # |
4634 | # This program is free software: you can redistribute it and/or modify |
4635 | # it under the terms of the GNU General Public License as published by |
4636 | @@ -15,13 +15,17 @@ |
4637 | # You should have received a copy of the GNU General Public License |
4638 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
4639 | |
4640 | + |
4641 | import argparse |
4642 | +import dbus |
4643 | +import os |
4644 | import signal |
4645 | import sys |
4646 | -import os |
4647 | -from gi.repository import GLib, GObject |
4648 | + |
4649 | +from dbus.mainloop.glib import DBusGMainLoop |
4650 | +from gi.repository import GLib |
4651 | from libertine import utils |
4652 | -from libertine.service import manager |
4653 | +from libertine.service import constants, operations, container_control, container_control_client |
4654 | |
4655 | |
4656 | class OutputRedirector(object): |
4657 | @@ -116,6 +120,7 @@ |
4658 | signal.SIGTERM, |
4659 | self.sigterm, |
4660 | None) |
4661 | + DBusGMainLoop(set_as_default=True) |
4662 | self.loop = GLib.MainLoop() |
4663 | |
4664 | def sigterm(self, code): |
4665 | @@ -135,13 +140,29 @@ |
4666 | config = Config() |
4667 | |
4668 | with OutputRedirector(config): |
4669 | - utils.get_logger().info("Starting libertine service") |
4670 | - service = manager.Manager() |
4671 | + utils.get_logger().info("Initializing libertined...") |
4672 | loop = Loop() |
4673 | - try: |
4674 | + |
4675 | + try: |
4676 | + bus_name = dbus.service.BusName(constants.SERVICE_NAME, |
4677 | + bus=dbus.SessionBus(), |
4678 | + do_not_queue=True) |
4679 | + except dbus.exceptions.NameExistsException: |
4680 | + utils.get_logger().warning("service is already running") |
4681 | + raise |
4682 | + |
4683 | + client = container_control_client.ContainerControlClient() |
4684 | + manager = operations.Operations(bus_name, client) |
4685 | + container_control.ContainerControl(manager.connection, client) |
4686 | + |
4687 | + try: |
4688 | + utils.get_logger().info("libertined ready") |
4689 | loop.run() |
4690 | except KeyboardInterrupt: |
4691 | utils.get_logger().debug("keyboard interrupt received") |
4692 | + except Exception as e: |
4693 | + utils.get_logger().error("Unexpected exception occurred: '{}'".format(str(e))) |
4694 | + finally: |
4695 | loop.shutdown() |
4696 | |
4697 |
Ok, +1