Merge lp:~ack/landscape-client/package-reporter-update into lp:~landscape/landscape-client/trunk
- package-reporter-update
- Merge into trunk
Proposed by
Alberto Donato
Status: | Merged |
---|---|
Approved by: | Alberto Donato |
Approved revision: | 398 |
Merged at revision: | 395 |
Proposed branch: | lp:~ack/landscape-client/package-reporter-update |
Merge into: | lp:~landscape/landscape-client/trunk |
Diff against target: |
579 lines (+439/-6) 10 files modified
.bzrignore (+9/-0) apt-update/Makefile (+7/-0) apt-update/apt-update.c (+81/-0) debian/landscape-client.postinst (+7/-2) debian/landscape-client.prerm (+5/-1) debian/rules (+3/-0) landscape/package/reporter.py (+56/-3) landscape/package/taskhandler.py (+5/-0) landscape/package/tests/test_reporter.py (+256/-0) landscape/package/tests/test_taskhandler.py (+10/-0) |
To merge this branch: | bzr merge lp:~ack/landscape-client/package-reporter-update |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Free Ekanayaka (community) | Approve | ||
Thomas Herve (community) | Approve | ||
Review via email: mp+81308@code.launchpad.net |
Commit message
Description of the change
This branch makes the package reporter use APT to update the package cache instead of smart, when USE_APT_FACADE is set.
At the moment, force_smart_update and smart_update_
To post a comment you must log in.
Revision history for this message
Free Ekanayaka (free.ekanayaka) wrote : | # |
Great! +1
[1]
+ else:
+ err = ("'%s' didn't run, update interval has not passed" %
+ self.apt_
+ result = succeed(("", err, 1))
I think we should not reproduce the behavior of smart-update in this case, we should just return 0 as fake exit code, and this will simplify the callback.
[2]
Please add a copyright notice to apt-update.c, like in smart-update.c
review:
Approve
- 398. By Alberto Donato
-
Addressed Free's comments.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2011-10-04 12:13:35 +0000 |
3 | +++ .bzrignore 2011-11-08 11:04:00 +0000 |
4 | @@ -8,8 +8,17 @@ |
5 | debian/landscape-client.postrm.debhelper |
6 | debian/landscape-client.prerm.debhelper |
7 | debian/landscape-client.substvars |
8 | +debian/landscape-client.debhelper.log |
9 | +debian/landscape-common/ |
10 | +debian/landscape-common.debhelper.log |
11 | +debian/landscape-common.postinst.debhelper |
12 | +debian/landscape-common.postrm.debhelper |
13 | +debian/landscape-common.prerm.debhelper |
14 | +debian/landscape-common.substvars |
15 | man/landscape-client.1 |
16 | man/landscape-config.1 |
17 | man/landscape-message.1 |
18 | +smart-update/smart-update |
19 | +apt-update/apt-update |
20 | docs |
21 | tags |
22 | |
23 | === added directory 'apt-update' |
24 | === added file 'apt-update/Makefile' |
25 | --- apt-update/Makefile 1970-01-01 00:00:00 +0000 |
26 | +++ apt-update/Makefile 2011-11-08 11:04:00 +0000 |
27 | @@ -0,0 +1,7 @@ |
28 | +NAME = apt-update |
29 | + |
30 | +$(NAME): $(NAME).c |
31 | + $(CC) $(CFLAGS) -Wall $< -o $@ |
32 | + |
33 | +clean: |
34 | + rm -f $(NAME) |
35 | |
36 | === added file 'apt-update/apt-update.c' |
37 | --- apt-update/apt-update.c 1970-01-01 00:00:00 +0000 |
38 | +++ apt-update/apt-update.c 2011-11-08 11:04:00 +0000 |
39 | @@ -0,0 +1,81 @@ |
40 | +/* |
41 | + |
42 | + Copyright (c) 2011 Canonical, Ltd. |
43 | + |
44 | +*/ |
45 | + |
46 | +#define _GNU_SOURCE |
47 | +#include <sys/resource.h> |
48 | +#include <sys/types.h> |
49 | +#include <sys/stat.h> |
50 | +#include <grp.h> |
51 | +#include <unistd.h> |
52 | +#include <stdlib.h> |
53 | +#include <string.h> |
54 | +#include <errno.h> |
55 | +#include <stdio.h> |
56 | +#include <pwd.h> |
57 | + |
58 | +int main(int argc, char *argv[], char *envp[]) |
59 | +{ |
60 | + char *apt_argv[] = {"/usr/bin/apt-get", "-q", "update", NULL}; |
61 | + char *apt_envp[] = {"PATH=/bin:/usr/bin", NULL, NULL}; |
62 | + |
63 | + // Set the HOME environment variable |
64 | + struct passwd *pwd = getpwuid(geteuid()); |
65 | + if (!pwd) { |
66 | + fprintf(stderr, "error: Unable to find passwd entry for uid %d (%s)\n", |
67 | + geteuid(), strerror(errno)); |
68 | + exit(1); |
69 | + } |
70 | + if (asprintf(&apt_envp[1], "HOME=%s", pwd->pw_dir) == -1) { |
71 | + perror("error: Unable to create HOME environment variable"); |
72 | + exit(1); |
73 | + } |
74 | + |
75 | + // Drop any supplementary group |
76 | + if (setgroups(0, NULL) == -1) { |
77 | + perror("error: Unable to set supplementary groups IDs"); |
78 | + exit(1); |
79 | + } |
80 | + |
81 | + // Set real/effective gid and uid |
82 | + if (setregid(pwd->pw_gid, pwd->pw_gid) == -1) { |
83 | + fprintf(stderr, "error: Unable to set real and effective gid (%s)\n", |
84 | + strerror(errno)); |
85 | + exit(1); |
86 | + } |
87 | + if (setreuid(pwd->pw_uid, pwd->pw_uid) == -1) { |
88 | + perror("error: Unable to set real and effective uid"); |
89 | + exit(1); |
90 | + } |
91 | + |
92 | + // Close all file descriptors except the standard ones |
93 | + struct rlimit rlp; |
94 | + if (getrlimit(RLIMIT_NOFILE, &rlp) == -1) { |
95 | + perror("error: Unable to determine file descriptor limits"); |
96 | + exit(1); |
97 | + } |
98 | + int file_max; |
99 | + if (rlp.rlim_max == RLIM_INFINITY || rlp.rlim_max > 4096) |
100 | + file_max = 4096; |
101 | + else |
102 | + file_max = rlp.rlim_max; |
103 | + int file; |
104 | + for (file = 3; file < file_max; file++) { |
105 | + close(file); |
106 | + } |
107 | + |
108 | + // Set umask to 022 |
109 | + umask(S_IWGRP | S_IWOTH); |
110 | + |
111 | + if (chdir("/") == -1) { |
112 | + perror("error: Unable to change working directory"); |
113 | + exit(1); |
114 | + } |
115 | + |
116 | + // Run apt-get update |
117 | + execve(apt_argv[0], apt_argv, apt_envp); |
118 | + perror("error: Unable to execute apt-get"); |
119 | + return 1; |
120 | +} |
121 | |
122 | === modified file 'debian/landscape-client.postinst' |
123 | --- debian/landscape-client.postinst 2011-10-07 11:52:47 +0000 |
124 | +++ debian/landscape-client.postinst 2011-11-08 11:04:00 +0000 |
125 | @@ -102,12 +102,17 @@ |
126 | echo "Old monolithic client data file migrated to new format." |
127 | fi |
128 | |
129 | - # Add the setuid flag to smart-update and it be executable by users in |
130 | - # the landscape group (that normally means landscape itself) |
131 | + # Add the setuid flag to smart-update and apt-update, and make them be |
132 | + # executable by users in the landscape group (that normally means |
133 | + # landscape itself) |
134 | smart_update=/usr/lib/landscape/smart-update |
135 | if ! dpkg-statoverride --list $smart_update >/dev/null 2>&1; then |
136 | dpkg-statoverride --update --add root landscape 4754 $smart_update |
137 | fi |
138 | + apt_update=/usr/lib/landscape/apt-update |
139 | + if ! dpkg-statoverride --list $apt_update >/dev/null 2>&1; then |
140 | + dpkg-statoverride --update --add root landscape 4754 $apt_update |
141 | + fi |
142 | |
143 | # Remove old cron jobs |
144 | old_cron_job=/etc/cron.hourly/landscape-client |
145 | |
146 | === modified file 'debian/landscape-client.prerm' |
147 | --- debian/landscape-client.prerm 2009-06-08 13:29:20 +0000 |
148 | +++ debian/landscape-client.prerm 2011-11-08 11:04:00 +0000 |
149 | @@ -20,11 +20,15 @@ |
150 | case "$1" in |
151 | remove|upgrade|deconfigure) |
152 | |
153 | - # Remove statoverride for smart-update |
154 | + # Remove statoverride for smart-update and apt-update |
155 | smart_update=/usr/lib/landscape/smart-update |
156 | if dpkg-statoverride --list $smart_update >/dev/null 2>&1; then |
157 | dpkg-statoverride --remove $smart_update |
158 | fi |
159 | + apt_update=/usr/lib/landscape/apt-update |
160 | + if dpkg-statoverride --list $apt_update >/dev/null 2>&1; then |
161 | + dpkg-statoverride --remove $apt_update |
162 | + fi |
163 | |
164 | ;; |
165 | |
166 | |
167 | === modified file 'debian/rules' |
168 | --- debian/rules 2011-04-26 09:47:16 +0000 |
169 | +++ debian/rules 2011-11-08 11:04:00 +0000 |
170 | @@ -30,6 +30,7 @@ |
171 | sed -i -e "s/^DEBIAN_REVISION = \"\"/DEBIAN_REVISION = \"-$(revision)\"/g" landscape/__init__.py |
172 | python setup.py build |
173 | make -C smart-update |
174 | + make -C apt-update |
175 | touch build-stamp |
176 | |
177 | clean: |
178 | @@ -38,6 +39,7 @@ |
179 | rm -f build-stamp |
180 | rm -rf build |
181 | make -C smart-update clean |
182 | + make -C apt-update clean |
183 | dh_clean |
184 | debconf-updatepo |
185 | sed -i -e "s/^DEBIAN_REVISION = .*/DEBIAN_REVISION = \"\"/g" landscape/__init__.py |
186 | @@ -57,6 +59,7 @@ |
187 | install -D -o root -g root -m 755 debian/landscape-sysinfo.wrapper $(root_dir)/usr/share/landscape/landscape-sysinfo.wrapper |
188 | install -D -o root -g root -m 644 debian/cloud-default.conf $(root_dir)/usr/share/landscape/cloud-default.conf |
189 | install -D -o root -g root -m 755 smart-update/smart-update $(root_dir)/usr/lib/landscape/smart-update |
190 | + install -D -o root -g root -m 755 apt-update/apt-update $(root_dir)/usr/lib/landscape/apt-update |
191 | install -D -o root -g root -m 644 dbus/landscape.conf $(root_dir)/etc/dbus-1/system.d/landscape.conf |
192 | |
193 | binary-indep: |
194 | |
195 | === modified file 'landscape/package/reporter.py' |
196 | --- landscape/package/reporter.py 2011-10-19 13:16:30 +0000 |
197 | +++ landscape/package/reporter.py 2011-11-08 11:04:00 +0000 |
198 | @@ -49,15 +49,20 @@ |
199 | |
200 | smart_update_interval = 60 |
201 | smart_update_filename = "/usr/lib/landscape/smart-update" |
202 | + apt_update_filename = "/usr/lib/landscape/apt-update" |
203 | sources_list_filename = "/etc/apt/sources.list" |
204 | sources_list_directory = "/etc/apt/sources.list.d" |
205 | |
206 | def run(self): |
207 | result = Deferred() |
208 | |
209 | - # Run smart-update before anything else, to make sure that |
210 | - # the SmartFacade will load freshly updated channels |
211 | - result.addCallback(lambda x: self.run_smart_update()) |
212 | + if os.environ.get("USE_APT_FACADE"): |
213 | + # Update APT cache if APT facade is enabled. |
214 | + result.addCallback(lambda x: self.run_apt_update()) |
215 | + else: |
216 | + # Run smart-update before anything else, to make sure that |
217 | + # the SmartFacade will load freshly updated channels |
218 | + result.addCallback(lambda x: self.run_smart_update()) |
219 | |
220 | # If the appropriate hash=>id db is not there, fetch it |
221 | result.addCallback(lambda x: self.fetch_hash_id_db()) |
222 | @@ -215,6 +220,54 @@ |
223 | result.addCallback(callback) |
224 | return result |
225 | |
226 | + def _apt_update_timeout_expired(self, interval): |
227 | + """Check if the apt-update timeout has passed.""" |
228 | + stamp = self._config.apt_update_stamp_filename |
229 | + |
230 | + if not os.path.exists(stamp): |
231 | + return True |
232 | + # check stamp file mtime |
233 | + last_update = os.stat(stamp)[8] |
234 | + now = int(time.time()) |
235 | + return (last_update + interval * 60) < now |
236 | + |
237 | + def run_apt_update(self): |
238 | + """Run apt-update and log a warning in case of non-zero exit code. |
239 | + |
240 | + @return: a deferred returning (out, err, code) |
241 | + """ |
242 | + if (self._config.force_smart_update or self._apt_sources_have_changed() |
243 | + or self._apt_update_timeout_expired(self.smart_update_interval)): |
244 | + |
245 | + result = spawn_process(self.apt_update_filename) |
246 | + |
247 | + def callback((out, err, code)): |
248 | + touch_file(self._config.apt_update_stamp_filename) |
249 | + logging.debug( |
250 | + "'%s' exited with status %d (out='%s', err='%s')" % ( |
251 | + self.apt_update_filename, code, out, err)) |
252 | + |
253 | + if code != 0: |
254 | + logging.warning("'%s' exited with status %d (%s)" % ( |
255 | + self.apt_update_filename, code, err)) |
256 | + elif not self._facade.get_channels(): |
257 | + code = 1 |
258 | + err = ("There are no APT sources configured in %s or %s." % |
259 | + (self.sources_list_filename, |
260 | + self.sources_list_directory)) |
261 | + |
262 | + deferred = self._broker.call_if_accepted( |
263 | + "package-reporter-result", self.send_result, code, err) |
264 | + deferred.addCallback(lambda ignore: (out, err, code)) |
265 | + return deferred |
266 | + |
267 | + return result.addCallback(callback) |
268 | + |
269 | + else: |
270 | + logging.debug("'%s' didn't run, update interval has not passed" % |
271 | + self.apt_update_filename) |
272 | + return succeed(("", "", 0)) |
273 | + |
274 | def send_result(self, code, err): |
275 | """ |
276 | Report the package reporter result to the server in a message. |
277 | |
278 | === modified file 'landscape/package/taskhandler.py' |
279 | --- landscape/package/taskhandler.py 2011-10-26 13:08:13 +0000 |
280 | +++ landscape/package/taskhandler.py 2011-11-08 11:04:00 +0000 |
281 | @@ -40,6 +40,11 @@ |
282 | """Get the path to the smart-update stamp file.""" |
283 | return os.path.join(self.package_directory, "smart-update-stamp") |
284 | |
285 | + @property |
286 | + def apt_update_stamp_filename(self): |
287 | + """Get the path to the apt-update stamp file.""" |
288 | + return os.path.join(self.package_directory, "apt-update-stamp") |
289 | + |
290 | |
291 | class LazyRemoteBroker(object): |
292 | """Wrapper class around L{RemoteBroker} providing lazy initialization. |
293 | |
294 | === modified file 'landscape/package/tests/test_reporter.py' |
295 | --- landscape/package/tests/test_reporter.py 2011-10-26 12:55:00 +0000 |
296 | +++ landscape/package/tests/test_reporter.py 2011-11-08 11:04:00 +0000 |
297 | @@ -1693,6 +1693,262 @@ |
298 | """Make it so that package "name1" is considered installed.""" |
299 | self._install_deb_file(os.path.join(self.repository_dir, PKGNAME1)) |
300 | |
301 | + def _make_fake_apt_update(self, out="output", err="error", code=0): |
302 | + """Create a fake apt-update executable""" |
303 | + self.reporter.apt_update_filename = self.makeFile( |
304 | + "#!/bin/sh\n" |
305 | + "echo -n %s\n" |
306 | + "echo -n %s >&2\n" |
307 | + "exit %d" % (out, err, code)) |
308 | + os.chmod(self.reporter.apt_update_filename, 0755) |
309 | + |
310 | + def test_run_apt_update(self): |
311 | + """ |
312 | + The L{PackageReporter.run_apt_update} method should run apt-update. |
313 | + """ |
314 | + self.reporter.sources_list_filename = "/I/Dont/Exist" |
315 | + self._make_fake_apt_update() |
316 | + debug_mock = self.mocker.replace("logging.debug") |
317 | + debug_mock("'%s' exited with status 0 (out='output', err='error')" % |
318 | + self.reporter.apt_update_filename) |
319 | + warning_mock = self.mocker.replace("logging.warning") |
320 | + self.expect(warning_mock(ANY)).count(0) |
321 | + self.mocker.replay() |
322 | + deferred = Deferred() |
323 | + |
324 | + def do_test(): |
325 | + |
326 | + result = self.reporter.run_apt_update() |
327 | + |
328 | + def callback((out, err, code)): |
329 | + self.assertEqual("output", out) |
330 | + self.assertEqual("error", err) |
331 | + self.assertEqual(0, code) |
332 | + result.addCallback(callback) |
333 | + result.chainDeferred(deferred) |
334 | + |
335 | + reactor.callWhenRunning(do_test) |
336 | + return deferred |
337 | + |
338 | + def test_run_apt_update_with_force_smart_update(self): |
339 | + """ |
340 | + L{PackageReporter.run_apt_update} forces an apt-update run if the |
341 | + '--force-smart-update' command line option was passed. |
342 | + """ |
343 | + self.makeFile("", path=self.config.apt_update_stamp_filename) |
344 | + self.config.load(["--force-smart-update"]) |
345 | + self._make_fake_apt_update() |
346 | + |
347 | + deferred = Deferred() |
348 | + |
349 | + def do_test(): |
350 | + result = self.reporter.run_apt_update() |
351 | + |
352 | + def callback((out, err, code)): |
353 | + self.assertEqual("output", out) |
354 | + result.addCallback(callback) |
355 | + result.chainDeferred(deferred) |
356 | + |
357 | + reactor.callWhenRunning(do_test) |
358 | + return deferred |
359 | + |
360 | + def test_run_apt_update_with_force_smart_update_if_sources_changed(self): |
361 | + """ |
362 | + L{PackageReporter.run_apt_update} forces an apt-update run if the APT |
363 | + sources.list file has changed. |
364 | + |
365 | + """ |
366 | + self.assertEqual(self.reporter.sources_list_filename, |
367 | + "/etc/apt/sources.list") |
368 | + self.reporter.sources_list_filename = self.makeFile("deb ftp://url ./") |
369 | + self._make_fake_apt_update() |
370 | + |
371 | + deferred = Deferred() |
372 | + |
373 | + def do_test(): |
374 | + result = self.reporter.run_apt_update() |
375 | + |
376 | + def callback((out, err, code)): |
377 | + self.assertEqual("output", out) |
378 | + result.addCallback(callback) |
379 | + result.chainDeferred(deferred) |
380 | + |
381 | + reactor.callWhenRunning(do_test) |
382 | + return deferred |
383 | + |
384 | + def test_run_apt_update_warns_about_failures(self): |
385 | + """ |
386 | + The L{PackageReporter.run_apt_update} method should log a warning in |
387 | + case apt-update terminates with a non-zero exit code. |
388 | + """ |
389 | + self._make_fake_apt_update(code=2) |
390 | + logging_mock = self.mocker.replace("logging.warning") |
391 | + logging_mock("'%s' exited with status 2" |
392 | + " (error)" % self.reporter.apt_update_filename) |
393 | + self.mocker.replay() |
394 | + deferred = Deferred() |
395 | + |
396 | + def do_test(): |
397 | + result = self.reporter.run_apt_update() |
398 | + |
399 | + def callback((out, err, code)): |
400 | + self.assertEqual("output", out) |
401 | + self.assertEqual("error", err) |
402 | + self.assertEqual(2, code) |
403 | + result.addCallback(callback) |
404 | + result.chainDeferred(deferred) |
405 | + |
406 | + reactor.callWhenRunning(do_test) |
407 | + return deferred |
408 | + |
409 | + def test_run_apt_update_report_apt_failure(self): |
410 | + """ |
411 | + If L{PackageReporter.run_apt_update} fails, a message is sent to the |
412 | + server reporting the error, to be able to fix the problem centrally. |
413 | + """ |
414 | + message_store = self.broker_service.message_store |
415 | + message_store.set_accepted_types(["package-reporter-result"]) |
416 | + self._make_fake_apt_update(code=2) |
417 | + deferred = Deferred() |
418 | + |
419 | + def do_test(): |
420 | + result = self.reporter.run_apt_update() |
421 | + |
422 | + def callback(ignore): |
423 | + self.assertMessages(message_store.get_pending_messages(), |
424 | + [{"type": "package-reporter-result", |
425 | + "code": 2, "err": u"error"}]) |
426 | + result.addCallback(callback) |
427 | + result.chainDeferred(deferred) |
428 | + |
429 | + reactor.callWhenRunning(do_test) |
430 | + return deferred |
431 | + |
432 | + def test_run_apt_update_report_no_sources(self): |
433 | + """ |
434 | + L{PackageReporter.run_apt_update} reports a failure if apt succeeds but |
435 | + there are no APT sources defined. APT doesn't fail if there are no |
436 | + sources, but we fake a failure in order to re-use the |
437 | + PackageReporterAlert on the server. |
438 | + """ |
439 | + self.facade.reset_channels() |
440 | + message_store = self.broker_service.message_store |
441 | + message_store.set_accepted_types(["package-reporter-result"]) |
442 | + self._make_fake_apt_update() |
443 | + deferred = Deferred() |
444 | + |
445 | + def do_test(): |
446 | + result = self.reporter.run_apt_update() |
447 | + |
448 | + def callback(ignore): |
449 | + error = "There are no APT sources configured in %s or %s." % ( |
450 | + self.reporter.sources_list_filename, |
451 | + self.reporter.sources_list_directory) |
452 | + self.assertMessages(message_store.get_pending_messages(), |
453 | + [{"type": "package-reporter-result", |
454 | + "code": 1, "err": error}]) |
455 | + result.addCallback(callback) |
456 | + result.chainDeferred(deferred) |
457 | + |
458 | + reactor.callWhenRunning(do_test) |
459 | + return deferred |
460 | + |
461 | + def test_run_apt_update_report_apt_failure_no_sources(self): |
462 | + """ |
463 | + If L{PackageReporter.run_apt_update} fails and there are no |
464 | + APT sources configured, the APT error takes precedence. |
465 | + """ |
466 | + self.facade.reset_channels() |
467 | + message_store = self.broker_service.message_store |
468 | + message_store.set_accepted_types(["package-reporter-result"]) |
469 | + self._make_fake_apt_update(code=2) |
470 | + deferred = Deferred() |
471 | + |
472 | + def do_test(): |
473 | + result = self.reporter.run_apt_update() |
474 | + |
475 | + def callback(ignore): |
476 | + self.assertMessages(message_store.get_pending_messages(), |
477 | + [{"type": "package-reporter-result", |
478 | + "code": 2, "err": u"error"}]) |
479 | + result.addCallback(callback) |
480 | + result.chainDeferred(deferred) |
481 | + |
482 | + reactor.callWhenRunning(do_test) |
483 | + return deferred |
484 | + |
485 | + def test_run_apt_update_report_success(self): |
486 | + """ |
487 | + L{PackageReporter.run_apt_update} also reports success to be able to |
488 | + know the proper state of the client. |
489 | + """ |
490 | + message_store = self.broker_service.message_store |
491 | + message_store.set_accepted_types(["package-reporter-result"]) |
492 | + self._make_fake_apt_update(err="message") |
493 | + deferred = Deferred() |
494 | + |
495 | + def do_test(): |
496 | + result = self.reporter.run_apt_update() |
497 | + |
498 | + def callback(ignore): |
499 | + self.assertMessages(message_store.get_pending_messages(), |
500 | + [{"type": "package-reporter-result", |
501 | + "code": 0, "err": u"message"}]) |
502 | + result.addCallback(callback) |
503 | + result.chainDeferred(deferred) |
504 | + |
505 | + reactor.callWhenRunning(do_test) |
506 | + return deferred |
507 | + |
508 | + def test_run_apt_update_no_run_in_interval(self): |
509 | + """ |
510 | + The L{PackageReporter.run_apt_update} logs a debug message if |
511 | + apt-update doesn't run because interval has not passed. |
512 | + """ |
513 | + self.makeFile("", path=self.config.apt_update_stamp_filename) |
514 | + |
515 | + logging_mock = self.mocker.replace("logging.debug") |
516 | + logging_mock("'%s' didn't run, update interval has not passed" % |
517 | + self.reporter.apt_update_filename) |
518 | + self.mocker.replay() |
519 | + deferred = Deferred() |
520 | + |
521 | + def do_test(): |
522 | + |
523 | + result = self.reporter.run_apt_update() |
524 | + |
525 | + def callback((out, err, code)): |
526 | + self.assertEqual("", out) |
527 | + self.assertEqual("", err) |
528 | + self.assertEqual(0, code) |
529 | + result.addCallback(callback) |
530 | + result.chainDeferred(deferred) |
531 | + |
532 | + reactor.callWhenRunning(do_test) |
533 | + return deferred |
534 | + |
535 | + def test_run_apt_update_touches_stamp_file(self): |
536 | + """ |
537 | + The L{PackageReporter.run_apt_update} method touches a stamp file |
538 | + after running the apt-update wrapper. |
539 | + """ |
540 | + self.reporter.sources_list_filename = "/I/Dont/Exist" |
541 | + self._make_fake_apt_update() |
542 | + deferred = Deferred() |
543 | + |
544 | + def do_test(): |
545 | + |
546 | + result = self.reporter.run_apt_update() |
547 | + |
548 | + def callback(ignored): |
549 | + self.assertTrue( |
550 | + os.path.exists(self.config.apt_update_stamp_filename)) |
551 | + result.addCallback(callback) |
552 | + result.chainDeferred(deferred) |
553 | + |
554 | + reactor.callWhenRunning(do_test) |
555 | + return deferred |
556 | + |
557 | |
558 | class GlobalPackageReporterTestMixin(object): |
559 | |
560 | |
561 | === modified file 'landscape/package/tests/test_taskhandler.py' |
562 | --- landscape/package/tests/test_taskhandler.py 2011-07-05 05:09:11 +0000 |
563 | +++ landscape/package/tests/test_taskhandler.py 2011-11-08 11:04:00 +0000 |
564 | @@ -35,6 +35,16 @@ |
565 | config.smart_update_stamp_filename, |
566 | "/var/lib/landscape/client/package/smart-update-stamp") |
567 | |
568 | + def test_force_apt_update_option(self): |
569 | + """ |
570 | + L{PackageReporterConfiguration.apt_update_stamp_filename} points |
571 | + to the apt-update stamp file. |
572 | + """ |
573 | + config = PackageTaskHandlerConfiguration() |
574 | + self.assertEqual( |
575 | + config.apt_update_stamp_filename, |
576 | + "/var/lib/landscape/client/package/apt-update-stamp") |
577 | + |
578 | |
579 | class PackageTaskHandlerTest(LandscapeTest): |
580 |
It looks good, but I suspect we need to get this reviewed by someone from the platform team. It shouldn't block the branch, but I suggest getting in touch with them sooner than later.
+1!