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