Merge lp:~ahasenack/landscape-client/landscape-client-12.05-0ubuntu1-quantal into lp:ubuntu/quantal/landscape-client
- landscape-client-12.05-0ubuntu1-quantal
- Merge into quantal
Proposed by
Andreas Hasenack
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 46 | ||||
Proposed branch: | lp:~ahasenack/landscape-client/landscape-client-12.05-0ubuntu1-quantal | ||||
Merge into: | lp:ubuntu/quantal/landscape-client | ||||
Diff against target: |
5384 lines (+762/-3332) 39 files modified
debian/changelog (+41/-0) debian/control (+6/-4) debian/landscape-client.templates (+1/-1) debian/landscape-common.templates (+1/-1) debian/po/templates.pot (+28/-6) debian/rules (+9/-6) debian/source.lintian-overrides (+16/-0) debian/source/format (+1/-0) debian/watch (+2/-0) landscape/__init__.py (+6/-2) landscape/constants.py (+3/-2) landscape/deployment.py (+1/-1) landscape/manager/aptsources.py (+2/-2) landscape/manager/tests/test_aptsources.py (+1/-1) landscape/monitor/packagemonitor.py (+1/-1) landscape/package/changer.py (+37/-119) landscape/package/facade.py (+159/-494) landscape/package/interface.py (+0/-84) landscape/package/releaseupgrader.py (+2/-2) landscape/package/reporter.py (+13/-110) landscape/package/skeleton.py (+0/-48) landscape/package/store.py (+0/-37) landscape/package/taskhandler.py (+4/-8) landscape/package/tests/helpers.py (+0/-39) landscape/package/tests/test_changer.py (+202/-521) landscape/package/tests/test_facade.py (+88/-735) landscape/package/tests/test_interface.py (+0/-34) landscape/package/tests/test_releaseupgrader.py (+2/-2) landscape/package/tests/test_reporter.py (+94/-695) landscape/package/tests/test_skeleton.py (+28/-87) landscape/package/tests/test_store.py (+3/-103) landscape/package/tests/test_taskhandler.py (+4/-48) landscape/ui/view/tests/test_configuration.py (+3/-0) landscape/ui/view/ui/landscape-client-settings.glade (+1/-1) landscape/watchdog.py (+1/-1) po/fr.po (+1/-1) po/landscape-client.pot (+1/-1) smart-update/Makefile (+0/-6) smart-update/smart-update.c (+0/-129) |
||||
To merge this branch: | bzr merge lp:~ahasenack/landscape-client/landscape-client-12.05-0ubuntu1-quantal | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu branches | Pending | ||
Review via email: mp+108569@code.launchpad.net |
Commit message
Description of the change
This updates landscape-client in quantal to upstream version 12.05.
Upstream now removes debian/* from the tarball, so this branch also addresses that. For details, please see the debian/changelog new entries.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'debian/changelog' |
2 | --- debian/changelog 2012-03-28 10:59:58 +0000 |
3 | +++ debian/changelog 2012-06-04 14:08:28 +0000 |
4 | @@ -1,3 +1,44 @@ |
5 | +landscape-client (12.05-0ubuntu1) quantal; urgency=low |
6 | + |
7 | + * New upstream release 12.05 (r561 in trunk) (LP: #1004678). |
8 | + * Make all subpackages that depend on each other require the exact same |
9 | + version, instead of >= $version. |
10 | + * Added python-gi to client depends starting natty. |
11 | + * Make change-packages also handle package holds (LP: #972489). |
12 | + * Fix typo in glade file (LP: #983096). |
13 | + * Tidy up apt facade (LP: #985493). |
14 | + * Remove SmartFacade and its tests, no longer used (LP: #996269). |
15 | + * Remove check for apt version, since we won't release this for |
16 | + Hardy where that check matters (LP: #996837). |
17 | + * Remove methods that were smart specific. We no longer use smart |
18 | + (LP: #996841). |
19 | + * Remove smart-update helper binary. We no longer use smart |
20 | + (LP: #997408). |
21 | + * Remove test-mixins that were useful only during the apt-to-smart |
22 | + code migration. Now with smart gone, they are no longer necessary |
23 | + (LP: #997760). |
24 | + * Build the packages from precise onward, not just precise. |
25 | + * Assorted packaging fixes: |
26 | + - Switched to format 3.0 (quilt). |
27 | + - Added source lintian overrides, with comments. |
28 | + - Updated debian/rules: |
29 | + - Added build-arch and build-indep dummy target. |
30 | + - Build the GUI packages from precise onwards, and not just on precise. |
31 | + - Re-enable dh_lintian. |
32 | + - Strip the binaries (dh_strip), and also call dh_shlibdeps for the |
33 | + automatic shlibs dependency. |
34 | + - Added python-gi from natty onwards. |
35 | + - Used __Choices instead of _Choices in landscape-common.templates, it's |
36 | + better for translators. |
37 | + - Updated standard version to 3.8.2, the version from Lucid (oldest one |
38 | + we support) |
39 | + - Added shlibs depends. |
40 | + - Dropped deprecated ${Source-Version} and replaced it with |
41 | + ${binary:Version} |
42 | + - Require exact version of the sibling package instead of >=. |
43 | + |
44 | + -- Andreas Hasenack <andreas@canonical.com> Fri, 01 Jun 2012 17:48:43 -0300 |
45 | + |
46 | landscape-client (12.04.3-0ubuntu1) precise; urgency=low |
47 | |
48 | * Warn on unicode entry into settings UI (LP: #956612). |
49 | |
50 | === modified file 'debian/control' |
51 | --- debian/control 2012-03-22 10:10:39 +0000 |
52 | +++ debian/control 2012-06-04 14:08:28 +0000 |
53 | @@ -4,12 +4,13 @@ |
54 | Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> |
55 | XSBC-Original-Maintainer: Landscape Team <landscape-team@canonical.com> |
56 | Build-Depends: debhelper (>= 5), po-debconf, python-dev, lsb-release, gawk, python-twisted-core, python-distutils-extra |
57 | -Standards-Version: 3.8.0 |
58 | +Standards-Version: 3.8.2 |
59 | XS-Python-Version: >= 2.4, << 2.8 |
60 | |
61 | Package: landscape-common |
62 | Architecture: any |
63 | Depends: ${python:Depends}, ${misc:Depends}, ${extra:Depends}, |
64 | + ${shlibs:Depends}, |
65 | python-gnupginterface, |
66 | python-twisted-core, |
67 | python-apt, |
68 | @@ -33,9 +34,10 @@ |
69 | Package: landscape-client |
70 | Architecture: any |
71 | Depends: ${python:Depends}, ${misc:Depends}, ${extra:Depends}, |
72 | + ${shlibs:Depends}, |
73 | python-twisted-web, |
74 | python-twisted-names, |
75 | - landscape-common (>= ${Source-Version}) |
76 | + landscape-common (= ${binary:Version}) |
77 | Suggests: ${extra:Suggests} |
78 | Description: The Landscape administration system client |
79 | Landscape is a web-based tool for managing Ubuntu systems. This |
80 | @@ -48,8 +50,8 @@ |
81 | Package: landscape-client-ui |
82 | Architecture: any |
83 | Depends: ${python:Depends}, ${misc:Depends}, |
84 | - landscape-client (>= ${Source-Version}), |
85 | - landscape-client-ui-install (>= ${Source-Version}), |
86 | + landscape-client (= ${binary:Version}), |
87 | + landscape-client-ui-install (= ${binary:Version}), |
88 | python-gi, |
89 | python-dbus, |
90 | policykit-1, |
91 | |
92 | === modified file 'debian/landscape-client.templates' |
93 | --- debian/landscape-client.templates 2012-03-19 09:33:34 +0000 |
94 | +++ debian/landscape-client.templates 2012-06-04 14:08:28 +0000 |
95 | @@ -64,7 +64,7 @@ |
96 | Template: landscape-client/tags |
97 | Type: string |
98 | Default: |
99 | -_Description: Initial tags for first registration |
100 | +_Description: Initial tags for first registration: |
101 | Comma separated list of tags which will be assigned to this computer on its |
102 | first registration. Once the machine is registered, these tags can only be |
103 | changed using the Landscape server. |
104 | |
105 | === modified file 'debian/landscape-common.templates' |
106 | --- debian/landscape-common.templates 2012-03-19 09:33:34 +0000 |
107 | +++ debian/landscape-common.templates 2012-06-04 14:08:28 +0000 |
108 | @@ -6,7 +6,7 @@ |
109 | # try to keep below ~71 characters. |
110 | # DO NOT USE commas (,) in Choices translations otherwise |
111 | # this will break the choices shown to users |
112 | -_Choices: Do not display sysinfo on login, Cache sysinfo in /etc/motd, Run sysinfo on every login |
113 | +__Choices: Do not display sysinfo on login, Cache sysinfo in /etc/motd, Run sysinfo on every login |
114 | Default: Cache sysinfo in /etc/motd |
115 | _Description: landscape-sysinfo configuration: |
116 | Landscape includes a tool and a set of modules that can display |
117 | |
118 | === modified file 'debian/po/templates.pot' |
119 | --- debian/po/templates.pot 2012-03-19 09:33:34 +0000 |
120 | +++ debian/po/templates.pot 2012-06-04 14:08:28 +0000 |
121 | @@ -6,9 +6,9 @@ |
122 | #, fuzzy |
123 | msgid "" |
124 | msgstr "" |
125 | -"Project-Id-Version: PACKAGE VERSION\n" |
126 | +"Project-Id-Version: landscape-client\n" |
127 | "Report-Msgid-Bugs-To: landscape-client@packages.debian.org\n" |
128 | -"POT-Creation-Date: 2012-03-07 17:07+0100\n" |
129 | +"POT-Creation-Date: 2012-06-01 18:35-0300\n" |
130 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
131 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
132 | "Language-Team: LANGUAGE <LL@li.org>\n" |
133 | @@ -152,7 +152,7 @@ |
134 | #. Type: string |
135 | #. Description |
136 | #: ../landscape-client.templates:11001 |
137 | -msgid "Initial tags for first registration" |
138 | +msgid "Initial tags for first registration:" |
139 | msgstr "" |
140 | |
141 | #. Type: string |
142 | @@ -187,9 +187,31 @@ |
143 | #. DO NOT USE commas (,) in Choices translations otherwise |
144 | #. this will break the choices shown to users |
145 | #: ../landscape-common.templates:1001 |
146 | -msgid "" |
147 | -"Do not display sysinfo on login, Cache sysinfo in /etc/motd, Run sysinfo on " |
148 | -"every login" |
149 | +msgid "Do not display sysinfo on login" |
150 | +msgstr "" |
151 | + |
152 | +#. Type: select |
153 | +#. Choices |
154 | +#. Translators beware! the following three strings form a single |
155 | +#. Choices menu. - Every one of these strings has to fit in a standard |
156 | +#. 80 characters console, as the fancy screen setup takes up some space |
157 | +#. try to keep below ~71 characters. |
158 | +#. DO NOT USE commas (,) in Choices translations otherwise |
159 | +#. this will break the choices shown to users |
160 | +#: ../landscape-common.templates:1001 |
161 | +msgid "Cache sysinfo in /etc/motd" |
162 | +msgstr "" |
163 | + |
164 | +#. Type: select |
165 | +#. Choices |
166 | +#. Translators beware! the following three strings form a single |
167 | +#. Choices menu. - Every one of these strings has to fit in a standard |
168 | +#. 80 characters console, as the fancy screen setup takes up some space |
169 | +#. try to keep below ~71 characters. |
170 | +#. DO NOT USE commas (,) in Choices translations otherwise |
171 | +#. this will break the choices shown to users |
172 | +#: ../landscape-common.templates:1001 |
173 | +msgid "Run sysinfo on every login" |
174 | msgstr "" |
175 | |
176 | #. Type: select |
177 | |
178 | === modified file 'debian/rules' |
179 | --- debian/rules 2012-03-28 10:59:58 +0000 |
180 | +++ debian/rules 2012-06-04 14:08:28 +0000 |
181 | @@ -9,7 +9,7 @@ |
182 | endif |
183 | |
184 | dh_extra_flags = -plandscape-common -plandscape-client |
185 | -ifneq (,$(filter $(dist_release),precise)) |
186 | +ifeq (,$(filter $(dist_release),hardy lucid natty oneiric)) |
187 | # We want landscape-client-ui only from precise onward |
188 | dh_extra_flags += -plandscape-client-ui -plandscape-client-ui-install |
189 | endif |
190 | @@ -30,6 +30,10 @@ |
191 | landscape_common_substvars = debian/landscape-common.substvars |
192 | landscape_client_substvars = debian/landscape-client.substvars |
193 | |
194 | +build-arch: build |
195 | + |
196 | +build-indep: build |
197 | + |
198 | build: build-stamp |
199 | build-stamp: |
200 | dh_testdir |
201 | @@ -69,10 +73,7 @@ |
202 | # do nothing |
203 | # |
204 | binary-arch: build install |
205 | - # That's not present in Ubuntu releases we still support, so |
206 | - # we're just installing the lintian overrides file by hand |
207 | - # for now. |
208 | - #dh_lintian |
209 | + dh_lintian |
210 | dh_testdir |
211 | dh_testroot |
212 | dh_installdocs |
213 | @@ -82,8 +83,10 @@ |
214 | dh_installinit -- start 45 2 3 4 5 . stop 15 0 1 6 . |
215 | dh_installlogrotate |
216 | dh_installdebconf |
217 | + dh_strip |
218 | dh_compress |
219 | dh_fixperms |
220 | + dh_shlibdeps |
221 | |
222 | ifneq (,$(findstring $(dist_release),hardy)) |
223 | # We depend on bug-fixed versions of python-dbus and pycurl on hardy |
224 | @@ -100,7 +103,7 @@ |
225 | ifeq (,$(filter $(dist_release),hardy lucid)) |
226 | # Starting natty, no more hal or dbus |
227 | echo "extra:Depends=libpam-modules (>= 1.0.1-9ubuntu3)" >> $(landscape_common_substvars) |
228 | - echo "extra:Depends=python-pycurl, gir1.2-gudev-1.0 (>= 165-0ubuntu2)" >> $(landscape_client_substvars) |
229 | + echo "extra:Depends=python-pycurl, gir1.2-gudev-1.0 (>= 165-0ubuntu2), python-gi" >> $(landscape_client_substvars) |
230 | echo "extra:Suggests=python-dbus, hal" >> $(landscape_client_substvars) |
231 | endif |
232 | |
233 | |
234 | === added directory 'debian/source' |
235 | === added file 'debian/source.lintian-overrides' |
236 | --- debian/source.lintian-overrides 1970-01-01 00:00:00 +0000 |
237 | +++ debian/source.lintian-overrides 2012-06-04 14:08:28 +0000 |
238 | @@ -0,0 +1,16 @@ |
239 | +# we use dh_python or dh_python2 depending on the ubuntu release |
240 | +# the package is being built on, this is detected dynamically |
241 | +# in the rules file |
242 | +landscape-client source: dh_python-is-obsolete |
243 | + |
244 | +# the package has to build on lucid, where the standards version |
245 | +# is 3.8.2 |
246 | +landscape-client source: ancient-standards-version |
247 | + |
248 | +# it's a bug that should be fixed in quantal |
249 | +landscape-client source: unknown-field-in-dsc original-maintainer |
250 | + |
251 | +# this is only used in a very specific client upgrade from |
252 | +# the dbus to the amp version |
253 | +landscape-client: start-stop-daemon-in-maintainer-script postinst:130 |
254 | + |
255 | |
256 | === added file 'debian/source/format' |
257 | --- debian/source/format 1970-01-01 00:00:00 +0000 |
258 | +++ debian/source/format 2012-06-04 14:08:28 +0000 |
259 | @@ -0,0 +1,1 @@ |
260 | +3.0 (quilt) |
261 | |
262 | === added file 'debian/watch' |
263 | --- debian/watch 1970-01-01 00:00:00 +0000 |
264 | +++ debian/watch 2012-06-04 14:08:28 +0000 |
265 | @@ -0,0 +1,2 @@ |
266 | +version=3 |
267 | +https://launchpad.net/landscape-client/+download https://launchpad.net/landscape-client/[^/]+/[^/]+/\+download/landscape-client-(.*)\.tar\.(?:bz2|gz) |
268 | |
269 | === modified file 'landscape/__init__.py' |
270 | --- landscape/__init__.py 2012-03-28 10:59:58 +0000 |
271 | +++ landscape/__init__.py 2012-06-04 14:08:28 +0000 |
272 | @@ -1,7 +1,7 @@ |
273 | import sys |
274 | |
275 | DEBIAN_REVISION = "" |
276 | -UPSTREAM_VERSION = "12.04.2" |
277 | +UPSTREAM_VERSION = "12.05" |
278 | VERSION = "%s%s" % (UPSTREAM_VERSION, DEBIAN_REVISION) |
279 | |
280 | # The "server-api" field of outgoing messages will be set to this value, and |
281 | @@ -32,7 +32,11 @@ |
282 | # * Add "policy" field to "change-packages" |
283 | # * Add new "change-package-locks" client accepted message type. |
284 | # |
285 | -CLIENT_API = "3.3" |
286 | +# 3.4: |
287 | +# * Add "hold" field to "change-packages" |
288 | +# * Add "remove-hold" field to "change-packages" |
289 | + |
290 | +CLIENT_API = "3.4" |
291 | |
292 | from twisted.python import util |
293 | |
294 | |
295 | === modified file 'landscape/constants.py' |
296 | --- landscape/constants.py 2012-03-21 16:15:49 +0000 |
297 | +++ landscape/constants.py 2012-06-04 14:08:28 +0000 |
298 | @@ -12,6 +12,7 @@ |
299 | SUCCESS_RESULT = 1 |
300 | ERROR_RESULT = 100 |
301 | DEPENDENCY_ERROR_RESULT = 101 |
302 | +CLIENT_VERSION_ERROR_RESULT = 102 |
303 | POLICY_STRICT = 0 |
304 | POLICY_ALLOW_INSTALLS = 1 |
305 | POLICY_ALLOW_ALL_CHANGES = 2 |
306 | @@ -25,8 +26,8 @@ |
307 | # package reporter. |
308 | # 2. We lost some package data, for example by a deb archive becoming |
309 | # inaccessible for a while. The earliest we can reasonably assume that to be |
310 | -# resolved is in 60 minutes, when the smart cronjob runs again. |
311 | +# resolved is in 60 minutes, when the package reporter runs again. |
312 | |
313 | # So we'll give the problem one chance to resolve itself, by only waiting for |
314 | -# one run of smart update. |
315 | +# one run of apt-update. |
316 | UNKNOWN_PACKAGE_DATA_TIMEOUT = 70 * 60 |
317 | |
318 | === modified file 'landscape/deployment.py' |
319 | --- landscape/deployment.py 2012-03-19 09:33:34 +0000 |
320 | +++ landscape/deployment.py 2012-06-04 14:08:28 +0000 |
321 | @@ -282,7 +282,7 @@ |
322 | - C{quiet} (C{False}) |
323 | - C{log_dir} (C{"/var/log/landscape"}) |
324 | - C{log_level} (C{"info"}) |
325 | - - C{url} (C{"http://landcape.canonical.com/message-system"}) |
326 | + - C{url} (C{"http://landscape.canonical.com/message-system"}) |
327 | - C{ping_url} (C{"http://landscape.canonical.com/ping"}) |
328 | - C{ssl_public_key} |
329 | - C{server_autodiscover} (C{"false"}) |
330 | |
331 | === modified file 'landscape/manager/aptsources.py' |
332 | --- landscape/manager/aptsources.py 2012-03-19 09:33:34 +0000 |
333 | +++ landscape/manager/aptsources.py 2012-06-04 14:08:28 +0000 |
334 | @@ -156,8 +156,8 @@ |
335 | """Once the repositories are modified, trigger a reporter run.""" |
336 | reporter = find_reporter_command() |
337 | |
338 | - # Force a smart-update run, because the sources.list has changed |
339 | - args = ["--force-smart-update"] |
340 | + # Force an apt-update run, because the sources.list has changed |
341 | + args = ["--force-apt-update"] |
342 | |
343 | if self.registry.config.config is not None: |
344 | args.append("--config=%s" % self.registry.config.config) |
345 | |
346 | === modified file 'landscape/manager/tests/test_aptsources.py' |
347 | --- landscape/manager/tests/test_aptsources.py 2012-03-19 09:33:34 +0000 |
348 | +++ landscape/manager/tests/test_aptsources.py 2012-06-04 14:08:28 +0000 |
349 | @@ -388,7 +388,7 @@ |
350 | |
351 | def _run_process(command, args, env={}, path=None, uid=None, gid=None): |
352 | self.assertEqual(find_reporter_command(), command) |
353 | - self.assertEqual(["--force-smart-update", "--config=%s" % |
354 | + self.assertEqual(["--force-apt-update", "--config=%s" % |
355 | self.manager.config.config], args) |
356 | deferred.callback(("ok", "", 0)) |
357 | return deferred |
358 | |
359 | === modified file 'landscape/monitor/packagemonitor.py' |
360 | --- landscape/monitor/packagemonitor.py 2012-03-19 09:33:34 +0000 |
361 | +++ landscape/monitor/packagemonitor.py 2012-06-04 14:08:28 +0000 |
362 | @@ -58,7 +58,7 @@ |
363 | |
364 | class FakeFacade(object): |
365 | """ |
366 | - A fake facade to workaround the issue that the SmartFacade |
367 | + A fake facade to workaround the issue that the AptFacade |
368 | essentially allows only once instance per process. |
369 | """ |
370 | |
371 | |
372 | === modified file 'landscape/package/changer.py' |
373 | --- landscape/package/changer.py 2012-03-19 09:33:34 +0000 |
374 | +++ landscape/package/changer.py 2012-06-04 14:08:28 +0000 |
375 | @@ -9,8 +9,8 @@ |
376 | from twisted.internet.defer import maybeDeferred, succeed |
377 | |
378 | from landscape.constants import ( |
379 | - SUCCESS_RESULT, ERROR_RESULT, DEPENDENCY_ERROR_RESULT, POLICY_STRICT, |
380 | - POLICY_ALLOW_INSTALLS, POLICY_ALLOW_ALL_CHANGES, |
381 | + SUCCESS_RESULT, ERROR_RESULT, DEPENDENCY_ERROR_RESULT, |
382 | + POLICY_STRICT, POLICY_ALLOW_INSTALLS, POLICY_ALLOW_ALL_CHANGES, |
383 | UNKNOWN_PACKAGE_DATA_TIMEOUT) |
384 | |
385 | from landscape.lib.fs import create_file |
386 | @@ -18,7 +18,7 @@ |
387 | from landscape.package.taskhandler import ( |
388 | PackageTaskHandler, PackageTaskHandlerConfiguration, PackageTaskError, |
389 | run_task_handler) |
390 | -from landscape.manager.manager import FAILED, SUCCEEDED |
391 | +from landscape.manager.manager import FAILED |
392 | |
393 | |
394 | class UnknownPackageData(Exception): |
395 | @@ -38,7 +38,7 @@ |
396 | """Value object to hold the results of change packages operation. |
397 | |
398 | @ivar code: The result code of the requested changes. |
399 | - @ivar text: The output from Smart. |
400 | + @ivar text: The output from Apt. |
401 | @ivar installs: Possible additional packages that need to be installed |
402 | in order to fulfill the request. |
403 | @ivar removals: Possible additional packages that need to be removed |
404 | @@ -80,10 +80,6 @@ |
405 | # Nothing was done |
406 | return |
407 | |
408 | - # In order to let the reporter run smart-update cleanly, |
409 | - # we have to deinitialize Smart, so that the write lock |
410 | - # gets released |
411 | - self._facade.deinit() |
412 | if os.getuid() == 0: |
413 | os.setgid(grp.getgrnam("landscape").gr_gid) |
414 | os.setuid(pwd.getpwnam("landscape").pw_uid) |
415 | @@ -103,8 +99,6 @@ |
416 | return result.addErrback(self.unknown_package_data_error, task) |
417 | if message["type"] == "change-package-locks": |
418 | return self.handle_change_package_locks(message) |
419 | - if message["type"] == "change-package-holds": |
420 | - return self.handle_change_package_holds(message) |
421 | |
422 | def unknown_package_data_error(self, failure, task): |
423 | """Handle L{UnknownPackageData} data errors. |
424 | @@ -145,7 +139,7 @@ |
425 | self._facade.clear_channels() |
426 | |
427 | def init_channels(self, binaries=()): |
428 | - """Initialize the Smart channels as needed. |
429 | + """Initialize the Apt channels as needed. |
430 | |
431 | @param binaries: A possibly empty list of 3-tuples of the form |
432 | (hash, id, deb), holding the hash, the id and the content of |
433 | @@ -168,12 +162,16 @@ |
434 | |
435 | self._facade.ensure_channels_reloaded() |
436 | |
437 | - def mark_packages(self, upgrade=False, install=(), remove=(), reset=True): |
438 | + def mark_packages(self, upgrade=False, install=(), remove=(), |
439 | + hold=(), remove_hold=(), reset=True): |
440 | """Mark packages for upgrade, installation or removal. |
441 | |
442 | @param upgrade: If C{True} mark all installed packages for upgrade. |
443 | @param install: A list of package ids to be marked for installation. |
444 | @param remove: A list of package ids to be marked for removal. |
445 | + @param hold: A list of package ids to be marked for holding. |
446 | + @param remove_hold: A list of package ids to be marked to have a hold |
447 | + removed. |
448 | @param reset: If C{True} all existing marks will be reset. |
449 | """ |
450 | if reset: |
451 | @@ -182,16 +180,19 @@ |
452 | if upgrade: |
453 | self._facade.mark_global_upgrade() |
454 | |
455 | - for ids, mark_func in [(install, self._facade.mark_install), |
456 | - (remove, self._facade.mark_remove)]: |
457 | - for id in ids: |
458 | - hash = self._store.get_id_hash(id) |
459 | + for mark_function, mark_ids in [ |
460 | + (self._facade.mark_install, install), |
461 | + (self._facade.mark_remove, remove), |
462 | + (self._facade.mark_hold, hold), |
463 | + (self._facade.mark_remove_hold, remove_hold)]: |
464 | + for mark_id in mark_ids: |
465 | + hash = self._store.get_id_hash(mark_id) |
466 | if hash is None: |
467 | - raise UnknownPackageData(id) |
468 | + raise UnknownPackageData(mark_id) |
469 | package = self._facade.get_package_by_hash(hash) |
470 | if package is None: |
471 | raise UnknownPackageData(hash) |
472 | - mark_func(package) |
473 | + mark_function(package) |
474 | |
475 | def change_packages(self, policy): |
476 | """Perform the requested changes. |
477 | @@ -202,10 +203,9 @@ |
478 | @return: A L{ChangePackagesResult} holding the details about the |
479 | outcome of the requested changes. |
480 | """ |
481 | - # Delay importing these so that we don't import Smart unless |
482 | + # Delay importing these so that we don't import Apt unless |
483 | # we really need to. |
484 | - from landscape.package.facade import ( |
485 | - DependencyError, TransactionError, SmartError) |
486 | + from landscape.package.facade import DependencyError, TransactionError |
487 | |
488 | result = ChangePackagesResult() |
489 | count = 0 |
490 | @@ -213,7 +213,7 @@ |
491 | count += 1 |
492 | try: |
493 | result.text = self._facade.perform_changes() |
494 | - except (TransactionError, SmartError), exception: |
495 | + except TransactionError, exception: |
496 | result.code = ERROR_RESULT |
497 | result.text = exception.args[0] |
498 | except DependencyError, exception: |
499 | @@ -264,10 +264,11 @@ |
500 | """Handle a C{change-packages} message.""" |
501 | |
502 | self.init_channels(message.get("binaries", ())) |
503 | - self.mark_packages(message.get("upgrade-all", False), |
504 | - message.get("install", ()), |
505 | - message.get("remove", ())) |
506 | - |
507 | + self.mark_packages(upgrade=message.get("upgrade-all", False), |
508 | + install=message.get("install", ()), |
509 | + remove=message.get("remove", ()), |
510 | + hold=message.get("hold", ()), |
511 | + remove_hold=message.get("remove-hold", ())) |
512 | result = self.change_packages(message.get("policy", POLICY_STRICT)) |
513 | self._clear_binaries() |
514 | |
515 | @@ -289,99 +290,16 @@ |
516 | def handle_change_package_locks(self, message): |
517 | """Handle a C{change-package-locks} message. |
518 | |
519 | - Create and delete package locks as requested by the given C{message}. |
520 | - """ |
521 | - |
522 | - if not self._facade.supports_package_locks: |
523 | - response = { |
524 | - "type": "operation-result", |
525 | - "operation-id": message.get("operation-id"), |
526 | - "status": FAILED, |
527 | - "result-text": "This client doesn't support package locks.", |
528 | - "result-code": 1} |
529 | - return self._broker.send_message(response, True) |
530 | - |
531 | - for lock in message.get("create", ()): |
532 | - self._facade.set_package_lock(*lock) |
533 | - for lock in message.get("delete", ()): |
534 | - self._facade.remove_package_lock(*lock) |
535 | - self._facade.save_config() |
536 | - |
537 | - response = {"type": "operation-result", |
538 | - "operation-id": message.get("operation-id"), |
539 | - "status": SUCCEEDED, |
540 | - "result-text": "Package locks successfully changed.", |
541 | - "result-code": 0} |
542 | - |
543 | - logging.info("Queuing message with change package locks results to " |
544 | - "exchange urgently.") |
545 | - return self._broker.send_message(response, True) |
546 | - |
547 | - def _send_change_package_holds_response(self, response): |
548 | - """Log that a package holds result is sent and send the response.""" |
549 | - logging.info("Queuing message with change package holds results to " |
550 | - "exchange urgently.") |
551 | - return self._broker.send_message(response, True) |
552 | - |
553 | - def handle_change_package_holds(self, message): |
554 | - """Handle a C{change-package-holds} message. |
555 | - |
556 | - Create and delete package holds as requested by the given C{message}. |
557 | - """ |
558 | - if not self._facade.supports_package_holds: |
559 | - response = { |
560 | - "type": "operation-result", |
561 | - "operation-id": message.get("operation-id"), |
562 | - "status": FAILED, |
563 | - "result-text": "This client doesn't support package holds.", |
564 | - "result-code": 1} |
565 | - return self._send_change_package_holds_response(response) |
566 | - |
567 | - not_installed = set() |
568 | - holds_to_create = message.get("create", []) |
569 | - versions_to_create = set() |
570 | - for id in holds_to_create: |
571 | - hash = self._store.get_id_hash(id) |
572 | - hold_version = self._facade.get_package_by_hash(hash) |
573 | - if (hold_version |
574 | - and self._facade.is_package_installed(hold_version)): |
575 | - versions_to_create.add((hold_version.package, hold_version)) |
576 | - else: |
577 | - not_installed.add(str(id)) |
578 | - holds_to_remove = message.get("delete", []) |
579 | - versions_to_remove = set() |
580 | - for id in holds_to_remove: |
581 | - hash = self._store.get_id_hash(id) |
582 | - hold_version = self._facade.get_package_by_hash(hash) |
583 | - if (hold_version |
584 | - and self._facade.is_package_installed(hold_version)): |
585 | - versions_to_remove.add((hold_version.package, hold_version)) |
586 | - |
587 | - if not_installed: |
588 | - response = { |
589 | - "type": "operation-result", |
590 | - "operation-id": message.get("operation-id"), |
591 | - "status": FAILED, |
592 | - "result-text": "Package holds not changed, since the" + |
593 | - " following packages are not installed: %s" % ( |
594 | - ", ".join(sorted(not_installed))), |
595 | - "result-code": 1} |
596 | - return self._send_change_package_holds_response(response) |
597 | - |
598 | - for package, hold_version in versions_to_create: |
599 | - self._facade.set_package_hold(hold_version) |
600 | - for package, hold_version in versions_to_remove: |
601 | - self._facade.remove_package_hold(hold_version) |
602 | - |
603 | - self._facade.reload_channels() |
604 | - |
605 | - response = {"type": "operation-result", |
606 | - "operation-id": message.get("operation-id"), |
607 | - "status": SUCCEEDED, |
608 | - "result-text": "Package holds successfully changed.", |
609 | - "result-code": 0} |
610 | - |
611 | - return self._send_change_package_holds_response(response) |
612 | + Package locks aren't supported anymore. |
613 | + """ |
614 | + |
615 | + response = { |
616 | + "type": "operation-result", |
617 | + "operation-id": message.get("operation-id"), |
618 | + "status": FAILED, |
619 | + "result-text": "This client doesn't support package locks.", |
620 | + "result-code": 1} |
621 | + return self._broker.send_message(response, True) |
622 | |
623 | @staticmethod |
624 | def find_command(): |
625 | |
626 | === modified file 'landscape/package/facade.py' |
627 | --- landscape/package/facade.py 2012-03-21 16:15:49 +0000 |
628 | +++ landscape/package/facade.py 2012-06-04 14:08:28 +0000 |
629 | @@ -5,15 +5,6 @@ |
630 | from cStringIO import StringIO |
631 | from operator import attrgetter |
632 | |
633 | -has_smart = True |
634 | -try: |
635 | - import smart |
636 | - from smart.transaction import ( |
637 | - Transaction, PolicyInstall, PolicyUpgrade, PolicyRemove, Failed) |
638 | - from smart.const import INSTALL, REMOVE, UPGRADE, ALWAYS, NEVER |
639 | -except ImportError: |
640 | - has_smart = False |
641 | - |
642 | # Importing apt throws a FutureWarning on hardy, that we don't want to |
643 | # see. |
644 | import warnings |
645 | @@ -24,19 +15,13 @@ |
646 | import apt_inst |
647 | import apt_pkg |
648 | |
649 | -has_new_enough_apt = True |
650 | from aptsources.sourceslist import SourcesList |
651 | -try: |
652 | - from apt.progress.text import AcquireProgress |
653 | - from apt.progress.base import InstallProgress |
654 | -except ImportError: |
655 | - AcquireProgress = object |
656 | - InstallProgress = object |
657 | - has_new_enough_apt = False |
658 | +from apt.progress.text import AcquireProgress |
659 | +from apt.progress.base import InstallProgress |
660 | |
661 | from landscape.lib.fs import append_file, create_file, read_file |
662 | from landscape.constants import UBUNTU_PATH |
663 | -from landscape.package.skeleton import build_skeleton, build_skeleton_apt |
664 | +from landscape.package.skeleton import build_skeleton_apt |
665 | |
666 | |
667 | class TransactionError(Exception): |
668 | @@ -54,10 +39,6 @@ |
669 | ", ".join([str(package) for package in self.packages])) |
670 | |
671 | |
672 | -class SmartError(Exception): |
673 | - """Raised when Smart fails in an undefined way.""" |
674 | - |
675 | - |
676 | class ChannelError(Exception): |
677 | """Raised when channels fail to load.""" |
678 | |
679 | @@ -108,8 +89,6 @@ |
680 | database. |
681 | """ |
682 | |
683 | - supports_package_holds = True |
684 | - supports_package_locks = False |
685 | _dpkg_status = "/var/lib/dpkg/status" |
686 | |
687 | def __init__(self, root=None): |
688 | @@ -127,6 +106,8 @@ |
689 | self._version_installs = [] |
690 | self._global_upgrade = False |
691 | self._version_removals = [] |
692 | + self._version_hold_creations = [] |
693 | + self._version_hold_removals = [] |
694 | self.refetch_package_index = False |
695 | |
696 | def _ensure_dir_structure(self): |
697 | @@ -150,9 +131,6 @@ |
698 | os.makedirs(full_path) |
699 | return full_path |
700 | |
701 | - def deinit(self): |
702 | - """This method exists solely to be compatible with C{SmartFacade}.""" |
703 | - |
704 | def get_packages(self): |
705 | """Get all the packages available in the channels.""" |
706 | return self._hash2pkg.itervalues() |
707 | @@ -167,17 +145,6 @@ |
708 | if (self.is_package_installed(version) |
709 | and self._is_package_held(version.package))] |
710 | |
711 | - def get_package_locks(self): |
712 | - """Return all set package locks. |
713 | - |
714 | - @return: A C{list} of ternary tuples, contaning the name, relation |
715 | - and version details for each lock currently set on the system. |
716 | - |
717 | - XXX: This method isn't implemented yet. It's here to make the |
718 | - transition to Apt in the package reporter easier. |
719 | - """ |
720 | - return [] |
721 | - |
722 | def get_package_holds(self): |
723 | """Return the name of all the packages that are on hold.""" |
724 | return [version.package.name for version in self.get_locked_packages()] |
725 | @@ -204,7 +171,8 @@ |
726 | |
727 | @param version: The version of the package to unhold. |
728 | """ |
729 | - if not self._is_package_held(version.package): |
730 | + if (not self.is_package_installed(version) or |
731 | + not self._is_package_held(version.package)): |
732 | return |
733 | self._set_dpkg_selections(version.package.name + " install") |
734 | |
735 | @@ -556,50 +524,125 @@ |
736 | all_info.append(info + or_divider.join(relation_infos)) |
737 | return "\n".join(all_info) |
738 | |
739 | - def perform_changes(self): |
740 | - """Perform the pending package operations.""" |
741 | - # Try to enforce non-interactivity |
742 | + def _set_frontend_noninteractive(self): |
743 | + """ |
744 | + Set the environment to avoid attempts by apt to interact with a user. |
745 | + """ |
746 | os.environ["DEBIAN_FRONTEND"] = "noninteractive" |
747 | os.environ["APT_LISTCHANGES_FRONTEND"] = "none" |
748 | os.environ["APT_LISTBUGS_FRONTEND"] = "none" |
749 | + |
750 | + def _default_path_when_missing(self): |
751 | + """ |
752 | + If no PATH is set in the environment, use the Ubuntu default PATH. |
753 | + |
754 | + When the client is launched from the landscape-client-settings-ui the |
755 | + PATH variable is incorrectly set, this method rectifies that. |
756 | + """ |
757 | # dpkg will fail if no path is set. |
758 | if "PATH" not in os.environ: |
759 | os.environ["PATH"] = UBUNTU_PATH |
760 | + |
761 | + def _setup_dpkg_for_changes(self): |
762 | + """ |
763 | + Setup environment and apt options for successful package operations. |
764 | + """ |
765 | + self._set_frontend_noninteractive() |
766 | + self._default_path_when_missing() |
767 | apt_pkg.config.clear("DPkg::options") |
768 | apt_pkg.config.set("DPkg::options::", "--force-confold") |
769 | |
770 | + def _perform_hold_changes(self): |
771 | + """ |
772 | + Perform pending hold operations on packages. |
773 | + """ |
774 | + hold_changes = (len(self._version_hold_creations) > 0 or |
775 | + len(self._version_hold_removals) > 0) |
776 | + if not hold_changes: |
777 | + return None |
778 | + not_installed = [version for version in |
779 | + self._version_hold_creations |
780 | + if not self.is_package_installed(version)] |
781 | + if not_installed: |
782 | + raise TransactionError( |
783 | + "Cannot perform the changes, since the following " + |
784 | + "packages are not installed: %s" % ", ".join( |
785 | + [version.package.name |
786 | + for version in sorted(not_installed)])) |
787 | + |
788 | + for version in self._version_hold_creations: |
789 | + self.set_package_hold(version) |
790 | + |
791 | + for version in self._version_hold_removals: |
792 | + self.remove_package_hold(version) |
793 | + |
794 | + return "Package holds successfully changed." |
795 | + |
796 | + def _commit_package_changes(self): |
797 | + """ |
798 | + Commit cached APT operations and give feedback on the results as a |
799 | + string. |
800 | + """ |
801 | + fetch_output = StringIO() |
802 | + # Redirect stdout and stderr to a file. We need to work with the |
803 | + # file descriptors, rather than sys.stdout/stderr, since dpkg is |
804 | + # run in a subprocess. |
805 | + fd, install_output_path = tempfile.mkstemp() |
806 | + old_stdout = os.dup(1) |
807 | + old_stderr = os.dup(2) |
808 | + os.dup2(fd, 1) |
809 | + os.dup2(fd, 2) |
810 | + install_progress = LandscapeInstallProgress() |
811 | + try: |
812 | + self._cache.commit( |
813 | + fetch_progress=LandscapeAcquireProgress(fetch_output), |
814 | + install_progress=install_progress) |
815 | + if not install_progress.dpkg_exited: |
816 | + raise SystemError("dpkg didn't exit cleanly.") |
817 | + except SystemError, error: |
818 | + result_text = ( |
819 | + fetch_output.getvalue() + read_file(install_output_path)) |
820 | + raise TransactionError(error.args[0] + |
821 | + "\n\nPackage operation log:\n" + |
822 | + result_text) |
823 | + else: |
824 | + result_text = ( |
825 | + fetch_output.getvalue() + read_file(install_output_path)) |
826 | + finally: |
827 | + # Restore stdout and stderr. |
828 | + os.dup2(old_stdout, 1) |
829 | + os.dup2(old_stderr, 2) |
830 | + os.remove(install_output_path) |
831 | + return result_text |
832 | + |
833 | + def _preprocess_installs(self, fixer): |
834 | + for version in self._version_installs: |
835 | + # Set the candidate version, so that the version we want to |
836 | + # install actually is the one getting installed. |
837 | + version.package.candidate = version |
838 | + # Set auto_fix=False to avoid removing the package we asked to |
839 | + # install when we need to resolve dependencies. |
840 | + version.package.mark_install(auto_fix=False) |
841 | + fixer.clear(version.package._pkg) |
842 | + fixer.protect(version.package._pkg) |
843 | + |
844 | + def _preprocess_removes(self, fixer): |
845 | held_package_names = set() |
846 | + |
847 | package_installs = set( |
848 | version.package for version in self._version_installs) |
849 | + |
850 | package_upgrades = set( |
851 | version.package for version in self._version_removals |
852 | if version.package in package_installs) |
853 | - version_changes = self._version_installs[:] |
854 | - version_changes.extend(self._version_removals) |
855 | - if not version_changes and not self._global_upgrade: |
856 | - return None |
857 | - fixer = apt_pkg.ProblemResolver(self._cache._depcache) |
858 | - already_broken_packages = self._get_broken_packages() |
859 | - for version in self._version_installs: |
860 | - # Set the candidate version, so that the version we want to |
861 | - # install actually is the one getting installed. |
862 | - version.package.candidate = version |
863 | - version.package.mark_install(auto_fix=False) |
864 | - # If we need to resolve dependencies, try avoiding having |
865 | - # the package we asked to be installed from being removed. |
866 | - # (This is what would have been done if auto_fix would have |
867 | - # been True. |
868 | - fixer.clear(version.package._pkg) |
869 | - fixer.protect(version.package._pkg) |
870 | - if self._global_upgrade: |
871 | - self._cache.upgrade(dist_upgrade=True) |
872 | + |
873 | for version in self._version_removals: |
874 | if self._is_package_held(version.package): |
875 | held_package_names.add(version.package.name) |
876 | if version.package in package_upgrades: |
877 | # The server requests the old version to be removed for |
878 | # upgrades, since Smart worked that way. For Apt we have |
879 | - # to take care not to mark upgraded packages for # removal. |
880 | + # to take care not to mark upgraded packages for removal. |
881 | continue |
882 | version.package.mark_delete(auto_fix=False) |
883 | # Configure the resolver in the same way |
884 | @@ -614,50 +657,65 @@ |
885 | "Can't perform the changes, since the following packages" + |
886 | " are held: %s" % ", ".join(sorted(held_package_names))) |
887 | |
888 | + def _preprocess_global_upgrade(self): |
889 | + if self._global_upgrade: |
890 | + self._cache.upgrade(dist_upgrade=True) |
891 | + |
892 | + def _resolve_broken_packages(self, fixer, already_broken_packages): |
893 | + """ |
894 | + Attempt to automatically resolve problems with broken packages. |
895 | + """ |
896 | now_broken_packages = self._get_broken_packages() |
897 | if now_broken_packages != already_broken_packages: |
898 | try: |
899 | fixer.resolve(True) |
900 | except SystemError, error: |
901 | - raise TransactionError( |
902 | - error.args[0] + "\n" + self._get_unmet_dependency_info()) |
903 | + raise TransactionError(error.args[0] + "\n" + |
904 | + self._get_unmet_dependency_info()) |
905 | + |
906 | + def _preprocess_package_changes(self): |
907 | + version_changes = self._version_installs[:] |
908 | + version_changes.extend(self._version_removals) |
909 | + if (not version_changes and not self._global_upgrade): |
910 | + return [] |
911 | + already_broken_packages = self._get_broken_packages() |
912 | + fixer = apt_pkg.ProblemResolver(self._cache._depcache) |
913 | + self._preprocess_installs(fixer) |
914 | + self._preprocess_global_upgrade() |
915 | + self._preprocess_removes(fixer) |
916 | + self._resolve_broken_packages(fixer, already_broken_packages) |
917 | + return version_changes |
918 | + |
919 | + def _perform_package_changes(self): |
920 | + """ |
921 | + Perform pending install/remove/upgrade operations. |
922 | + """ |
923 | + version_changes = self._preprocess_package_changes() |
924 | if not self._check_changes(version_changes): |
925 | return None |
926 | - fetch_output = StringIO() |
927 | - # Redirect stdout and stderr to a file. We need to work with the |
928 | - # file descriptors, rather than sys.stdout/stderr, since dpkg is |
929 | - # run in a subprocess. |
930 | - fd, install_output_path = tempfile.mkstemp() |
931 | - old_stdout = os.dup(1) |
932 | - old_stderr = os.dup(2) |
933 | - os.dup2(fd, 1) |
934 | - os.dup2(fd, 2) |
935 | - install_progress = LandscapeInstallProgress() |
936 | - try: |
937 | - self._cache.commit( |
938 | - fetch_progress=LandscapeAcquireProgress(fetch_output), |
939 | - install_progress=install_progress) |
940 | - if not install_progress.dpkg_exited: |
941 | - raise SystemError("dpkg didn't exit cleanly.") |
942 | - except SystemError, error: |
943 | - result_text = ( |
944 | - fetch_output.getvalue() + read_file(install_output_path)) |
945 | - raise TransactionError( |
946 | - error.args[0] + "\n\nPackage operation log:\n" + result_text) |
947 | - else: |
948 | - result_text = ( |
949 | - fetch_output.getvalue() + read_file(install_output_path)) |
950 | - finally: |
951 | - # Restore stdout and stderr. |
952 | - os.dup2(old_stdout, 1) |
953 | - os.dup2(old_stderr, 2) |
954 | - os.remove(install_output_path) |
955 | - return result_text |
956 | + return self._commit_package_changes() |
957 | + |
958 | + def perform_changes(self): |
959 | + """ |
960 | + Perform the pending package operations. |
961 | + """ |
962 | + self._setup_dpkg_for_changes() |
963 | + hold_result_text = self._perform_hold_changes() |
964 | + package_result_text = self._perform_package_changes() |
965 | + results = [] |
966 | + if package_result_text is not None: |
967 | + results.append(package_result_text) |
968 | + if hold_result_text is not None: |
969 | + results.append(hold_result_text) |
970 | + if len(results) > 0: |
971 | + return " ".join(results) |
972 | |
973 | def reset_marks(self): |
974 | """Clear the pending package operations.""" |
975 | del self._version_installs[:] |
976 | del self._version_removals[:] |
977 | + del self._version_hold_removals[:] |
978 | + del self._version_hold_creations[:] |
979 | self._global_upgrade = False |
980 | self._cache.clear() |
981 | |
982 | @@ -673,403 +731,10 @@ |
983 | """Mark the package for removal.""" |
984 | self._version_removals.append(version) |
985 | |
986 | - |
987 | -class SmartFacade(object): |
988 | - """Wrapper for tasks using Smart. |
989 | - |
990 | - This object wraps Smart features, in a way that makes using and testing |
991 | - these features slightly more comfortable. |
992 | - |
993 | - @param smart_init_kwargs: A dictionary that can be used to pass specific |
994 | - keyword parameters to to L{smart.init}. |
995 | - """ |
996 | - |
997 | - _deb_package_type = None |
998 | - supports_package_holds = False |
999 | - supports_package_locks = True |
1000 | - |
1001 | - def __init__(self, smart_init_kwargs={}, sysconf_args=None): |
1002 | - if not has_smart: |
1003 | - raise RuntimeError( |
1004 | - "Smart needs to be installed if SmartFacade is used.") |
1005 | - self._smart_init_kwargs = smart_init_kwargs.copy() |
1006 | - self._smart_init_kwargs.setdefault("interface", "landscape") |
1007 | - self._sysconfig_args = sysconf_args or {} |
1008 | - self._reset() |
1009 | - |
1010 | - def _reset(self): |
1011 | - # This attribute is initialized lazily in the _get_ctrl() method. |
1012 | - self._ctrl = None |
1013 | - self._pkg2hash = {} |
1014 | - self._hash2pkg = {} |
1015 | - self._marks = {} |
1016 | - self._caching = ALWAYS |
1017 | - self._channels_reloaded = False |
1018 | - |
1019 | - def deinit(self): |
1020 | - """Deinitialize the Facade and the Smart library.""" |
1021 | - if self._ctrl: |
1022 | - smart.deinit() |
1023 | - self._reset() |
1024 | - |
1025 | - def _get_ctrl(self): |
1026 | - if self._ctrl is None: |
1027 | - if self._smart_init_kwargs.get("interface") == "landscape": |
1028 | - from landscape.package.interface import ( |
1029 | - install_landscape_interface) |
1030 | - install_landscape_interface() |
1031 | - self._ctrl = smart.init(**self._smart_init_kwargs) |
1032 | - for key, value in self._sysconfig_args.items(): |
1033 | - smart.sysconf.set(key, value, soft=True) |
1034 | - smart.initDistro(self._ctrl) |
1035 | - smart.initPlugins() |
1036 | - smart.sysconf.set("pm-iface-output", True, soft=True) |
1037 | - smart.sysconf.set("deb-non-interactive", True, soft=True) |
1038 | - |
1039 | - # We can't import it before hand because reaching .deb.* depends |
1040 | - # on initialization (yeah, sucky). |
1041 | - from smart.backends.deb.base import DebPackage |
1042 | - self._deb_package_type = DebPackage |
1043 | - |
1044 | - self.smart_initialized() |
1045 | - return self._ctrl |
1046 | - |
1047 | - def smart_initialized(self): |
1048 | - """Hook called when the Smart library is initialized.""" |
1049 | - |
1050 | - def ensure_channels_reloaded(self): |
1051 | - """Reload the channels if they haven't been reloaded yet.""" |
1052 | - if self._channels_reloaded: |
1053 | - return |
1054 | - self._channels_reloaded = True |
1055 | - self.reload_channels() |
1056 | - |
1057 | - def reload_channels(self, force_reload_binaries=False): |
1058 | - """ |
1059 | - Reload Smart channels, getting all the cache (packages) in memory. |
1060 | - |
1061 | - @raise: L{ChannelError} if Smart fails to reload the channels. |
1062 | - """ |
1063 | - ctrl = self._get_ctrl() |
1064 | - |
1065 | - try: |
1066 | - reload_result = ctrl.reloadChannels(caching=self._caching) |
1067 | - except smart.Error: |
1068 | - failed = True |
1069 | - else: |
1070 | - # Raise an error only if we are trying to download remote lists |
1071 | - failed = not reload_result and self._caching == NEVER |
1072 | - if failed: |
1073 | - raise ChannelError("Smart failed to reload channels (%s)" |
1074 | - % smart.sysconf.get("channels")) |
1075 | - |
1076 | - self._hash2pkg.clear() |
1077 | - self._pkg2hash.clear() |
1078 | - |
1079 | - for pkg in self.get_packages(): |
1080 | - hash = self.get_package_skeleton(pkg, False).get_hash() |
1081 | - self._hash2pkg[hash] = pkg |
1082 | - self._pkg2hash[pkg] = hash |
1083 | - |
1084 | - self.channels_reloaded() |
1085 | - |
1086 | - def channels_reloaded(self): |
1087 | - """Hook called after Smart channels are reloaded.""" |
1088 | - |
1089 | - def get_package_skeleton(self, pkg, with_info=True): |
1090 | - """Return a skeleton for the provided package. |
1091 | - |
1092 | - The skeleton represents the basic structure of the package. |
1093 | - |
1094 | - @param pkg: Package to build skeleton from. |
1095 | - @param with_info: If True, the skeleton will include information |
1096 | - useful for sending data to the server. Such information isn't |
1097 | - necessary if the skeleton will be used to build a hash. |
1098 | - |
1099 | - @return: a L{PackageSkeleton} object. |
1100 | - """ |
1101 | - return build_skeleton(pkg, with_info) |
1102 | - |
1103 | - def get_package_hash(self, pkg): |
1104 | - """Return a hash from the given package. |
1105 | - |
1106 | - @param pkg: a L{smart.backends.deb.base.DebPackage} objects |
1107 | - """ |
1108 | - return self._pkg2hash.get(pkg) |
1109 | - |
1110 | - def get_package_hashes(self): |
1111 | - """Get the hashes of all the packages available in the channels.""" |
1112 | - return self._pkg2hash.values() |
1113 | - |
1114 | - def get_packages(self): |
1115 | - """ |
1116 | - Get all the packages available in the channels. |
1117 | - |
1118 | - @return: a C{list} of L{smart.backends.deb.base.DebPackage} objects |
1119 | - """ |
1120 | - return [pkg for pkg in self._get_ctrl().getCache().getPackages() |
1121 | - if isinstance(pkg, self._deb_package_type)] |
1122 | - |
1123 | - def get_locked_packages(self): |
1124 | - """Get all packages in the channels matching the set locks.""" |
1125 | - return smart.pkgconf.filterByFlag("lock", self.get_packages()) |
1126 | - |
1127 | - def get_packages_by_name(self, name): |
1128 | - """ |
1129 | - Get all available packages matching the provided name. |
1130 | - |
1131 | - @return: a C{list} of L{smart.backends.deb.base.DebPackage} objects |
1132 | - """ |
1133 | - return [pkg for pkg in self._get_ctrl().getCache().getPackages(name) |
1134 | - if isinstance(pkg, self._deb_package_type)] |
1135 | - |
1136 | - def get_package_by_hash(self, hash): |
1137 | - """ |
1138 | - Get all available packages matching the provided hash. |
1139 | - |
1140 | - @return: a C{list} of L{smart.backends.deb.base.DebPackage} objects |
1141 | - """ |
1142 | - return self._hash2pkg.get(hash) |
1143 | - |
1144 | - def mark_install(self, pkg): |
1145 | - self._marks[pkg] = INSTALL |
1146 | - |
1147 | - def mark_remove(self, pkg): |
1148 | - self._marks[pkg] = REMOVE |
1149 | - |
1150 | - def mark_upgrade(self, pkg): |
1151 | - self._marks[pkg] = UPGRADE |
1152 | - |
1153 | - def mark_global_upgrade(self): |
1154 | - """Upgrade all installed packages.""" |
1155 | - for package in self.get_packages(): |
1156 | - if self.is_package_installed(package): |
1157 | - self.mark_upgrade(package) |
1158 | - |
1159 | - def reset_marks(self): |
1160 | - self._marks.clear() |
1161 | - |
1162 | - def perform_changes(self): |
1163 | - ctrl = self._get_ctrl() |
1164 | - cache = ctrl.getCache() |
1165 | - |
1166 | - transaction = Transaction(cache) |
1167 | - |
1168 | - policy = PolicyInstall |
1169 | - |
1170 | - only_remove = True |
1171 | - for pkg, oper in self._marks.items(): |
1172 | - if oper == UPGRADE: |
1173 | - policy = PolicyUpgrade |
1174 | - if oper != REMOVE: |
1175 | - only_remove = False |
1176 | - transaction.enqueue(pkg, oper) |
1177 | - |
1178 | - if only_remove: |
1179 | - policy = PolicyRemove |
1180 | - |
1181 | - transaction.setPolicy(policy) |
1182 | - |
1183 | - try: |
1184 | - transaction.run() |
1185 | - except Failed, e: |
1186 | - raise TransactionError(e.args[0]) |
1187 | - changeset = transaction.getChangeSet() |
1188 | - |
1189 | - if not changeset: |
1190 | - return None # Nothing to do. |
1191 | - |
1192 | - missing = [] |
1193 | - for pkg, op in changeset.items(): |
1194 | - if self._marks.get(pkg) != op: |
1195 | - missing.append(pkg) |
1196 | - if missing: |
1197 | - raise DependencyError(missing) |
1198 | - |
1199 | - try: |
1200 | - self._ctrl.commitChangeSet(changeset) |
1201 | - except smart.Error, e: |
1202 | - raise TransactionError(e.args[0]) |
1203 | - |
1204 | - output = smart.iface.get_output_for_landscape() |
1205 | - failed = smart.iface.has_failed_for_landscape() |
1206 | - |
1207 | - smart.iface.reset_for_landscape() |
1208 | - |
1209 | - if failed: |
1210 | - raise SmartError(output) |
1211 | - return output |
1212 | - |
1213 | - def reload_cache(self): |
1214 | - cache = self._get_ctrl().getCache() |
1215 | - cache.reset() |
1216 | - cache.load() |
1217 | - |
1218 | - def get_arch(self): |
1219 | - """ |
1220 | - Get the host dpkg architecture. |
1221 | - """ |
1222 | - self._get_ctrl() |
1223 | - from smart.backends.deb.loader import DEBARCH |
1224 | - return DEBARCH |
1225 | - |
1226 | - def set_arch(self, arch): |
1227 | - """ |
1228 | - Set the host dpkg architecture. |
1229 | - |
1230 | - To take effect it must be called before L{reload_channels}. |
1231 | - |
1232 | - @param arch: the dpkg architecture to use (e.g. C{"i386"}) |
1233 | - """ |
1234 | - self._get_ctrl() |
1235 | - smart.sysconf.set("deb-arch", arch) |
1236 | - |
1237 | - # XXX workaround Smart setting DEBARCH statically in the |
1238 | - # smart.backends.deb.base module |
1239 | - import smart.backends.deb.loader as loader |
1240 | - loader.DEBARCH = arch |
1241 | - |
1242 | - def set_caching(self, mode): |
1243 | - """ |
1244 | - Set Smart's caching mode. |
1245 | - |
1246 | - @param mode: The caching mode to pass to Smart's C{reloadChannels} |
1247 | - when calling L{reload_channels} (e.g C{smart.const.NEVER} or |
1248 | - C{smart.const.ALWAYS}). |
1249 | - """ |
1250 | - self._caching = mode |
1251 | - |
1252 | - def reset_channels(self): |
1253 | - """Remove all configured Smart channels.""" |
1254 | - self._get_ctrl() |
1255 | - smart.sysconf.set("channels", {}, soft=True) |
1256 | - |
1257 | - def add_channel(self, alias, channel): |
1258 | - """ |
1259 | - Add a Smart channel. |
1260 | - |
1261 | - This method can be called more than once to set multiple channels. |
1262 | - To take effect it must be called before L{reload_channels}. |
1263 | - |
1264 | - @param alias: A string identifying the channel to be added. |
1265 | - @param channel: A C{dict} holding information about the channel to |
1266 | - add (see the Smart API for details about valid keys and values). |
1267 | - """ |
1268 | - channels = self.get_channels() |
1269 | - channels.update({alias: channel}) |
1270 | - smart.sysconf.set("channels", channels, soft=True) |
1271 | - |
1272 | - def add_channel_apt_deb(self, url, codename, components): |
1273 | - """Add a Smart channel of type C{"apt-deb"}. |
1274 | - |
1275 | - @see: L{add_channel} |
1276 | - """ |
1277 | - alias = codename |
1278 | - channel = {"baseurl": url, "distribution": codename, |
1279 | - "components": components, "type": "apt-deb"} |
1280 | - self.add_channel(alias, channel) |
1281 | - |
1282 | - def add_channel_deb_dir(self, path): |
1283 | - """Add a Smart channel of type C{"deb-dir"}. |
1284 | - |
1285 | - @see: L{add_channel} |
1286 | - """ |
1287 | - alias = path |
1288 | - channel = {"path": path, "type": "deb-dir"} |
1289 | - self.add_channel(alias, channel) |
1290 | - |
1291 | - def clear_channels(self): |
1292 | - """Clear channels. |
1293 | - |
1294 | - This method exists to be compatible with AptFacade. Smart |
1295 | - doesn't need to clear its channels. |
1296 | - """ |
1297 | - |
1298 | - def get_channels(self): |
1299 | - """ |
1300 | - @return: A C{dict} of all configured channels. |
1301 | - """ |
1302 | - self._get_ctrl() |
1303 | - return smart.sysconf.get("channels") |
1304 | - |
1305 | - def get_package_locks(self): |
1306 | - """Return all set package locks. |
1307 | - |
1308 | - @return: A C{list} of ternary tuples, contaning the name, relation |
1309 | - and version details for each lock currently set on the system. |
1310 | - """ |
1311 | - self._get_ctrl() |
1312 | - locks = [] |
1313 | - locks_by_name = smart.pkgconf.getFlagTargets("lock") |
1314 | - for name in locks_by_name: |
1315 | - for condition in locks_by_name[name]: |
1316 | - relation = condition[0] or "" |
1317 | - version = condition[1] or "" |
1318 | - locks.append((name, relation, version)) |
1319 | - return locks |
1320 | - |
1321 | - def _validate_lock_condition(self, relation, version): |
1322 | - if relation and not version: |
1323 | - raise RuntimeError("Package lock version not provided") |
1324 | - if version and not relation: |
1325 | - raise RuntimeError("Package lock relation not provided") |
1326 | - |
1327 | - def set_package_lock(self, name, relation=None, version=None): |
1328 | - """Set a new package lock. |
1329 | - |
1330 | - Any package matching the given name and possibly the given version |
1331 | - condition will be locked. |
1332 | - |
1333 | - @param name: The name a package must match in order to be locked. |
1334 | - @param relation: Optionally, the relation of the version condition the |
1335 | - package must satisfy in order to be considered as locked. |
1336 | - @param version: Optionally, the version associated with C{relation}. |
1337 | - |
1338 | - @note: If used at all, the C{relation} and C{version} parameter must be |
1339 | - both provided. |
1340 | - """ |
1341 | - self._validate_lock_condition(relation, version) |
1342 | - self._get_ctrl() |
1343 | - smart.pkgconf.setFlag("lock", name, relation, version) |
1344 | - |
1345 | - def remove_package_lock(self, name, relation=None, version=None): |
1346 | - """Remove a package lock.""" |
1347 | - self._validate_lock_condition(relation, version) |
1348 | - self._get_ctrl() |
1349 | - smart.pkgconf.clearFlag("lock", name=name, relation=relation, |
1350 | - version=version) |
1351 | - |
1352 | - def save_config(self): |
1353 | - """Flush the current smart configuration to disk.""" |
1354 | - control = self._get_ctrl() |
1355 | - control.saveSysConf() |
1356 | - |
1357 | - def is_package_installed(self, package): |
1358 | - """Is the package installed?""" |
1359 | - return package.installed |
1360 | - |
1361 | - def is_package_available(self, package): |
1362 | - """Is the package available for installation?""" |
1363 | - for loader in package.loaders: |
1364 | - # Is the package also in a non-installed |
1365 | - # loader? IOW, "available". |
1366 | - if not loader.getInstalled(): |
1367 | - return True |
1368 | - return False |
1369 | - |
1370 | - def is_package_upgrade(self, package): |
1371 | - """Is the package an upgrade for another installed package?""" |
1372 | - is_upgrade = False |
1373 | - for upgrade in package.upgrades: |
1374 | - for provides in upgrade.providedby: |
1375 | - for provides_package in provides.packages: |
1376 | - if provides_package.installed: |
1377 | - is_upgrade = True |
1378 | - break |
1379 | - else: |
1380 | - continue |
1381 | - break |
1382 | - else: |
1383 | - continue |
1384 | - break |
1385 | - return is_upgrade |
1386 | + def mark_hold(self, version): |
1387 | + """Mark the package to be held.""" |
1388 | + self._version_hold_creations.append(version) |
1389 | + |
1390 | + def mark_remove_hold(self, version): |
1391 | + """Mark the package to have its hold removed.""" |
1392 | + self._version_hold_removals.append(version) |
1393 | |
1394 | === removed file 'landscape/package/interface.py' |
1395 | --- landscape/package/interface.py 2012-03-19 09:33:34 +0000 |
1396 | +++ landscape/package/interface.py 1970-01-01 00:00:00 +0000 |
1397 | @@ -1,84 +0,0 @@ |
1398 | -import logging |
1399 | -import types |
1400 | -import sys |
1401 | - |
1402 | -try: |
1403 | - import smart.interfaces |
1404 | - from smart.interface import Interface |
1405 | - from smart.const import ERROR, WARNING, INFO, DEBUG |
1406 | -except ImportError: |
1407 | - # Smart is optional if AptFacade is being used. |
1408 | - Interface = object |
1409 | - |
1410 | - |
1411 | -class LandscapeInterface(Interface): |
1412 | - |
1413 | - __output = "" |
1414 | - __failed = False |
1415 | - |
1416 | - def reset_for_landscape(self): |
1417 | - """Reset output and failed flag.""" |
1418 | - self.__failed = False |
1419 | - self.__output = u"" |
1420 | - |
1421 | - def get_output_for_landscape(self): |
1422 | - """showOutput() is cached, and returned by this method.""" |
1423 | - return self.__output |
1424 | - |
1425 | - def has_failed_for_landscape(self): |
1426 | - """Return true if any error() messages were logged.""" |
1427 | - return self.__failed |
1428 | - |
1429 | - def error(self, msg): |
1430 | - self.__failed = True |
1431 | - # Calling these logging.* functions here instead of message() |
1432 | - # below will output the message or not depending on the debug |
1433 | - # level set in landscape-client, rather than the one set in |
1434 | - # Smart's configuration. |
1435 | - logging.error("[Smart] %s", msg) |
1436 | - super(LandscapeInterface, self).error(msg) |
1437 | - |
1438 | - def warning(self, msg): |
1439 | - logging.warning("[Smart] %s", msg) |
1440 | - super(LandscapeInterface, self).warning(msg) |
1441 | - |
1442 | - def info(self, msg): |
1443 | - logging.info("[Smart] %s", msg) |
1444 | - super(LandscapeInterface, self).info(msg) |
1445 | - |
1446 | - def debug(self, msg): |
1447 | - logging.debug("[Smart] %s", msg) |
1448 | - super(LandscapeInterface, self).debug(msg) |
1449 | - |
1450 | - def message(self, level, msg): |
1451 | - prefix = {ERROR: "ERROR", WARNING: "WARNING", |
1452 | - INFO: "INFO", DEBUG: "DEBUG"}.get(level) |
1453 | - self.showOutput("%s: %s\n" % (prefix, msg)) |
1454 | - |
1455 | - def showOutput(self, output): |
1456 | - if not isinstance(output, unicode): |
1457 | - try: |
1458 | - output = output.decode("utf-8") |
1459 | - except UnicodeDecodeError: |
1460 | - output = output.decode("ascii", "replace") |
1461 | - self.__output += output |
1462 | - |
1463 | - |
1464 | -class LandscapeInterfaceModule(types.ModuleType): |
1465 | - |
1466 | - def __init__(self): |
1467 | - super(LandscapeInterfaceModule, self).__init__("landscape") |
1468 | - |
1469 | - def create(self, ctrl, command=None, argv=None): |
1470 | - return LandscapeInterface(ctrl) |
1471 | - |
1472 | - |
1473 | -def install_landscape_interface(): |
1474 | - if "smart.interfaces.landscape" not in sys.modules: |
1475 | - # Plug the interface in a place Smart will recognize. |
1476 | - smart.interfaces.landscape = LandscapeInterfaceModule() |
1477 | - sys.modules["smart.interfaces.landscape"] = smart.interfaces.landscape |
1478 | - |
1479 | - |
1480 | -def uninstall_landscape_interface(): |
1481 | - sys.modules.pop("smart.interfaces.landscape", None) |
1482 | |
1483 | === modified file 'landscape/package/releaseupgrader.py' |
1484 | --- landscape/package/releaseupgrader.py 2011-07-18 15:16:18 +0000 |
1485 | +++ landscape/package/releaseupgrader.py 2012-06-04 14:08:28 +0000 |
1486 | @@ -301,8 +301,8 @@ |
1487 | |
1488 | reporter = find_reporter_command() |
1489 | |
1490 | - # Force a smart-update run, because the sources.list has changed |
1491 | - args = ["--force-smart-update"] |
1492 | + # Force an apt-update run, because the sources.list has changed |
1493 | + args = ["--force-apt-update"] |
1494 | |
1495 | if self._config.config is not None: |
1496 | args.append("--config=%s" % self._config.config) |
1497 | |
1498 | === modified file 'landscape/package/reporter.py' |
1499 | --- landscape/package/reporter.py 2012-03-19 09:33:34 +0000 |
1500 | +++ landscape/package/reporter.py 2012-06-04 14:08:28 +0000 |
1501 | @@ -12,7 +12,6 @@ |
1502 | from landscape.lib.fs import touch_file |
1503 | from landscape.lib import bpickle |
1504 | |
1505 | -from landscape.package.facade import AptFacade |
1506 | from landscape.package.taskhandler import ( |
1507 | PackageTaskHandlerConfiguration, PackageTaskHandler, run_task_handler) |
1508 | from landscape.package.store import UnknownHashIDRequest, FakePackageStore |
1509 | @@ -31,9 +30,9 @@ |
1510 | reporter-specific options. |
1511 | """ |
1512 | parser = super(PackageReporterConfiguration, self).make_parser() |
1513 | - parser.add_option("--force-smart-update", default=False, |
1514 | + parser.add_option("--force-apt-update", default=False, |
1515 | action="store_true", |
1516 | - help="Force running smart-update.") |
1517 | + help="Force running apt-update.") |
1518 | return parser |
1519 | |
1520 | |
1521 | @@ -41,15 +40,14 @@ |
1522 | """Report information about the system packages. |
1523 | |
1524 | @cvar queue_name: Name of the task queue to pick tasks from. |
1525 | - @cvar smart_update_interval: Time interval in minutes to pass to |
1526 | - the C{--after} command line option of C{smart-update}. |
1527 | + @cvar apt_update_interval: Don't update the APT index more often |
1528 | + than the given interval in minutes. |
1529 | """ |
1530 | config_factory = PackageReporterConfiguration |
1531 | |
1532 | queue_name = "reporter" |
1533 | |
1534 | - smart_update_interval = 60 |
1535 | - smart_update_filename = "/usr/lib/landscape/smart-update" |
1536 | + apt_update_interval = 60 |
1537 | apt_update_filename = "/usr/lib/landscape/apt-update" |
1538 | sources_list_filename = "/etc/apt/sources.list" |
1539 | sources_list_directory = "/etc/apt/sources.list.d" |
1540 | @@ -57,13 +55,7 @@ |
1541 | def run(self): |
1542 | result = Deferred() |
1543 | |
1544 | - if isinstance(self._facade, AptFacade): |
1545 | - # Update APT cache if APT facade is enabled. |
1546 | - result.addCallback(lambda x: self.run_apt_update()) |
1547 | - else: |
1548 | - # Run smart-update before anything else, to make sure that |
1549 | - # the SmartFacade will load freshly updated channels |
1550 | - result.addCallback(lambda x: self.run_smart_update()) |
1551 | + result.addCallback(lambda x: self.run_apt_update()) |
1552 | |
1553 | # If the appropriate hash=>id db is not there, fetch it |
1554 | result.addCallback(lambda x: self.fetch_hash_id_db()) |
1555 | @@ -183,44 +175,6 @@ |
1556 | |
1557 | return False |
1558 | |
1559 | - def run_smart_update(self): |
1560 | - """Run smart-update and log a warning in case of non-zero exit code. |
1561 | - |
1562 | - @return: a deferred returning (out, err, code) |
1563 | - """ |
1564 | - if self._config.force_smart_update or self._apt_sources_have_changed(): |
1565 | - args = () |
1566 | - else: |
1567 | - args = ("--after", str(self.smart_update_interval)) |
1568 | - result = spawn_process(self.smart_update_filename, args=args) |
1569 | - |
1570 | - def callback((out, err, code)): |
1571 | - # smart-update --after N will exit with error code 1 when it |
1572 | - # doesn't actually run the update code because to enough time |
1573 | - # has passed yet, but we don't actually consider it a failure. |
1574 | - smart_failed = False |
1575 | - if code != 0 and code != 1: |
1576 | - smart_failed = True |
1577 | - if code == 1 and err.strip() != "": |
1578 | - smart_failed = True |
1579 | - if smart_failed: |
1580 | - logging.warning("'%s' exited with status %d (%s)" % ( |
1581 | - self.smart_update_filename, code, err)) |
1582 | - logging.debug("'%s' exited with status %d (out='%s', err='%s'" % ( |
1583 | - self.smart_update_filename, code, out, err)) |
1584 | - touch_file(self._config.update_stamp_filename) |
1585 | - if not smart_failed and not self._facade.get_channels(): |
1586 | - code = 1 |
1587 | - err = "There are no APT sources configured in %s or %s." % ( |
1588 | - self.sources_list_filename, self.sources_list_directory) |
1589 | - deferred = self._broker.call_if_accepted( |
1590 | - "package-reporter-result", self.send_result, code, err) |
1591 | - deferred.addCallback(lambda ignore: (out, err, code)) |
1592 | - return deferred |
1593 | - |
1594 | - result.addCallback(callback) |
1595 | - return result |
1596 | - |
1597 | def _apt_update_timeout_expired(self, interval): |
1598 | """Check if the apt-update timeout has passed.""" |
1599 | stamp = self._config.update_stamp_filename |
1600 | @@ -237,8 +191,8 @@ |
1601 | |
1602 | @return: a deferred returning (out, err, code) |
1603 | """ |
1604 | - if (self._config.force_smart_update or self._apt_sources_have_changed() |
1605 | - or self._apt_update_timeout_expired(self.smart_update_interval)): |
1606 | + if (self._config.force_apt_update or self._apt_sources_have_changed() |
1607 | + or self._apt_update_timeout_expired(self.apt_update_interval)): |
1608 | |
1609 | result = spawn_process(self.apt_update_filename) |
1610 | |
1611 | @@ -323,7 +277,6 @@ |
1612 | self._store.clear_available_upgrades() |
1613 | self._store.clear_installed() |
1614 | self._store.clear_locked() |
1615 | - self._store.clear_package_locks() |
1616 | |
1617 | # Don't clear the hash_id_requests table because the messages |
1618 | # associated with the existing requests might still have to be |
1619 | @@ -405,7 +358,7 @@ |
1620 | def request_unknown_hashes(self): |
1621 | """Detect available packages for which we have no hash=>id mappings. |
1622 | |
1623 | - This method will verify if there are packages that Smart knows |
1624 | + This method will verify if there are packages that APT knows |
1625 | about but for which we don't have an id yet (no hash => id |
1626 | translation), and deliver a message (unknown-package-hashes) |
1627 | to request them. |
1628 | @@ -466,16 +419,13 @@ |
1629 | reactor. |
1630 | """ |
1631 | |
1632 | - def changes_detected(results): |
1633 | - # Release all smart locks, in case the changer runs after us. |
1634 | - self._facade.deinit() |
1635 | - if True in results: |
1636 | + def changes_detected(result): |
1637 | + if result: |
1638 | # Something has changed, notify the broker. |
1639 | return self._broker.fire_event("package-data-changed") |
1640 | |
1641 | - result = gather_results([self.detect_packages_changes(), |
1642 | - self.detect_package_locks_changes()]) |
1643 | - return result.addCallback(changes_detected) |
1644 | + deferred = self.detect_packages_changes() |
1645 | + return deferred.addCallback(changes_detected) |
1646 | |
1647 | def detect_packages_changes(self): |
1648 | """Detect changes in the universe of known packages. |
1649 | @@ -609,53 +559,6 @@ |
1650 | |
1651 | return result |
1652 | |
1653 | - def detect_package_locks_changes(self): |
1654 | - """Detect changes in known package locks. |
1655 | - |
1656 | - This method will verify if there are package locks that: |
1657 | - |
1658 | - - are now set, and were not; |
1659 | - - were previously set but are not anymore; |
1660 | - |
1661 | - In all cases, the server is notified of the new situation |
1662 | - with a "packages" message. |
1663 | - |
1664 | - @return: A deferred resulting in C{True} if package lock changes were |
1665 | - detected with respect to the previous run, or C{False} otherwise. |
1666 | - """ |
1667 | - old_package_locks = set(self._store.get_package_locks()) |
1668 | - current_package_locks = set(self._facade.get_package_locks()) |
1669 | - |
1670 | - set_package_locks = current_package_locks - old_package_locks |
1671 | - unset_package_locks = old_package_locks - current_package_locks |
1672 | - |
1673 | - message = {} |
1674 | - if set_package_locks: |
1675 | - message["created"] = sorted(set_package_locks) |
1676 | - if unset_package_locks: |
1677 | - message["deleted"] = sorted(unset_package_locks) |
1678 | - |
1679 | - if not message: |
1680 | - return succeed(False) |
1681 | - |
1682 | - message["type"] = "package-locks" |
1683 | - result = self.send_message(message) |
1684 | - |
1685 | - logging.info("Queuing message with changes in known package locks:" |
1686 | - " %d created, %d deleted." % |
1687 | - (len(set_package_locks), len(unset_package_locks))) |
1688 | - |
1689 | - def update_currently_known(result): |
1690 | - if set_package_locks: |
1691 | - self._store.add_package_locks(set_package_locks) |
1692 | - if unset_package_locks: |
1693 | - self._store.remove_package_locks(unset_package_locks) |
1694 | - return True |
1695 | - |
1696 | - result.addCallback(update_currently_known) |
1697 | - |
1698 | - return result |
1699 | - |
1700 | |
1701 | class FakeGlobalReporter(PackageReporter): |
1702 | """ |
1703 | |
1704 | === modified file 'landscape/package/skeleton.py' |
1705 | --- landscape/package/skeleton.py 2012-03-19 09:33:34 +0000 |
1706 | +++ landscape/package/skeleton.py 2012-06-04 14:08:28 +0000 |
1707 | @@ -47,54 +47,6 @@ |
1708 | return digest.digest() |
1709 | |
1710 | |
1711 | -def build_skeleton(pkg, with_info=False, with_unicode=False): |
1712 | - if not build_skeleton.inited: |
1713 | - build_skeleton.inited = True |
1714 | - global DebPackage, DebNameProvides, DebOrDepends |
1715 | - |
1716 | - # Importing from backends depends on smart.init(). |
1717 | - from smart.backends.deb.base import ( |
1718 | - DebPackage, DebNameProvides, DebOrDepends) |
1719 | - |
1720 | - if not isinstance(pkg, DebPackage): |
1721 | - raise PackageTypeError() |
1722 | - |
1723 | - if with_unicode: |
1724 | - skeleton = PackageSkeleton(DEB_PACKAGE, unicode(pkg.name), |
1725 | - unicode(pkg.version)) |
1726 | - else: |
1727 | - skeleton = PackageSkeleton(DEB_PACKAGE, pkg.name, pkg.version) |
1728 | - relations = set() |
1729 | - for relation in pkg.provides: |
1730 | - if isinstance(relation, DebNameProvides): |
1731 | - relations.add((DEB_NAME_PROVIDES, str(relation))) |
1732 | - else: |
1733 | - relations.add((DEB_PROVIDES, str(relation))) |
1734 | - for relation in pkg.requires: |
1735 | - if isinstance(relation, DebOrDepends): |
1736 | - relations.add((DEB_OR_REQUIRES, str(relation))) |
1737 | - else: |
1738 | - relations.add((DEB_REQUIRES, str(relation))) |
1739 | - for relation in pkg.upgrades: |
1740 | - relations.add((DEB_UPGRADES, str(relation))) |
1741 | - for relation in pkg.conflicts: |
1742 | - relations.add((DEB_CONFLICTS, str(relation))) |
1743 | - |
1744 | - skeleton.relations = sorted(relations) |
1745 | - |
1746 | - if with_info: |
1747 | - info = pkg.loaders.keys()[0].getInfo(pkg) |
1748 | - skeleton.section = info.getGroup() |
1749 | - skeleton.summary = info.getSummary() |
1750 | - skeleton.description = info.getDescription() |
1751 | - skeleton.size = sum(info.getSize(url) for url in info.getURLs()) |
1752 | - skeleton.installed_size = info.getInstalledSize() |
1753 | - |
1754 | - return skeleton |
1755 | - |
1756 | -build_skeleton.inited = False |
1757 | - |
1758 | - |
1759 | def relation_to_string(relation_tuple): |
1760 | """Convert an apt relation to a string representation. |
1761 | |
1762 | |
1763 | === modified file 'landscape/package/store.py' |
1764 | --- landscape/package/store.py 2012-03-19 09:33:34 +0000 |
1765 | +++ landscape/package/store.py 2012-06-04 14:08:28 +0000 |
1766 | @@ -249,40 +249,6 @@ |
1767 | cursor.execute("DELETE FROM locked") |
1768 | |
1769 | @with_cursor |
1770 | - def get_package_locks(self, cursor): |
1771 | - """Get all package locks.""" |
1772 | - cursor.execute("SELECT name, relation, version FROM package_locks") |
1773 | - return [(row[0], row[1], row[2]) for row in cursor.fetchall()] |
1774 | - |
1775 | - @with_cursor |
1776 | - def add_package_locks(self, cursor, locks): |
1777 | - """Add a list of package locks to the store. |
1778 | - |
1779 | - @param locks: A C{list} of ternary tuples each one contains the |
1780 | - name, the relation and the version of the package lock to be added. |
1781 | - """ |
1782 | - for name, relation, version in locks: |
1783 | - cursor.execute("REPLACE INTO package_locks VALUES (?, ?, ?)", |
1784 | - (name, relation or "", version or "",)) |
1785 | - |
1786 | - @with_cursor |
1787 | - def remove_package_locks(self, cursor, locks): |
1788 | - """Remove a list of package locks from the store. |
1789 | - |
1790 | - @param locks: A C{list} of ternary tuples each one contains the name, |
1791 | - the relation and the version of the package lock to be removed. |
1792 | - """ |
1793 | - for name, relation, version in locks: |
1794 | - cursor.execute("DELETE FROM package_locks WHERE name=? AND " |
1795 | - "relation=? AND version=?", |
1796 | - (name, relation or "", version or "")) |
1797 | - |
1798 | - @with_cursor |
1799 | - def clear_package_locks(self, cursor): |
1800 | - """Remove all package locks.""" |
1801 | - cursor.execute("DELETE FROM package_locks") |
1802 | - |
1803 | - @with_cursor |
1804 | def add_hash_id_request(self, cursor, hashes): |
1805 | hashes = list(hashes) |
1806 | cursor.execute("INSERT INTO hash_id_request (hashes, timestamp)" |
1807 | @@ -458,9 +424,6 @@ |
1808 | # try block. |
1809 | cursor = db.cursor() |
1810 | try: |
1811 | - cursor.execute("CREATE TABLE package_locks" |
1812 | - " (name TEXT NOT NULL, relation TEXT, version TEXT," |
1813 | - " UNIQUE(name, relation, version))") |
1814 | cursor.execute("CREATE TABLE locked" |
1815 | " (id INTEGER PRIMARY KEY)") |
1816 | cursor.execute("CREATE TABLE available" |
1817 | |
1818 | === modified file 'landscape/package/taskhandler.py' |
1819 | --- landscape/package/taskhandler.py 2012-03-19 09:33:34 +0000 |
1820 | +++ landscape/package/taskhandler.py 2012-06-04 14:08:28 +0000 |
1821 | @@ -254,19 +254,15 @@ |
1822 | words = re.findall("[A-Z][a-z]+", cls.__name__) |
1823 | init_logging(config, "-".join(word.lower() for word in words)) |
1824 | |
1825 | - # Setup our umask for Smart to use, this needs to setup file permissions to |
1826 | + # Setup our umask for Apt to use, this needs to setup file permissions to |
1827 | # 0644 so... |
1828 | os.umask(022) |
1829 | |
1830 | package_store = cls.package_store_class(config.store_filename) |
1831 | # Delay importing of the facades so that we don't |
1832 | - # import Smart unless we need to. |
1833 | - from landscape.package.facade import ( |
1834 | - AptFacade, SmartFacade, has_new_enough_apt) |
1835 | - if has_new_enough_apt: |
1836 | - package_facade = AptFacade() |
1837 | - else: |
1838 | - package_facade = SmartFacade() |
1839 | + # import Apt unless we need to. |
1840 | + from landscape.package.facade import AptFacade |
1841 | + package_facade = AptFacade() |
1842 | |
1843 | def finish(): |
1844 | connector.disconnect() |
1845 | |
1846 | === modified file 'landscape/package/tests/helpers.py' |
1847 | --- landscape/package/tests/helpers.py 2012-03-19 09:33:34 +0000 |
1848 | +++ landscape/package/tests/helpers.py 2012-06-04 14:08:28 +0000 |
1849 | @@ -3,12 +3,6 @@ |
1850 | import textwrap |
1851 | import time |
1852 | |
1853 | -try: |
1854 | - import smart |
1855 | -except ImportError: |
1856 | - # Smart is optional if AptFacade is being used. |
1857 | - pass |
1858 | - |
1859 | import apt_inst |
1860 | import apt_pkg |
1861 | |
1862 | @@ -127,39 +121,6 @@ |
1863 | test_case.facade.add_channel_deb_dir(test_case.repository_dir) |
1864 | |
1865 | |
1866 | -class SmartHelper(object): |
1867 | - |
1868 | - def set_up(self, test_case): |
1869 | - test_case.smart_dir = test_case.makeDir() |
1870 | - test_case.smart_config = test_case.makeFile("") |
1871 | - test_case.repository_dir = test_case.makeDir() |
1872 | - create_simple_repository(test_case.repository_dir) |
1873 | - |
1874 | - def tear_down(self, test_case): |
1875 | - if smart.iface.object: |
1876 | - smart.deinit() |
1877 | - |
1878 | - |
1879 | -class SmartFacadeHelper(SmartHelper): |
1880 | - |
1881 | - def set_up(self, test_case): |
1882 | - super(SmartFacadeHelper, self).set_up(test_case) |
1883 | - |
1884 | - from landscape.package.facade import SmartFacade |
1885 | - |
1886 | - class Facade(SmartFacade): |
1887 | - repository_dir = test_case.repository_dir |
1888 | - |
1889 | - def smart_initialized(self): |
1890 | - self.reset_channels() |
1891 | - self.add_channel_deb_dir(test_case.repository_dir) |
1892 | - |
1893 | - test_case.Facade = Facade |
1894 | - test_case.facade = Facade({"datadir": test_case.smart_dir, |
1895 | - "configfile": test_case.smart_config}, |
1896 | - {"sync-apt-sources": False}) |
1897 | - |
1898 | - |
1899 | PKGNAME1 = "name1_version1-release1_all.deb" |
1900 | PKGNAME2 = "name2_version2-release2_all.deb" |
1901 | PKGNAME3 = "name3_version3-release3_all.deb" |
1902 | |
1903 | === modified file 'landscape/package/tests/test_changer.py' |
1904 | --- landscape/package/tests/test_changer.py 2012-03-21 16:15:49 +0000 |
1905 | +++ landscape/package/tests/test_changer.py 2012-06-04 14:08:28 +0000 |
1906 | @@ -6,12 +6,6 @@ |
1907 | |
1908 | from twisted.internet.defer import Deferred |
1909 | |
1910 | -try: |
1911 | - from smart.cache import Provides |
1912 | -except ImportError: |
1913 | - # Smart is optional if AptFacade is being used. |
1914 | - pass |
1915 | - |
1916 | from landscape.lib.fs import create_file, read_file, touch_file |
1917 | from landscape.package.changer import ( |
1918 | PackageChanger, main, find_changer_command, UNKNOWN_PACKAGE_DATA_TIMEOUT, |
1919 | @@ -19,19 +13,107 @@ |
1920 | POLICY_ALLOW_ALL_CHANGES, ERROR_RESULT) |
1921 | from landscape.package.store import PackageStore |
1922 | from landscape.package.facade import ( |
1923 | - DependencyError, TransactionError, SmartError, has_new_enough_apt) |
1924 | + DependencyError, TransactionError) |
1925 | from landscape.package.changer import ( |
1926 | PackageChangerConfiguration, ChangePackagesResult) |
1927 | from landscape.tests.mocker import ANY |
1928 | from landscape.tests.helpers import ( |
1929 | LandscapeTest, BrokerServiceHelper) |
1930 | from landscape.package.tests.helpers import ( |
1931 | - SmartFacadeHelper, HASH1, HASH2, HASH3, PKGDEB1, PKGDEB2, PKGNAME2, |
1932 | + HASH1, HASH2, HASH3, PKGDEB1, PKGDEB2, |
1933 | AptFacadeHelper, SimpleRepositoryHelper) |
1934 | -from landscape.manager.manager import FAILED, SUCCEEDED |
1935 | - |
1936 | - |
1937 | -class PackageChangerTestMixin(object): |
1938 | +from landscape.manager.manager import FAILED |
1939 | + |
1940 | + |
1941 | +class AptPackageChangerTest(LandscapeTest): |
1942 | + |
1943 | + helpers = [AptFacadeHelper, SimpleRepositoryHelper, BrokerServiceHelper] |
1944 | + |
1945 | + def setUp(self): |
1946 | + |
1947 | + def set_up(ignored): |
1948 | + |
1949 | + self.store = PackageStore(self.makeFile()) |
1950 | + self.config = PackageChangerConfiguration() |
1951 | + self.config.data_path = self.makeDir() |
1952 | + os.mkdir(self.config.package_directory) |
1953 | + os.mkdir(self.config.binaries_path) |
1954 | + touch_file(self.config.update_stamp_filename) |
1955 | + self.changer = PackageChanger( |
1956 | + self.store, self.facade, self.remote, self.config) |
1957 | + service = self.broker_service |
1958 | + service.message_store.set_accepted_types(["change-packages-result", |
1959 | + "operation-result"]) |
1960 | + |
1961 | + result = super(AptPackageChangerTest, self).setUp() |
1962 | + return result.addCallback(set_up) |
1963 | + |
1964 | + def set_pkg1_installed(self): |
1965 | + """Return the hash of a package that is installed.""" |
1966 | + self._add_system_package("foo") |
1967 | + self.facade.reload_channels() |
1968 | + [foo] = self.facade.get_packages_by_name("foo") |
1969 | + return self.facade.get_package_hash(foo) |
1970 | + |
1971 | + def set_pkg2_satisfied(self): |
1972 | + """Return the hash of a package that can be installed.""" |
1973 | + self._add_package_to_deb_dir(self.repository_dir, "bar") |
1974 | + self.facade.reload_channels() |
1975 | + [bar] = self.facade.get_packages_by_name("bar") |
1976 | + return self.facade.get_package_hash(bar) |
1977 | + |
1978 | + def set_pkg1_and_pkg2_satisfied(self): |
1979 | + """Make a package depend on another package. |
1980 | + |
1981 | + Return the hashes of the two packages. |
1982 | + """ |
1983 | + self._add_package_to_deb_dir( |
1984 | + self.repository_dir, "foo", control_fields={"Depends": "bar"}) |
1985 | + self._add_package_to_deb_dir(self.repository_dir, "bar") |
1986 | + self.facade.reload_channels() |
1987 | + [foo] = self.facade.get_packages_by_name("foo") |
1988 | + [bar] = self.facade.get_packages_by_name("bar") |
1989 | + return ( |
1990 | + self.facade.get_package_hash(foo), |
1991 | + self.facade.get_package_hash(bar)) |
1992 | + |
1993 | + def set_pkg2_upgrades_pkg1(self): |
1994 | + """Make it so that one package upgrades another. |
1995 | + |
1996 | + Return the hashes of the two packages. |
1997 | + """ |
1998 | + self._add_system_package("foo", version="1.0") |
1999 | + self._add_package_to_deb_dir(self.repository_dir, "foo", version="2.0") |
2000 | + self.facade.reload_channels() |
2001 | + foo_1, foo_2 = sorted(self.facade.get_packages_by_name("foo")) |
2002 | + return ( |
2003 | + self.facade.get_package_hash(foo_1), |
2004 | + self.facade.get_package_hash(foo_2)) |
2005 | + |
2006 | + def remove_pkg2(self): |
2007 | + """Remove package name2 from its repository.""" |
2008 | + packages_file = os.path.join(self.repository_dir, "Packages") |
2009 | + packages_contents = read_file(packages_file) |
2010 | + packages_contents = "\n\n".join( |
2011 | + [stanza for stanza in packages_contents.split("\n\n") |
2012 | + if "Package: name2" not in stanza]) |
2013 | + create_file(packages_file, packages_contents) |
2014 | + |
2015 | + def get_transaction_error_message(self): |
2016 | + """Return part of the apt transaction error message.""" |
2017 | + return "Unable to correct problems" |
2018 | + |
2019 | + def get_binaries_channels(self, binaries_path): |
2020 | + """Return the channels that will be used for the binaries.""" |
2021 | + return [{"baseurl": "file://%s" % binaries_path, |
2022 | + "components": "", |
2023 | + "distribution": "./", |
2024 | + "type": "deb"}] |
2025 | + |
2026 | + def get_package_name(self, version): |
2027 | + """Return the name of the package.""" |
2028 | + return version.package.name |
2029 | + |
2030 | |
2031 | def disable_clear_channels(self): |
2032 | """Disable clear_channels(), so that it doesn't remove test setup. |
2033 | @@ -441,7 +523,7 @@ |
2034 | |
2035 | def test_tasks_are_isolated_cache(self): |
2036 | """ |
2037 | - The package (apt/smart) cache should be reset between task runs. |
2038 | + The package (APT) cache should be reset between task runs. |
2039 | In this test, we try to run two different operations, first |
2040 | installing package 2, then removing package 1. Both tasks will |
2041 | fail for lack of superuser privileges. If the package cache |
2042 | @@ -533,7 +615,7 @@ |
2043 | """ |
2044 | Besides asking for individual changes, the server may also request |
2045 | the client to perform a global upgrade. This would be the equivalent |
2046 | - of a "smart upgrade" command being executed in the command line. |
2047 | + of a "apt-get upgrade" command being executed in the command line. |
2048 | """ |
2049 | hash1, hash2 = self.set_pkg2_upgrades_pkg1() |
2050 | self.store.set_hash_ids({hash1: 1, hash2: 2}) |
2051 | @@ -638,8 +720,7 @@ |
2052 | """ |
2053 | After the package changer has run, we want the package-reporter to run |
2054 | to report the recent changes. If we're running as root, we want to |
2055 | - change to the "landscape" user and "landscape" group. We also want to |
2056 | - deinitialize Smart to let the reporter run smart-update cleanly. |
2057 | + change to the "landscape" user and "landscape" group. |
2058 | """ |
2059 | |
2060 | # We are running as root |
2061 | @@ -647,13 +728,8 @@ |
2062 | getuid_mock() |
2063 | self.mocker.result(0) |
2064 | |
2065 | - # The order matters (first smart then gid and finally uid) |
2066 | self.mocker.order() |
2067 | |
2068 | - # Deinitialize smart |
2069 | - facade_mock = self.mocker.patch(self.facade) |
2070 | - facade_mock.deinit() |
2071 | - |
2072 | # We want to return a known gid |
2073 | grnam_mock = self.mocker.replace("grp.getgrnam") |
2074 | grnam_mock("landscape") |
2075 | @@ -810,27 +886,6 @@ |
2076 | "type": "change-packages-result"}]) |
2077 | return result.addCallback(got_result) |
2078 | |
2079 | - def test_smart_error_with_unicode_data(self): |
2080 | - self.store.set_hash_ids({HASH1: 1}) |
2081 | - self.store.add_task("changer", |
2082 | - {"type": "change-packages", "install": [1], |
2083 | - "operation-id": 123}) |
2084 | - |
2085 | - def raise_error(self): |
2086 | - raise SmartError(u"áéÃóú") |
2087 | - self.replace_perform_changes(raise_error) |
2088 | - self.disable_clear_channels() |
2089 | - |
2090 | - result = self.changer.handle_tasks() |
2091 | - |
2092 | - def got_result(result): |
2093 | - self.assertMessages(self.get_pending_messages(), |
2094 | - [{"operation-id": 123, |
2095 | - "result-code": 100, |
2096 | - "result-text": u"áéÃóú", |
2097 | - "type": "change-packages-result"}]) |
2098 | - return result.addCallback(got_result) |
2099 | - |
2100 | def test_update_stamp_exists(self): |
2101 | """ |
2102 | L{PackageChanger.update_exists} returns C{True} if the |
2103 | @@ -892,360 +947,6 @@ |
2104 | self.assertFalse(os.path.exists(existing_deb_path)) |
2105 | |
2106 | |
2107 | -class SmartPackageChangerTest(LandscapeTest, PackageChangerTestMixin): |
2108 | - |
2109 | - helpers = [SmartFacadeHelper, BrokerServiceHelper] |
2110 | - |
2111 | - def setUp(self): |
2112 | - |
2113 | - def set_up(ignored): |
2114 | - |
2115 | - self.store = PackageStore(self.makeFile()) |
2116 | - self.config = PackageChangerConfiguration() |
2117 | - self.config.data_path = self.makeDir() |
2118 | - os.mkdir(self.config.package_directory) |
2119 | - os.mkdir(self.config.binaries_path) |
2120 | - touch_file(self.config.update_stamp_filename) |
2121 | - self.changer = PackageChanger( |
2122 | - self.store, self.facade, self.remote, self.config) |
2123 | - service = self.broker_service |
2124 | - service.message_store.set_accepted_types(["change-packages-result", |
2125 | - "operation-result"]) |
2126 | - |
2127 | - result = super(SmartPackageChangerTest, self).setUp() |
2128 | - return result.addCallback(set_up) |
2129 | - |
2130 | - def set_pkg1_installed(self): |
2131 | - previous = self.Facade.channels_reloaded |
2132 | - |
2133 | - def callback(self): |
2134 | - previous(self) |
2135 | - self.get_packages_by_name("name1")[0].installed = True |
2136 | - self.Facade.channels_reloaded = callback |
2137 | - return HASH1 |
2138 | - |
2139 | - def set_pkg2_upgrades_pkg1(self): |
2140 | - previous = self.Facade.channels_reloaded |
2141 | - |
2142 | - def callback(self): |
2143 | - from smart.backends.deb.base import DebUpgrades |
2144 | - previous(self) |
2145 | - [pkg2] = self.get_packages_by_name("name2") |
2146 | - pkg2.upgrades += (DebUpgrades("name1", "=", "version1-release1"),) |
2147 | - self.reload_cache() # Relink relations. |
2148 | - self.Facade.channels_reloaded = callback |
2149 | - self.set_pkg2_satisfied() |
2150 | - self.set_pkg1_installed() |
2151 | - return HASH1, HASH2 |
2152 | - |
2153 | - def set_pkg2_satisfied(self): |
2154 | - previous = self.Facade.channels_reloaded |
2155 | - |
2156 | - def callback(self): |
2157 | - previous(self) |
2158 | - [pkg2] = self.get_packages_by_name("name2") |
2159 | - pkg2.requires = () |
2160 | - self.reload_cache() # Relink relations. |
2161 | - self.Facade.channels_reloaded = callback |
2162 | - return HASH2 |
2163 | - |
2164 | - def set_pkg1_and_pkg2_satisfied(self): |
2165 | - previous = self.Facade.channels_reloaded |
2166 | - |
2167 | - def callback(self): |
2168 | - previous(self) |
2169 | - |
2170 | - provide1 = Provides("prerequirename1", "prerequireversion1") |
2171 | - provide2 = Provides("requirename1", "requireversion1") |
2172 | - [pkg2] = self.get_packages_by_name("name2") |
2173 | - pkg2.provides += (provide1, provide2) |
2174 | - |
2175 | - provide1 = Provides("prerequirename2", "prerequireversion2") |
2176 | - provide2 = Provides("requirename2", "requireversion2") |
2177 | - [pkg1] = self.get_packages_by_name("name1") |
2178 | - pkg1.provides += (provide1, provide2) |
2179 | - |
2180 | - # Ask Smart to reprocess relationships. |
2181 | - self.reload_cache() |
2182 | - self.Facade.channels_reloaded = callback |
2183 | - return HASH1, HASH2 |
2184 | - |
2185 | - def remove_pkg2(self): |
2186 | - os.remove(os.path.join(self.repository_dir, PKGNAME2)) |
2187 | - |
2188 | - def get_transaction_error_message(self): |
2189 | - return "requirename1 = requireversion1" |
2190 | - |
2191 | - def get_binaries_channels(self, binaries_path): |
2192 | - return {binaries_path: {"type": "deb-dir", |
2193 | - "path": binaries_path}} |
2194 | - |
2195 | - def get_package_name(self, package): |
2196 | - return package.name |
2197 | - |
2198 | - def test_change_package_locks(self): |
2199 | - """ |
2200 | - The L{PackageChanger.handle_tasks} method appropriately creates and |
2201 | - deletes package locks as requested by the C{change-package-locks} |
2202 | - message. |
2203 | - """ |
2204 | - self.facade.set_package_lock("bar") |
2205 | - self.store.add_task("changer", {"type": "change-package-locks", |
2206 | - "create": [("foo", ">=", "1.0")], |
2207 | - "delete": [("bar", None, None)], |
2208 | - "operation-id": 123}) |
2209 | - |
2210 | - def assert_result(result): |
2211 | - self.facade.deinit() |
2212 | - self.assertEqual(self.facade.get_package_locks(), |
2213 | - [("foo", ">=", "1.0")]) |
2214 | - self.assertIn("Queuing message with change package locks results " |
2215 | - "to exchange urgently.", self.logfile.getvalue()) |
2216 | - self.assertMessages(self.get_pending_messages(), |
2217 | - [{"type": "operation-result", |
2218 | - "operation-id": 123, |
2219 | - "status": SUCCEEDED, |
2220 | - "result-text": "Package locks successfully" |
2221 | - " changed.", |
2222 | - "result-code": 0}]) |
2223 | - |
2224 | - result = self.changer.handle_tasks() |
2225 | - return result.addCallback(assert_result) |
2226 | - |
2227 | - def test_change_package_locks_create_with_already_existing(self): |
2228 | - """ |
2229 | - The L{PackageChanger.handle_tasks} method gracefully handles requests |
2230 | - for creating package locks that already exist. |
2231 | - """ |
2232 | - self.facade.set_package_lock("foo") |
2233 | - self.store.add_task("changer", {"type": "change-package-locks", |
2234 | - "create": [("foo", None, None)], |
2235 | - "operation-id": 123}) |
2236 | - |
2237 | - def assert_result(result): |
2238 | - self.facade.deinit() |
2239 | - self.assertEqual(self.facade.get_package_locks(), |
2240 | - [("foo", "", "")]) |
2241 | - self.assertMessages(self.get_pending_messages(), |
2242 | - [{"type": "operation-result", |
2243 | - "operation-id": 123, |
2244 | - "status": SUCCEEDED, |
2245 | - "result-text": "Package locks successfully" |
2246 | - " changed.", |
2247 | - "result-code": 0}]) |
2248 | - |
2249 | - result = self.changer.handle_tasks() |
2250 | - return result.addCallback(assert_result) |
2251 | - |
2252 | - def test_change_package_locks_delete_without_already_existing(self): |
2253 | - """ |
2254 | - The L{PackageChanger.handle_tasks} method gracefully handles requests |
2255 | - for deleting package locks that don't exist. |
2256 | - """ |
2257 | - self.store.add_task("changer", {"type": "change-package-locks", |
2258 | - "delete": [("foo", ">=", "1.0")], |
2259 | - "operation-id": 123}) |
2260 | - |
2261 | - def assert_result(result): |
2262 | - self.facade.deinit() |
2263 | - self.assertEqual(self.facade.get_package_locks(), []) |
2264 | - self.assertMessages(self.get_pending_messages(), |
2265 | - [{"type": "operation-result", |
2266 | - "operation-id": 123, |
2267 | - "status": SUCCEEDED, |
2268 | - "result-text": "Package locks successfully" |
2269 | - " changed.", |
2270 | - "result-code": 0}]) |
2271 | - |
2272 | - result = self.changer.handle_tasks() |
2273 | - return result.addCallback(assert_result) |
2274 | - |
2275 | - def test_dpkg_error(self): |
2276 | - """ |
2277 | - Verify that errors emitted by dpkg are correctly reported to |
2278 | - the server as problems. |
2279 | - |
2280 | - This test is to make sure that Smart reports the problem |
2281 | - correctly. It doesn't make sense for AptFacade, since there we |
2282 | - don't call dpkg. |
2283 | - """ |
2284 | - self.log_helper.ignore_errors(".*dpkg") |
2285 | - |
2286 | - installed_hash = self.set_pkg1_installed() |
2287 | - self.store.set_hash_ids({installed_hash: 1}) |
2288 | - self.store.add_task("changer", |
2289 | - {"type": "change-packages", "remove": [1], |
2290 | - "operation-id": 123}) |
2291 | - |
2292 | - result = self.changer.handle_tasks() |
2293 | - |
2294 | - def got_result(result): |
2295 | - messages = self.get_pending_messages() |
2296 | - self.assertEqual(len(messages), 1, "Too many messages") |
2297 | - message = messages[0] |
2298 | - self.assertEqual(message["operation-id"], 123) |
2299 | - self.assertEqual(message["result-code"], 100) |
2300 | - self.assertEqual(message["type"], "change-packages-result") |
2301 | - text = message["result-text"] |
2302 | - # We can't test the actual content of the message because the dpkg |
2303 | - # error can be localized |
2304 | - self.assertIn("\n[remove] name1_version1-release1\ndpkg: ", text) |
2305 | - self.assertIn("ERROR", text) |
2306 | - self.assertIn("(2)", text) |
2307 | - return result.addCallback(got_result) |
2308 | - |
2309 | - def test_change_package_holds(self): |
2310 | - """ |
2311 | - If C{SmartFacade} is used, the L{PackageChanger.handle_tasks} |
2312 | - method fails the activity, since it can't add or remove dpkg holds. |
2313 | - """ |
2314 | - self.facade.reload_channels() |
2315 | - self.store.add_task("changer", {"type": "change-package-holds", |
2316 | - "create": [1], |
2317 | - "delete": [2], |
2318 | - "operation-id": 123}) |
2319 | - |
2320 | - def assert_result(result): |
2321 | - self.assertIn("Queuing message with change package holds results " |
2322 | - "to exchange urgently.", self.logfile.getvalue()) |
2323 | - self.assertMessages( |
2324 | - self.get_pending_messages(), |
2325 | - [{"type": "operation-result", |
2326 | - "operation-id": 123, |
2327 | - "status": FAILED, |
2328 | - "result-text": "This client doesn't support package holds.", |
2329 | - "result-code": 1}]) |
2330 | - |
2331 | - result = self.changer.handle_tasks() |
2332 | - return result.addCallback(assert_result) |
2333 | - |
2334 | - def test_global_upgrade(self): |
2335 | - """ |
2336 | - Besides asking for individual changes, the server may also request |
2337 | - the client to perform a global upgrade. This would be the equivalent |
2338 | - of a "smart upgrade" command being executed in the command line. |
2339 | - |
2340 | - This test should be run for both C{AptFacade} and |
2341 | - C{SmartFacade}, but due to the smart test setting up that two |
2342 | - packages with different names upgrade each other, the message |
2343 | - doesn't correctly report that the old version should be |
2344 | - uninstalled. The test is still useful, since it shows that the |
2345 | - message contains the changes that smart says are needed. |
2346 | - |
2347 | - Making the test totally correct is a lot of work, that is not |
2348 | - worth doing, since we're removing smart soon. |
2349 | - """ |
2350 | - hash1, hash2 = self.set_pkg2_upgrades_pkg1() |
2351 | - self.store.set_hash_ids({hash1: 1, hash2: 2}) |
2352 | - |
2353 | - self.store.add_task("changer", |
2354 | - {"type": "change-packages", "upgrade-all": True, |
2355 | - "operation-id": 123}) |
2356 | - |
2357 | - result = self.changer.handle_tasks() |
2358 | - |
2359 | - def got_result(result): |
2360 | - self.assertMessages(self.get_pending_messages(), |
2361 | - [{"operation-id": 123, |
2362 | - "must-install": [2], |
2363 | - "result-code": 101, |
2364 | - "type": "change-packages-result"}]) |
2365 | - |
2366 | - return result.addCallback(got_result) |
2367 | - |
2368 | - |
2369 | -class AptPackageChangerTest(LandscapeTest, PackageChangerTestMixin): |
2370 | - |
2371 | - if not has_new_enough_apt: |
2372 | - skip = "Can't use AptFacade on hardy" |
2373 | - |
2374 | - helpers = [AptFacadeHelper, SimpleRepositoryHelper, BrokerServiceHelper] |
2375 | - |
2376 | - def setUp(self): |
2377 | - |
2378 | - def set_up(ignored): |
2379 | - |
2380 | - self.store = PackageStore(self.makeFile()) |
2381 | - self.config = PackageChangerConfiguration() |
2382 | - self.config.data_path = self.makeDir() |
2383 | - os.mkdir(self.config.package_directory) |
2384 | - os.mkdir(self.config.binaries_path) |
2385 | - touch_file(self.config.update_stamp_filename) |
2386 | - self.changer = PackageChanger( |
2387 | - self.store, self.facade, self.remote, self.config) |
2388 | - service = self.broker_service |
2389 | - service.message_store.set_accepted_types(["change-packages-result", |
2390 | - "operation-result"]) |
2391 | - |
2392 | - result = super(AptPackageChangerTest, self).setUp() |
2393 | - return result.addCallback(set_up) |
2394 | - |
2395 | - def set_pkg1_installed(self): |
2396 | - """Return the hash of a package that is installed.""" |
2397 | - self._add_system_package("foo") |
2398 | - self.facade.reload_channels() |
2399 | - [foo] = self.facade.get_packages_by_name("foo") |
2400 | - return self.facade.get_package_hash(foo) |
2401 | - |
2402 | - def set_pkg2_satisfied(self): |
2403 | - """Return the hash of a package that can be installed.""" |
2404 | - self._add_package_to_deb_dir(self.repository_dir, "bar") |
2405 | - self.facade.reload_channels() |
2406 | - [bar] = self.facade.get_packages_by_name("bar") |
2407 | - return self.facade.get_package_hash(bar) |
2408 | - |
2409 | - def set_pkg1_and_pkg2_satisfied(self): |
2410 | - """Make a package depend on another package. |
2411 | - |
2412 | - Return the hashes of the two packages. |
2413 | - """ |
2414 | - self._add_package_to_deb_dir( |
2415 | - self.repository_dir, "foo", control_fields={"Depends": "bar"}) |
2416 | - self._add_package_to_deb_dir(self.repository_dir, "bar") |
2417 | - self.facade.reload_channels() |
2418 | - [foo] = self.facade.get_packages_by_name("foo") |
2419 | - [bar] = self.facade.get_packages_by_name("bar") |
2420 | - return ( |
2421 | - self.facade.get_package_hash(foo), |
2422 | - self.facade.get_package_hash(bar)) |
2423 | - |
2424 | - def set_pkg2_upgrades_pkg1(self): |
2425 | - """Make it so that one package upgrades another. |
2426 | - |
2427 | - Return the hashes of the two packages. |
2428 | - """ |
2429 | - self._add_system_package("foo", version="1.0") |
2430 | - self._add_package_to_deb_dir(self.repository_dir, "foo", version="2.0") |
2431 | - self.facade.reload_channels() |
2432 | - foo_1, foo_2 = sorted(self.facade.get_packages_by_name("foo")) |
2433 | - return ( |
2434 | - self.facade.get_package_hash(foo_1), |
2435 | - self.facade.get_package_hash(foo_2)) |
2436 | - |
2437 | - def remove_pkg2(self): |
2438 | - """Remove package name2 from its repository.""" |
2439 | - packages_file = os.path.join(self.repository_dir, "Packages") |
2440 | - packages_contents = read_file(packages_file) |
2441 | - packages_contents = "\n\n".join( |
2442 | - [stanza for stanza in packages_contents.split("\n\n") |
2443 | - if "Package: name2" not in stanza]) |
2444 | - create_file(packages_file, packages_contents) |
2445 | - |
2446 | - def get_transaction_error_message(self): |
2447 | - """Return part of the apt transaction error message.""" |
2448 | - return "Unable to correct problems" |
2449 | - |
2450 | - def get_binaries_channels(self, binaries_path): |
2451 | - """Return the channels that will be used for the binaries.""" |
2452 | - return [{"baseurl": "file://%s" % binaries_path, |
2453 | - "components": "", |
2454 | - "distribution": "./", |
2455 | - "type": "deb"}] |
2456 | - |
2457 | - def get_package_name(self, version): |
2458 | - """Return the name of the package.""" |
2459 | - return version.package.name |
2460 | - |
2461 | def test_binaries_available_in_cache(self): |
2462 | """ |
2463 | If binaries are included in the changes-packages message, those |
2464 | @@ -1275,7 +976,7 @@ |
2465 | def test_change_package_holds(self): |
2466 | """ |
2467 | The L{PackageChanger.handle_tasks} method appropriately creates and |
2468 | - deletes package holds as requested by the C{change-package-holds} |
2469 | + deletes package holds as requested by the C{change-packages} |
2470 | message. |
2471 | """ |
2472 | self._add_system_package("foo") |
2473 | @@ -1292,23 +993,22 @@ |
2474 | old_mtime = time.time() - 10 |
2475 | os.utime(self.facade._dpkg_status, (old_mtime, old_mtime)) |
2476 | self.facade.reload_channels() |
2477 | - self.store.add_task("changer", {"type": "change-package-holds", |
2478 | - "create": [foo.package.id], |
2479 | - "delete": [bar.package.id], |
2480 | + self.store.add_task("changer", {"type": "change-packages", |
2481 | + "hold": [foo.package.id], |
2482 | + "remove-hold": [bar.package.id], |
2483 | "operation-id": 123}) |
2484 | |
2485 | def assert_result(result): |
2486 | self.facade.reload_channels() |
2487 | self.assertEqual(["foo"], self.facade.get_package_holds()) |
2488 | - self.assertIn("Queuing message with change package holds results " |
2489 | + self.assertIn("Queuing response with change package results " |
2490 | "to exchange urgently.", self.logfile.getvalue()) |
2491 | self.assertMessages( |
2492 | self.get_pending_messages(), |
2493 | - [{"type": "operation-result", |
2494 | + [{"type": "change-packages-result", |
2495 | "operation-id": 123, |
2496 | - "status": SUCCEEDED, |
2497 | "result-text": "Package holds successfully changed.", |
2498 | - "result-code": 0}]) |
2499 | + "result-code": 1}]) |
2500 | |
2501 | result = self.changer.handle_tasks() |
2502 | return result.addCallback(assert_result) |
2503 | @@ -1316,7 +1016,7 @@ |
2504 | def test_create_package_holds_with_identical_version(self): |
2505 | """ |
2506 | The L{PackageChanger.handle_tasks} method appropriately creates |
2507 | - holds as requested by the C{change-package-holds} message even |
2508 | + holds as requested by the C{change-packages} message even |
2509 | when versions from two different packages are the same. |
2510 | """ |
2511 | self._add_system_package("foo", version="1.1") |
2512 | @@ -1327,12 +1027,13 @@ |
2513 | [foo] = self.facade.get_packages_by_name("foo") |
2514 | [bar] = self.facade.get_packages_by_name("bar") |
2515 | self.facade.reload_channels() |
2516 | - self.store.add_task("changer", {"type": "change-package-holds", |
2517 | - "create": [foo.package.id, |
2518 | - bar.package.id], |
2519 | + self.store.add_task("changer", {"type": "change-packages", |
2520 | + "hold": [foo.package.id, |
2521 | + bar.package.id], |
2522 | "operation-id": 123}) |
2523 | |
2524 | def assert_result(result): |
2525 | + self.facade.reload_channels() |
2526 | self.assertEqual(["foo", "bar"], self.facade.get_package_holds()) |
2527 | |
2528 | result = self.changer.handle_tasks() |
2529 | @@ -1341,7 +1042,7 @@ |
2530 | def test_delete_package_holds_with_identical_version(self): |
2531 | """ |
2532 | The L{PackageChanger.handle_tasks} method appropriately deletes |
2533 | - holds as requested by the C{change-package-holds} message even |
2534 | + holds as requested by the C{change-packages} message even |
2535 | when versions from two different packages are the same. |
2536 | """ |
2537 | self._add_system_package("foo", version="1.1") |
2538 | @@ -1354,12 +1055,13 @@ |
2539 | self.facade.set_package_hold(foo) |
2540 | self.facade.set_package_hold(bar) |
2541 | self.facade.reload_channels() |
2542 | - self.store.add_task("changer", {"type": "change-package-holds", |
2543 | - "delete": [foo.package.id, |
2544 | - bar.package.id], |
2545 | + self.store.add_task("changer", {"type": "change-packages", |
2546 | + "remove-hold": [foo.package.id, |
2547 | + bar.package.id], |
2548 | "operation-id": 123}) |
2549 | |
2550 | def assert_result(result): |
2551 | + self.facade.reload_channels() |
2552 | self.assertEqual([], self.facade.get_package_holds()) |
2553 | |
2554 | result = self.changer.handle_tasks() |
2555 | @@ -1367,7 +1069,7 @@ |
2556 | |
2557 | def test_change_package_holds_create_already_held(self): |
2558 | """ |
2559 | - If the C{change-package-holds} message requests to add holds for |
2560 | + If the C{change-packages} message requests to add holds for |
2561 | packages that are already held, the activity succeeds, since the |
2562 | end result is that the requested package holds are there. |
2563 | """ |
2564 | @@ -1377,29 +1079,28 @@ |
2565 | [foo] = self.facade.get_packages_by_name("foo") |
2566 | self.facade.set_package_hold(foo) |
2567 | self.facade.reload_channels() |
2568 | - self.store.add_task("changer", {"type": "change-package-holds", |
2569 | - "create": [foo.package.id], |
2570 | + self.store.add_task("changer", {"type": "change-packages", |
2571 | + "hold": [foo.package.id], |
2572 | "operation-id": 123}) |
2573 | |
2574 | def assert_result(result): |
2575 | self.facade.reload_channels() |
2576 | self.assertEqual(["foo"], self.facade.get_package_holds()) |
2577 | - self.assertIn("Queuing message with change package holds results " |
2578 | + self.assertIn("Queuing response with change package results " |
2579 | "to exchange urgently.", self.logfile.getvalue()) |
2580 | self.assertMessages( |
2581 | self.get_pending_messages(), |
2582 | - [{"type": "operation-result", |
2583 | + [{"type": "change-packages-result", |
2584 | "operation-id": 123, |
2585 | - "status": SUCCEEDED, |
2586 | "result-text": "Package holds successfully changed.", |
2587 | - "result-code": 0}]) |
2588 | + "result-code": 1}]) |
2589 | |
2590 | result = self.changer.handle_tasks() |
2591 | return result.addCallback(assert_result) |
2592 | |
2593 | def test_change_package_holds_create_other_version_installed(self): |
2594 | """ |
2595 | - If the C{change-package-holds} message requests to add holds for |
2596 | + If the C{change-packages} message requests to add holds for |
2597 | packages that have a different version installed than the one |
2598 | being requested to hold, the activity fails. |
2599 | |
2600 | @@ -1420,30 +1121,29 @@ |
2601 | self.facade.get_package_hash(bar1): 3, |
2602 | self.facade.get_package_hash(bar2): 4}) |
2603 | self.facade.reload_channels() |
2604 | - self.store.add_task("changer", {"type": "change-package-holds", |
2605 | - "create": [2, 3], |
2606 | + self.store.add_task("changer", {"type": "change-packages", |
2607 | + "hold": [2, 3], |
2608 | "operation-id": 123}) |
2609 | |
2610 | def assert_result(result): |
2611 | self.facade.reload_channels() |
2612 | self.assertEqual([], self.facade.get_package_holds()) |
2613 | - self.assertIn("Queuing message with change package holds results " |
2614 | + self.assertIn("Queuing response with change package results " |
2615 | "to exchange urgently.", self.logfile.getvalue()) |
2616 | self.assertMessages( |
2617 | self.get_pending_messages(), |
2618 | - [{"type": "operation-result", |
2619 | + [{"type": "change-packages-result", |
2620 | "operation-id": 123, |
2621 | - "status": FAILED, |
2622 | - "result-text": "Package holds not changed, since the" + |
2623 | - " following packages are not installed: 2", |
2624 | - "result-code": 1}]) |
2625 | + "result-text": "Cannot perform the changes, since the" + |
2626 | + " following packages are not installed: foo", |
2627 | + "result-code": 100}]) |
2628 | |
2629 | result = self.changer.handle_tasks() |
2630 | return result.addCallback(assert_result) |
2631 | |
2632 | def test_change_package_holds_create_not_installed(self): |
2633 | """ |
2634 | - If the C{change-package-holds} message requests to add holds for |
2635 | + If the C{change-packages} message requests to add holds for |
2636 | packages that aren't installed, the whole activity is failed. If |
2637 | multiple holds are specified, those won't be added. There's no |
2638 | difference between a package that is available in some |
2639 | @@ -1460,62 +1160,71 @@ |
2640 | [foo] = self.facade.get_packages_by_name("foo") |
2641 | [bar] = self.facade.get_packages_by_name("bar") |
2642 | [baz] = self.facade.get_packages_by_name("baz") |
2643 | - self.store.add_task("changer", {"type": "change-package-holds", |
2644 | - "create": [foo.package.id, |
2645 | - bar.package.id, |
2646 | - baz.package.id], |
2647 | + self.store.add_task("changer", {"type": "change-packages", |
2648 | + "hold": [foo.package.id, |
2649 | + bar.package.id, |
2650 | + baz.package.id], |
2651 | "operation-id": 123}) |
2652 | |
2653 | def assert_result(result): |
2654 | self.facade.reload_channels() |
2655 | self.assertEqual([], self.facade.get_package_holds()) |
2656 | - self.assertIn("Queuing message with change package holds results " |
2657 | + self.assertIn("Queuing response with change package results " |
2658 | "to exchange urgently.", self.logfile.getvalue()) |
2659 | self.assertMessages( |
2660 | self.get_pending_messages(), |
2661 | - [{"type": "operation-result", |
2662 | + [{"type": "change-packages-result", |
2663 | "operation-id": 123, |
2664 | - "status": FAILED, |
2665 | - "result-text": "Package holds not changed, since the " |
2666 | + "result-text": "Cannot perform the changes, since the " |
2667 | "following packages are not installed: " |
2668 | - "%s, %s" % tuple(sorted([bar.package.id, |
2669 | - baz.package.id])), |
2670 | - "result-code": 1}]) |
2671 | + "%s, %s" % tuple(sorted([bar.package.name, |
2672 | + baz.package.name])), |
2673 | + "result-code": 100}]) |
2674 | |
2675 | result = self.changer.handle_tasks() |
2676 | return result.addCallback(assert_result) |
2677 | |
2678 | def test_change_package_holds_create_unknown_hash(self): |
2679 | """ |
2680 | - If the C{change-package-holds} message requests to add holds for |
2681 | - packages that the client doesn't know about, it's being treated |
2682 | - as the packages not being installed. |
2683 | + If the C{change-packages} message requests to add holds for |
2684 | + packages that the client doesn't know about results in a not yet |
2685 | + synchronized message and a failure of the operation. |
2686 | """ |
2687 | - self.facade.reload_channels() |
2688 | - self.store.add_task("changer", {"type": "change-package-holds", |
2689 | - "create": [1], |
2690 | - "operation-id": 123}) |
2691 | - |
2692 | - def assert_result(result): |
2693 | - self.facade.reload_channels() |
2694 | - self.assertEqual([], self.facade.get_package_holds()) |
2695 | - self.assertIn("Queuing message with change package holds results " |
2696 | - "to exchange urgently.", self.logfile.getvalue()) |
2697 | - self.assertMessages( |
2698 | - self.get_pending_messages(), |
2699 | - [{"type": "operation-result", |
2700 | - "operation-id": 123, |
2701 | - "status": FAILED, |
2702 | - "result-text": "Package holds not changed, since the" + |
2703 | - " following packages are not installed: 1", |
2704 | - "result-code": 1}]) |
2705 | - |
2706 | - result = self.changer.handle_tasks() |
2707 | - return result.addCallback(assert_result) |
2708 | + |
2709 | + self.store.add_task("changer", |
2710 | + {"type": "change-packages", |
2711 | + "hold": [123], |
2712 | + "operation-id": 123}) |
2713 | + |
2714 | + time_mock = self.mocker.replace("time.time") |
2715 | + time_mock() |
2716 | + self.mocker.result(time.time() + UNKNOWN_PACKAGE_DATA_TIMEOUT) |
2717 | + self.mocker.count(1, None) |
2718 | + self.mocker.replay() |
2719 | + |
2720 | + try: |
2721 | + result = self.changer.handle_tasks() |
2722 | + self.mocker.verify() |
2723 | + finally: |
2724 | + # Reset it earlier so that Twisted has the true time function. |
2725 | + self.mocker.reset() |
2726 | + |
2727 | + self.assertIn("Package data not yet synchronized with server (123)", |
2728 | + self.logfile.getvalue()) |
2729 | + |
2730 | + def got_result(result): |
2731 | + message = {"type": "change-packages-result", |
2732 | + "operation-id": 123, |
2733 | + "result-code": 100, |
2734 | + "result-text": "Package data has changed. " |
2735 | + "Please retry the operation."} |
2736 | + self.assertMessages(self.get_pending_messages(), [message]) |
2737 | + self.assertEqual(self.store.get_next_task("changer"), None) |
2738 | + return result.addCallback(got_result) |
2739 | |
2740 | def test_change_package_holds_delete_not_held(self): |
2741 | """ |
2742 | - If the C{change-package-holds} message requests to remove holds |
2743 | + If the C{change-packages} message requests to remove holds |
2744 | for packages that aren't held, the activity succeeds if the |
2745 | right version is installed, since the end result is that the |
2746 | hold is removed. |
2747 | @@ -1524,29 +1233,28 @@ |
2748 | self.facade.reload_channels() |
2749 | self._hash_packages_by_name(self.facade, self.store, "foo") |
2750 | [foo] = self.facade.get_packages_by_name("foo") |
2751 | - self.store.add_task("changer", {"type": "change-package-holds", |
2752 | - "delete": [foo.package.id], |
2753 | + self.store.add_task("changer", {"type": "change-packages", |
2754 | + "remove-hold": [foo.package.id], |
2755 | "operation-id": 123}) |
2756 | |
2757 | def assert_result(result): |
2758 | self.facade.reload_channels() |
2759 | self.assertEqual([], self.facade.get_package_holds()) |
2760 | - self.assertIn("Queuing message with change package holds results " |
2761 | + self.assertIn("Queuing response with change package results " |
2762 | "to exchange urgently.", self.logfile.getvalue()) |
2763 | self.assertMessages( |
2764 | self.get_pending_messages(), |
2765 | - [{"type": "operation-result", |
2766 | + [{"type": "change-packages-result", |
2767 | "operation-id": 123, |
2768 | - "status": SUCCEEDED, |
2769 | "result-text": "Package holds successfully changed.", |
2770 | - "result-code": 0}]) |
2771 | + "result-code": 1}]) |
2772 | |
2773 | result = self.changer.handle_tasks() |
2774 | return result.addCallback(assert_result) |
2775 | |
2776 | def test_change_package_holds_delete_different_version_held(self): |
2777 | """ |
2778 | - If the C{change-package-holds} message requests to remove holds |
2779 | + If the C{change-packages} message requests to remove holds |
2780 | for packages that aren't held, the activity succeeds if the |
2781 | right version is installed, since the end result is that the |
2782 | hold is removed. |
2783 | @@ -1556,60 +1264,34 @@ |
2784 | self.repository_dir, "foo", version="2.0") |
2785 | self.facade.reload_channels() |
2786 | [foo1, foo2] = sorted(self.facade.get_packages_by_name("foo")) |
2787 | - self.facade.set_package_hold(foo1) |
2788 | self.store.set_hash_ids({self.facade.get_package_hash(foo1): 1, |
2789 | self.facade.get_package_hash(foo2): 2}) |
2790 | + self.facade.mark_install(foo1) |
2791 | + self.facade.mark_hold(foo1) |
2792 | + self.facade.perform_changes() |
2793 | self.facade.reload_channels() |
2794 | - self.store.add_task("changer", {"type": "change-package-holds", |
2795 | - "delete": [2], |
2796 | + self.store.add_task("changer", {"type": "change-packages", |
2797 | + "remove-hold": [2], |
2798 | "operation-id": 123}) |
2799 | |
2800 | def assert_result(result): |
2801 | self.facade.reload_channels() |
2802 | self.assertEqual(["foo"], self.facade.get_package_holds()) |
2803 | - self.assertIn("Queuing message with change package holds results " |
2804 | - "to exchange urgently.", self.logfile.getvalue()) |
2805 | - self.assertMessages( |
2806 | - self.get_pending_messages(), |
2807 | - [{"type": "operation-result", |
2808 | - "operation-id": 123, |
2809 | - "status": SUCCEEDED, |
2810 | - "result-text": "Package holds successfully changed.", |
2811 | - "result-code": 0}]) |
2812 | - |
2813 | - result = self.changer.handle_tasks() |
2814 | - return result.addCallback(assert_result) |
2815 | - |
2816 | - def test_change_package_holds_delete_unknown_hash(self): |
2817 | - """ |
2818 | - If the C{change-package-holds} message requests to remove holds |
2819 | - for packages that aren't known by the client, the activity |
2820 | - succeeds, since the end result is that the package isn't |
2821 | - held at that version. |
2822 | - """ |
2823 | - self.store.add_task("changer", {"type": "change-package-holds", |
2824 | - "delete": [1], |
2825 | - "operation-id": 123}) |
2826 | - |
2827 | - def assert_result(result): |
2828 | - self.facade.reload_channels() |
2829 | - self.assertEqual([], self.facade.get_package_holds()) |
2830 | - self.assertIn("Queuing message with change package holds results " |
2831 | - "to exchange urgently.", self.logfile.getvalue()) |
2832 | - self.assertMessages( |
2833 | - self.get_pending_messages(), |
2834 | - [{"type": "operation-result", |
2835 | - "operation-id": 123, |
2836 | - "status": SUCCEEDED, |
2837 | - "result-text": "Package holds successfully changed.", |
2838 | - "result-code": 0}]) |
2839 | + self.assertIn("Queuing response with change package results " |
2840 | + "to exchange urgently.", self.logfile.getvalue()) |
2841 | + self.assertMessages( |
2842 | + self.get_pending_messages(), |
2843 | + [{"type": "change-packages-result", |
2844 | + "operation-id": 123, |
2845 | + "result-text": "Package holds successfully changed.", |
2846 | + "result-code": 1}]) |
2847 | |
2848 | result = self.changer.handle_tasks() |
2849 | return result.addCallback(assert_result) |
2850 | |
2851 | def test_change_package_holds_delete_not_installed(self): |
2852 | """ |
2853 | - If the C{change-package-holds} message requests to remove holds |
2854 | + If the C{change-packages} message requests to remove holds |
2855 | for packages that aren't installed, the activity succeeds, since |
2856 | the end result is still that the package isn't held at the |
2857 | requested version. |
2858 | @@ -1618,31 +1300,30 @@ |
2859 | self.facade.reload_channels() |
2860 | self._hash_packages_by_name(self.facade, self.store, "foo") |
2861 | [foo] = self.facade.get_packages_by_name("foo") |
2862 | - self.store.add_task("changer", {"type": "change-package-holds", |
2863 | - "delete": [foo.package.id], |
2864 | + self.store.add_task("changer", {"type": "change-packages", |
2865 | + "remove-hold": [foo.package.id], |
2866 | "operation-id": 123}) |
2867 | |
2868 | def assert_result(result): |
2869 | self.facade.reload_channels() |
2870 | self.assertEqual([], self.facade.get_package_holds()) |
2871 | - self.assertIn("Queuing message with change package holds results " |
2872 | + self.assertIn("Queuing response with change package results " |
2873 | "to exchange urgently.", self.logfile.getvalue()) |
2874 | self.assertMessages( |
2875 | self.get_pending_messages(), |
2876 | - [{"type": "operation-result", |
2877 | + [{"type": "change-packages-result", |
2878 | "operation-id": 123, |
2879 | - "status": SUCCEEDED, |
2880 | "result-text": "Package holds successfully changed.", |
2881 | - "result-code": 0}]) |
2882 | + "result-code": 1}]) |
2883 | |
2884 | result = self.changer.handle_tasks() |
2885 | return result.addCallback(assert_result) |
2886 | |
2887 | def test_change_package_locks(self): |
2888 | """ |
2889 | - If C{AptFacade} is used, the L{PackageChanger.handle_tasks} |
2890 | - method fails the activity, since it can't add or remove locks because |
2891 | - apt doesn't support this. |
2892 | + The L{PackageChanger.handle_tasks} method fails |
2893 | + change-package-locks activities, since it can't add or remove |
2894 | + locks because apt doesn't support this. |
2895 | """ |
2896 | self.store.add_task("changer", {"type": "change-package-locks", |
2897 | "create": [("foo", ">=", "1.0")], |
2898 | |
2899 | === modified file 'landscape/package/tests/test_facade.py' |
2900 | --- landscape/package/tests/test_facade.py 2012-03-21 16:15:49 +0000 |
2901 | +++ landscape/package/tests/test_facade.py 2012-06-04 14:08:28 +0000 |
2902 | @@ -1,40 +1,22 @@ |
2903 | -import time |
2904 | import os |
2905 | -import re |
2906 | -import sys |
2907 | import textwrap |
2908 | import tempfile |
2909 | |
2910 | -try: |
2911 | - import smart |
2912 | - from smart.control import Control |
2913 | - from smart.cache import Provides |
2914 | - from smart.const import NEVER, ALWAYS |
2915 | -except ImportError: |
2916 | - # Smart is optional if AptFacade is being used. |
2917 | - pass |
2918 | - |
2919 | import apt_pkg |
2920 | from apt.package import Package |
2921 | from aptsources.sourceslist import SourcesList |
2922 | |
2923 | -from twisted.internet import reactor |
2924 | -from twisted.internet.defer import Deferred |
2925 | -from twisted.internet.utils import getProcessOutputAndValue |
2926 | - |
2927 | from landscape.constants import UBUNTU_PATH |
2928 | from landscape.lib.fs import read_file, create_file |
2929 | -from landscape.package import facade as facade_module |
2930 | from landscape.package.facade import ( |
2931 | - TransactionError, DependencyError, ChannelError, SmartError, AptFacade, |
2932 | - has_new_enough_apt) |
2933 | + TransactionError, DependencyError, ChannelError, AptFacade) |
2934 | |
2935 | from landscape.tests.mocker import ANY |
2936 | from landscape.tests.helpers import LandscapeTest, EnvironSaverHelper |
2937 | from landscape.package.tests.helpers import ( |
2938 | - SmartFacadeHelper, HASH1, HASH2, HASH3, PKGNAME1, PKGNAME2, PKGNAME3, |
2939 | - PKGNAME4, PKGDEB4, PKGDEB1, PKGNAME_MINIMAL, PKGDEB_MINIMAL, |
2940 | - create_full_repository, create_deb, AptFacadeHelper, |
2941 | + HASH1, HASH2, HASH3, PKGNAME1, PKGNAME2, PKGNAME3, |
2942 | + PKGDEB1, PKGNAME_MINIMAL, PKGDEB_MINIMAL, |
2943 | + create_deb, AptFacadeHelper, |
2944 | create_simple_repository) |
2945 | |
2946 | |
2947 | @@ -60,9 +42,6 @@ |
2948 | |
2949 | class AptFacadeTest(LandscapeTest): |
2950 | |
2951 | - if not has_new_enough_apt: |
2952 | - skip = "Can't use AptFacade on hardy" |
2953 | - |
2954 | helpers = [AptFacadeHelper, EnvironSaverHelper] |
2955 | |
2956 | def version_sortkey(self, version): |
2957 | @@ -1564,16 +1543,24 @@ |
2958 | self._add_package_to_deb_dir(deb_dir, "bar", version="1.5") |
2959 | self._add_system_package("baz") |
2960 | self.facade.add_channel_apt_deb("file://%s" % deb_dir, "./") |
2961 | + self._add_system_package("quux", version="1.0") |
2962 | + self._add_system_package("wibble", version="1.0") |
2963 | self.facade.reload_channels() |
2964 | [foo] = self.facade.get_packages_by_name("foo") |
2965 | self.facade.mark_install(foo) |
2966 | self.facade.mark_global_upgrade() |
2967 | [baz] = self.facade.get_packages_by_name("baz") |
2968 | self.facade.mark_remove(baz) |
2969 | + [quux] = self.facade.get_packages_by_name("quux") |
2970 | + self.facade.mark_hold(quux) |
2971 | + [wibble] = self.facade.get_packages_by_name("wibble") |
2972 | + self.facade.mark_remove_hold(wibble) |
2973 | self.facade.reset_marks() |
2974 | self.assertEqual(self.facade._version_installs, []) |
2975 | self.assertEqual(self.facade._version_removals, []) |
2976 | self.assertFalse(self.facade._global_upgrade) |
2977 | + self.assertEqual(self.facade._version_hold_creations, []) |
2978 | + self.assertEqual(self.facade._version_hold_removals, []) |
2979 | self.assertEqual(self.facade.perform_changes(), None) |
2980 | |
2981 | def test_reset_marks_resets_cache(self): |
2982 | @@ -2349,50 +2336,81 @@ |
2983 | self.assertEqual( |
2984 | ["baz", "foo"], sorted(self.facade.get_package_holds())) |
2985 | |
2986 | - def test_set_package_hold(self): |
2987 | - """ |
2988 | - C{set_package_hold} marks a package to be on hold. |
2989 | - """ |
2990 | - self._add_system_package("foo") |
2991 | - self.facade.reload_channels() |
2992 | - [foo] = self.facade.get_packages_by_name("foo") |
2993 | - self.facade.set_package_hold(foo) |
2994 | - self.facade.reload_channels() |
2995 | - |
2996 | - self.assertEqual(["foo"], self.facade.get_package_holds()) |
2997 | - |
2998 | - def test_set_package_hold_existing_hold(self): |
2999 | - """ |
3000 | - If a package is already hel, C{set_package_hold} doesn't return |
3001 | - an error. |
3002 | - """ |
3003 | - self._add_system_package( |
3004 | - "foo", control_fields={"Status": "hold ok installed"}) |
3005 | - self.facade.reload_channels() |
3006 | - [foo] = self.facade.get_packages_by_name("foo") |
3007 | - self.facade.set_package_hold(foo) |
3008 | - self.facade.reload_channels() |
3009 | - |
3010 | - self.assertEqual(["foo"], self.facade.get_package_holds()) |
3011 | - |
3012 | - def test_remove_package_hold(self): |
3013 | - """ |
3014 | - C{remove_package_hold} marks a package not to be on hold. |
3015 | - """ |
3016 | - self._add_system_package( |
3017 | - "foo", control_fields={"Status": "hold ok installed"}) |
3018 | - self.facade.reload_channels() |
3019 | - [foo] = self.facade.get_packages_by_name("foo") |
3020 | - self.facade.remove_package_hold(foo) |
3021 | + def test_mark_hold_and_perform_hold_changes(self): |
3022 | + """ |
3023 | + Test that L{perform_hold_changes} holds packages that have previously |
3024 | + been marked for hold. |
3025 | + """ |
3026 | + self._add_system_package("foo") |
3027 | + self.facade.reload_channels() |
3028 | + [foo] = self.facade.get_packages_by_name("foo") |
3029 | + self.facade.mark_hold(foo) |
3030 | + self.assertEqual("Package holds successfully changed.", |
3031 | + self.facade._perform_hold_changes()) |
3032 | + self.facade.reload_channels() |
3033 | + self.assertEqual(["foo"], self.facade.get_package_holds()) |
3034 | + |
3035 | + def test_mark_hold(self): |
3036 | + """ |
3037 | + C{mark_hold} marks a package to be held. |
3038 | + """ |
3039 | + self._add_system_package("foo") |
3040 | + self.facade.reload_channels() |
3041 | + [foo] = self.facade.get_packages_by_name("foo") |
3042 | + self.facade.mark_hold(foo) |
3043 | + self.facade.perform_changes() |
3044 | + self.facade.reload_channels() |
3045 | + self.assertEqual(["foo"], self.facade.get_package_holds()) |
3046 | + |
3047 | + def test_two_holds_with_the_same_version_id(self): |
3048 | + """ |
3049 | + Test C{mark_hold} can distinguish between two different packages with |
3050 | + the same version number (the version number is used to make the unique |
3051 | + hash for the package version). |
3052 | + """ |
3053 | + self._add_system_package("foo", version="1.0") |
3054 | + self._add_system_package("bar", version="1.0") |
3055 | + self.facade.reload_channels() |
3056 | + [foo] = self.facade.get_packages_by_name("foo") |
3057 | + [bar] = self.facade.get_packages_by_name("bar") |
3058 | + self.facade.mark_hold(foo) |
3059 | + self.facade.mark_hold(bar) |
3060 | + self.assertEqual(2, len(self.facade._version_hold_creations)) |
3061 | + |
3062 | + def test_mark_hold_existing_hold(self): |
3063 | + """ |
3064 | + If a package is already held, C{mark_hold} and |
3065 | + C{perform_changes} won't return an error. |
3066 | + """ |
3067 | + self._add_system_package( |
3068 | + "foo", control_fields={"Status": "hold ok installed"}) |
3069 | + self.facade.reload_channels() |
3070 | + [foo] = self.facade.get_packages_by_name("foo") |
3071 | + self.facade.mark_hold(foo) |
3072 | + self.facade.perform_changes() |
3073 | + self.facade.reload_channels() |
3074 | + |
3075 | + self.assertEqual(["foo"], self.facade.get_package_holds()) |
3076 | + |
3077 | + def test_mark_remove_hold(self): |
3078 | + """ |
3079 | + C{mark_remove_hold} marks a package as not held. |
3080 | + """ |
3081 | + self._add_system_package( |
3082 | + "foo", control_fields={"Status": "hold ok installed"}) |
3083 | + self.facade.reload_channels() |
3084 | + [foo] = self.facade.get_packages_by_name("foo") |
3085 | + self.facade.mark_remove_hold(foo) |
3086 | + self.facade.perform_changes() |
3087 | self.facade.reload_channels() |
3088 | |
3089 | self.assertEqual([], self.facade.get_package_holds()) |
3090 | |
3091 | - def test_remove_package_hold_no_package(self): |
3092 | + def test_mark_remove_hold_no_package(self): |
3093 | """ |
3094 | - If a package doesn't exist, C{remove_package_hold} doesn't |
3095 | - return an error. It's up to the caller to make sure that the |
3096 | - package exist, if it's important. |
3097 | + If a package doesn't exist, C{mark_remove_hold} followed by |
3098 | + C{perform_changes} doesn't return an error. It's up to the caller to |
3099 | + make sure that the package exist, if it's important. |
3100 | """ |
3101 | self._add_system_package("foo") |
3102 | deb_dir = self.makeDir() |
3103 | @@ -2400,21 +2418,23 @@ |
3104 | self.facade.add_channel_apt_deb("file://%s" % deb_dir, "./") |
3105 | self.facade.reload_channels() |
3106 | [bar] = self.facade.get_packages_by_name("bar") |
3107 | - self.facade.remove_package_hold(bar) |
3108 | + self.facade.mark_remove_hold(bar) |
3109 | + self.facade.perform_changes() |
3110 | self.facade.reload_channels() |
3111 | |
3112 | self.assertEqual([], self.facade.get_package_holds()) |
3113 | |
3114 | - def test_remove_package_hold_no_hold(self): |
3115 | + def test_mark_remove_hold_no_hold(self): |
3116 | """ |
3117 | If a package isn't held, the existing selection is retained when |
3118 | - C{remove_package_hold} is called. |
3119 | + C{mark_remove_hold} and C{perform_changes} are called. |
3120 | """ |
3121 | self._add_system_package( |
3122 | "foo", control_fields={"Status": "deinstall ok installed"}) |
3123 | self.facade.reload_channels() |
3124 | [foo] = self.facade.get_packages_by_name("foo") |
3125 | - self.facade.remove_package_hold(foo) |
3126 | + self.facade.mark_remove_hold(foo) |
3127 | + self.facade.perform_changes() |
3128 | self.facade.reload_channels() |
3129 | |
3130 | self.assertEqual([], self.facade.get_package_holds()) |
3131 | @@ -2430,670 +2450,3 @@ |
3132 | test_wb_mark_install_upgrade_non_main_arch_dependency_error.skip = ( |
3133 | skip_message) |
3134 | test_wb_mark_install_upgrade_non_main_arch.skip = skip_message |
3135 | - |
3136 | - |
3137 | -class SmartFacadeTest(LandscapeTest): |
3138 | - |
3139 | - helpers = [SmartFacadeHelper] |
3140 | - |
3141 | - def test_needs_smart(self): |
3142 | - """ |
3143 | - If the Smart python modules can't be imported, a C{RuntimeError} |
3144 | - is raised when trying to create a C{SmartFacade}. |
3145 | - """ |
3146 | - |
3147 | - def reset_has_smart(): |
3148 | - facade_module.has_smart = old_has_smart |
3149 | - |
3150 | - self.addCleanup(reset_has_smart) |
3151 | - old_has_smart = facade_module.has_smart |
3152 | - facade_module.has_smart = False |
3153 | - |
3154 | - self.assertRaises(RuntimeError, self.Facade) |
3155 | - |
3156 | - def test_get_packages(self): |
3157 | - self.facade.reload_channels() |
3158 | - pkgs = self.facade.get_packages() |
3159 | - self.assertEqual(sorted(pkg.name for pkg in pkgs), |
3160 | - ["name1", "name2", "name3"]) |
3161 | - |
3162 | - def test_get_packages_wont_return_non_debian_packages(self): |
3163 | - self.facade.reload_channels() |
3164 | - ctrl_mock = self.mocker.patch(Control) |
3165 | - |
3166 | - class StubPackage(object): |
3167 | - pass |
3168 | - |
3169 | - cache_mock = ctrl_mock.getCache() |
3170 | - cache_mock.getPackages() |
3171 | - self.mocker.result([StubPackage(), StubPackage()]) |
3172 | - self.mocker.replay() |
3173 | - self.assertEqual(self.facade.get_packages(), []) |
3174 | - |
3175 | - def test_get_packages_by_name(self): |
3176 | - self.facade.reload_channels() |
3177 | - pkgs = self.facade.get_packages_by_name("name1") |
3178 | - self.assertEqual([pkg.name for pkg in pkgs], ["name1"]) |
3179 | - pkgs = self.facade.get_packages_by_name("name2") |
3180 | - self.assertEqual([pkg.name for pkg in pkgs], ["name2"]) |
3181 | - |
3182 | - def test_get_packages_by_name_wont_return_non_debian_packages(self): |
3183 | - self.facade.reload_channels() |
3184 | - ctrl_mock = self.mocker.patch(Control) |
3185 | - |
3186 | - class StubPackage(object): |
3187 | - pass |
3188 | - |
3189 | - cache_mock = ctrl_mock.getCache() |
3190 | - cache_mock.getPackages("name") |
3191 | - self.mocker.result([StubPackage(), StubPackage()]) |
3192 | - self.mocker.replay() |
3193 | - self.assertEqual(self.facade.get_packages_by_name("name"), []) |
3194 | - |
3195 | - def test_get_package_skeleton(self): |
3196 | - self.facade.reload_channels() |
3197 | - [pkg1] = self.facade.get_packages_by_name("name1") |
3198 | - [pkg2] = self.facade.get_packages_by_name("name2") |
3199 | - skeleton1 = self.facade.get_package_skeleton(pkg1) |
3200 | - skeleton2 = self.facade.get_package_skeleton(pkg2) |
3201 | - self.assertEqual(skeleton1.get_hash(), HASH1) |
3202 | - self.assertEqual(skeleton2.get_hash(), HASH2) |
3203 | - |
3204 | - def test_build_skeleton_with_info(self): |
3205 | - self.facade.reload_channels() |
3206 | - [pkg] = self.facade.get_packages_by_name("name1") |
3207 | - skeleton = self.facade.get_package_skeleton(pkg, True) |
3208 | - self.assertEqual(skeleton.section, "Group1") |
3209 | - self.assertEqual(skeleton.summary, "Summary1") |
3210 | - self.assertEqual(skeleton.description, "Description1") |
3211 | - self.assertEqual(skeleton.size, 1038) |
3212 | - self.assertEqual(skeleton.installed_size, 28672) |
3213 | - |
3214 | - def test_get_package_hash(self): |
3215 | - self.facade.reload_channels() |
3216 | - [pkg] = self.facade.get_packages_by_name("name1") |
3217 | - self.assertEqual(self.facade.get_package_hash(pkg), HASH1) |
3218 | - [pkg] = self.facade.get_packages_by_name("name2") |
3219 | - self.assertEqual(self.facade.get_package_hash(pkg), HASH2) |
3220 | - |
3221 | - def test_get_package_hashes(self): |
3222 | - self.facade.reload_channels() |
3223 | - hashes = self.facade.get_package_hashes() |
3224 | - self.assertEqual(sorted(hashes), sorted([HASH1, HASH2, HASH3])) |
3225 | - |
3226 | - def test_get_package_by_hash(self): |
3227 | - self.facade.reload_channels() |
3228 | - pkg = self.facade.get_package_by_hash(HASH1) |
3229 | - self.assertEqual(pkg.name, "name1") |
3230 | - pkg = self.facade.get_package_by_hash(HASH2) |
3231 | - self.assertEqual(pkg.name, "name2") |
3232 | - pkg = self.facade.get_package_by_hash("none") |
3233 | - self.assertEqual(pkg, None) |
3234 | - |
3235 | - def test_reload_channels_clears_hash_cache(self): |
3236 | - # Load hashes. |
3237 | - self.facade.reload_channels() |
3238 | - |
3239 | - # Hold a reference to packages. |
3240 | - [pkg1] = self.facade.get_packages_by_name("name1") |
3241 | - [pkg2] = self.facade.get_packages_by_name("name2") |
3242 | - [pkg3] = self.facade.get_packages_by_name("name3") |
3243 | - self.assertTrue(pkg1 and pkg2) |
3244 | - |
3245 | - # Remove the package from the repository. |
3246 | - os.unlink(os.path.join(self.repository_dir, PKGNAME1)) |
3247 | - |
3248 | - # Forcibly change the mtime of our repository, so that Smart |
3249 | - # will consider it as changed (if the change is inside the |
3250 | - # same second the directory's mtime will be the same) |
3251 | - mtime = int(time.time() + 1) |
3252 | - os.utime(self.repository_dir, (mtime, mtime)) |
3253 | - |
3254 | - # Reload channels. |
3255 | - self.facade.reload_channels() |
3256 | - |
3257 | - # Only packages with name2 and name3 should be loaded, and they're |
3258 | - # not the same objects anymore. |
3259 | - self.assertEqual( |
3260 | - sorted([pkg.name for pkg in self.facade.get_packages()]), |
3261 | - ["name2", "name3"]) |
3262 | - self.assertNotEquals(set(self.facade.get_packages()), |
3263 | - set([pkg2, pkg3])) |
3264 | - |
3265 | - # The hash cache shouldn't include either of the old packages. |
3266 | - self.assertEqual(self.facade.get_package_hash(pkg1), None) |
3267 | - self.assertEqual(self.facade.get_package_hash(pkg2), None) |
3268 | - self.assertEqual(self.facade.get_package_hash(pkg3), None) |
3269 | - |
3270 | - # Also, the hash for package1 shouldn't be present at all. |
3271 | - self.assertEqual(self.facade.get_package_by_hash(HASH1), None) |
3272 | - |
3273 | - # While HASH2 and HASH3 should point to the new packages. |
3274 | - new_pkgs = self.facade.get_packages() |
3275 | - self.assertTrue(self.facade.get_package_by_hash(HASH2) |
3276 | - in new_pkgs) |
3277 | - self.assertTrue(self.facade.get_package_by_hash(HASH3) |
3278 | - in new_pkgs) |
3279 | - |
3280 | - # Which are not the old packages. |
3281 | - self.assertFalse(pkg2 in new_pkgs) |
3282 | - self.assertFalse(pkg3 in new_pkgs) |
3283 | - |
3284 | - def test_ensure_reload_channels(self): |
3285 | - """ |
3286 | - The L{SmartFacade.ensure_channels_reloaded} can be called more |
3287 | - than once, but channels will be reloaded only the first time. |
3288 | - """ |
3289 | - self.assertEqual(len(self.facade.get_packages()), 0) |
3290 | - self.facade.ensure_channels_reloaded() |
3291 | - self.assertEqual(len(self.facade.get_packages()), 3) |
3292 | - |
3293 | - # Calling it once more won't reload channels again. |
3294 | - self.facade.get_packages_by_name("name1")[0].installed = True |
3295 | - self.facade.ensure_channels_reloaded() |
3296 | - self.assertTrue(self.facade.get_packages_by_name("name1")[0].installed) |
3297 | - |
3298 | - def test_perform_changes_with_nothing_to_do(self): |
3299 | - """perform_changes() should return None when there's nothing to do. |
3300 | - """ |
3301 | - self.facade.reload_channels() |
3302 | - self.assertEqual(self.facade.perform_changes(), None) |
3303 | - |
3304 | - def test_reset_marks(self): |
3305 | - """perform_changes() should return None when there's nothing to do. |
3306 | - """ |
3307 | - self.facade.reload_channels() |
3308 | - [pkg] = self.facade.get_packages_by_name("name1") |
3309 | - self.facade.mark_install(pkg) |
3310 | - self.facade.reset_marks() |
3311 | - self.assertEqual(self.facade.perform_changes(), None) |
3312 | - |
3313 | - def test_mark_install_transaction_error(self): |
3314 | - """ |
3315 | - Mark package 'name1' for installation, and try to perform changes. |
3316 | - It should fail because 'name1' depends on 'requirename1'. |
3317 | - """ |
3318 | - self.facade.reload_channels() |
3319 | - |
3320 | - [pkg] = self.facade.get_packages_by_name("name1") |
3321 | - self.facade.mark_install(pkg) |
3322 | - exception = self.assertRaises(TransactionError, |
3323 | - self.facade.perform_changes) |
3324 | - self.assertIn("requirename", exception.args[0]) |
3325 | - |
3326 | - def test_mark_install_dependency_error(self): |
3327 | - """ |
3328 | - Now we artificially inject the needed dependencies of 'name1' |
3329 | - in 'name2', but we don't mark 'name2' for installation, and |
3330 | - that should make perform_changes() fail with a dependency |
3331 | - error on the needed package. |
3332 | - """ |
3333 | - self.facade.reload_channels() |
3334 | - |
3335 | - provide1 = Provides("prerequirename1", "prerequireversion1") |
3336 | - provide2 = Provides("requirename1", "requireversion1") |
3337 | - [pkg2] = self.facade.get_packages_by_name("name2") |
3338 | - pkg2.provides += (provide1, provide2) |
3339 | - |
3340 | - # We have to satisfy *both* packages. |
3341 | - provide1 = Provides("prerequirename2", "prerequireversion2") |
3342 | - provide2 = Provides("requirename2", "requireversion2") |
3343 | - [pkg1] = self.facade.get_packages_by_name("name1") |
3344 | - pkg1.provides += (provide1, provide2) |
3345 | - |
3346 | - # Ask Smart to reprocess relationships. |
3347 | - self.facade.reload_cache() |
3348 | - |
3349 | - self.assertEqual(pkg1.requires[0].providedby[0].packages[0], pkg2) |
3350 | - self.assertEqual(pkg1.requires[1].providedby[0].packages[0], pkg2) |
3351 | - |
3352 | - self.facade.mark_install(pkg1) |
3353 | - try: |
3354 | - self.facade.perform_changes() |
3355 | - except DependencyError, exception: |
3356 | - pass |
3357 | - else: |
3358 | - exception = None |
3359 | - self.assertTrue(exception, "DependencyError not raised") |
3360 | - self.assertEqual(exception.packages, [pkg2]) |
3361 | - |
3362 | - def test_mark_remove_dependency_error(self): |
3363 | - """ |
3364 | - Besides making 'name1' satisfy 'name2' and the contrary. We'll |
3365 | - mark both packages installed, so that we can get an error on |
3366 | - removal. |
3367 | - """ |
3368 | - self.facade.reload_channels() |
3369 | - |
3370 | - provide1 = Provides("prerequirename1", "prerequireversion1") |
3371 | - provide2 = Provides("requirename1", "requireversion1") |
3372 | - [pkg2] = self.facade.get_packages_by_name("name2") |
3373 | - pkg2.provides += (provide1, provide2) |
3374 | - |
3375 | - # We have to satisfy *both* packages. |
3376 | - provide1 = Provides("prerequirename2", "prerequireversion2") |
3377 | - provide2 = Provides("requirename2", "requireversion2") |
3378 | - [pkg1] = self.facade.get_packages_by_name("name1") |
3379 | - pkg1.provides += (provide1, provide2) |
3380 | - |
3381 | - # Ask Smart to reprocess relationships. |
3382 | - self.facade.reload_cache() |
3383 | - |
3384 | - pkg1.installed = True |
3385 | - pkg2.installed = True |
3386 | - |
3387 | - self.assertEqual(pkg1.requires[0].providedby[0].packages[0], pkg2) |
3388 | - self.assertEqual(pkg1.requires[1].providedby[0].packages[0], pkg2) |
3389 | - |
3390 | - self.facade.mark_remove(pkg2) |
3391 | - try: |
3392 | - output = self.facade.perform_changes() |
3393 | - except DependencyError, exception: |
3394 | - output = "" |
3395 | - else: |
3396 | - exception = None |
3397 | - self.assertTrue(exception, "DependencyError not raised. Output: %s" |
3398 | - % repr(output)) |
3399 | - self.assertEqual(exception.packages, [pkg1]) |
3400 | - |
3401 | - def test_mark_upgrade_dependency_error(self): |
3402 | - """Artificially make pkg2 upgrade pkg1, and mark pkg1 for upgrade.""" |
3403 | - |
3404 | - # The backend only works after initialized. |
3405 | - from smart.backends.deb.base import DebUpgrades, DebConflicts |
3406 | - |
3407 | - self.facade.reload_channels() |
3408 | - |
3409 | - [pkg1] = self.facade.get_packages_by_name("name1") |
3410 | - [pkg2] = self.facade.get_packages_by_name("name2") |
3411 | - |
3412 | - # Artificially make pkg2 be self-satisfied, and make it upgrade and |
3413 | - # conflict with pkg1. |
3414 | - pkg2.requires = [] |
3415 | - pkg2.upgrades = [DebUpgrades("name1", "=", "version1-release1")] |
3416 | - pkg2.conflicts = [DebConflicts("name1", "=", "version1-release1")] |
3417 | - |
3418 | - # pkg1 will also be self-satisfied. |
3419 | - pkg1.requires = [] |
3420 | - |
3421 | - # Ask Smart to reprocess relationships. |
3422 | - self.facade.reload_cache() |
3423 | - |
3424 | - # Mark the pkg1 as installed. Must be done after reloading |
3425 | - # the cache as reloading will reset it to the loader installed |
3426 | - # status. |
3427 | - pkg1.installed = True |
3428 | - |
3429 | - # Check that the linkage worked. |
3430 | - self.assertEqual(pkg2.upgrades[0].providedby[0].packages[0], pkg1) |
3431 | - |
3432 | - # Perform the upgrade test. |
3433 | - self.facade.mark_upgrade(pkg1) |
3434 | - try: |
3435 | - self.facade.perform_changes() |
3436 | - except DependencyError, exception: |
3437 | - pass |
3438 | - else: |
3439 | - exception = None |
3440 | - self.assertTrue(exception, "DependencyError not raised") |
3441 | - |
3442 | - # Both packages should be included in the dependency error. One |
3443 | - # must be removed, and the other installed. |
3444 | - self.assertEqual(set(exception.packages), set([pkg1, pkg2])) |
3445 | - |
3446 | - def test_perform_changes_with_logged_error(self): |
3447 | - self.log_helper.ignore_errors(".*dpkg") |
3448 | - |
3449 | - self.facade.reload_channels() |
3450 | - |
3451 | - [pkg] = self.facade.get_packages_by_name("name1") |
3452 | - pkg.requires = () |
3453 | - |
3454 | - self.facade.reload_cache() |
3455 | - |
3456 | - self.facade.mark_install(pkg) |
3457 | - |
3458 | - try: |
3459 | - output = self.facade.perform_changes() |
3460 | - except SmartError, exception: |
3461 | - output = "" |
3462 | - else: |
3463 | - exception = None |
3464 | - |
3465 | - self.assertTrue(exception, |
3466 | - "SmartError not raised. Output: %s" % repr(output)) |
3467 | - # We can't check the whole message because the dpkg error can be |
3468 | - # localized. We can't use str(exception) either because it can contain |
3469 | - # unicode |
3470 | - self.assertIn("ERROR", exception.args[0]) |
3471 | - self.assertIn("(2)", exception.args[0]) |
3472 | - self.assertIn("\n[unpack] name1_version1-release1\ndpkg: ", |
3473 | - exception.args[0]) |
3474 | - |
3475 | - def test_perform_changes_is_non_interactive(self): |
3476 | - from smart.backends.deb.pm import DebPackageManager |
3477 | - |
3478 | - self.facade.reload_channels() |
3479 | - |
3480 | - [pkg] = self.facade.get_packages_by_name("name1") |
3481 | - pkg.requires = () |
3482 | - |
3483 | - self.facade.reload_cache() |
3484 | - |
3485 | - self.facade.mark_install(pkg) |
3486 | - |
3487 | - environ = [] |
3488 | - |
3489 | - def check_environ(self, argv, output): |
3490 | - environ.append(os.environ.get("DEBIAN_FRONTEND")) |
3491 | - environ.append(os.environ.get("APT_LISTCHANGES_FRONTEND")) |
3492 | - return 0 |
3493 | - |
3494 | - DebPackageManager.dpkg, olddpkg = check_environ, DebPackageManager.dpkg |
3495 | - |
3496 | - try: |
3497 | - self.facade.perform_changes() |
3498 | - finally: |
3499 | - DebPackageManager.dpkg = olddpkg |
3500 | - |
3501 | - self.assertEqual(environ, ["noninteractive", "none", |
3502 | - "noninteractive", "none"]) |
3503 | - |
3504 | - def test_perform_changes_with_policy_remove(self): |
3505 | - """ |
3506 | - When requested changes are only about removing packages, we set |
3507 | - the Smart transaction policy to C{PolicyRemove}. |
3508 | - """ |
3509 | - create_deb(self.repository_dir, PKGNAME4, PKGDEB4) |
3510 | - self.facade.reload_channels() |
3511 | - |
3512 | - # Importing these modules fail if Smart is not initialized |
3513 | - from smart.backends.deb.base import DebRequires |
3514 | - |
3515 | - pkg1 = self.facade.get_package_by_hash(HASH1) |
3516 | - pkg1.requires.append(DebRequires("name3", ">=", "version3-release3")) |
3517 | - |
3518 | - pkg3 = self.facade.get_package_by_hash(HASH3) |
3519 | - |
3520 | - # Ask Smart to reprocess relationships. |
3521 | - self.facade.reload_cache() |
3522 | - |
3523 | - pkg1.installed = True |
3524 | - pkg3.installed = True |
3525 | - |
3526 | - self.facade.mark_remove(pkg3) |
3527 | - error = self.assertRaises(DependencyError, self.facade.perform_changes) |
3528 | - [missing] = error.packages |
3529 | - self.assertIdentical(pkg1, missing) |
3530 | - |
3531 | - def test_perform_changes_with_commit_change_set_errors(self): |
3532 | - |
3533 | - self.facade.reload_channels() |
3534 | - |
3535 | - [pkg] = self.facade.get_packages_by_name("name1") |
3536 | - pkg.requires = () |
3537 | - |
3538 | - self.facade.mark_install(pkg) |
3539 | - |
3540 | - ctrl_mock = self.mocker.patch(Control) |
3541 | - ctrl_mock.commitChangeSet(ANY) |
3542 | - self.mocker.throw(smart.Error("commit error")) |
3543 | - self.mocker.replay() |
3544 | - |
3545 | - self.assertRaises(TransactionError, self.facade.perform_changes) |
3546 | - |
3547 | - def test_deinit_cleans_the_state(self): |
3548 | - self.facade.reload_channels() |
3549 | - self.assertTrue(self.facade.get_package_by_hash(HASH1)) |
3550 | - self.facade.deinit() |
3551 | - self.assertFalse(self.facade.get_package_by_hash(HASH1)) |
3552 | - |
3553 | - def test_deinit_deinits_smart(self): |
3554 | - self.facade.reload_channels() |
3555 | - self.assertTrue(smart.iface.object) |
3556 | - self.facade.deinit() |
3557 | - self.assertFalse(smart.iface.object) |
3558 | - |
3559 | - def test_deinit_when_smart_wasnt_initialized(self): |
3560 | - self.assertFalse(smart.iface.object) |
3561 | - # Nothing bad should happen. |
3562 | - self.facade.deinit() |
3563 | - |
3564 | - def test_reload_channels_wont_consider_non_debian_packages(self): |
3565 | - |
3566 | - class StubPackage(object): |
3567 | - pass |
3568 | - |
3569 | - pkg = StubPackage() |
3570 | - |
3571 | - ctrl_mock = self.mocker.patch(Control) |
3572 | - cache_mock = ctrl_mock.getCache() |
3573 | - cache_mock.getPackages() |
3574 | - self.mocker.result([pkg]) |
3575 | - self.mocker.replay() |
3576 | - |
3577 | - self.facade.reload_channels() |
3578 | - self.assertEqual(self.facade.get_package_hash(pkg), None) |
3579 | - |
3580 | - def test_reload_channels_with_channel_error(self): |
3581 | - """ |
3582 | - The L{SmartFacade.reload_channels} method raises a L{ChannelsError} if |
3583 | - smart fails to load the configured channels. |
3584 | - """ |
3585 | - ctrl_mock = self.mocker.patch(Control) |
3586 | - ctrl_mock.reloadChannels(caching=ALWAYS) |
3587 | - self.mocker.throw(smart.Error(u"Channel information is locked")) |
3588 | - self.mocker.replay() |
3589 | - self.assertRaises(ChannelError, self.facade.reload_channels) |
3590 | - |
3591 | - def test_reset_add_get_channels(self): |
3592 | - |
3593 | - channels = [("alias0", {"type": "test"}), |
3594 | - ("alias1", {"type": "test"})] |
3595 | - |
3596 | - self.facade.reset_channels() |
3597 | - |
3598 | - self.assertEqual(self.facade.get_channels(), {}) |
3599 | - |
3600 | - self.facade.add_channel(*channels[0]) |
3601 | - self.facade.add_channel(*channels[1]) |
3602 | - |
3603 | - self.assertEqual(self.facade.get_channels(), dict(channels)) |
3604 | - |
3605 | - def test_add_apt_deb_channel(self): |
3606 | - """ |
3607 | - The L{SmartFacade.add_channel_apt_deb} add a Smart channel of |
3608 | - type C{"apt-deb"}. |
3609 | - """ |
3610 | - self.facade.reset_channels() |
3611 | - self.facade.add_channel_apt_deb("http://url/", "name", "component") |
3612 | - self.assertEqual(self.facade.get_channels(), |
3613 | - {"name": {"baseurl": "http://url/", |
3614 | - "distribution": "name", |
3615 | - "components": "component", |
3616 | - "type": "apt-deb"}}) |
3617 | - |
3618 | - def test_add_deb_dir_channel(self): |
3619 | - """ |
3620 | - The L{SmartFacade.add_channel_deb_dir} add a Smart channel of |
3621 | - type C{"deb-dir"}. |
3622 | - """ |
3623 | - self.facade.reset_channels() |
3624 | - self.facade.add_channel_deb_dir("/my/repo") |
3625 | - self.assertEqual(self.facade.get_channels(), |
3626 | - {"/my/repo": {"path": "/my/repo", |
3627 | - "type": "deb-dir"}}) |
3628 | - |
3629 | - def test_get_arch(self): |
3630 | - """ |
3631 | - The L{SmartFacade.get_arch} should return the system dpkg |
3632 | - architecture. |
3633 | - """ |
3634 | - deferred = Deferred() |
3635 | - |
3636 | - def do_test(): |
3637 | - result = getProcessOutputAndValue("/usr/bin/dpkg", |
3638 | - ("--print-architecture",)) |
3639 | - |
3640 | - def callback((out, err, code)): |
3641 | - self.assertEqual(self.facade.get_arch(), out.strip()) |
3642 | - result.addCallback(callback) |
3643 | - result.chainDeferred(deferred) |
3644 | - |
3645 | - reactor.callWhenRunning(do_test) |
3646 | - return deferred |
3647 | - |
3648 | - def test_set_arch_multiple_times(self): |
3649 | - |
3650 | - repo = create_full_repository(self.makeDir()) |
3651 | - |
3652 | - self.facade.set_arch("i386") |
3653 | - self.facade.reset_channels() |
3654 | - self.facade.add_channel_apt_deb(repo.url, repo.codename, |
3655 | - " ".join(repo.components)) |
3656 | - self.facade.reload_channels() |
3657 | - |
3658 | - pkgs = self.facade.get_packages() |
3659 | - self.assertEqual(len(pkgs), 2) |
3660 | - self.assertEqual(pkgs[0].name, "syslinux") |
3661 | - self.assertEqual(pkgs[1].name, "kairos") |
3662 | - |
3663 | - self.facade.deinit() |
3664 | - self.facade.set_arch("amd64") |
3665 | - self.facade.reset_channels() |
3666 | - self.facade.add_channel_apt_deb(repo.url, repo.codename, |
3667 | - " ".join(repo.components)) |
3668 | - self.facade.reload_channels() |
3669 | - |
3670 | - pkgs = self.facade.get_packages() |
3671 | - self.assertEqual(len(pkgs), 2) |
3672 | - self.assertEqual(pkgs[0].name, "libclthreads2") |
3673 | - self.assertEqual(pkgs[1].name, "kairos") |
3674 | - |
3675 | - def test_set_caching_with_reload_error(self): |
3676 | - |
3677 | - alias = "alias" |
3678 | - channel = {"type": "deb-dir", |
3679 | - "path": "/does/not/exist"} |
3680 | - |
3681 | - self.facade.reset_channels() |
3682 | - self.facade.add_channel(alias, channel) |
3683 | - self.facade.set_caching(NEVER) |
3684 | - |
3685 | - self.assertRaises(ChannelError, self.facade.reload_channels) |
3686 | - self.facade._channels = {} |
3687 | - |
3688 | - ignore_re = re.compile("\[Smart\].*'alias'.*/does/not/exist") |
3689 | - |
3690 | - self.log_helper.ignored_exception_regexes = [ignore_re] |
3691 | - |
3692 | - def test_init_landscape_plugins(self): |
3693 | - """ |
3694 | - The landscape plugin which helps managing proxies is loaded when smart |
3695 | - is initialized: this sets a smart configuration variable and load the |
3696 | - module. |
3697 | - """ |
3698 | - self.facade.reload_channels() |
3699 | - self.assertTrue(smart.sysconf.get("use-landscape-proxies")) |
3700 | - self.assertIn("smart.plugins.landscape", sys.modules) |
3701 | - |
3702 | - def test_get_package_locks_with_no_lock(self): |
3703 | - """ |
3704 | - If no package locks are set, L{SmartFacade.get_package_locks} returns |
3705 | - an empty C{list}. |
3706 | - """ |
3707 | - self.assertEqual(self.facade.get_package_locks(), []) |
3708 | - |
3709 | - def test_get_package_locks_with_one_lock(self): |
3710 | - """ |
3711 | - If one lock is set, the list of locks contains one item. |
3712 | - """ |
3713 | - self.facade.set_package_lock("name1", "<", "version1") |
3714 | - self.assertEqual(self.facade.get_package_locks(), |
3715 | - [("name1", "<", "version1")]) |
3716 | - |
3717 | - def test_get_package_locks_with_many_locks(self): |
3718 | - """ |
3719 | - It's possible to have more than one package lock and several conditions |
3720 | - for each of them. |
3721 | - """ |
3722 | - self.facade.set_package_lock("name1", "<", "version1") |
3723 | - self.facade.set_package_lock("name1", ">=", "version3") |
3724 | - self.facade.set_package_lock("name2") |
3725 | - self.assertEqual(sorted(self.facade.get_package_locks()), |
3726 | - sorted([("name1", "<", "version1"), |
3727 | - ("name1", ">=", "version3"), |
3728 | - ("name2", "", "")])) |
3729 | - |
3730 | - def test_set_package_lock(self): |
3731 | - """ |
3732 | - It is possible to lock a package by simply specifying its name. |
3733 | - """ |
3734 | - self.facade.set_package_lock("name1") |
3735 | - self.facade.reload_channels() |
3736 | - [package] = self.facade.get_locked_packages() |
3737 | - self.assertEqual(package.name, "name1") |
3738 | - |
3739 | - def test_set_package_lock_with_matching_condition(self): |
3740 | - """ |
3741 | - It is possible to set a package lock specifying both a |
3742 | - package name and version condition. Any matching package |
3743 | - will be locked. |
3744 | - """ |
3745 | - self.facade.set_package_lock("name1", "<", "version2") |
3746 | - self.facade.reload_channels() |
3747 | - [package] = self.facade.get_locked_packages() |
3748 | - self.assertEqual(package.name, "name1") |
3749 | - |
3750 | - def test_set_package_lock_with_non_matching_condition(self): |
3751 | - """ |
3752 | - If the package lock conditions do not match any package, |
3753 | - no package will be locked. |
3754 | - """ |
3755 | - self.facade.set_package_lock("name1", "<", "version1") |
3756 | - self.facade.reload_channels() |
3757 | - self.assertEqual(self.facade.get_locked_packages(), []) |
3758 | - |
3759 | - def test_set_package_lock_with_missing_version(self): |
3760 | - """ |
3761 | - When specifing a relation for a package lock condition, a version |
3762 | - must be provided as well. |
3763 | - """ |
3764 | - error = self.assertRaises(RuntimeError, self.facade.set_package_lock, |
3765 | - "name1", "<", "") |
3766 | - self.assertEqual(str(error), "Package lock version not provided") |
3767 | - |
3768 | - def test_set_package_lock_with_missing_relation(self): |
3769 | - """ |
3770 | - When specifing a version for a package lock condition, a relation |
3771 | - must be provided as well. |
3772 | - """ |
3773 | - error = self.assertRaises(RuntimeError, self.facade.set_package_lock, |
3774 | - "name1", "", "version1") |
3775 | - self.assertEqual(str(error), "Package lock relation not provided") |
3776 | - |
3777 | - def test_remove_package_lock(self): |
3778 | - """ |
3779 | - It is possibly to remove a package lock without any version condition. |
3780 | - """ |
3781 | - self.facade.set_package_lock("name1") |
3782 | - self.facade.remove_package_lock("name1") |
3783 | - self.assertEqual(self.facade.get_locked_packages(), []) |
3784 | - |
3785 | - def test_remove_package_lock_with_condition(self): |
3786 | - """ |
3787 | - It is possibly to remove a package lock with a version condition. |
3788 | - """ |
3789 | - self.facade.set_package_lock("name1", "<", "version1") |
3790 | - self.facade.remove_package_lock("name1", "<", "version1") |
3791 | - self.assertEqual(self.facade.get_locked_packages(), []) |
3792 | - |
3793 | - def test_save_config(self): |
3794 | - """ |
3795 | - It is possible to lock a package by simply specifying its name. |
3796 | - """ |
3797 | - self.facade.set_package_lock("python", "=>", "2.5") |
3798 | - self.facade.save_config() |
3799 | - self.facade.deinit() |
3800 | - self.assertEqual(self.facade.get_package_locks(), |
3801 | - [("python", "=>", "2.5")]) |
3802 | |
3803 | === removed file 'landscape/package/tests/test_interface.py' |
3804 | --- landscape/package/tests/test_interface.py 2011-07-18 15:16:18 +0000 |
3805 | +++ landscape/package/tests/test_interface.py 1970-01-01 00:00:00 +0000 |
3806 | @@ -1,34 +0,0 @@ |
3807 | -# -*- encoding: utf-8 -*- |
3808 | -from landscape.package.interface import LandscapeInterface |
3809 | - |
3810 | -from landscape.tests.helpers import LandscapeTest |
3811 | -from landscape.package.tests.helpers import SmartFacadeHelper |
3812 | - |
3813 | - |
3814 | -class LandscapeInterfaceTest(LandscapeTest): |
3815 | - |
3816 | - helpers = [SmartFacadeHelper] |
3817 | - |
3818 | - def setUp(self): |
3819 | - super(LandscapeInterfaceTest, self).setUp() |
3820 | - self.facade.reload_channels() |
3821 | - self.iface = LandscapeInterface(None) |
3822 | - |
3823 | - def test_message_with_unicode_and_utf8(self): |
3824 | - self.iface.info(u"áéÃóú") |
3825 | - self.iface.info("áéÃóú") |
3826 | - self.assertEqual(self.iface.get_output_for_landscape(), |
3827 | - u"INFO: áéÃóú\nINFO: áéÃóú\n") |
3828 | - |
3829 | - def test_message_with_unicode_and_unknown_encoding(self): |
3830 | - self.iface.info(u"áéÃóú") |
3831 | - self.iface.info("aeÃou\xc3") # UTF-8 expects a byte after \xc3 |
3832 | - c = u"\N{REPLACEMENT CHARACTER}" |
3833 | - self.assertEqual(self.iface.get_output_for_landscape(), |
3834 | - u"INFO: áéÃóú\nINFO: ae%s%sou%s\n" % (c, c, c)) |
3835 | - |
3836 | - def test_output_with_unicode_and_utf8(self): |
3837 | - self.iface.showOutput(u"áéÃóú") |
3838 | - self.iface.showOutput("áéÃóú") |
3839 | - self.assertEqual(self.iface.get_output_for_landscape(), |
3840 | - u"áéÃóúáéÃóú") |
3841 | |
3842 | === modified file 'landscape/package/tests/test_releaseupgrader.py' |
3843 | --- landscape/package/tests/test_releaseupgrader.py 2012-03-19 09:33:34 +0000 |
3844 | +++ landscape/package/tests/test_releaseupgrader.py 2012-06-04 14:08:28 +0000 |
3845 | @@ -655,7 +655,7 @@ |
3846 | |
3847 | def check_result((out, err, code)): |
3848 | self.assertFalse(os.path.exists(upgrade_tool_directory)) |
3849 | - self.assertEqual(out, "--force-smart-update\n%s\n" |
3850 | + self.assertEqual(out, "--force-apt-update\n%s\n" |
3851 | % os.getcwd()) |
3852 | self.assertEqual(err, "") |
3853 | self.assertEqual(code, 0) |
3854 | @@ -738,7 +738,7 @@ |
3855 | result = self.upgrader.finish() |
3856 | |
3857 | def check_result((out, err, code)): |
3858 | - self.assertEqual(out, "--force-smart-update " |
3859 | + self.assertEqual(out, "--force-apt-update " |
3860 | "--config=/some/config\n") |
3861 | self.assertEqual(err, "") |
3862 | self.assertEqual(code, 0) |
3863 | |
3864 | === modified file 'landscape/package/tests/test_reporter.py' |
3865 | --- landscape/package/tests/test_reporter.py 2012-03-19 09:33:34 +0000 |
3866 | +++ landscape/package/tests/test_reporter.py 2012-06-04 14:08:28 +0000 |
3867 | @@ -1,4 +1,3 @@ |
3868 | -import glob |
3869 | import sys |
3870 | import os |
3871 | import unittest |
3872 | @@ -17,9 +16,9 @@ |
3873 | PackageReporter, HASH_ID_REQUEST_TIMEOUT, main, find_reporter_command, |
3874 | PackageReporterConfiguration, FakeGlobalReporter, FakeReporter) |
3875 | from landscape.package import reporter |
3876 | -from landscape.package.facade import AptFacade, has_new_enough_apt |
3877 | +from landscape.package.facade import AptFacade |
3878 | from landscape.package.tests.helpers import ( |
3879 | - SmartFacadeHelper, AptFacadeHelper, SimpleRepositoryHelper, |
3880 | + AptFacadeHelper, SimpleRepositoryHelper, |
3881 | HASH1, HASH2, HASH3, PKGNAME1) |
3882 | from landscape.tests.helpers import ( |
3883 | LandscapeTest, BrokerServiceHelper, EnvironSaverHelper) |
3884 | @@ -30,18 +29,63 @@ |
3885 | |
3886 | class PackageReporterConfigurationTest(unittest.TestCase): |
3887 | |
3888 | - def test_force_smart_update_option(self): |
3889 | + def test_force_apt_update_option(self): |
3890 | """ |
3891 | - The L{PackageReporterConfiguration} supports a '--force-smart-update' |
3892 | + The L{PackageReporterConfiguration} supports a '--force-apt-update' |
3893 | command line option. |
3894 | """ |
3895 | config = PackageReporterConfiguration() |
3896 | - self.assertFalse(config.force_smart_update) |
3897 | - config.load(["--force-smart-update"]) |
3898 | - self.assertTrue(config.force_smart_update) |
3899 | - |
3900 | - |
3901 | -class PackageReporterTestMixin(object): |
3902 | + self.assertFalse(config.force_apt_update) |
3903 | + config.load(["--force-apt-update"]) |
3904 | + self.assertTrue(config.force_apt_update) |
3905 | + |
3906 | + |
3907 | +class PackageReporterAptTest(LandscapeTest): |
3908 | + |
3909 | + helpers = [AptFacadeHelper, SimpleRepositoryHelper, BrokerServiceHelper] |
3910 | + |
3911 | + Facade = AptFacade |
3912 | + |
3913 | + def setUp(self): |
3914 | + |
3915 | + def set_up(ignored): |
3916 | + self.store = PackageStore(self.makeFile()) |
3917 | + self.config = PackageReporterConfiguration() |
3918 | + self.reporter = PackageReporter( |
3919 | + self.store, self.facade, self.remote, self.config) |
3920 | + self.config.data_path = self.makeDir() |
3921 | + os.mkdir(self.config.package_directory) |
3922 | + |
3923 | + result = super(PackageReporterAptTest, self).setUp() |
3924 | + return result.addCallback(set_up) |
3925 | + |
3926 | + def _clear_repository(self): |
3927 | + """Remove all packages from self.repository.""" |
3928 | + create_file(self.repository_dir + "/Packages", "") |
3929 | + |
3930 | + def set_pkg1_upgradable(self): |
3931 | + """Make it so that package "name1" is considered to be upgradable. |
3932 | + |
3933 | + Return the hash of the package that upgrades "name1". |
3934 | + """ |
3935 | + self._add_package_to_deb_dir( |
3936 | + self.repository_dir, "name1", version="version2") |
3937 | + self.facade.reload_channels() |
3938 | + name1_upgrade = sorted(self.facade.get_packages_by_name("name1"))[1] |
3939 | + return self.facade.get_package_hash(name1_upgrade) |
3940 | + |
3941 | + def set_pkg1_installed(self): |
3942 | + """Make it so that package "name1" is considered installed.""" |
3943 | + self._install_deb_file(os.path.join(self.repository_dir, PKGNAME1)) |
3944 | + |
3945 | + def _make_fake_apt_update(self, out="output", err="error", code=0): |
3946 | + """Create a fake apt-update executable""" |
3947 | + self.reporter.apt_update_filename = self.makeFile( |
3948 | + "#!/bin/sh\n" |
3949 | + "echo -n %s\n" |
3950 | + "echo -n %s >&2\n" |
3951 | + "exit %d" % (out, err, code)) |
3952 | + os.chmod(self.reporter.apt_update_filename, 0755) |
3953 | |
3954 | def test_set_package_ids_with_all_known(self): |
3955 | self.store.add_hash_id_request(["hash1", "hash2"]) |
3956 | @@ -497,64 +541,6 @@ |
3957 | |
3958 | return result |
3959 | |
3960 | - def test_run_smart_update(self): |
3961 | - """ |
3962 | - The L{PackageReporter.run_smart_update} method should run smart-update |
3963 | - with the proper arguments. |
3964 | - """ |
3965 | - self.reporter.sources_list_filename = "/I/Dont/Exist" |
3966 | - self.reporter.sources_list_directory = "/I/Dont/Exist" |
3967 | - self.reporter.smart_update_filename = self.makeFile( |
3968 | - "#!/bin/sh\necho -n $@") |
3969 | - os.chmod(self.reporter.smart_update_filename, 0755) |
3970 | - debug_mock = self.mocker.replace("logging.debug") |
3971 | - debug_mock("'%s' exited with status 0 (out='--after %d', err=''" % ( |
3972 | - self.reporter.smart_update_filename, |
3973 | - self.reporter.smart_update_interval)) |
3974 | - warning_mock = self.mocker.replace("logging.warning") |
3975 | - self.expect(warning_mock(ANY)).count(0) |
3976 | - self.mocker.replay() |
3977 | - deferred = Deferred() |
3978 | - |
3979 | - def do_test(): |
3980 | - |
3981 | - result = self.reporter.run_smart_update() |
3982 | - |
3983 | - def callback((out, err, code)): |
3984 | - interval = self.reporter.smart_update_interval |
3985 | - self.assertEqual(err, "") |
3986 | - self.assertEqual(out, "--after %d" % interval) |
3987 | - self.assertEqual(code, 0) |
3988 | - result.addCallback(callback) |
3989 | - result.chainDeferred(deferred) |
3990 | - |
3991 | - reactor.callWhenRunning(do_test) |
3992 | - return deferred |
3993 | - |
3994 | - def test_run_smart_update_with_force_smart_update(self): |
3995 | - """ |
3996 | - L{PackageReporter.run_smart_update} forces a smart-update run if |
3997 | - the '--force-smart-update' command line option was passed. |
3998 | - |
3999 | - """ |
4000 | - self.config.load(["--force-smart-update"]) |
4001 | - self.reporter.smart_update_filename = self.makeFile( |
4002 | - "#!/bin/sh\necho -n $@") |
4003 | - os.chmod(self.reporter.smart_update_filename, 0755) |
4004 | - |
4005 | - deferred = Deferred() |
4006 | - |
4007 | - def do_test(): |
4008 | - result = self.reporter.run_smart_update() |
4009 | - |
4010 | - def callback((out, err, code)): |
4011 | - self.assertEqual(out, "") |
4012 | - result.addCallback(callback) |
4013 | - result.chainDeferred(deferred) |
4014 | - |
4015 | - reactor.callWhenRunning(do_test) |
4016 | - return deferred |
4017 | - |
4018 | def test_wb_apt_sources_have_changed(self): |
4019 | """ |
4020 | The L{PackageReporter._apt_sources_have_changed} method returns a bool |
4021 | @@ -581,244 +567,6 @@ |
4022 | content="deb http://foo ./") |
4023 | self.assertTrue(self.reporter._apt_sources_have_changed()) |
4024 | |
4025 | - def test_run_smart_update_with_force_smart_update_if_sources_changed(self): |
4026 | - """ |
4027 | - L{PackageReporter.run_smart_update} forces a smart-update run if |
4028 | - the APT sources.list file has changed. |
4029 | - |
4030 | - """ |
4031 | - self.assertEqual(self.reporter.sources_list_filename, |
4032 | - "/etc/apt/sources.list") |
4033 | - self.reporter.sources_list_filename = self.makeFile("deb ftp://url ./") |
4034 | - self.reporter.smart_update_filename = self.makeFile( |
4035 | - "#!/bin/sh\necho -n $@") |
4036 | - os.chmod(self.reporter.smart_update_filename, 0755) |
4037 | - |
4038 | - deferred = Deferred() |
4039 | - |
4040 | - def do_test(): |
4041 | - result = self.reporter.run_smart_update() |
4042 | - |
4043 | - def callback((out, err, code)): |
4044 | - # Smart update was called without the --after parameter |
4045 | - self.assertEqual(out, "") |
4046 | - result.addCallback(callback) |
4047 | - result.chainDeferred(deferred) |
4048 | - |
4049 | - reactor.callWhenRunning(do_test) |
4050 | - return deferred |
4051 | - |
4052 | - def test_run_smart_update_warns_about_failures(self): |
4053 | - """ |
4054 | - The L{PackageReporter.run_smart_update} method should log a warning |
4055 | - in case smart-update terminates with a non-zero exit code other than 1. |
4056 | - """ |
4057 | - self.reporter.smart_update_filename = self.makeFile( |
4058 | - "#!/bin/sh\necho -n error >&2\necho -n output\nexit 2") |
4059 | - os.chmod(self.reporter.smart_update_filename, 0755) |
4060 | - logging_mock = self.mocker.replace("logging.warning") |
4061 | - logging_mock("'%s' exited with status 2" |
4062 | - " (error)" % self.reporter.smart_update_filename) |
4063 | - self.mocker.replay() |
4064 | - deferred = Deferred() |
4065 | - |
4066 | - def do_test(): |
4067 | - result = self.reporter.run_smart_update() |
4068 | - |
4069 | - def callback((out, err, code)): |
4070 | - self.assertEqual(out, "output") |
4071 | - self.assertEqual(err, "error") |
4072 | - self.assertEqual(code, 2) |
4073 | - result.addCallback(callback) |
4074 | - result.chainDeferred(deferred) |
4075 | - |
4076 | - reactor.callWhenRunning(do_test) |
4077 | - return deferred |
4078 | - |
4079 | - def test_run_smart_update_report_smart_failure(self): |
4080 | - """ |
4081 | - If L{PackageReporter.run_smart_update} fails, a message is sent to the |
4082 | - server reporting the error, to be able to fix the problem centrally. |
4083 | - """ |
4084 | - message_store = self.broker_service.message_store |
4085 | - message_store.set_accepted_types(["package-reporter-result"]) |
4086 | - self.reporter.smart_update_filename = self.makeFile( |
4087 | - "#!/bin/sh\necho -n error >&2\necho -n output\nexit 2") |
4088 | - os.chmod(self.reporter.smart_update_filename, 0755) |
4089 | - deferred = Deferred() |
4090 | - |
4091 | - def do_test(): |
4092 | - result = self.reporter.run_smart_update() |
4093 | - |
4094 | - def callback(ignore): |
4095 | - self.assertMessages(message_store.get_pending_messages(), |
4096 | - [{"type": "package-reporter-result", |
4097 | - "code": 2, "err": u"error"}]) |
4098 | - result.addCallback(callback) |
4099 | - result.chainDeferred(deferred) |
4100 | - |
4101 | - reactor.callWhenRunning(do_test) |
4102 | - return deferred |
4103 | - |
4104 | - def test_run_smart_update_report_no_sources(self): |
4105 | - """ |
4106 | - L{PackageReporter.run_smart_update} reports a failure if smart |
4107 | - succeeds but there are no APT sources defined. Smart doesn't |
4108 | - fail if there are no sources, but we fake a failure in order to |
4109 | - re-use the PackageReporterAlert on the server. |
4110 | - """ |
4111 | - self.facade.reset_channels() |
4112 | - message_store = self.broker_service.message_store |
4113 | - message_store.set_accepted_types(["package-reporter-result"]) |
4114 | - self.reporter.smart_update_filename = self.makeFile( |
4115 | - "#!/bin/sh\necho -n error >&2\necho -n output\nexit 0") |
4116 | - os.chmod(self.reporter.smart_update_filename, 0755) |
4117 | - deferred = Deferred() |
4118 | - |
4119 | - def do_test(): |
4120 | - result = self.reporter.run_smart_update() |
4121 | - |
4122 | - def callback(ignore): |
4123 | - error = "There are no APT sources configured in %s or %s." % ( |
4124 | - self.reporter.sources_list_filename, |
4125 | - self.reporter.sources_list_directory) |
4126 | - self.assertMessages(message_store.get_pending_messages(), |
4127 | - [{"type": "package-reporter-result", |
4128 | - "code": 1, "err": error}]) |
4129 | - result.addCallback(callback) |
4130 | - result.chainDeferred(deferred) |
4131 | - |
4132 | - reactor.callWhenRunning(do_test) |
4133 | - return deferred |
4134 | - |
4135 | - def test_run_smart_update_report_smart_failure_no_sources(self): |
4136 | - """ |
4137 | - If L{PackageReporter.run_smart_update} fails and there are no |
4138 | - APT sources configured, the Smart error takes precedence. |
4139 | - """ |
4140 | - self.facade.reset_channels() |
4141 | - message_store = self.broker_service.message_store |
4142 | - message_store.set_accepted_types(["package-reporter-result"]) |
4143 | - self.reporter.smart_update_filename = self.makeFile( |
4144 | - "#!/bin/sh\necho -n error >&2\necho -n output\nexit 2") |
4145 | - os.chmod(self.reporter.smart_update_filename, 0755) |
4146 | - deferred = Deferred() |
4147 | - |
4148 | - def do_test(): |
4149 | - result = self.reporter.run_smart_update() |
4150 | - |
4151 | - def callback(ignore): |
4152 | - self.assertMessages(message_store.get_pending_messages(), |
4153 | - [{"type": "package-reporter-result", |
4154 | - "code": 2, "err": u"error"}]) |
4155 | - result.addCallback(callback) |
4156 | - result.chainDeferred(deferred) |
4157 | - |
4158 | - reactor.callWhenRunning(do_test) |
4159 | - return deferred |
4160 | - |
4161 | - def test_run_smart_update_report_success(self): |
4162 | - """ |
4163 | - L{PackageReporter.run_smart_update} also reports success to be able to |
4164 | - know the proper state of the client. |
4165 | - """ |
4166 | - message_store = self.broker_service.message_store |
4167 | - message_store.set_accepted_types(["package-reporter-result"]) |
4168 | - self.reporter.smart_update_filename = self.makeFile( |
4169 | - "#!/bin/sh\necho -n error >&2\necho -n output\nexit 0") |
4170 | - os.chmod(self.reporter.smart_update_filename, 0755) |
4171 | - deferred = Deferred() |
4172 | - |
4173 | - def do_test(): |
4174 | - result = self.reporter.run_smart_update() |
4175 | - |
4176 | - def callback(ignore): |
4177 | - self.assertMessages(message_store.get_pending_messages(), |
4178 | - [{"type": "package-reporter-result", |
4179 | - "code": 0, "err": u"error"}]) |
4180 | - result.addCallback(callback) |
4181 | - result.chainDeferred(deferred) |
4182 | - |
4183 | - reactor.callWhenRunning(do_test) |
4184 | - return deferred |
4185 | - |
4186 | - def test_run_smart_update_warns_exit_code_1_and_non_empty_stderr(self): |
4187 | - """ |
4188 | - The L{PackageReporter.run_smart_update} method should log a warning |
4189 | - in case smart-update terminates with exit code 1 and non empty stderr. |
4190 | - """ |
4191 | - self.reporter.smart_update_filename = self.makeFile( |
4192 | - "#!/bin/sh\necho -n \"error \" >&2\nexit 1") |
4193 | - os.chmod(self.reporter.smart_update_filename, 0755) |
4194 | - logging_mock = self.mocker.replace("logging.warning") |
4195 | - logging_mock("'%s' exited with status 1" |
4196 | - " (error )" % self.reporter.smart_update_filename) |
4197 | - self.mocker.replay() |
4198 | - deferred = Deferred() |
4199 | - |
4200 | - def do_test(): |
4201 | - result = self.reporter.run_smart_update() |
4202 | - |
4203 | - def callback((out, err, code)): |
4204 | - self.assertEqual(out, "") |
4205 | - self.assertEqual(err, "error ") |
4206 | - self.assertEqual(code, 1) |
4207 | - result.addCallback(callback) |
4208 | - result.chainDeferred(deferred) |
4209 | - |
4210 | - reactor.callWhenRunning(do_test) |
4211 | - return deferred |
4212 | - |
4213 | - def test_run_smart_update_ignores_exit_code_1_and_empty_output(self): |
4214 | - """ |
4215 | - The L{PackageReporter.run_smart_update} method should not log anything |
4216 | - in case smart-update terminates with exit code 1 and output containing |
4217 | - only a newline character. |
4218 | - """ |
4219 | - self.reporter.smart_update_filename = self.makeFile( |
4220 | - "#!/bin/sh\necho\nexit 1") |
4221 | - os.chmod(self.reporter.smart_update_filename, 0755) |
4222 | - logging_mock = self.mocker.replace("logging.warning") |
4223 | - self.expect(logging_mock(ANY)).count(0) |
4224 | - self.mocker.replay() |
4225 | - deferred = Deferred() |
4226 | - |
4227 | - def do_test(): |
4228 | - |
4229 | - result = self.reporter.run_smart_update() |
4230 | - |
4231 | - def callback((out, err, code)): |
4232 | - self.assertEqual(out, "\n") |
4233 | - self.assertEqual(err, "") |
4234 | - self.assertEqual(code, 1) |
4235 | - result.addCallback(callback) |
4236 | - result.chainDeferred(deferred) |
4237 | - |
4238 | - reactor.callWhenRunning(do_test) |
4239 | - return deferred |
4240 | - |
4241 | - def test_run_smart_update_touches_stamp_file(self): |
4242 | - """ |
4243 | - The L{PackageReporter.run_smart_update} method touches a stamp file |
4244 | - after running the smart-update wrapper. |
4245 | - """ |
4246 | - self.reporter.sources_list_filename = "/I/Dont/Exist" |
4247 | - self.reporter.smart_update_filename = "/bin/true" |
4248 | - deferred = Deferred() |
4249 | - |
4250 | - def do_test(): |
4251 | - |
4252 | - result = self.reporter.run_smart_update() |
4253 | - |
4254 | - def callback(ignored): |
4255 | - self.assertTrue( |
4256 | - os.path.exists(self.config.update_stamp_filename)) |
4257 | - result.addCallback(callback) |
4258 | - result.chainDeferred(deferred) |
4259 | - |
4260 | - reactor.callWhenRunning(do_test) |
4261 | - return deferred |
4262 | - |
4263 | def test_remove_expired_hash_id_request(self): |
4264 | request = self.store.add_hash_id_request(["hash1"]) |
4265 | request.message_id = 9999 |
4266 | @@ -1133,11 +881,7 @@ |
4267 | |
4268 | upgrade_hash = self.set_pkg1_upgradable() |
4269 | self.set_pkg1_installed() |
4270 | - # Don't reload for SmartFacade, since the hash of pkg2 will be |
4271 | - # changed, resulting in that name2 will be considered not |
4272 | - # available.. |
4273 | - if isinstance(self.facade, AptFacade): |
4274 | - self.facade.reload_channels() |
4275 | + self.facade.reload_channels() |
4276 | |
4277 | self.store.set_hash_ids( |
4278 | {HASH1: 1, upgrade_hash: 2, HASH3: 3}) |
4279 | @@ -1193,20 +937,13 @@ |
4280 | result = self.reporter.detect_packages_changes() |
4281 | return result.addCallback(got_result) |
4282 | |
4283 | - def test_detect_changes_considers_packages_and_locks_changes(self): |
4284 | + def test_detect_changes_considers_packages_changes(self): |
4285 | """ |
4286 | - The L{PackageReporter.detect_changes} method considers both package and |
4287 | - package locks changes. It also releases smart locks by calling the |
4288 | - L{SmartFacade.deinit} method. |
4289 | + The L{PackageReporter.detect_changes} method package changes. |
4290 | """ |
4291 | reporter_mock = self.mocker.patch(self.reporter) |
4292 | reporter_mock.detect_packages_changes() |
4293 | self.mocker.result(succeed(True)) |
4294 | - reporter_mock.detect_package_locks_changes() |
4295 | - self.mocker.result(succeed(True)) |
4296 | - |
4297 | - facade_mock = self.mocker.patch(self.facade) |
4298 | - facade_mock.deinit() |
4299 | |
4300 | self.mocker.replay() |
4301 | return self.reporter.detect_changes() |
4302 | @@ -1219,8 +956,6 @@ |
4303 | """ |
4304 | reporter_mock = self.mocker.patch(self.reporter) |
4305 | reporter_mock.detect_packages_changes() |
4306 | - self.mocker.result(succeed(False)) |
4307 | - reporter_mock.detect_package_locks_changes() |
4308 | self.mocker.result(succeed(True)) |
4309 | callback = self.mocker.mock() |
4310 | callback() |
4311 | @@ -1236,11 +971,7 @@ |
4312 | |
4313 | results = [Deferred() for i in range(7)] |
4314 | |
4315 | - # Either the Apt or Smart cache will be updated, not both. |
4316 | - if isinstance(self.facade, AptFacade): |
4317 | - reporter_mock.run_apt_update() |
4318 | - else: |
4319 | - reporter_mock.run_smart_update() |
4320 | + reporter_mock.run_apt_update() |
4321 | self.mocker.result(results[0]) |
4322 | |
4323 | reporter_mock.fetch_hash_id_db() |
4324 | @@ -1306,16 +1037,19 @@ |
4325 | This is done in the reporter so that we know it happens when |
4326 | no other reporter is possibly running at the same time. |
4327 | """ |
4328 | + self._add_system_package("foo") |
4329 | + self.facade.reload_channels() |
4330 | + [foo] = self.facade.get_packages_by_name("foo") |
4331 | + foo_hash = self.facade.get_package_hash(foo) |
4332 | + self.facade.set_package_hold(foo) |
4333 | + self.facade.reload_channels() |
4334 | message_store = self.broker_service.message_store |
4335 | message_store.set_accepted_types(["package-locks"]) |
4336 | - self.store.set_hash_ids({HASH1: 3, HASH2: 4}) |
4337 | + self.store.set_hash_ids({foo_hash: 3, HASH2: 4}) |
4338 | self.store.add_available([1]) |
4339 | self.store.add_available_upgrades([2]) |
4340 | self.store.add_installed([2]) |
4341 | self.store.add_locked([3]) |
4342 | - self.store.add_package_locks([("name1", None, None)]) |
4343 | - if self.facade.supports_package_locks: |
4344 | - self.facade.set_package_lock("name1") |
4345 | request1 = self.store.add_hash_id_request(["hash3"]) |
4346 | request2 = self.store.add_hash_id_request(["hash4"]) |
4347 | |
4348 | @@ -1328,12 +1062,6 @@ |
4349 | self.assertEqual(self.store.get_available_upgrades(), [2]) |
4350 | self.assertEqual(self.store.get_available(), [1]) |
4351 | self.assertEqual(self.store.get_installed(), [2]) |
4352 | - # XXX: Don't check get_locked() and get_package_locks() until |
4353 | - # package locks are implemented in AptFacade. |
4354 | - if not isinstance(self.facade, AptFacade): |
4355 | - self.assertEqual(self.store.get_locked(), [3]) |
4356 | - self.assertEqual( |
4357 | - self.store.get_package_locks(), [("name1", "", "")]) |
4358 | self.assertEqual(self.store.get_hash_id_request(request1.id).id, |
4359 | request1.id) |
4360 | |
4361 | @@ -1344,7 +1072,7 @@ |
4362 | def check_result(result): |
4363 | |
4364 | # The hashes should not go away. |
4365 | - hash1 = self.store.get_hash_id(HASH1) |
4366 | + hash1 = self.store.get_hash_id(foo_hash) |
4367 | hash2 = self.store.get_hash_id(HASH2) |
4368 | self.assertEqual([hash1, hash2], [3, 4]) |
4369 | |
4370 | @@ -1353,12 +1081,9 @@ |
4371 | |
4372 | # After running the resychronize task, detect_packages_changes is |
4373 | # called, and the existing known hashes are made available. |
4374 | - self.assertEqual(self.store.get_available(), [3, 4]) |
4375 | - self.assertEqual(self.store.get_installed(), []) |
4376 | - # XXX: Don't check get_locked() until package locks are |
4377 | - # implemented in AptFacade. |
4378 | - if not isinstance(self.facade, AptFacade): |
4379 | - self.assertEqual(self.store.get_locked(), [3]) |
4380 | + self.assertEqual(self.store.get_available(), [4]) |
4381 | + self.assertEqual(self.store.get_installed(), [3]) |
4382 | + self.assertEqual(self.store.get_locked(), [3]) |
4383 | |
4384 | # The two original hash id requests should be still there, and |
4385 | # a new hash id request should also be detected for HASH3. |
4386 | @@ -1371,314 +1096,14 @@ |
4387 | elif request.id == request2.id: |
4388 | self.assertEqual(request.hashes, ["hash4"]) |
4389 | elif not new_request_found: |
4390 | - self.assertEqual(request.hashes, [HASH3]) |
4391 | + self.assertEqual(request.hashes, [HASH3, HASH1]) |
4392 | else: |
4393 | self.fail("Unexpected hash-id request!") |
4394 | self.assertEqual(requests_count, 3) |
4395 | |
4396 | - # XXX: Don't check for package-locks messages until package |
4397 | - # locks are implemented in AptFacade. |
4398 | - if not isinstance(self.facade, AptFacade): |
4399 | - self.assertMessages(message_store.get_pending_messages(), |
4400 | - [{"type": "package-locks", |
4401 | - "created": [("name1", "", "")]}]) |
4402 | - |
4403 | deferred.addCallback(check_result) |
4404 | return deferred |
4405 | |
4406 | - |
4407 | -class PackageReporterSmartTest(LandscapeTest, PackageReporterTestMixin): |
4408 | - |
4409 | - helpers = [SmartFacadeHelper, BrokerServiceHelper] |
4410 | - |
4411 | - def setUp(self): |
4412 | - |
4413 | - def set_up(ignored): |
4414 | - self.store = PackageStore(self.makeFile()) |
4415 | - self.config = PackageReporterConfiguration() |
4416 | - self.reporter = PackageReporter( |
4417 | - self.store, self.facade, self.remote, self.config) |
4418 | - self.config.data_path = self.makeDir() |
4419 | - os.mkdir(self.config.package_directory) |
4420 | - |
4421 | - result = super(PackageReporterSmartTest, self).setUp() |
4422 | - return result.addCallback(set_up) |
4423 | - |
4424 | - def _clear_repository(self): |
4425 | - """Remove all packages from self.repository.""" |
4426 | - for filename in glob.glob(self.repository_dir + "/*"): |
4427 | - os.unlink(filename) |
4428 | - |
4429 | - def set_pkg1_upgradable(self): |
4430 | - """Make it so that package "name1" is considered to be upgradable. |
4431 | - |
4432 | - Return the hash of the package that upgrades "name1". |
4433 | - """ |
4434 | - previous = self.Facade.channels_reloaded |
4435 | - |
4436 | - def callback(self): |
4437 | - from smart.backends.deb.base import DebUpgrades |
4438 | - previous(self) |
4439 | - pkg2 = self.get_packages_by_name("name2")[0] |
4440 | - pkg2.upgrades += (DebUpgrades("name1", "=", "version1-release1"),) |
4441 | - self.reload_cache() # Relink relations. |
4442 | - self.Facade.channels_reloaded = callback |
4443 | - return HASH2 |
4444 | - |
4445 | - def set_pkg1_installed(self): |
4446 | - """Make it so that package "name1" is considered installed.""" |
4447 | - previous = self.Facade.channels_reloaded |
4448 | - |
4449 | - def callback(self): |
4450 | - previous(self) |
4451 | - self.get_packages_by_name("name1")[0].installed = True |
4452 | - self.Facade.channels_reloaded = callback |
4453 | - |
4454 | - def test_detect_packages_changes_with_locked(self): |
4455 | - """ |
4456 | - If Smart indicates locked packages we didn't know about, report |
4457 | - them to the server. |
4458 | - """ |
4459 | - message_store = self.broker_service.message_store |
4460 | - message_store.set_accepted_types(["packages"]) |
4461 | - |
4462 | - self.facade.set_package_lock("name1") |
4463 | - self.facade.set_package_lock("name2", ">=", "version2") |
4464 | - |
4465 | - self.store.set_hash_ids({HASH1: 1, HASH2: 2}) |
4466 | - self.store.add_available([1, 2]) |
4467 | - |
4468 | - def got_result(result): |
4469 | - self.assertMessages(message_store.get_pending_messages(), |
4470 | - [{"type": "packages", "locked": [1, 2]}]) |
4471 | - self.assertEqual(sorted(self.store.get_locked()), [1, 2]) |
4472 | - |
4473 | - result = self.reporter.detect_packages_changes() |
4474 | - return result.addCallback(got_result) |
4475 | - |
4476 | - def test_detect_packages_changes_with_locked_and_ranges(self): |
4477 | - """ |
4478 | - Ranges are used when reporting changes to 3 or more locked packages |
4479 | - having consecutive ids. |
4480 | - """ |
4481 | - message_store = self.broker_service.message_store |
4482 | - message_store.set_accepted_types(["packages"]) |
4483 | - |
4484 | - self.facade.set_package_lock("name1") |
4485 | - self.facade.set_package_lock("name2", ">=", "version2") |
4486 | - self.facade.set_package_lock("name3", "<", "version4") |
4487 | - |
4488 | - self.store.set_hash_ids({HASH1: 1, HASH2: 2, HASH3: 3}) |
4489 | - self.store.add_available([1, 2, 3]) |
4490 | - |
4491 | - def got_result(result): |
4492 | - self.assertMessages(message_store.get_pending_messages(), |
4493 | - [{"type": "packages", "locked": [(1, 3)]}]) |
4494 | - self.assertEqual(sorted(self.store.get_locked()), [1, 2, 3]) |
4495 | - |
4496 | - result = self.reporter.detect_packages_changes() |
4497 | - return result.addCallback(got_result) |
4498 | - |
4499 | - def test_detect_packages_changes_with_locked_with_unknown_hash(self): |
4500 | - """ |
4501 | - Locked packages whose hashes are unknown don't get reported. |
4502 | - """ |
4503 | - self.facade.set_package_lock("name1") |
4504 | - |
4505 | - def got_result(result): |
4506 | - self.assertEqual(self.store.get_locked(), []) |
4507 | - |
4508 | - result = self.reporter.detect_packages_changes() |
4509 | - return result.addCallback(got_result) |
4510 | - |
4511 | - def test_detect_packages_changes_with_locked_and_previously_known(self): |
4512 | - """ |
4513 | - We don't report locked packages we already know about. |
4514 | - """ |
4515 | - message_store = self.broker_service.message_store |
4516 | - message_store.set_accepted_types(["packages"]) |
4517 | - |
4518 | - self.facade.set_package_lock("name1") |
4519 | - self.facade.set_package_lock("name2", ">=", "version2") |
4520 | - |
4521 | - self.store.set_hash_ids({HASH1: 1, HASH2: 2}) |
4522 | - self.store.add_available([1, 2]) |
4523 | - self.store.add_locked([1]) |
4524 | - |
4525 | - def got_result(result): |
4526 | - self.assertMessages(message_store.get_pending_messages(), |
4527 | - [{"type": "packages", "locked": [2]}]) |
4528 | - |
4529 | - self.assertEqual(sorted(self.store.get_locked()), [1, 2]) |
4530 | - |
4531 | - result = self.reporter.detect_packages_changes() |
4532 | - return result.addCallback(got_result) |
4533 | - |
4534 | - def test_detect_packages_changes_with_not_locked(self): |
4535 | - """ |
4536 | - We report when a package was previously locked and isn't anymore. |
4537 | - """ |
4538 | - message_store = self.broker_service.message_store |
4539 | - message_store.set_accepted_types(["packages"]) |
4540 | - |
4541 | - self.store.set_hash_ids({HASH1: 1}) |
4542 | - self.store.add_available([1]) |
4543 | - self.store.add_locked([1]) |
4544 | - |
4545 | - def got_result(result): |
4546 | - self.assertMessages(message_store.get_pending_messages(), |
4547 | - [{"type": "packages", "not-locked": [1]}]) |
4548 | - self.assertEqual(self.store.get_locked(), []) |
4549 | - |
4550 | - result = self.reporter.detect_packages_changes() |
4551 | - return result.addCallback(got_result) |
4552 | - |
4553 | - def test_detect_package_locks_changes_with_create_locks(self): |
4554 | - """ |
4555 | - If Smart indicates package locks we didn't know about, report |
4556 | - them to the server. |
4557 | - """ |
4558 | - message_store = self.broker_service.message_store |
4559 | - message_store.set_accepted_types(["package-locks"]) |
4560 | - |
4561 | - self.facade.set_package_lock("name") |
4562 | - |
4563 | - logging_mock = self.mocker.replace("logging.info") |
4564 | - logging_mock("Queuing message with changes in known package locks:" |
4565 | - " 1 created, 0 deleted.") |
4566 | - self.mocker.replay() |
4567 | - |
4568 | - def got_result(result): |
4569 | - self.assertMessages(message_store.get_pending_messages(), |
4570 | - [{"type": "package-locks", |
4571 | - "created": [("name", "", "")]}]) |
4572 | - self.assertEqual(self.store.get_package_locks(), |
4573 | - [("name", "", "")]) |
4574 | - |
4575 | - result = self.reporter.detect_package_locks_changes() |
4576 | - return result.addCallback(got_result) |
4577 | - |
4578 | - def test_detect_package_locks_changes_with_already_known_locks(self): |
4579 | - """ |
4580 | - We don't report changes about locks we already know about. |
4581 | - """ |
4582 | - message_store = self.broker_service.message_store |
4583 | - message_store.set_accepted_types(["package-locks"]) |
4584 | - |
4585 | - self.facade.set_package_lock("name1") |
4586 | - self.facade.set_package_lock("name2", "<", "1.2") |
4587 | - |
4588 | - self.store.add_package_locks([("name1", "", "")]) |
4589 | - |
4590 | - logging_mock = self.mocker.replace("logging.info") |
4591 | - logging_mock("Queuing message with changes in known package locks:" |
4592 | - " 1 created, 0 deleted.") |
4593 | - self.mocker.replay() |
4594 | - |
4595 | - def got_result(result): |
4596 | - self.assertMessages(message_store.get_pending_messages(), |
4597 | - [{"type": "package-locks", |
4598 | - "created": [("name2", "<", "1.2")]}]) |
4599 | - self.assertEqual(sorted(self.store.get_package_locks()), |
4600 | - [("name1", "", ""), |
4601 | - ("name2", "<", "1.2")]) |
4602 | - |
4603 | - result = self.reporter.detect_package_locks_changes() |
4604 | - return result.addCallback(got_result) |
4605 | - |
4606 | - def test_detect_package_locks_changes_with_deleted_locks(self): |
4607 | - """ |
4608 | - If Smart indicates newly unset package locks, report them to the |
4609 | - server. |
4610 | - """ |
4611 | - message_store = self.broker_service.message_store |
4612 | - message_store.set_accepted_types(["package-locks"]) |
4613 | - |
4614 | - self.store.add_package_locks([("name1", "", "")]) |
4615 | - |
4616 | - logging_mock = self.mocker.replace("logging.info") |
4617 | - logging_mock("Queuing message with changes in known package locks:" |
4618 | - " 0 created, 1 deleted.") |
4619 | - self.mocker.replay() |
4620 | - |
4621 | - def got_result(result): |
4622 | - self.assertMessages(message_store.get_pending_messages(), |
4623 | - [{"type": "package-locks", |
4624 | - "deleted": [("name1", "", "")]}]) |
4625 | - self.assertEqual(self.store.get_package_locks(), []) |
4626 | - |
4627 | - result = self.reporter.detect_package_locks_changes() |
4628 | - return result.addCallback(got_result) |
4629 | - |
4630 | - def test_detect_package_locks_changes_with_locked_already_known(self): |
4631 | - """ |
4632 | - If we didn't detect any change in the package locks, we don't send any |
4633 | - message, and we return a deferred resulting in C{False}. |
4634 | - """ |
4635 | - message_store = self.broker_service.message_store |
4636 | - message_store.set_accepted_types(["package-locks"]) |
4637 | - |
4638 | - self.facade.set_package_lock("name1") |
4639 | - self.store.add_package_locks([("name1", "", "")]) |
4640 | - |
4641 | - def got_result(result): |
4642 | - self.assertFalse(result) |
4643 | - self.assertMessages(message_store.get_pending_messages(), []) |
4644 | - |
4645 | - result = self.reporter.detect_packages_changes() |
4646 | - return result.addCallback(got_result) |
4647 | - |
4648 | - |
4649 | -class PackageReporterAptTest(LandscapeTest, PackageReporterTestMixin): |
4650 | - |
4651 | - if not has_new_enough_apt: |
4652 | - skip = "Can't use AptFacade on hardy" |
4653 | - |
4654 | - helpers = [AptFacadeHelper, SimpleRepositoryHelper, BrokerServiceHelper] |
4655 | - |
4656 | - Facade = AptFacade |
4657 | - |
4658 | - def setUp(self): |
4659 | - |
4660 | - def set_up(ignored): |
4661 | - self.store = PackageStore(self.makeFile()) |
4662 | - self.config = PackageReporterConfiguration() |
4663 | - self.reporter = PackageReporter( |
4664 | - self.store, self.facade, self.remote, self.config) |
4665 | - self.config.data_path = self.makeDir() |
4666 | - os.mkdir(self.config.package_directory) |
4667 | - |
4668 | - result = super(PackageReporterAptTest, self).setUp() |
4669 | - return result.addCallback(set_up) |
4670 | - |
4671 | - def _clear_repository(self): |
4672 | - """Remove all packages from self.repository.""" |
4673 | - create_file(self.repository_dir + "/Packages", "") |
4674 | - |
4675 | - def set_pkg1_upgradable(self): |
4676 | - """Make it so that package "name1" is considered to be upgradable. |
4677 | - |
4678 | - Return the hash of the package that upgrades "name1". |
4679 | - """ |
4680 | - self._add_package_to_deb_dir( |
4681 | - self.repository_dir, "name1", version="version2") |
4682 | - self.facade.reload_channels() |
4683 | - name1_upgrade = sorted(self.facade.get_packages_by_name("name1"))[1] |
4684 | - return self.facade.get_package_hash(name1_upgrade) |
4685 | - |
4686 | - def set_pkg1_installed(self): |
4687 | - """Make it so that package "name1" is considered installed.""" |
4688 | - self._install_deb_file(os.path.join(self.repository_dir, PKGNAME1)) |
4689 | - |
4690 | - def _make_fake_apt_update(self, out="output", err="error", code=0): |
4691 | - """Create a fake apt-update executable""" |
4692 | - self.reporter.apt_update_filename = self.makeFile( |
4693 | - "#!/bin/sh\n" |
4694 | - "echo -n %s\n" |
4695 | - "echo -n %s >&2\n" |
4696 | - "exit %d" % (out, err, code)) |
4697 | - os.chmod(self.reporter.apt_update_filename, 0755) |
4698 | - |
4699 | def test_run_apt_update(self): |
4700 | """ |
4701 | The L{PackageReporter.run_apt_update} method should run apt-update. |
4702 | @@ -1708,13 +1133,13 @@ |
4703 | reactor.callWhenRunning(do_test) |
4704 | return deferred |
4705 | |
4706 | - def test_run_apt_update_with_force_smart_update(self): |
4707 | + def test_run_apt_update_with_force_apt_update(self): |
4708 | """ |
4709 | L{PackageReporter.run_apt_update} forces an apt-update run if the |
4710 | - '--force-smart-update' command line option was passed. |
4711 | + '--force-apt-update' command line option was passed. |
4712 | """ |
4713 | self.makeFile("", path=self.config.update_stamp_filename) |
4714 | - self.config.load(["--force-smart-update"]) |
4715 | + self.config.load(["--force-apt-update"]) |
4716 | self._make_fake_apt_update() |
4717 | |
4718 | deferred = Deferred() |
4719 | @@ -1730,7 +1155,7 @@ |
4720 | reactor.callWhenRunning(do_test) |
4721 | return deferred |
4722 | |
4723 | - def test_run_apt_update_with_force_smart_update_if_sources_changed(self): |
4724 | + def test_run_apt_update_with_force_apt_update_if_sources_changed(self): |
4725 | """ |
4726 | L{PackageReporter.run_apt_update} forces an apt-update run if the APT |
4727 | sources.list file has changed. |
4728 | @@ -1929,7 +1354,22 @@ |
4729 | return deferred |
4730 | |
4731 | |
4732 | -class GlobalPackageReporterTestMixin(object): |
4733 | +class GlobalPackageReporterAptTest(LandscapeTest): |
4734 | + |
4735 | + helpers = [AptFacadeHelper, SimpleRepositoryHelper, BrokerServiceHelper] |
4736 | + |
4737 | + def setUp(self): |
4738 | + |
4739 | + def set_up(ignored): |
4740 | + self.store = FakePackageStore(self.makeFile()) |
4741 | + self.config = PackageReporterConfiguration() |
4742 | + self.reporter = FakeGlobalReporter( |
4743 | + self.store, self.facade, self.remote, self.config) |
4744 | + self.config.data_path = self.makeDir() |
4745 | + os.mkdir(self.config.package_directory) |
4746 | + |
4747 | + result = super(GlobalPackageReporterAptTest, self).setUp() |
4748 | + return result.addCallback(set_up) |
4749 | |
4750 | def test_store_messages(self): |
4751 | """ |
4752 | @@ -1937,13 +1377,13 @@ |
4753 | """ |
4754 | message_store = self.broker_service.message_store |
4755 | message_store.set_accepted_types(["package-reporter-result"]) |
4756 | - self.reporter.smart_update_filename = self.makeFile( |
4757 | + self.reporter.apt_update_filename = self.makeFile( |
4758 | "#!/bin/sh\necho -n error >&2\necho -n output\nexit 0") |
4759 | - os.chmod(self.reporter.smart_update_filename, 0755) |
4760 | + os.chmod(self.reporter.apt_update_filename, 0755) |
4761 | deferred = Deferred() |
4762 | |
4763 | def do_test(): |
4764 | - result = self.reporter.run_smart_update() |
4765 | + result = self.reporter.run_apt_update() |
4766 | |
4767 | def callback(ignore): |
4768 | message = {"type": "package-reporter-result", |
4769 | @@ -1962,47 +1402,6 @@ |
4770 | return deferred |
4771 | |
4772 | |
4773 | -class GlobalPackageReporterAptTest(LandscapeTest, |
4774 | - GlobalPackageReporterTestMixin): |
4775 | - |
4776 | - if not has_new_enough_apt: |
4777 | - skip = "Can't use AptFacade on hardy" |
4778 | - |
4779 | - helpers = [AptFacadeHelper, SimpleRepositoryHelper, BrokerServiceHelper] |
4780 | - |
4781 | - def setUp(self): |
4782 | - |
4783 | - def set_up(ignored): |
4784 | - self.store = FakePackageStore(self.makeFile()) |
4785 | - self.config = PackageReporterConfiguration() |
4786 | - self.reporter = FakeGlobalReporter( |
4787 | - self.store, self.facade, self.remote, self.config) |
4788 | - self.config.data_path = self.makeDir() |
4789 | - os.mkdir(self.config.package_directory) |
4790 | - |
4791 | - result = super(GlobalPackageReporterAptTest, self).setUp() |
4792 | - return result.addCallback(set_up) |
4793 | - |
4794 | - |
4795 | -class GlobalPackageReporterSmartTest(LandscapeTest, |
4796 | - GlobalPackageReporterTestMixin): |
4797 | - |
4798 | - helpers = [SmartFacadeHelper, BrokerServiceHelper] |
4799 | - |
4800 | - def setUp(self): |
4801 | - |
4802 | - def set_up(ignored): |
4803 | - self.store = FakePackageStore(self.makeFile()) |
4804 | - self.config = PackageReporterConfiguration() |
4805 | - self.reporter = FakeGlobalReporter( |
4806 | - self.store, self.facade, self.remote, self.config) |
4807 | - self.config.data_path = self.makeDir() |
4808 | - os.mkdir(self.config.package_directory) |
4809 | - |
4810 | - result = super(GlobalPackageReporterSmartTest, self).setUp() |
4811 | - return result.addCallback(set_up) |
4812 | - |
4813 | - |
4814 | class FakePackageReporterTest(LandscapeTest): |
4815 | |
4816 | helpers = [EnvironSaverHelper, BrokerServiceHelper] |
4817 | |
4818 | === modified file 'landscape/package/tests/test_skeleton.py' |
4819 | --- landscape/package/tests/test_skeleton.py 2012-03-19 09:33:34 +0000 |
4820 | +++ landscape/package/tests/test_skeleton.py 2012-06-04 14:08:28 +0000 |
4821 | @@ -1,21 +1,10 @@ |
4822 | -try: |
4823 | - import smart |
4824 | - from smart.cache import Package |
4825 | -except ImportError: |
4826 | - # Smart is optional if AptFacade is being used. |
4827 | - pass |
4828 | - |
4829 | -from landscape.package.interface import ( |
4830 | - install_landscape_interface, uninstall_landscape_interface) |
4831 | - |
4832 | -from landscape.package.facade import has_new_enough_apt |
4833 | from landscape.package.skeleton import ( |
4834 | - build_skeleton, PackageTypeError, build_skeleton_apt, DEB_PROVIDES, |
4835 | + build_skeleton_apt, DEB_PROVIDES, |
4836 | DEB_NAME_PROVIDES, DEB_REQUIRES, DEB_OR_REQUIRES, DEB_UPGRADES, |
4837 | DEB_CONFLICTS) |
4838 | |
4839 | from landscape.package.tests.helpers import ( |
4840 | - AptFacadeHelper, SmartHelper, HASH1, create_simple_repository, create_deb, |
4841 | + AptFacadeHelper, HASH1, create_simple_repository, create_deb, |
4842 | PKGNAME_MINIMAL, PKGDEB_MINIMAL, HASH_MINIMAL, PKGNAME_SIMPLE_RELATIONS, |
4843 | PKGDEB_SIMPLE_RELATIONS, HASH_SIMPLE_RELATIONS, PKGNAME_VERSION_RELATIONS, |
4844 | PKGDEB_VERSION_RELATIONS, HASH_VERSION_RELATIONS, |
4845 | @@ -47,16 +36,32 @@ |
4846 | PKGDEB_OR_RELATIONS) |
4847 | |
4848 | |
4849 | -class SkeletonTestMixin(object): |
4850 | - """Tests for building a skeleton from a package. |
4851 | - |
4852 | - This class should be mixed in to test different backends, like smart |
4853 | - and apt. |
4854 | - |
4855 | - The main test case classes need to implement C{get_package(name)} to |
4856 | - get a package by name, and C{build_skeleton(package, with_info, |
4857 | - with_unicode}, which builds the skeleton. |
4858 | - """ |
4859 | +class SkeletonAptTest(LandscapeTest): |
4860 | + """C{PackageSkeleton} tests for apt packages.""" |
4861 | + |
4862 | + helpers = [AptFacadeHelper, SkeletonTestHelper] |
4863 | + |
4864 | + def setUp(self): |
4865 | + super(SkeletonAptTest, self).setUp() |
4866 | + self.facade.add_channel_deb_dir(self.skeleton_repository_dir) |
4867 | + # Don't use reload_channels(), since that causes the test setup |
4868 | + # depending on build_skeleton_apt working correctly, which makes |
4869 | + # it harder to do TDD for these tests. |
4870 | + self.facade._cache.open(None) |
4871 | + self.facade._cache.update(None) |
4872 | + self.facade._cache.open(None) |
4873 | + |
4874 | + def get_package(self, name): |
4875 | + """Return the package with the specified name.""" |
4876 | + # Don't use get_packages(), since that causes the test setup |
4877 | + # depending on build_skeleton_apt working correctly, which makes |
4878 | + # it harder to to TDD for these tests. |
4879 | + package = self.facade._cache[name] |
4880 | + return package.candidate |
4881 | + |
4882 | + def build_skeleton(self, *args, **kwargs): |
4883 | + """Build the skeleton to be tested.""" |
4884 | + return build_skeleton_apt(*args, **kwargs) |
4885 | |
4886 | def test_build_skeleton(self): |
4887 | """ |
4888 | @@ -253,67 +258,3 @@ |
4889 | (DEB_UPGRADES, "or-relations < 1.0")] |
4890 | self.assertEqual(relations, skeleton.relations) |
4891 | self.assertEqual(HASH_OR_RELATIONS, skeleton.get_hash()) |
4892 | - |
4893 | - |
4894 | -class SmartSkeletonTest(LandscapeTest, SkeletonTestMixin): |
4895 | - """C{PackageSkeleton} tests for smart packages.""" |
4896 | - |
4897 | - helpers = [SmartHelper, SkeletonTestHelper] |
4898 | - |
4899 | - def setUp(self): |
4900 | - super(SmartSkeletonTest, self).setUp() |
4901 | - install_landscape_interface() |
4902 | - self.ctrl = smart.init(interface="landscape", datadir=self.smart_dir) |
4903 | - smart.sysconf.set( |
4904 | - "channels", {"alias": {"type": "deb-dir", |
4905 | - "path": self.skeleton_repository_dir}}) |
4906 | - self.ctrl.reloadChannels() |
4907 | - self.cache = self.ctrl.getCache() |
4908 | - |
4909 | - def tearDown(self): |
4910 | - uninstall_landscape_interface() |
4911 | - super(SmartSkeletonTest, self).tearDown() |
4912 | - |
4913 | - def get_package(self, name): |
4914 | - """Return the package with the specified name.""" |
4915 | - [package] = self.cache.getPackages(name) |
4916 | - return package |
4917 | - |
4918 | - def build_skeleton(self, *args, **kwargs): |
4919 | - """Build the skeleton to be tested.""" |
4920 | - return build_skeleton(*args, **kwargs) |
4921 | - |
4922 | - def test_refuse_to_build_non_debian_packages(self): |
4923 | - self.assertRaises(PackageTypeError, build_skeleton, |
4924 | - Package("name", "version")) |
4925 | - |
4926 | - |
4927 | -class SkeletonAptTest(LandscapeTest, SkeletonTestMixin): |
4928 | - """C{PackageSkeleton} tests for apt packages.""" |
4929 | - |
4930 | - if not has_new_enough_apt: |
4931 | - skip = "Can't use AptFacade on hardy" |
4932 | - |
4933 | - helpers = [AptFacadeHelper, SkeletonTestHelper] |
4934 | - |
4935 | - def setUp(self): |
4936 | - super(SkeletonAptTest, self).setUp() |
4937 | - self.facade.add_channel_deb_dir(self.skeleton_repository_dir) |
4938 | - # Don't use reload_channels(), since that causes the test setup |
4939 | - # depending on build_skeleton_apt working correctly, which makes |
4940 | - # it harder to to TDD for these tests. |
4941 | - self.facade._cache.open(None) |
4942 | - self.facade._cache.update(None) |
4943 | - self.facade._cache.open(None) |
4944 | - |
4945 | - def get_package(self, name): |
4946 | - """Return the package with the specified name.""" |
4947 | - # Don't use get_packages(), since that causes the test setup |
4948 | - # depending on build_skeleton_apt working correctly, which makes |
4949 | - # it harder to to TDD for these tests. |
4950 | - package = self.facade._cache[name] |
4951 | - return package.candidate |
4952 | - |
4953 | - def build_skeleton(self, *args, **kwargs): |
4954 | - """Build the skeleton to be tested.""" |
4955 | - return build_skeleton_apt(*args, **kwargs) |
4956 | |
4957 | === modified file 'landscape/package/tests/test_store.py' |
4958 | --- landscape/package/tests/test_store.py 2011-07-18 15:16:18 +0000 |
4959 | +++ landscape/package/tests/test_store.py 2012-06-04 14:08:28 +0000 |
4960 | @@ -1,6 +1,5 @@ |
4961 | import threading |
4962 | import time |
4963 | -import sys |
4964 | |
4965 | import sqlite3 |
4966 | from landscape.tests.helpers import LandscapeTest |
4967 | @@ -356,11 +355,9 @@ |
4968 | |
4969 | database = sqlite3.connect(filename) |
4970 | cursor = database.cursor() |
4971 | - for table in ["package_locks", "locked"]: |
4972 | - query = "pragma table_info(%s)" % table |
4973 | - cursor.execute(query) |
4974 | - result = cursor.fetchall() |
4975 | - self.assertTrue(len(result) > 0) |
4976 | + cursor.execute("pragma table_info(locked)") |
4977 | + result = cursor.fetchall() |
4978 | + self.assertTrue(len(result) > 0) |
4979 | |
4980 | def test_add_and_get_locked(self): |
4981 | """ |
4982 | @@ -401,103 +398,6 @@ |
4983 | self.store1.clear_locked() |
4984 | self.assertEqual(self.store2.get_locked(), []) |
4985 | |
4986 | - def test_get_package_locks_with_no_lock(self): |
4987 | - """ |
4988 | - L{PackageStore.get_package_locks} returns an empty list if no package |
4989 | - locks are stored. |
4990 | - """ |
4991 | - self.assertEqual(self.store1.get_package_locks(), []) |
4992 | - |
4993 | - def test_add_package_locks(self): |
4994 | - """ |
4995 | - L{PackageStore.add_package_locks} adds a package lock to the store. |
4996 | - """ |
4997 | - self.store1.add_package_locks([("name", "", "")]) |
4998 | - self.assertEqual(self.store2.get_package_locks(), |
4999 | - [("name", "", "")]) |
5000 | - |
The diff has been truncated for viewing.