Merge lp:~mvo/unattended-upgrades/lp1061498 into lp:~mvo/unattended-upgrades/debian-sid-mirror
- lp1061498
- Merge into debian-sid-mirror
Proposed by
Michael Vogt
Status: | Needs review |
---|---|
Proposed branch: | lp:~mvo/unattended-upgrades/lp1061498 |
Merge into: | lp:~mvo/unattended-upgrades/debian-sid-mirror |
Diff against target: |
1912 lines (+457/-270) 23 files modified
.bzrignore (+2/-0) debian/changelog (+23/-2) debian/control (+5/-4) debian/rules (+13/-11) debian/tests/control (+2/-0) debian/tests/run-tests (+4/-0) debian/unattended-upgrades.init (+1/-1) pm/sleep.d/10_unattended-upgrades-hibernate (+1/-1) setup.py (+4/-3) test/Makefile (+9/-2) test/create_debug_lock.py (+2/-1) test/test_against_real_archive.py (+14/-4) test/test_conffile.py (+29/-6) test/test_in_chroot.py (+41/-34) test/test_logdir.py (+3/-2) test/test_mail.py (+33/-16) test/test_minimal_partitions.py (+9/-9) test/test_origin_pattern.py (+31/-15) test/test_pep8.py (+17/-0) test/test_pyflakes.py (+4/-2) test/test_substitute.py (+2/-7) unattended-upgrade (+205/-147) unattended-upgrade-shutdown (+3/-3) |
To merge this branch: | bzr merge lp:~mvo/unattended-upgrades/lp1061498 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Vogt | Pending | ||
Review via email: mp+128271@code.launchpad.net |
Commit message
Description of the change
Fix crash #1061498 and add test
To post a comment you must log in.
Unmerged revisions
- 303. By Michael Vogt
-
fix dpkg_conffile_
prompt( ) LP: #1061498 and add testcase - 302. By Michael Vogt
-
test/Makefile: fix cleanup
- 301. By Michael Vogt
-
debian/
tests/run- tests: add run-test script - 300. By Michael Vogt
-
add dep8 tests
- 299. By Michael Vogt
-
Fixed debug output when a package has no candidates (LP: #1046438)
- 298. By Michael Vogt
-
releasing version 0.79.3ubuntu1
- 297. By Michael Vogt
-
fully pep8 clean (yeah!)
- 296. By Michael Vogt
-
add pyflakes/pep8 tests
- 295. By Michael Vogt
-
add py2 compatiblity back for easier backporting and run the tests in both py2/py3 and also run python-coverage
- 294. By Michael Vogt
-
add missing +x for mock_sendmail
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file '.bzrignore' |
2 | --- .bzrignore 1970-01-01 00:00:00 +0000 |
3 | +++ .bzrignore 2012-10-05 14:59:30 +0000 |
4 | @@ -0,0 +1,2 @@ |
5 | +__pycache__ |
6 | +build |
7 | |
8 | === modified file 'debian/changelog' |
9 | --- debian/changelog 2012-08-14 13:04:45 +0000 |
10 | +++ debian/changelog 2012-10-05 14:59:30 +0000 |
11 | @@ -1,3 +1,24 @@ |
12 | +unattended-upgrades (0.79.3ubuntu2) quantal; urgency=low |
13 | + |
14 | + [ Marc Tardif ] |
15 | + * Fixed debug output when a package has no candidates (LP: #1046438) |
16 | + |
17 | + [ Michael Vogt ] |
18 | + * debian/test/: |
19 | + - add dep8 tests |
20 | + |
21 | + -- Marc Tardif <marc@ubuntu.com> Thu, 13 Sep 2012 16:16:04 -0400 |
22 | + |
23 | +unattended-upgrades (0.79.3ubuntu1) quantal; urgency=low |
24 | + |
25 | + [ Thomas Kluyver ] |
26 | + * Port to Python 3 |
27 | + |
28 | + [ Brian Murray ] |
29 | + * unattended-upgrade: fix typo in debugging output |
30 | + |
31 | + -- Michael Vogt <michael.vogt@ubuntu.com> Mon, 10 Sep 2012 09:55:19 +0200 |
32 | + |
33 | unattended-upgrades (0.79.4) UNRELEASED; urgency=low |
34 | |
35 | * data/50unattended-upgrades.{Debian,Ubuntu}: |
36 | @@ -63,7 +84,7 @@ |
37 | - added, thanks to Pedro Ribeiro, closes: #678738 |
38 | * po/sk.po: |
39 | - added, thanks to helix84, closes: #677471 |
40 | - |
41 | + |
42 | [ Teodor MICU ] |
43 | * debian/unattended-upgrades.init: |
44 | - fixes new style lsb-init output, closes: #678030 |
45 | @@ -93,7 +114,7 @@ |
46 | - updated, thanks to Joe Dalton, closes: #677804 |
47 | * po/de.po: |
48 | - updated, thanks to Chris Leick (closes: #678204) |
49 | - |
50 | + |
51 | [ Teodor MICU ] |
52 | * debian/unattended-upgrades.init: |
53 | - use new style lsb-init output, closes: #678030 |
54 | |
55 | === modified file 'debian/control' |
56 | --- debian/control 2012-07-13 18:51:00 +0000 |
57 | +++ debian/control 2012-10-05 14:59:30 +0000 |
58 | @@ -3,14 +3,15 @@ |
59 | Priority: optional |
60 | Maintainer: Michael Vogt <michael.vogt@ubuntu.com> |
61 | Build-Depends: debhelper (>= 7.0.50~), po-debconf, lsb-release |
62 | -Build-Depends-Indep: python (>= 2.6.6-3~), python-distutils-extra |
63 | -Standards-Version: 3.8.3 |
64 | +Build-Depends-Indep: python3, python3-distutils-extra |
65 | +Standards-Version: 3.9.3 |
66 | Vcs-Bzr: http://code.launchpad.net/~ubuntu-core-dev/unattended-upgrades/ubuntu/ |
67 | +XS-Testsuite: autopkgtest |
68 | |
69 | Package: unattended-upgrades |
70 | Architecture: all |
71 | -Depends: ${shlibs:Depends}, ${misc:Depends}, debconf, python, |
72 | - python-apt (>= 0.7.90), apt-utils, apt, ucf, lsb-release, |
73 | +Depends: ${shlibs:Depends}, ${misc:Depends}, debconf, python3, |
74 | + python3-apt (>= 0.7.90), apt-utils, apt, ucf, lsb-release, |
75 | lsb-base (>= 3.2-14) |
76 | Suggests: bsd-mailx, mail-transport-agent |
77 | Description: automatic installation of security upgrades |
78 | |
79 | === modified file 'debian/rules' |
80 | --- debian/rules 2011-11-09 19:20:50 +0000 |
81 | +++ debian/rules 2012-10-05 14:59:30 +0000 |
82 | @@ -3,24 +3,26 @@ |
83 | DIST=$(shell /usr/bin/lsb_release -i -s) |
84 | |
85 | %: |
86 | - dh $@ --with python2 |
87 | + dh $@ --with python3 |
88 | |
89 | override_dh_auto_build: |
90 | # copy the right template into place |
91 | cp data/50unattended-upgrades.$(DIST) data/50unattended-upgrades |
92 | - dh_auto_build |
93 | + python3 setup.py build |
94 | + |
95 | +override_dh_auto_install: |
96 | + python3 setup.py install \ |
97 | + --root=$(CURDIR)/debian/unattended-upgrades \ |
98 | + --install-layout=deb |
99 | |
100 | override_dh_auto_clean: |
101 | # Sanity-check before upload. |
102 | - set -e; if [ -e /usr/lib/python$(PYVER)/py_compile.py ]; then \ |
103 | - for f in unattended-upgrade unattended-upgrade-shutdown; do \ |
104 | - ln -nsf $$f $$f.py; \ |
105 | - python$(PYVER) /usr/lib/python$(PYVER)/py_compile.py \ |
106 | - $$f.py; \ |
107 | - rm -f $$f.py; \ |
108 | - done; \ |
109 | - fi |
110 | - dh_auto_clean |
111 | + set -e; for f in unattended-upgrade unattended-upgrade-shutdown; do \ |
112 | + ln -nsf $$f $$f.py; \ |
113 | + py3compile $$f.py; \ |
114 | + rm -f $$f.py; \ |
115 | + done |
116 | + python3 setup.py clean -a |
117 | |
118 | override_dh_installinit: |
119 | # we do not want to run the init script in the postinst/prerm, its |
120 | |
121 | === added directory 'debian/tests' |
122 | === added file 'debian/tests/control' |
123 | --- debian/tests/control 1970-01-01 00:00:00 +0000 |
124 | +++ debian/tests/control 2012-10-05 14:59:30 +0000 |
125 | @@ -0,0 +1,2 @@ |
126 | +Tests: run-tests |
127 | +Depends: @, make, python-dev, python3-dev, python-coverage |
128 | |
129 | === added file 'debian/tests/run-tests' |
130 | --- debian/tests/run-tests 1970-01-01 00:00:00 +0000 |
131 | +++ debian/tests/run-tests 2012-10-05 14:59:30 +0000 |
132 | @@ -0,0 +1,4 @@ |
133 | +#!/bin/sh |
134 | + |
135 | +cd test |
136 | +make |
137 | |
138 | === modified file 'debian/unattended-upgrades.init' |
139 | --- debian/unattended-upgrades.init 2012-06-29 08:09:25 +0000 |
140 | +++ debian/unattended-upgrades.init 2012-10-05 14:59:30 +0000 |
141 | @@ -33,7 +33,7 @@ |
142 | stop) |
143 | if [ -e $SHUTDOWN_HELPER ]; then |
144 | [ "$VERBOSE" != "no" ] && log_action_begin_msg "Checking for running $DESC" |
145 | - python $SHUTDOWN_HELPER |
146 | + python3 $SHUTDOWN_HELPER |
147 | [ "$VERBOSE" != "no" ] && log_action_end_msg $? "$NAME" |
148 | fi |
149 | ;; |
150 | |
151 | === modified file 'pm/sleep.d/10_unattended-upgrades-hibernate' |
152 | --- pm/sleep.d/10_unattended-upgrades-hibernate 2011-11-08 16:56:58 +0000 |
153 | +++ pm/sleep.d/10_unattended-upgrades-hibernate 2012-10-05 14:59:30 +0000 |
154 | @@ -17,7 +17,7 @@ |
155 | case "${1}" in |
156 | hibernate) |
157 | if [ -e $SHUTDOWN_HELPER ]; then |
158 | - python $SHUTDOWN_HELPER |
159 | + python3 $SHUTDOWN_HELPER |
160 | fi |
161 | ;; |
162 | resume|thaw) |
163 | |
164 | === modified file 'setup.py' |
165 | --- setup.py 2011-10-24 10:20:18 +0000 |
166 | +++ setup.py 2012-10-05 14:59:30 +0000 |
167 | @@ -1,9 +1,10 @@ |
168 | #!/usr/bin/env python |
169 | |
170 | from distutils.core import setup |
171 | -from DistUtilsExtra.command import * |
172 | -import glob |
173 | -import os |
174 | +from DistUtilsExtra.command import ( |
175 | + build_extra, |
176 | + build_i18n, |
177 | + ) |
178 | |
179 | |
180 | setup(name='unattended-upgrades', version='0.1', |
181 | |
182 | === modified file 'test/Makefile' |
183 | --- test/Makefile 2011-10-07 09:22:19 +0000 |
184 | +++ test/Makefile 2012-10-05 14:59:30 +0000 |
185 | @@ -3,12 +3,15 @@ |
186 | all: check |
187 | |
188 | check: |
189 | + # test with both py2 and py3 for now and also use coverage for the py2 |
190 | set -e; \ |
191 | find . -name 'test_*.py' | \ |
192 | while read file; do \ |
193 | - echo "Running $$file"; \ |
194 | if [ -x $$file ]; then \ |
195 | - python $$file ; \ |
196 | + echo "Running $$file with python3"; \ |
197 | + python3 $$file ; \ |
198 | + echo "Running $$file with python"; \ |
199 | + python-coverage run -a $$file; \ |
200 | fi \ |
201 | done |
202 | |
203 | @@ -16,4 +19,8 @@ |
204 | rm -rf ./aptroot/var/cache/ |
205 | rm -rf ./aptroot/var/lib/apt |
206 | rm -rf ./aptroot/var/run |
207 | + find .. -type d -name __pycache__ | xargs rm -rf |
208 | |
209 | +coverage-html: |
210 | + echo "output in htmlcov/ |
211 | + python-coverage html |
212 | \ No newline at end of file |
213 | |
214 | === modified file 'test/create_debug_lock.py' |
215 | --- test/create_debug_lock.py 2011-06-16 07:10:07 +0000 |
216 | +++ test/create_debug_lock.py 2012-10-05 14:59:30 +0000 |
217 | @@ -1,4 +1,4 @@ |
218 | -#!/usr/bin/python |
219 | +#!/usr/bin/python3 |
220 | # |
221 | # create a lock file so that unattended-upgrades-shutdown pauses |
222 | # on shutdown -- useful for testing |
223 | @@ -7,6 +7,7 @@ |
224 | import os |
225 | import time |
226 | |
227 | + |
228 | pid = os.fork() |
229 | if pid == 0: |
230 | os.setsid() |
231 | |
232 | === modified file 'test/test_against_real_archive.py' (properties changed: +x to -x) |
233 | --- test/test_against_real_archive.py 2012-02-28 10:48:18 +0000 |
234 | +++ test/test_against_real_archive.py 2012-10-05 14:59:30 +0000 |
235 | @@ -1,22 +1,31 @@ |
236 | -#!/usr/bin/python |
237 | +#!/usr/bin/python3 |
238 | +"""Test unattended_upgrades against the real archive in a chroot. |
239 | + |
240 | +Note that this test is not run by the makefile in this folder, as it requires |
241 | +network access, and it fails in some situations (unclear which). |
242 | +""" |
243 | |
244 | import apt |
245 | import apt_pkg |
246 | import glob |
247 | +import logging |
248 | import os |
249 | import re |
250 | import unittest |
251 | |
252 | import unattended_upgrade |
253 | |
254 | + |
255 | apt_pkg.config.set("APT::Architecture", "amd64") |
256 | |
257 | + |
258 | class MockOptions(): |
259 | def __init__(self, debug=True, dry_run=True): |
260 | self.debug = debug |
261 | self.dry_run = dry_run |
262 | self.minimal_upgrade_steps = False |
263 | |
264 | + |
265 | class TestAgainstRealArchive(unittest.TestCase): |
266 | |
267 | def setUp(self): |
268 | @@ -40,11 +49,13 @@ |
269 | apt_pkg.config.set("APT::UnattendedUpgrades::LogDir", logdir) |
270 | unattended_upgrade.DISTRO_CODENAME = "lucid" |
271 | res = unattended_upgrade.main(options, os.path.abspath("./aptroot")) |
272 | + logging.debug(res) |
273 | # check if the log file exists |
274 | self.assertTrue(os.path.exists(logfile)) |
275 | - log = open(logfile).read() |
276 | + with open(logfile) as fp: |
277 | + log = fp.read() |
278 | # check that stuff worked |
279 | - self.assertFalse(" ERROR " in log) |
280 | + self.assertFalse(" ERROR " in log, log) |
281 | # check if we actually have the expected ugprade in it |
282 | self.assertTrue( |
283 | re.search("INFO Packages that are upgraded:.*awstats", log)) |
284 | @@ -59,4 +70,3 @@ |
285 | |
286 | if __name__ == "__main__": |
287 | unittest.main() |
288 | - |
289 | |
290 | === modified file 'test/test_conffile.py' |
291 | --- test/test_conffile.py 2012-06-28 20:06:37 +0000 |
292 | +++ test/test_conffile.py 2012-10-05 14:59:30 +0000 |
293 | @@ -1,11 +1,15 @@ |
294 | -#!/usr/bin/python |
295 | +#!/usr/bin/python3 |
296 | |
297 | import apt_pkg |
298 | import logging |
299 | import unittest |
300 | -import sys |
301 | - |
302 | -from unattended_upgrade import conffile_prompt |
303 | + |
304 | + |
305 | +from unattended_upgrade import ( |
306 | + conffile_prompt, |
307 | + dpkg_conffile_prompt, |
308 | + ) |
309 | + |
310 | |
311 | class ConffilePromptTestCase(unittest.TestCase): |
312 | |
313 | @@ -19,7 +23,7 @@ |
314 | test_pkg = "./packages/conf-test-package_1.1.deb" |
315 | self.assertTrue(conffile_prompt(test_pkg, prefix="./root.conffile"), |
316 | "conffile prompt detection incorrect") |
317 | - |
318 | + |
319 | def test_will_not_prompt(self): |
320 | # conf-test 0.9 is installed, 1.0 gets installed |
321 | # they both have the same config files |
322 | @@ -52,9 +56,28 @@ |
323 | test_pkg = "./packages/conf-test-package-new-conffile_1.deb" |
324 | self.assertTrue(conffile_prompt(test_pkg, prefix="./root.conffile"), |
325 | "conffile prompt detection incorrect") |
326 | + |
327 | +class DpkgConffileTestCase(unittest.TestCase): |
328 | + """ |
329 | + This tests that the detection if dpkg will prompt at all works, |
330 | + i.e. if the user has decided to use a --force-conf{old,new} option |
331 | + """ |
332 | + |
333 | + def setUp(self): |
334 | + apt_pkg.config.clear("DPkg::Options") |
335 | + |
336 | + def test_no_dpkg_prompt_option(self): |
337 | + self.assertTrue(dpkg_conffile_prompt()) |
338 | + |
339 | + def test_regression_lp1061498(self): |
340 | + apt_pkg.config.set("DPkg::Options::", "muup") |
341 | + self.assertTrue(dpkg_conffile_prompt()) |
342 | + |
343 | + def test_dpkg_will_never_prompt(self): |
344 | + apt_pkg.config.set("DPkg::Options::", "--force-confold") |
345 | + self.assertFalse(dpkg_conffile_prompt()) |
346 | |
347 | |
348 | if __name__ == "__main__": |
349 | logging.basicConfig(level=logging.DEBUG) |
350 | unittest.main() |
351 | - |
352 | |
353 | === modified file 'test/test_in_chroot.py' |
354 | --- test/test_in_chroot.py 2012-06-28 20:06:37 +0000 |
355 | +++ test/test_in_chroot.py 2012-10-05 14:59:30 +0000 |
356 | @@ -1,4 +1,4 @@ |
357 | -#!/usr/bin/python |
358 | +#!/usr/bin/python3 |
359 | |
360 | import apt |
361 | import logging |
362 | @@ -15,7 +15,8 @@ |
363 | #SOURCES_LIST=""" |
364 | #deb http://ftp.de.debian.org/debian squeeze main contrib non-free |
365 | #deb http://ftp.de.debian.org/debian squeeze-updates main contrib non-free |
366 | -#deb http://ftp.de.debian.org/debian squeeze-proposed-updates main contrib non-f#ree |
367 | +#deb http://ftp.de.debian.org/debian squeeze-proposed-updates main contrib \ |
368 | +# non-free |
369 | #deb http://security.debian.org squeeze/updates main contrib non-free |
370 | #""" |
371 | #DISTRO="squeeze" |
372 | @@ -27,7 +28,7 @@ |
373 | |
374 | |
375 | # ubuntu |
376 | -SOURCES_LIST=""" |
377 | +SOURCES_LIST = """ |
378 | deb http://archive.ubuntu.com/ubuntu/ lucid main restricted |
379 | deb-src http://archive.ubuntu.com/ubuntu/ lucid main restricted |
380 | |
381 | @@ -37,35 +38,39 @@ |
382 | deb http://security.ubuntu.com/ubuntu/ lucid-security main restricted |
383 | deb-src http://security.ubuntu.com/ubuntu/ lucid-security main restricted |
384 | """ |
385 | -DISTRO="lucid" |
386 | -ARCH="i386" |
387 | -TARBALL="%s-%s.tgz" % (DISTRO, ARCH) |
388 | -MIRROR="http://archive.ubuntu.com/ubuntu" |
389 | -APT_CONF="""APT::Architecture "%s";""" % ARCH |
390 | -ORIGINS_PATTERN="origin=Ubuntu,archive=lucid-security" |
391 | +DISTRO = "lucid" |
392 | +ARCH = "i386" |
393 | +TARBALL = "%s-%s.tgz" % (DISTRO, ARCH) |
394 | +MIRROR = "http://archive.ubuntu.com/ubuntu" |
395 | +APT_CONF = """APT::Architecture "%s";""" % ARCH |
396 | +ORIGINS_PATTERN = "origin=Ubuntu,archive=lucid-security" |
397 | |
398 | apt.apt_pkg.config.set("APT::Architecture", ARCH) |
399 | sys.path.insert(0, "..") |
400 | import unattended_upgrade |
401 | |
402 | + |
403 | class MockOptions(object): |
404 | debug = True |
405 | dry_run = False |
406 | minimal_upgrade_steps = False |
407 | |
408 | + |
409 | class TestUnattendedUpgrade(unittest.TestCase): |
410 | |
411 | def _create_new_debootstrap_tarball(self, tarball, target): |
412 | - print "creating initial test tarball, this is needed only once" |
413 | + print("creating initial test tarball, this is needed only once") |
414 | # force i386 |
415 | - subprocess.call(["debootstrap", |
416 | - "--arch=%s" % ARCH, |
417 | - # smaller version of the minimal system |
418 | - "--variant=minbase", |
419 | - "--include=python-apt,apt-utils,gpgv,ubuntu-keyring,ca-certificates", |
420 | - DISTRO, |
421 | - target, |
422 | - MIRROR]) |
423 | + subprocess.call( |
424 | + ["debootstrap", |
425 | + "--arch=%s" % ARCH, |
426 | + # smaller version of the minimal system |
427 | + "--variant=minbase", |
428 | + "--include=python-apt,apt-utils,gpgv,ubuntu-keyring," |
429 | + "ca-certificates", |
430 | + DISTRO, |
431 | + target, |
432 | + MIRROR]) |
433 | subprocess.call(["chroot", target, "apt-get", "clean"]) |
434 | subprocess.call(["tar", "czf", tarball, target]) |
435 | |
436 | @@ -73,7 +78,7 @@ |
437 | subprocess.call(["tar", "xzf", tarball]) |
438 | |
439 | def test_normal_upgrade(self): |
440 | - print "Running normal unattended upgrade in chroot" |
441 | + print("Running normal unattended upgrade in chroot") |
442 | options = MockOptions() |
443 | options.minimal_upgrade_steps = False |
444 | # run it |
445 | @@ -82,7 +87,7 @@ |
446 | self.assertTrue(self._verify_install_log_in_real_chroot(target)) |
447 | |
448 | def test_minimal_steps_upgrade(self): |
449 | - print "Running minimal steps unattended upgrade in chroot" |
450 | + print("Running minimal steps unattended upgrade in chroot") |
451 | options = MockOptions() |
452 | options.minimal_upgrade_steps = True |
453 | # run it |
454 | @@ -91,14 +96,15 @@ |
455 | self.assertTrue(self._verify_install_log_in_real_chroot(target)) |
456 | |
457 | def test_upgrade_on_shutdown_upgrade(self): |
458 | - print "Running unattended upgrade on shutdown (download and install) in chroot" |
459 | + print("Running unattended upgrade on shutdown (download and install) " |
460 | + "in chroot") |
461 | # ensure that it actually installs in shutdown env mode |
462 | options = MockOptions() |
463 | os.environ["UNATTENDED_UPGRADES_FORCE_INSTALL_ON_SHUTDOWN"] = "1" |
464 | apt.apt_pkg.config.set("Unattended-Upgrade::InstallOnShutdown", "1") |
465 | target = self._run_upgrade_test_in_real_chroot(options) |
466 | self.assertTrue(self._verify_install_log_in_real_chroot(target)) |
467 | - |
468 | + |
469 | def _get_lockfile_location(self, target): |
470 | return os.path.join( |
471 | target, "var/log/unattended-upgrades/unattended-upgrades.log") |
472 | @@ -114,14 +120,13 @@ |
473 | open(os.path.join(target, "etc/apt/apt.conf"), "w").write(APT_CONF) |
474 | open(os.path.join(target, "etc/apt/sources.list"), "w").write( |
475 | SOURCES_LIST) |
476 | - |
477 | |
478 | def _run_upgrade_test_in_real_chroot(self, options, clean_chroot=True): |
479 | """ helper that runs the unattended-upgrade in a chroot |
480 | and does some basic verifications |
481 | """ |
482 | if os.getuid() != 0: |
483 | - print "Skipping because uid != 0" |
484 | + print("Skipping because uid != 0") |
485 | return |
486 | |
487 | # clear to avoid pollution in the chroot |
488 | @@ -130,7 +135,7 @@ |
489 | # create chroot |
490 | target = "./test-chroot.%s" % DISTRO |
491 | |
492 | - # setup chroot if needed |
493 | + # setup chroot if needed |
494 | if clean_chroot: |
495 | self._setup_chroot(target) |
496 | |
497 | @@ -143,7 +148,7 @@ |
498 | if not os.path.exists("/var/log/unattended-upgrades/"): |
499 | os.makedirs("/var/log/unattended-upgrades/") |
500 | # make sure we are up-to-date |
501 | - subprocess.call(["apt-get","update", "-q", "-q"]) |
502 | + subprocess.call(["apt-get", "update", "-q", "-q"]) |
503 | # run it |
504 | apt.apt_pkg.config.clear("Unattended-Upgrade::Allowed-Origins") |
505 | apt.apt_pkg.config.clear("Unattended-Upgrade::Origins-Pattern") |
506 | @@ -153,7 +158,7 @@ |
507 | unattended_upgrade.main(options) |
508 | os._exit(0) |
509 | else: |
510 | - has_progress=False |
511 | + has_progress = False |
512 | all_progress = "" |
513 | last_progress = "" |
514 | progress_log = os.path.join( |
515 | @@ -171,9 +176,9 @@ |
516 | if pid == apid: |
517 | ret = os.WEXITSTATUS(status) |
518 | break |
519 | - #print "*******************", all_progress |
520 | + #print("*******************", all_progress) |
521 | self.assertEqual(ret, 0) |
522 | - # this number is a bit random, we just want to be sure we have |
523 | + # this number is a bit random, we just want to be sure we have |
524 | # progress data |
525 | self.assertTrue(has_progress, True) |
526 | self.assertTrue(len(all_progress) > 5) |
527 | @@ -183,11 +188,12 @@ |
528 | # examine log |
529 | log = self._get_lockfile_location(target) |
530 | logfile = open(log).read() |
531 | - #print logfile |
532 | - NEEDLE_PKG="ca-certificates" |
533 | + #print(logfile) |
534 | + NEEDLE_PKG = "ca-certificates" |
535 | if not re.search( |
536 | "Packages that are upgraded:.*%s" % NEEDLE_PKG, logfile): |
537 | - logging.warn("Can not find expected %s upgrade in log" % NEEDLE_PKG) |
538 | + logging.warn("Can not find expected %s upgrade in log" % |
539 | + NEEDLE_PKG) |
540 | return False |
541 | if "ERROR Installing the upgrades failed" in logfile: |
542 | logging.warn("Got a ERROR in the logfile") |
543 | @@ -196,9 +202,10 @@ |
544 | target, "var/log/unattended-upgrades/*-dpkg*.log") |
545 | dpkg_logfile = open(glob.glob(dpkg_log)[0]).read() |
546 | if not "Preparing to replace %s" % NEEDLE_PKG in dpkg_logfile: |
547 | - logging.warn("Did not find %s upgrade in the dpkg.log" % NEEDLE_PKG) |
548 | + logging.warn("Did not find %s upgrade in the dpkg.log" % |
549 | + NEEDLE_PKG) |
550 | return False |
551 | - #print dpkg_logfile |
552 | + #print(dpkg_logfile) |
553 | return True |
554 | |
555 | |
556 | |
557 | === modified file 'test/test_logdir.py' |
558 | --- test/test_logdir.py 2012-06-29 07:08:35 +0000 |
559 | +++ test/test_logdir.py 2012-10-05 14:59:30 +0000 |
560 | @@ -1,9 +1,8 @@ |
561 | -#!/usr/bin/python |
562 | +#!/usr/bin/python3 |
563 | |
564 | import apt_pkg |
565 | import logging |
566 | import os |
567 | -import mock |
568 | import sys |
569 | import tempfile |
570 | import unittest |
571 | @@ -11,10 +10,12 @@ |
572 | sys.path.insert(0, "..") |
573 | from unattended_upgrade import _setup_logging |
574 | |
575 | + |
576 | class MockOptions: |
577 | dry_run = False |
578 | debug = False |
579 | |
580 | + |
581 | class TestLogdir(unittest.TestCase): |
582 | |
583 | def setUp(self): |
584 | |
585 | === modified file 'test/test_mail.py' |
586 | --- test/test_mail.py 2012-07-13 12:20:03 +0000 |
587 | +++ test/test_mail.py 2012-10-05 14:59:30 +0000 |
588 | @@ -1,11 +1,14 @@ |
589 | -#!/usr/bin/python |
590 | +#!/usr/bin/python3 |
591 | # -*- coding: utf-8 -*- |
592 | +from __future__ import unicode_literals |
593 | + |
594 | import apt_pkg |
595 | import os |
596 | +import sys |
597 | import unittest |
598 | |
599 | +from io import StringIO |
600 | from email.parser import Parser |
601 | -from StringIO import StringIO |
602 | |
603 | import unattended_upgrade |
604 | from unattended_upgrade import send_summary_mail, setup_apt_listchanges |
605 | @@ -40,9 +43,10 @@ |
606 | res = successful |
607 | pkgs_kept_back = [] |
608 | # include some unicode chars here for good measure |
609 | - mem_log = StringIO(u"mem_log text üöä") |
610 | + mem_log = StringIO("mem_log text üöä") |
611 | logfile_dpkg = "./apt-term.log" |
612 | - open("./apt-term.log", "w").write("logfile_dpkg text") |
613 | + with open("./apt-term.log", "w") as fp: |
614 | + fp.write("logfile_dpkg text") |
615 | return (pkgs, res, pkgs_kept_back, mem_log, logfile_dpkg) |
616 | |
617 | def _verify_common_mail_content(self, mail_txt): |
618 | @@ -50,47 +54,55 @@ |
619 | self.assertTrue(expected_string in mail_txt) |
620 | |
621 | def test_summary_mail_reboot(self): |
622 | - open("./reboot-required","w").write("") |
623 | + with open("./reboot-required", "w") as fp: |
624 | + fp.write("") |
625 | send_summary_mail(*self._return_mock_data()) |
626 | os.unlink("./reboot-required") |
627 | - mail_txt = open("mail.txt").read() |
628 | + # this is used for py2 compat for py3 only we can do |
629 | + # remove the "rb" and the subsequent '.decode("utf-8")' |
630 | + with open("mail.txt", "rb") as fp: |
631 | + mail_txt = fp.read().decode("utf-8") |
632 | self.assertTrue("[reboot required]" in mail_txt) |
633 | self._verify_common_mail_content(mail_txt) |
634 | - |
635 | + |
636 | def test_summary_mail_no_reboot(self): |
637 | send_summary_mail(*self._return_mock_data()) |
638 | - mail_txt = open("mail.txt").read() |
639 | + with open("mail.txt", "rb") as fp: |
640 | + mail_txt = fp.read().decode("utf-8") |
641 | self.assertFalse("[reboot required]" in mail_txt) |
642 | self._verify_common_mail_content(mail_txt) |
643 | - |
644 | + |
645 | def test_summary_mail_only_on_error(self): |
646 | # default is to always send mail, ensure this is correct |
647 | # for both success and failure |
648 | apt_pkg.config.set("Unattended-Upgrade::MailOnlyOnError", "false") |
649 | send_summary_mail(*self._return_mock_data(successful=True)) |
650 | - self._verify_common_mail_content(open("mail.txt").read()) |
651 | + with open("mail.txt", "rb") as fp: |
652 | + self._verify_common_mail_content(fp.read().decode("utf-8")) |
653 | os.remove("mail.txt") |
654 | # now with a simulated failure |
655 | send_summary_mail(*self._return_mock_data(successful=False)) |
656 | - self._verify_common_mail_content(open("mail.txt").read()) |
657 | + with open("mail.txt", "rb") as fp: |
658 | + self._verify_common_mail_content(fp.read().decode("utf-8")) |
659 | os.remove("mail.txt") |
660 | # now test with "MailOnlyOnError" |
661 | apt_pkg.config.set("Unattended-Upgrade::MailOnlyOnError", "true") |
662 | send_summary_mail(*self._return_mock_data(successful=True)) |
663 | self.assertFalse(os.path.exists("mail.txt")) |
664 | send_summary_mail(*self._return_mock_data(successful=False)) |
665 | - mail_txt = open("mail.txt").read() |
666 | + with open("mail.txt", "rb") as fp: |
667 | + mail_txt = fp.read().decode("utf-8") |
668 | self._verify_common_mail_content(mail_txt) |
669 | self.assertTrue("Unattended upgrade returned: False" in mail_txt) |
670 | self.assertTrue(os.path.exists("mail.txt")) |
671 | |
672 | def test_apt_listchanges(self): |
673 | # test with sendmail available |
674 | - unattended_upgrade.SENDMAIL_BINARY="/bin/true" |
675 | + unattended_upgrade.SENDMAIL_BINARY = "/bin/true" |
676 | setup_apt_listchanges("./data/listchanges.conf.mail") |
677 | self.assertEqual(os.environ["APT_LISTCHANGES_FRONTEND"], "mail") |
678 | # test without sendmail |
679 | - unattended_upgrade.SENDMAIL_BINARY="/bin/not-here-xxxxxxxxx" |
680 | + unattended_upgrade.SENDMAIL_BINARY = "/bin/not-here-xxxxxxxxx" |
681 | setup_apt_listchanges("./data/listchanges.conf.pager") |
682 | self.assertEqual(os.environ["APT_LISTCHANGES_FRONTEND"], "none") |
683 | |
684 | @@ -108,6 +120,7 @@ |
685 | # we don't accidently try |
686 | self.assertFalse('text/plain; charset="utf-8"' in mail_txt) |
687 | |
688 | + |
689 | class SendmailTestCase(CommonTestsForMailxAndSendmail, unittest.TestCase): |
690 | |
691 | def setUp(self): |
692 | @@ -117,10 +130,15 @@ |
693 | def _verify_common_mail_content(self, mail_txt): |
694 | CommonTestsForMailxAndSendmail._verify_common_mail_content( |
695 | self, mail_txt) |
696 | + |
697 | + # python2 needs this as utf8 encoded string (not unicode) |
698 | + if sys.version < '3': |
699 | + mail_txt = mail_txt.encode("utf-8") |
700 | + |
701 | msg = Parser().parsestr(mail_txt) |
702 | content_type = msg["Content-Type"] |
703 | self.assertEqual(content_type, 'text/plain; charset="utf-8"') |
704 | - |
705 | + |
706 | |
707 | class SendmailAndMailxTestCase(SendmailTestCase): |
708 | |
709 | @@ -132,4 +150,3 @@ |
710 | if __name__ == "__main__": |
711 | #logging.basicConfig(level=logging.DEBUG) |
712 | unittest.main() |
713 | - |
714 | |
715 | === modified file 'test/test_minimal_partitions.py' |
716 | --- test/test_minimal_partitions.py 2011-11-18 10:46:15 +0000 |
717 | +++ test/test_minimal_partitions.py 2012-10-05 14:59:30 +0000 |
718 | @@ -1,33 +1,32 @@ |
719 | -#!/usr/bin/python |
720 | +#!/usr/bin/python3 |
721 | |
722 | import apt |
723 | import apt_pkg |
724 | import os |
725 | -import logging |
726 | import unittest |
727 | -import sys |
728 | -import time |
729 | |
730 | import unattended_upgrade |
731 | |
732 | + |
733 | class LogInstallProgressMock(unattended_upgrade.LogInstallProgress): |
734 | |
735 | # klass data so that we can veriy in the test as the actual |
736 | # object is destroyed |
737 | DATA = [] |
738 | - |
739 | + |
740 | # overwrite to log the data |
741 | def status_change(self, pkg, percent, status): |
742 | - print pkg, percent |
743 | + print(pkg, percent) |
744 | self.DATA.append([pkg, percent]) |
745 | |
746 | + |
747 | class TestMinimalPartitions(unittest.TestCase): |
748 | |
749 | def setUp(self): |
750 | # setup dry-run mode for apt |
751 | apt_pkg.config.set("Dir::Cache", "/tmp") |
752 | - apt_pkg.config.set("Debug::NoLocking","1") |
753 | - apt_pkg.config.set("Debug::pkgDPkgPM","1") |
754 | + apt_pkg.config.set("Debug::NoLocking", "1") |
755 | + apt_pkg.config.set("Debug::pkgDPkgPM", "1") |
756 | apt_pkg.config.set("Dir::State::extended_states", "./extended_states") |
757 | apt_pkg.config.clear("Dpkg::Post-Invoke") |
758 | apt_pkg.config.clear("Dpkg::Pre-Install-Pkgs") |
759 | @@ -40,7 +39,8 @@ |
760 | def test_upgrade_in_minimal_steps(self): |
761 | self.cache.upgrade(True) |
762 | pkgs_to_upgrade = [pkg.name for pkg in self.cache.get_changes()] |
763 | - unattended_upgrade.PROGRESS_LOG="./aptroot/var/run/unatteded-upgrades.progress" |
764 | + unattended_upgrade.PROGRESS_LOG = \ |
765 | + "./aptroot/var/run/unatteded-upgrades.progress" |
766 | unattended_upgrade.LogInstallProgress = LogInstallProgressMock |
767 | unattended_upgrade.upgrade_in_minimal_steps( |
768 | self.cache, pkgs_to_upgrade) |
769 | |
770 | === modified file 'test/test_origin_pattern.py' |
771 | --- test/test_origin_pattern.py 2012-08-14 11:55:21 +0000 |
772 | +++ test/test_origin_pattern.py 2012-10-05 14:59:30 +0000 |
773 | @@ -1,4 +1,4 @@ |
774 | -#!/usr/bin/python |
775 | +#!/usr/bin/python3 |
776 | |
777 | import apt_pkg |
778 | import logging |
779 | @@ -12,49 +12,63 @@ |
780 | UnknownMatcherError, |
781 | ) |
782 | |
783 | + |
784 | class MockOrigin(): |
785 | pass |
786 | + |
787 | + |
788 | class MockCandidate(): |
789 | pass |
790 | + |
791 | + |
792 | class MockPackage(): |
793 | pass |
794 | + |
795 | + |
796 | class MockCache(list): |
797 | pass |
798 | + |
799 | + |
800 | class MockDepCache(): |
801 | pass |
802 | |
803 | + |
804 | class TestOriginPatern(unittest.TestCase): |
805 | |
806 | def setUp(self): |
807 | pass |
808 | + |
809 | def tearDown(self): |
810 | pass |
811 | + |
812 | def test_match_whitelist_string(self): |
813 | origin = self._get_mock_origin( |
814 | "OriginUbuntu", "LabelUbuntu", "ArchiveUbuntu", |
815 | "archive.ubuntu.com", "main") |
816 | # good |
817 | - s="o=OriginUbuntu" |
818 | + s = "o=OriginUbuntu" |
819 | self.assertTrue(match_whitelist_string(s, origin)) |
820 | - s="o=OriginUbuntu,l=LabelUbuntu,a=ArchiveUbuntu,site=archive.ubuntu.com" |
821 | + s = "o=OriginUbuntu,l=LabelUbuntu,a=ArchiveUbuntu," \ |
822 | + "site=archive.ubuntu.com" |
823 | self.assertTrue(match_whitelist_string(s, origin)) |
824 | # bad |
825 | - s="" |
826 | - self.assertFalse(match_whitelist_string(s, origin)) |
827 | - s="o=something" |
828 | - self.assertFalse(match_whitelist_string(s, origin)) |
829 | - s="o=LabelUbuntu,a=no-match" |
830 | + s = "" |
831 | + self.assertFalse(match_whitelist_string(s, origin)) |
832 | + s = "o=something" |
833 | + self.assertFalse(match_whitelist_string(s, origin)) |
834 | + s = "o=LabelUbuntu,a=no-match" |
835 | self.assertFalse(match_whitelist_string(s, origin)) |
836 | # with escaping |
837 | origin = self._get_mock_origin("Google, Inc.", archive="stable") |
838 | # good |
839 | - s="o=Google\, Inc.,a=stable" |
840 | + s = "o=Google\, Inc.,a=stable" |
841 | self.assertTrue(match_whitelist_string(s, origin)) |
842 | |
843 | def test_match_whitelist_from_conffile(self): |
844 | # read some |
845 | apt_pkg.config.clear("Unattended-Upgrade") |
846 | - apt_pkg.read_config_file(apt_pkg.config, "./data/50unattended-upgrades.Test") |
847 | + apt_pkg.read_config_file( |
848 | + apt_pkg.config, "./data/50unattended-upgrades.Test") |
849 | allowed_origins = unattended_upgrade.get_allowed_origins() |
850 | #print allowed_origins |
851 | self.assertTrue("o=aOrigin,a=aArchive" in allowed_origins) |
852 | @@ -63,7 +77,8 @@ |
853 | |
854 | def test_compatiblity(self): |
855 | apt_pkg.config.clear("Unattended-Upgrade") |
856 | - apt_pkg.read_config_file(apt_pkg.config, "./data/50unattended-upgrades.compat") |
857 | + apt_pkg.read_config_file( |
858 | + apt_pkg.config, "./data/50unattended-upgrades.compat") |
859 | allowed_origins = unattended_upgrade.get_allowed_origins() |
860 | #print allowed_origins |
861 | self.assertTrue("o=Google\, Inc.,a=stable" in allowed_origins) |
862 | @@ -74,7 +89,7 @@ |
863 | |
864 | def test_unkown_matcher(self): |
865 | apt_pkg.config.clear("Unattended-Upgrade") |
866 | - s="xxx=OriginUbuntu" |
867 | + s = "xxx=OriginUbuntu" |
868 | with self.assertRaises(UnknownMatcherError): |
869 | self.assertTrue(match_whitelist_string(s, None)) |
870 | |
871 | @@ -90,10 +105,12 @@ |
872 | allowed_origins = ["o=Ubuntu"] |
873 | blacklist = ["linux-.*"] |
874 | # with blacklist pkg |
875 | - self.assertFalse(check_changes_for_sanity(cache, allowed_origins, blacklist)) |
876 | + self.assertFalse( |
877 | + check_changes_for_sanity(cache, allowed_origins, blacklist)) |
878 | # with "normal" pkg |
879 | pkg.name = "apt" |
880 | - self.assertTrue(check_changes_for_sanity(cache, allowed_origins, blacklist)) |
881 | + self.assertTrue( |
882 | + check_changes_for_sanity(cache, allowed_origins, blacklist)) |
883 | |
884 | def _get_mock_origin(self, aorigin="", label="", archive="", |
885 | site="", component=""): |
886 | @@ -125,4 +142,3 @@ |
887 | if __name__ == "__main__": |
888 | logging.basicConfig(level=logging.DEBUG) |
889 | unittest.main() |
890 | - |
891 | |
892 | === added file 'test/test_pep8.py' |
893 | --- test/test_pep8.py 1970-01-01 00:00:00 +0000 |
894 | +++ test/test_pep8.py 2012-10-05 14:59:30 +0000 |
895 | @@ -0,0 +1,17 @@ |
896 | +import glob |
897 | +import os |
898 | +import subprocess |
899 | +import unittest |
900 | + |
901 | + |
902 | +class PackagePep8TestCase(unittest.TestCase): |
903 | + |
904 | + def test_all_code(self): |
905 | + res = 0 |
906 | + py_files = glob.glob(os.path.join(os.path.dirname(__file__), "*.py")) |
907 | + res += subprocess.call(["pep8", "--repeat", ] + py_files) |
908 | + self.assertEqual(res, 0) |
909 | + |
910 | + |
911 | +if __name__ == "__main__": |
912 | + unittest.main() |
913 | |
914 | === modified file 'test/test_pyflakes.py' |
915 | --- test/test_pyflakes.py 2012-07-13 16:40:10 +0000 |
916 | +++ test/test_pyflakes.py 2012-10-05 14:59:30 +0000 |
917 | @@ -2,12 +2,14 @@ |
918 | import subprocess |
919 | import unittest |
920 | |
921 | + |
922 | class TestPyflakesClean(unittest.TestCase): |
923 | """ ensure that the tree is pyflakes clean """ |
924 | |
925 | def test_pyflakes_clean(self): |
926 | - target = os.path.join(os.path.dirname(__file__), "..", "unattended-upgrade") |
927 | - self.assertEqual(subprocess.call(["pyflakes", target]), 0) |
928 | + path = os.path.join( |
929 | + os.path.dirname(__file__), "unattended_upgrade.py") |
930 | + self.assertEqual(subprocess.call(["pyflakes", path]), 0) |
931 | |
932 | |
933 | if __name__ == "__main__": |
934 | |
935 | === modified file 'test/test_substitute.py' |
936 | --- test/test_substitute.py 2011-02-04 11:05:12 +0000 |
937 | +++ test/test_substitute.py 2012-10-05 14:59:30 +0000 |
938 | @@ -1,17 +1,13 @@ |
939 | -#!/usr/bin/python |
940 | +#!/usr/bin/python3 |
941 | |
942 | -import apt |
943 | import apt_pkg |
944 | -import os |
945 | import logging |
946 | import unittest |
947 | -import sys |
948 | - |
949 | -from StringIO import StringIO |
950 | |
951 | import unattended_upgrade |
952 | from unattended_upgrade import substitute, get_allowed_origins |
953 | |
954 | + |
955 | class TestSubstitude(unittest.TestCase): |
956 | |
957 | def setUp(self): |
958 | @@ -36,4 +32,3 @@ |
959 | if __name__ == "__main__": |
960 | logging.basicConfig(level=logging.DEBUG) |
961 | unittest.main() |
962 | - |
963 | |
964 | === modified file 'unattended-upgrade' |
965 | --- unattended-upgrade 2012-08-14 11:55:21 +0000 |
966 | +++ unattended-upgrade 2012-10-05 14:59:30 +0000 |
967 | @@ -1,4 +1,4 @@ |
968 | -#!/usr/bin/python |
969 | +#!/usr/bin/python3 |
970 | # Copyright (c) 2005-2012 Canonical Ltd |
971 | # |
972 | # AUTHOR: |
973 | @@ -20,26 +20,27 @@ |
974 | # along with unattended-upgrades; if not, write to the Free Software |
975 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
976 | # |
977 | - |
978 | import apt_inst |
979 | import apt_pkg |
980 | |
981 | import copy |
982 | import datetime |
983 | -import email.Charset |
984 | +import email.charset |
985 | import fcntl |
986 | import re |
987 | import os |
988 | import string |
989 | import sys |
990 | |
991 | -from email.Message import Message |
992 | +from io import StringIO |
993 | +from email.message import Message |
994 | from optparse import OptionParser |
995 | -from StringIO import StringIO |
996 | -from subprocess import Popen, PIPE |
997 | - |
998 | -import warnings |
999 | -warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning) |
1000 | + |
1001 | +from subprocess import ( |
1002 | + Popen, |
1003 | + PIPE, |
1004 | + ) |
1005 | + |
1006 | import apt |
1007 | import logging |
1008 | import lsb_release |
1009 | @@ -57,29 +58,32 @@ |
1010 | DISTRO_ID = lsb_release.get_distro_information()['ID'] |
1011 | |
1012 | # progress information is written here |
1013 | -PROGRESS_LOG="/var/run/unattended-upgrades.progress" |
1014 | +PROGRESS_LOG = "/var/run/unattended-upgrades.progress" |
1015 | |
1016 | # set from the sigint signal handler |
1017 | -SIGNAL_STOP_REQUEST=False |
1018 | +SIGNAL_STOP_REQUEST = False |
1019 | + |
1020 | |
1021 | class UnknownMatcherError(ValueError): |
1022 | pass |
1023 | |
1024 | |
1025 | class UnattendedUpgradesCache(apt.Cache): |
1026 | - |
1027 | + |
1028 | def __init__(self, rootdir, allowed_origins): |
1029 | apt.Cache.__init__(self, rootdir=rootdir) |
1030 | self.allowed_origins = allowed_origins |
1031 | - # ensure we update the candidate versions |
1032 | + # ensure we update the candidate versions |
1033 | self.adjust_candidate_versions() |
1034 | + |
1035 | def clear(self): |
1036 | apt.Cache.clear(self) |
1037 | - # ensure we update the candidate versions |
1038 | + # ensure we update the candidate versions |
1039 | self.adjust_candidate_versions() |
1040 | + |
1041 | def adjust_candidate_versions(self): |
1042 | """ Adjust candidate versions to match highest allowed origin |
1043 | - |
1044 | + |
1045 | This adjusts the origin even if the candidate has a higher |
1046 | version |
1047 | """ |
1048 | @@ -114,20 +118,19 @@ |
1049 | (/var/run/unattended-upgrades.progress by default) |
1050 | """ |
1051 | |
1052 | - LOG = PROGRESS_LOG |
1053 | + LOG = PROGRESS_LOG |
1054 | |
1055 | def status_change(self, pkg, percent, status): |
1056 | - f=open(self.LOG, "w") |
1057 | - f.write(_("Progress: %s %% (%s)") % (percent, pkg)) |
1058 | - f.close() |
1059 | + with open(self.LOG, "w") as f: |
1060 | + f.write(_("Progress: %s %% (%s)") % (percent, pkg)) |
1061 | |
1062 | def _fixup_fds(self): |
1063 | - required_fds = [ 0, 1, 2, # stdin, stdout, stderr |
1064 | - self.writefd, |
1065 | - self.write_stream.fileno(), |
1066 | - self.statusfd, |
1067 | - self.status_stream.fileno() |
1068 | - ] |
1069 | + required_fds = [0, 1, 2, # stdin, stdout, stderr |
1070 | + self.writefd, |
1071 | + self.write_stream.fileno(), |
1072 | + self.statusfd, |
1073 | + self.status_stream.fileno() |
1074 | + ] |
1075 | # ensure that our required fds close on exec |
1076 | for fd in required_fds[3:]: |
1077 | old_flags = fcntl.fcntl(fd, fcntl.F_GETFD) |
1078 | @@ -140,19 +143,19 @@ |
1079 | try: |
1080 | fd = int(fdname) |
1081 | except Exception as e: |
1082 | - print "ERROR: can not get fd for '%s'" % fdname |
1083 | + print("ERROR: can not get fd for '%s'" % fdname) |
1084 | if fd in required_fds: |
1085 | continue |
1086 | try: |
1087 | os.close(fd) |
1088 | - #print "closed: ", fd |
1089 | + #print("closed: ", fd) |
1090 | except OSError as e: |
1091 | # there will be one fd that can not be closed |
1092 | # as its the fd from pythons internal diropen() |
1093 | # so its ok to ignore one close error |
1094 | error_count += 1 |
1095 | if error_count > 1: |
1096 | - print "ERROR: os.close(%s): %s" % (fd, e) |
1097 | + print("ERROR: os.close(%s): %s" % (fd, e)) |
1098 | |
1099 | def fork(self): |
1100 | pid = os.fork() |
1101 | @@ -162,53 +165,62 @@ |
1102 | |
1103 | |
1104 | class Unlocked: |
1105 | - """ context manager for unlocking the apt lock while cache.commit() |
1106 | - is run |
1107 | - """ |
1108 | + """ |
1109 | + Context manager for unlocking the apt lock while cache.commit() is run |
1110 | + """ |
1111 | + |
1112 | def __enter__(self): |
1113 | try: |
1114 | apt_pkg.pkgsystem_unlock() |
1115 | except: |
1116 | pass |
1117 | + |
1118 | def __exit__(self, exc_type, exc_value, exc_tb): |
1119 | try: |
1120 | apt_pkg.pkgsystem_unlock() |
1121 | except: |
1122 | pass |
1123 | |
1124 | + |
1125 | def is_dpkg_journal_dirty(): |
1126 | """ |
1127 | - test if the dpkg journal is dirty |
1128 | + Return True if the dpkg journal is dirty |
1129 | (similar to debSystem::CheckUpdates) |
1130 | """ |
1131 | - d = os.path.dirname( |
1132 | - apt_pkg.config.find_file("Dir::State::status"))+"/updates" |
1133 | + d = os.path.join( |
1134 | + os.path.dirname(apt_pkg.config.find_file("Dir::State::status")), |
1135 | + "updates") |
1136 | for f in os.listdir(d): |
1137 | if re.match("[0-9]+", f): |
1138 | return True |
1139 | return False |
1140 | |
1141 | + |
1142 | def signal_handler(signal, frame): |
1143 | logging.warn("SIGUSR1 recieved, will stop") |
1144 | global SIGNAL_STOP_REQUEST |
1145 | - SIGNAL_STOP_REQUEST=True |
1146 | + SIGNAL_STOP_REQUEST = True |
1147 | + |
1148 | |
1149 | def substitute(line): |
1150 | - """ substitude known mappings and return a new string |
1151 | + """ substitude known mappings and return a new string |
1152 | |
1153 | Currently supported ${distro-release} |
1154 | """ |
1155 | - mapping = {"distro_codename" : get_distro_codename(), |
1156 | - "distro_id" : get_distro_id(), |
1157 | + mapping = {"distro_codename": get_distro_codename(), |
1158 | + "distro_id": get_distro_id(), |
1159 | } |
1160 | return string.Template(line).substitute(mapping) |
1161 | - |
1162 | + |
1163 | + |
1164 | def get_distro_codename(): |
1165 | return DISTRO_CODENAME |
1166 | |
1167 | + |
1168 | def get_distro_id(): |
1169 | return DISTRO_ID |
1170 | |
1171 | + |
1172 | def get_allowed_origins_legacy(): |
1173 | """ legacy support for old Allowed-Origins var """ |
1174 | allowed_origins = [] |
1175 | @@ -222,10 +234,11 @@ |
1176 | distro_id = re.sub(r'([^\\]),', r'\1\\,', distro_id) |
1177 | distro_codename = re.sub(r'([^\\]),', r'\1\\,', distro_codename) |
1178 | # convert to new format |
1179 | - allowed_origins.append("o=%s,a=%s" % (substitute(distro_id), |
1180 | + allowed_origins.append("o=%s,a=%s" % (substitute(distro_id), |
1181 | substitute(distro_codename))) |
1182 | return allowed_origins |
1183 | |
1184 | + |
1185 | def get_allowed_origins(): |
1186 | """ return a list of allowed origins from apt.conf |
1187 | |
1188 | @@ -236,6 +249,7 @@ |
1189 | allowed_origins.append(substitute(s)) |
1190 | return allowed_origins |
1191 | |
1192 | + |
1193 | def match_whitelist_string(whitelist, origin): |
1194 | """ |
1195 | take a whitelist string in the form "origin=Debian,label=Debian-Security" |
1196 | @@ -251,9 +265,10 @@ |
1197 | whitelist = whitelist.replace("\,", "%2C") |
1198 | for token in whitelist.split(","): |
1199 | # strip and unquote the "," back |
1200 | - (what, value) = [s.strip().replace("%2C",",") |
1201 | + (what, value) = [s.strip().replace("%2C", ",") |
1202 | for s in token.split("=")] |
1203 | - #logging.debug("matching '%s'='%s' against '%s'" % (what, value, origin)) |
1204 | + #logging.debug("matching '%s'='%s' against '%s'" % ( |
1205 | + # what, value, origin)) |
1206 | # first char is apt-cache policy output, send is the name |
1207 | # in the Release file |
1208 | if what in ("o", "origin"): |
1209 | @@ -272,6 +287,7 @@ |
1210 | what, token)) |
1211 | return res |
1212 | |
1213 | + |
1214 | def upgrade_normal(cache, pkgs_to_upgrade, logfile_dpkg): |
1215 | error = None |
1216 | res = False |
1217 | @@ -279,17 +295,18 @@ |
1218 | try: |
1219 | with Unlocked(): |
1220 | res = cache.commit(install_progress=iprogress) |
1221 | - except SystemError,e: |
1222 | + except SystemError as e: |
1223 | error = e |
1224 | if res: |
1225 | logging.info(_("All upgrades installed")) |
1226 | else: |
1227 | logging.error(_("Installing the upgrades failed!")) |
1228 | logging.error(_("error message: '%s'") % error) |
1229 | - logging.error(_("dpkg returned a error! See '%s' for details") % \ |
1230 | + logging.error(_("dpkg returned a error! See '%s' for details") % |
1231 | logfile_dpkg) |
1232 | return res |
1233 | |
1234 | + |
1235 | def upgrade_in_minimal_steps(cache, pkgs_to_upgrade, logfile_dpkg=""): |
1236 | |
1237 | install_log = LogInstallProgress() |
1238 | @@ -320,13 +337,15 @@ |
1239 | smallest_partition = changes |
1240 | break |
1241 | if len(changes) < len(smallest_partition): |
1242 | - logging.debug("found partition of size %s (%s)" % (len(changes), changes)) |
1243 | + logging.debug("found partition of size %s (%s)" % ( |
1244 | + len(changes), changes)) |
1245 | smallest_partition = changes |
1246 | cache.clear() |
1247 | |
1248 | # write progress log information |
1249 | if len(pkgs_to_upgrade) > 0: |
1250 | - percent = (len(pkgs_to_upgrade)-len(to_upgrade)) / float(len(pkgs_to_upgrade))*100.0 |
1251 | + percent = ((len(pkgs_to_upgrade) - len(to_upgrade)) / |
1252 | + float(len(pkgs_to_upgrade)) * 100.0) |
1253 | else: |
1254 | percent = 100.0 |
1255 | install_log.status_change(pkg=",".join(smallest_partition), |
1256 | @@ -343,19 +362,20 @@ |
1257 | if not res: |
1258 | raise Exception("cache.commit() returned false") |
1259 | cache.open() |
1260 | - except Exception, e: |
1261 | + except Exception as e: |
1262 | logging.error(_("Installing the upgrades failed!")) |
1263 | logging.error(_("error message: '%s'") % e) |
1264 | - logging.error(_("dpkg returned a error! See '%s' for details") % \ |
1265 | + logging.error(_("dpkg returned a error! See '%s' for details") % |
1266 | logfile_dpkg) |
1267 | return False |
1268 | - to_upgrade = to_upgrade-set(smallest_partition) |
1269 | + to_upgrade = to_upgrade - set(smallest_partition) |
1270 | logging.debug("left to upgrade %s" % to_upgrade) |
1271 | if len(to_upgrade) == 0: |
1272 | logging.info(_("All upgrades installed")) |
1273 | break |
1274 | return True |
1275 | |
1276 | + |
1277 | def is_allowed_origin(ver, allowed_origins): |
1278 | if not ver: |
1279 | return False |
1280 | @@ -365,6 +385,7 @@ |
1281 | return True |
1282 | return False |
1283 | |
1284 | + |
1285 | def is_pkgname_in_blacklist(pkgname, blacklist): |
1286 | for blacklist_regexp in blacklist: |
1287 | if re.match(blacklist_regexp, pkgname): |
1288 | @@ -372,6 +393,7 @@ |
1289 | return True |
1290 | return False |
1291 | |
1292 | + |
1293 | def check_changes_for_sanity(cache, allowed_origins, blacklist): |
1294 | if cache._depcache.broken_count != 0: |
1295 | return False |
1296 | @@ -392,33 +414,39 @@ |
1297 | ignore_require_restart = apt_pkg.config.find_b( |
1298 | "Unattended-Upgrade::IgnoreAppsRequireRestart", False) |
1299 | if (pkg.marked_upgrade and |
1300 | - ignore_require_restart == False and |
1301 | + ignore_require_restart is False and |
1302 | pkg.candidate.record.get("Upgrade-Requires") == "app-restart"): |
1303 | - logging.debug("pkg '%s' requires app-restart, not safe to upgrade unattended") |
1304 | + logging.debug("pkg '%s' requires app-restart, not safe to " |
1305 | + "upgrade unattended") |
1306 | return False |
1307 | return True |
1308 | |
1309 | + |
1310 | def pkgname_from_deb(debfile): |
1311 | # FIXME: add error checking here |
1312 | try: |
1313 | control = apt_inst.DebFile(debfile).control.extractdata("control") |
1314 | sections = apt_pkg.TagSection(control) |
1315 | return sections["Package"] |
1316 | - except (IOError, SystemError), e: |
1317 | + except (IOError, SystemError) as e: |
1318 | logging.error("failed to read deb file '%s' (%s)" % (debfile, e)) |
1319 | # dumb fallback |
1320 | return debfile.split("_")[0] |
1321 | |
1322 | + |
1323 | def get_md5sum_for_file_in_deb(deb_file, conf_file): |
1324 | - dpkg_cmd = ["dpkg-deb","--fsys-tarfile", deb_file] |
1325 | - tar_cmd = ["tar","-x","-O", "-f","-", "."+conf_file] |
1326 | + dpkg_cmd = ["dpkg-deb", "--fsys-tarfile", deb_file] |
1327 | + tar_cmd = ["tar", "-x", "-O", "-f", "-", "." + conf_file] |
1328 | md5_cmd = ["md5sum"] |
1329 | dpkg_p = Popen(dpkg_cmd, stdout=PIPE) |
1330 | - tar_p = Popen(tar_cmd, stdin=dpkg_p.stdout, stdout=PIPE) |
1331 | - md5_p = Popen(md5_cmd, stdin=tar_p.stdout, stdout=PIPE) |
1332 | + tar_p = Popen(tar_cmd, stdin=dpkg_p.stdout, stdout=PIPE, |
1333 | + universal_newlines=True) |
1334 | + md5_p = Popen(md5_cmd, stdin=tar_p.stdout, stdout=PIPE, |
1335 | + universal_newlines=True) |
1336 | pkg_md5sum = md5_p.communicate()[0].split()[0] |
1337 | return pkg_md5sum |
1338 | |
1339 | + |
1340 | # prefix is *only* needed for the build-in tests |
1341 | def conffile_prompt(destFile, prefix=""): |
1342 | logging.debug("check_conffile_prompt('%s')" % destFile) |
1343 | @@ -426,7 +454,7 @@ |
1344 | |
1345 | # get the conffiles for the /var/lib/dpkg/status file |
1346 | status_file = apt_pkg.config.find("Dir::State::status") |
1347 | - tagfile = apt_pkg.TagFile(open(status_file,"r")) |
1348 | + tagfile = apt_pkg.TagFile(open(status_file, "r")) |
1349 | conffiles = "" |
1350 | for section in tagfile: |
1351 | if section.get("Package") == pkgname: |
1352 | @@ -440,21 +468,22 @@ |
1353 | pkg_conffiles = "" |
1354 | deb = apt_inst.DebFile(destFile) |
1355 | try: |
1356 | - pkg_conffiles = deb.control.extractdata("conffiles").strip() |
1357 | + pkg_conffiles = deb.control.extractdata("conffiles").strip().decode( |
1358 | + "utf-8") |
1359 | except LookupError as e: |
1360 | logging.debug("No conffiles in deb '%s' (%s)" % (destFile, e)) |
1361 | |
1362 | # Conffiles: |
1363 | # /etc/bash_completion.d/m-a c7780fab6b14d75ca54e11e992a6c11c |
1364 | dpkg_status_conffiles = {} |
1365 | - for line in string.split(conffiles,"\n"): |
1366 | + for line in conffiles.splitlines(): |
1367 | # ignore empty lines |
1368 | - line = string.strip(line) |
1369 | + line = line.strip() |
1370 | if not line: |
1371 | continue |
1372 | # show what we do |
1373 | logging.debug("conffile line: '%s'", line) |
1374 | - l = string.split(line) |
1375 | + l = line.split() |
1376 | conf_file = l[0] |
1377 | md5 = l[1] |
1378 | if len(l) > 2: |
1379 | @@ -462,13 +491,13 @@ |
1380 | else: |
1381 | obs = None |
1382 | # ignore if conffile is obsolete or does not exist |
1383 | - if obs == "obsolete" or not os.path.exists(prefix+conf_file): |
1384 | + if obs == "obsolete" or not os.path.exists(prefix + conf_file): |
1385 | continue |
1386 | # ignore state "newconffile" until its clearer if there |
1387 | # might be a dpkg prompt (LP: #936870) |
1388 | if md5 == "newconffile": |
1389 | continue |
1390 | - if (not pkg_conffiles or |
1391 | + if (not pkg_conffiles or |
1392 | not conf_file in pkg_conffiles.split("\n")): |
1393 | logging.debug("'%s' not in package conffiles '%s'" % ( |
1394 | conf_file, pkg_conffiles)) |
1395 | @@ -476,7 +505,8 @@ |
1396 | # record for later |
1397 | dpkg_status_conffiles[conf_file] = md5 |
1398 | # test against the installed file |
1399 | - current_md5 = apt_pkg.md5sum(open(prefix+conf_file).read()) |
1400 | + with open(prefix + conf_file, 'rb') as fb: |
1401 | + current_md5 = apt_pkg.md5sum(fb) |
1402 | logging.debug("current md5: %s" % current_md5) |
1403 | # hashes are the same, no conffile prompt |
1404 | if current_md5 == md5: |
1405 | @@ -484,7 +514,7 @@ |
1406 | # calculate md5sum from the deb (may take a bit) |
1407 | pkg_md5sum = get_md5sum_for_file_in_deb(destFile, conf_file) |
1408 | logging.debug("pkg_md5sum: %s" % pkg_md5sum) |
1409 | - # the md5sum in the deb is unchanged, this will not |
1410 | + # the md5sum in the deb is unchanged, this will not |
1411 | # trigger a conffile prompt |
1412 | if pkg_md5sum == md5: |
1413 | continue |
1414 | @@ -493,18 +523,19 @@ |
1415 | # and that will trigger a conffile prompt, we can |
1416 | # stop processing at this point and just return True |
1417 | return True |
1418 | - |
1419 | + |
1420 | # now check if there are conffiles in the pkg that where not there |
1421 | # in the previous version in the dpkg status file |
1422 | if pkg_conffiles: |
1423 | for conf_file in pkg_conffiles.split("\n"): |
1424 | if (not conf_file in dpkg_status_conffiles and |
1425 | - os.path.exists(prefix+conf_file)): |
1426 | + os.path.exists(prefix + conf_file)): |
1427 | logging.debug("found conffile '%s' in new pkg but on dpkg " |
1428 | "status" % conf_file) |
1429 | pkg_md5sum = get_md5sum_for_file_in_deb(destFile, conf_file) |
1430 | - if pkg_md5sum != apt_pkg.md5sum(open(prefix+conf_file).read()): |
1431 | - return True |
1432 | + with open(prefix + conf_file, 'rb') as fp: |
1433 | + if pkg_md5sum != apt_pkg.md5sum(fp): |
1434 | + return True |
1435 | return False |
1436 | |
1437 | |
1438 | @@ -512,9 +543,9 @@ |
1439 | if not "DPkg::Options" in apt_pkg.config: |
1440 | return True |
1441 | options = apt_pkg.config.value_list("DPkg::Options") |
1442 | - for option in map(string.strip, options): |
1443 | - if (option == "--force-confold" or |
1444 | - option == "--force-confnew"): |
1445 | + for option in options: |
1446 | + option = option.strip() |
1447 | + if option in ["--force-confold", "--force-confnew"]: |
1448 | return False |
1449 | return True |
1450 | |
1451 | @@ -535,7 +566,7 @@ |
1452 | def wrap(t, width=70, subsequent_indent=""): |
1453 | out = "" |
1454 | for s in t.split(): |
1455 | - if (len(out)-out.rfind("\n")) + len(s) > width: |
1456 | + if (len(out) - out.rfind("\n")) + len(s) > width: |
1457 | out += "\n" + subsequent_indent |
1458 | out += s + " " |
1459 | return out |
1460 | @@ -554,8 +585,9 @@ |
1461 | |
1462 | |
1463 | def _send_mail_using_mailx(to_address, subject, body): |
1464 | - mail = subprocess.Popen([ |
1465 | - MAIL_BINARY, "-s", subject, to_address], stdin=subprocess.PIPE) |
1466 | + mail = subprocess.Popen( |
1467 | + [MAIL_BINARY, "-s", subject, to_address], |
1468 | + stdin=subprocess.PIPE, universal_newlines=True) |
1469 | mail.stdin.write(body) |
1470 | mail.stdin.close() |
1471 | ret = mail.wait() |
1472 | @@ -565,14 +597,15 @@ |
1473 | def _send_mail_using_sendmail(to_address, subject, body): |
1474 | # format as a proper mail |
1475 | msg = Message() |
1476 | - charset = email.Charset.Charset("utf-8") |
1477 | - charset.body_encoding = email.Charset.QP |
1478 | + charset = email.charset.Charset("utf-8") |
1479 | + charset.body_encoding = email.charset.QP |
1480 | msg.set_charset(charset) |
1481 | msg.set_payload(body) |
1482 | msg['Subject'] = subject |
1483 | msg['To'] = to_address |
1484 | sendmail = subprocess.Popen( |
1485 | - [SENDMAIL_BINARY, "-oi", "-t"], stdin=subprocess.PIPE) |
1486 | + [SENDMAIL_BINARY, "-oi", "-t"], |
1487 | + stdin=subprocess.PIPE, universal_newlines=True) |
1488 | sendmail.stdin.write(msg.as_string()) |
1489 | sendmail.stdin.close() |
1490 | ret = sendmail.wait() |
1491 | @@ -594,16 +627,18 @@ |
1492 | # mails on on errors, just exit here |
1493 | if (res and |
1494 | apt_pkg.config.find_b("Unattended-Upgrade::MailOnlyOnError", False)): |
1495 | - return |
1496 | + return |
1497 | # Check if reboot-required flag is present |
1498 | logging.debug("Sending mail with '%s' to '%s'" % (logfile_dpkg, to_email)) |
1499 | if os.path.isfile(REBOOT_REQUIRED_FILE): |
1500 | - subject = _("[reboot required] unattended-upgrades result for '%s'") % host() |
1501 | + subject = _( |
1502 | + "[reboot required] unattended-upgrades result for '%s'") % host() |
1503 | else: |
1504 | subject = _("unattended-upgrades result for '%s'") % host() |
1505 | body = _("Unattended upgrade returned: %s\n\n") % res |
1506 | if os.path.isfile(REBOOT_REQUIRED_FILE): |
1507 | - body += _("Warning: A reboot is required to complete this upgrade.\n\n") |
1508 | + body += _( |
1509 | + "Warning: A reboot is required to complete this upgrade.\n\n") |
1510 | body += _("Packages that are upgraded:\n") |
1511 | body += " " + wrap(pkgs, 70, " ") |
1512 | body += "\n" |
1513 | @@ -613,15 +648,16 @@ |
1514 | body += "\n" |
1515 | body += "\n" |
1516 | if os.path.exists(logfile_dpkg): |
1517 | - body += _("Package installation log:")+"\n" |
1518 | - body += open(logfile_dpkg).read() |
1519 | + body += _("Package installation log:") + "\n" |
1520 | + with open(logfile_dpkg) as fp: |
1521 | + body += fp.read() |
1522 | body += "\n\n" |
1523 | body += _("Unattended-upgrades log:\n") |
1524 | body += mem_log.getvalue() |
1525 | |
1526 | - # ensure that the message a utf8 encoded string |
1527 | - if type(body) is unicode: |
1528 | - body= body.encode("utf-8", "replace") |
1529 | + # python2 needs this as utf8 encoded string (not unicode) |
1530 | + if sys.version < '3': |
1531 | + body = body.encode("utf-8") |
1532 | |
1533 | if os.path.exists(SENDMAIL_BINARY): |
1534 | ret = _send_mail_using_sendmail(to_email, subject, body) |
1535 | @@ -636,13 +672,13 @@ |
1536 | |
1537 | def do_install(cache, pkgs_to_upgrade, options, logfile_dpkg): |
1538 | # set debconf to NON_INTERACTIVE, redirect output |
1539 | - os.putenv("DEBIAN_FRONTEND","noninteractive"); |
1540 | + os.putenv("DEBIAN_FRONTEND", "noninteractive") |
1541 | setup_apt_listchanges() |
1542 | - |
1543 | + |
1544 | # redirect to log |
1545 | REDIRECT_INPUT = os.devnull |
1546 | fd = os.open(REDIRECT_INPUT, os.O_RDWR) |
1547 | - os.dup2(fd,0) |
1548 | + os.dup2(fd, 0) |
1549 | |
1550 | logging.info(_("Writing dpkg log to '%s'") % logfile_dpkg) |
1551 | |
1552 | @@ -651,18 +687,21 @@ |
1553 | old_stdout = 1 |
1554 | old_stderr = 2 |
1555 | else: |
1556 | - fd = os.open(logfile_dpkg, os.O_RDWR|os.O_CREAT, 0644) |
1557 | + fd = os.open(logfile_dpkg, os.O_RDWR | os.O_CREAT, 0o644) |
1558 | old_stdout = os.dup(1) |
1559 | old_stderr = os.dup(2) |
1560 | - os.dup2(fd,1) |
1561 | - os.dup2(fd,2) |
1562 | + os.dup2(fd, 1) |
1563 | + os.dup2(fd, 2) |
1564 | |
1565 | try: |
1566 | - if (options.minimal_upgrade_steps or |
1567 | + if (options.minimal_upgrade_steps or |
1568 | # COMPAT with the mispelling |
1569 | - apt_pkg.config.find_b("Unattended-Upgrades::MinimalSteps", False) or |
1570 | - apt_pkg.config.find_b("Unattended-Upgrade::MinimalSteps", False)): |
1571 | - open("/var/run/unattended-upgrades.pid", "w").write("%s" % os.getpid()) |
1572 | + apt_pkg.config.find_b( |
1573 | + "Unattended-Upgrades::MinimalSteps", False) or |
1574 | + apt_pkg.config.find_b( |
1575 | + "Unattended-Upgrade::MinimalSteps", False)): |
1576 | + with open("/var/run/unattended-upgrades.pid", "w") as fp: |
1577 | + fp.write("%s" % os.getpid()) |
1578 | # try upgrade all "pkgs" in minimal steps |
1579 | pkg_install_success = upgrade_in_minimal_steps( |
1580 | cache, [pkg.name for pkg in pkgs_to_upgrade], logfile_dpkg) |
1581 | @@ -685,15 +724,16 @@ |
1582 | apt_pkg.config.clear("Unattended-Upgrade") |
1583 | # read rootdir (taken from apt.Cache, but we need to run it |
1584 | # here before the cache gets initialized |
1585 | - if os.path.exists(rootdir+"/etc/apt/apt.conf"): |
1586 | + if os.path.exists(rootdir + "/etc/apt/apt.conf"): |
1587 | apt_pkg.read_config_file(apt_pkg.config, |
1588 | rootdir + "/etc/apt/apt.conf") |
1589 | - if os.path.isdir(rootdir+"/etc/apt/apt.conf.d"): |
1590 | + if os.path.isdir(rootdir + "/etc/apt/apt.conf.d"): |
1591 | apt_pkg.read_config_dir(apt_pkg.config, |
1592 | rootdir + "/etc/apt/apt.conf.d") |
1593 | |
1594 | + |
1595 | def _get_logdir(): |
1596 | - logdir= apt_pkg.config.find_dir( |
1597 | + logdir = apt_pkg.config.find_dir( |
1598 | "Unattended-Upgrade::LogDir", |
1599 | # COMPAT only |
1600 | apt_pkg.config.find_dir("APT::UnattendedUpgrades::LogDir", |
1601 | @@ -722,7 +762,6 @@ |
1602 | logging.basicConfig(level=logging.INFO, |
1603 | format='%(asctime)s %(levelname)s %(message)s', |
1604 | filename=logfile) |
1605 | - |
1606 | # additional logging |
1607 | logger = logging.getLogger() |
1608 | mem_log = StringIO() |
1609 | @@ -734,7 +773,7 @@ |
1610 | mem_log_handler = logging.StreamHandler(mem_log) |
1611 | logger.addHandler(mem_log_handler) |
1612 | return mem_log |
1613 | - |
1614 | + |
1615 | |
1616 | def main(options, rootdir=""): |
1617 | |
1618 | @@ -749,24 +788,28 @@ |
1619 | allowed_origins = get_allowed_origins() |
1620 | |
1621 | # pkgs that are (for some reason) not save to install |
1622 | - blacklisted_pkgs = apt_pkg.config.value_list("Unattended-Upgrade::Package-Blacklist") |
1623 | - logging.info(_("Initial blacklisted packages: %s"), " ".join(blacklisted_pkgs)) |
1624 | + blacklisted_pkgs = apt_pkg.config.value_list( |
1625 | + "Unattended-Upgrade::Package-Blacklist") |
1626 | + logging.info(_("Initial blacklisted packages: %s"), |
1627 | + " ".join(blacklisted_pkgs)) |
1628 | logging.info(_("Starting unattended upgrades script")) |
1629 | |
1630 | # display available origin |
1631 | - logging.info(_("Allowed origins are: %s") % map(str,allowed_origins)) |
1632 | + logging.info(_("Allowed origins are: %s") % allowed_origins) |
1633 | |
1634 | # check if the journal is dirty and if so, take emergceny action |
1635 | # the alternative is to leave the system potentially unsecure until |
1636 | # the user comes in and fixes |
1637 | if (is_dpkg_journal_dirty() and |
1638 | - apt_pkg.config.find_b("Unattended-Upgrade::AutoFixInterruptedDpkg", True)): |
1639 | + apt_pkg.config.find_b( |
1640 | + "Unattended-Upgrade::AutoFixInterruptedDpkg", True)): |
1641 | # ensure the dpkg database is not already locked (LP: #754330) |
1642 | admindir = os.path.dirname(apt_pkg.config.find("Dir::State::Status")) |
1643 | lockfd = apt_pkg.get_lock(os.path.join(admindir, "lock"), False) |
1644 | if lockfd > 0: |
1645 | - logging.warning(_("Unclean dpkg state detected, trying to correct")) |
1646 | - print _("Unclean dpkg state detected, trying to correct") |
1647 | + logging.warning( |
1648 | + _("Unclean dpkg state detected, trying to correct")) |
1649 | + print(_("Unclean dpkg state detected, trying to correct")) |
1650 | env = copy.copy(os.environ) |
1651 | env["DEBIAN_FRONTEND"] = "noninteractive" |
1652 | try: |
1653 | @@ -777,22 +820,23 @@ |
1654 | output = e.output |
1655 | logging.warning(_("dpkg --configure -a output:\n%s" % output)) |
1656 | else: |
1657 | - logging.debug("Unclean dpkg state, but locked, another package manager working?") |
1658 | - |
1659 | + logging.debug("Unclean dpkg state, but locked, another package " |
1660 | + "manager working?") |
1661 | + |
1662 | # check and get lock |
1663 | try: |
1664 | apt_pkg.pkgsystem_lock() |
1665 | - except SystemError, e: |
1666 | + except SystemError as e: |
1667 | logging.error(_("Lock could not be acquired (another package " |
1668 | "manager running?)")) |
1669 | - print _("Cache lock can not be acquired, exiting") |
1670 | + print(_("Cache lock can not be acquired, exiting")) |
1671 | sys.exit(1) |
1672 | |
1673 | # get a cache |
1674 | - cache = UnattendedUpgradesCache(rootdir=rootdir, |
1675 | + cache = UnattendedUpgradesCache(rootdir=rootdir, |
1676 | allowed_origins=allowed_origins) |
1677 | if cache._depcache.broken_count > 0: |
1678 | - print _("Cache has broken packages, exiting") |
1679 | + print(_("Cache has broken packages, exiting")) |
1680 | logging.error(_("Cache has broken packages, exiting")) |
1681 | sys.exit(1) |
1682 | # speed things up with latest apt |
1683 | @@ -802,13 +846,14 @@ |
1684 | # find out about the packages that are upgradable (in a allowed_origin) |
1685 | pkgs_to_upgrade = [] |
1686 | pkgs_kept_back = [] |
1687 | - pkgs_auto_removable = set([pkg.name for pkg in cache |
1688 | + pkgs_auto_removable = set([pkg.name for pkg in cache |
1689 | if pkg.is_auto_removable]) |
1690 | |
1691 | # now do the actual upgrade |
1692 | for pkg in cache: |
1693 | if options.debug and pkg.is_upgradable: |
1694 | - logging.debug("Checking: %s (%s)" % (pkg.name, map(str, pkg.candidate.origins))) |
1695 | + logging.debug("Checking: %s (%s)" % ( |
1696 | + pkg.name, map(str, getattr(pkg.candidate, "origins", [])))) |
1697 | if (pkg.is_upgradable and |
1698 | not is_pkgname_in_blacklist(pkg.name, blacklisted_pkgs) and |
1699 | is_allowed_origin(pkg.candidate, allowed_origins)): |
1700 | @@ -818,7 +863,7 @@ |
1701 | blacklisted_pkgs): |
1702 | # add to packages to upgrade |
1703 | pkgs_to_upgrade.append(pkg) |
1704 | - # re-eval pkgs_kept_back as the resolver may fail to |
1705 | + # re-eval pkgs_kept_back as the resolver may fail to |
1706 | # directly upgrade a pkg, but that may work during |
1707 | # a subsequent operation, see debian bug #639840 |
1708 | for pkgname in pkgs_kept_back: |
1709 | @@ -830,17 +875,18 @@ |
1710 | logging.debug("sanity check failed") |
1711 | rewind_cache(cache, pkgs_to_upgrade) |
1712 | pkgs_kept_back.append(pkg.name) |
1713 | - except SystemError, e: |
1714 | + except SystemError as e: |
1715 | # can't upgrade |
1716 | - logging.warning(_("package '%s' upgradable but fails to be marked for upgrade (%s)") % (pkg.name, e)) |
1717 | + logging.warning( |
1718 | + _("package '%s' upgradable but fails to " |
1719 | + "be marked for upgrade (%s)") % (pkg.name, e)) |
1720 | rewind_cache(cache, pkgs_to_upgrade) |
1721 | pkgs_kept_back.append(pkg.name) |
1722 | - |
1723 | |
1724 | pkgs_to_upgrade.sort(key=lambda p: p.name) |
1725 | pkgs = "\n".join([pkg.name for pkg in pkgs_to_upgrade]) |
1726 | logging.debug("pkgs that look like they should be upgraded: %s" % pkgs) |
1727 | - |
1728 | + |
1729 | # download what looks good |
1730 | if options.debug: |
1731 | fetcher = apt_pkg.Acquire(apt.progress.text.AcquireProgress()) |
1732 | @@ -851,8 +897,8 @@ |
1733 | recs = cache._records |
1734 | pm = apt_pkg.PackageManager(cache._depcache) |
1735 | try: |
1736 | - pm.get_archives(fetcher,list,recs) |
1737 | - except SystemError, e: |
1738 | + pm.get_archives(fetcher, list, recs) |
1739 | + except SystemError as e: |
1740 | logging.error(_("GetArchives() failed: '%s'") % e) |
1741 | res = fetcher.run() |
1742 | logging.debug("fetch.run() result: %s" % res) |
1743 | @@ -863,15 +909,19 @@ |
1744 | for item in fetcher.items: |
1745 | logging.debug("%s" % item) |
1746 | if item.status == item.STAT_ERROR: |
1747 | - print _("An error ocured: '%s'") % item.error_text |
1748 | + print(_("An error ocured: '%s'") % item.error_text) |
1749 | logging.error(_("An error ocured: '%s'") % item.error_text) |
1750 | if not item.complete: |
1751 | - print _("The URI '%s' failed to download, aborting") % item.desc_uri |
1752 | - logging.error(_("The URI '%s' failed to download, aborting") % item.desc_uri) |
1753 | + print(_("The URI '%s' failed to download, aborting") % |
1754 | + item.desc_uri) |
1755 | + logging.error(_("The URI '%s' failed to download, aborting") % |
1756 | + item.desc_uri) |
1757 | sys.exit(1) |
1758 | if not os.path.exists(item.destfile): |
1759 | - print _("Download finished, but file '%s' not there?!?" % item.destfile) |
1760 | - logging.error("Download finished, but file '%s' not there?!?" % item.destfile) |
1761 | + print(_("Download finished, but file '%s' not there?!?" % |
1762 | + item.destfile)) |
1763 | + logging.error("Download finished, but file '%s' not " |
1764 | + "there?!?" % item.destfile) |
1765 | sys.exit(1) |
1766 | if not item.is_trusted: |
1767 | blacklisted_pkgs.append(pkgname_from_deb(item.destfile)) |
1768 | @@ -879,18 +929,21 @@ |
1769 | # skip package (means to re-run the whole marking again |
1770 | # and making sure that the package will not be pulled in by |
1771 | # some other package again!) |
1772 | - # |
1773 | + # |
1774 | # print to stdout to ensure that this message is part of |
1775 | # the cron mail (only if no summary mail is requested) |
1776 | email = apt_pkg.config.find("Unattended-Upgrade::Mail", "") |
1777 | if not email: |
1778 | - print _("Package '%s' has conffile prompt and needs to be upgraded manually") % pkgname_from_deb(item.destfile) |
1779 | + print(_("Package '%s' has conffile prompt and needs " |
1780 | + "to be upgraded manually") % pkgname_from_deb( |
1781 | + item.destfile)) |
1782 | # log to the logfile |
1783 | - logging.warning(_("Package '%s' has conffile prompt and needs to be upgraded manually") % pkgname_from_deb(item.destfile)) |
1784 | + logging.warning(_("Package '%s' has conffile prompt and " |
1785 | + "needs to be upgraded manually") % |
1786 | + pkgname_from_deb(item.destfile)) |
1787 | blacklisted_pkgs.append(pkgname_from_deb(item.destfile)) |
1788 | pkgs_kept_back.append(pkgname_from_deb(item.destfile)) |
1789 | |
1790 | - |
1791 | # redo the selection about the packages to upgrade based on the new |
1792 | # blacklist |
1793 | logging.debug("blacklist: %s" % blacklisted_pkgs) |
1794 | @@ -904,7 +957,7 @@ |
1795 | pkg.mark_upgrade() |
1796 | if check_changes_for_sanity(cache, allowed_origins, |
1797 | blacklisted_pkgs): |
1798 | - pkgs_to_upgrade.append(pkg) |
1799 | + pkgs_to_upgrade.append(pkg) |
1800 | else: |
1801 | if not (pkg.name in pkgs_kept_back): |
1802 | pkgs_kept_back.append(pkg.name) |
1803 | @@ -916,23 +969,26 @@ |
1804 | logging.debug("dpkg is configured not to cause conffile prompts") |
1805 | |
1806 | # do auto-remove |
1807 | - if apt_pkg.config.find_b("Unattended-Upgrade::Remove-Unused-Dependencies", False): |
1808 | - now_auto_removable = set([pkg.name for pkg in cache |
1809 | + if apt_pkg.config.find_b( |
1810 | + "Unattended-Upgrade::Remove-Unused-Dependencies", False): |
1811 | + now_auto_removable = set([pkg.name for pkg in cache |
1812 | if pkg.is_auto_removable]) |
1813 | - for pkgname in now_auto_removable-pkgs_auto_removable: |
1814 | + for pkgname in now_auto_removable - pkgs_auto_removable: |
1815 | logging.debug("marking %s for remove" % pkgname) |
1816 | cache[pkgname].mark_delete() |
1817 | logging.info(_("Packages that are auto removed: '%s'") % |
1818 | - " ".join(now_auto_removable-pkgs_auto_removable)) |
1819 | + " ".join(now_auto_removable - pkgs_auto_removable)) |
1820 | |
1821 | - logging.debug("InstCount=%i DelCount=%i BrokenCout=%i" % (cache._depcache.inst_count, cache._depcache.del_count, cache._depcache.broken_count)) |
1822 | + logging.debug("InstCount=%i DelCount=%i BrokenCount=%i" % ( |
1823 | + cache._depcache.inst_count, cache._depcache.del_count, |
1824 | + cache._depcache.broken_count)) |
1825 | |
1826 | # exit if there is nothing to do and nothing to report |
1827 | if (len(pkgs_to_upgrade) == 0) and (len(pkgs_kept_back) == 0): |
1828 | logging.info(_("No packages found that can be upgraded unattended")) |
1829 | return |
1830 | |
1831 | - # check if its configured for install on shutdown, if so, the |
1832 | + # check if its configured for install on shutdown, if so, the |
1833 | # environment UNATTENDED_UPGRADES_FORCE_INSTALL_ON_SHUTDOWN will |
1834 | # be set by the unatteded-upgrades-shutdown script |
1835 | if (not "UNATTENDED_UPGRADES_FORCE_INSTALL_ON_SHUTDOWN" in os.environ and |
1836 | @@ -944,7 +1000,7 @@ |
1837 | # check if we are in dry-run mode |
1838 | if options.dry_run: |
1839 | logging.info("Option --dry-run given, *not* performing real actions") |
1840 | - apt_pkg.config.set("Debug::pkgDPkgPM","1") |
1841 | + apt_pkg.config.set("Debug::pkgDPkgPM", "1") |
1842 | |
1843 | # do the install based on the new list of pkgs |
1844 | pkgs = " ".join([pkg.name for pkg in pkgs_to_upgrade]) |
1845 | @@ -972,17 +1028,18 @@ |
1846 | pkgs, pkg_install_success, pkgs_kept_back, mem_log, logfile_dpkg) |
1847 | |
1848 | # auto-reboot (if required and the config for this is set |
1849 | - if (apt_pkg.config.find_b("Unattended-Upgrade::Automatic-Reboot", False) and |
1850 | + if (apt_pkg.config.find_b( |
1851 | + "Unattended-Upgrade::Automatic-Reboot", False) and |
1852 | os.path.exists(REBOOT_REQUIRED_FILE)): |
1853 | if shutdown_lock > 0: |
1854 | os.close(shutdown_lock) |
1855 | logging.warning("Found %s, rebooting" % REBOOT_REQUIRED_FILE) |
1856 | subprocess.call(["/sbin/reboot"]) |
1857 | - |
1858 | + |
1859 | |
1860 | if __name__ == "__main__": |
1861 | - localesApp="unattended-upgrades" |
1862 | - localesDir="/usr/share/locale" |
1863 | + localesApp = "unattended-upgrades" |
1864 | + localesDir = "/usr/share/locale" |
1865 | gettext.bindtextdomain(localesApp, localesDir) |
1866 | gettext.textdomain(localesApp) |
1867 | |
1868 | @@ -996,19 +1053,20 @@ |
1869 | help=_("Simulation, download but do not install")) |
1870 | parser.add_option("", "--minimal_upgrade_steps", |
1871 | action="store_true", default=False, |
1872 | - help=_("Upgrade in minimal steps (and allow interrupting with SIGINT")) |
1873 | + help=_("Upgrade in minimal steps (and allow " |
1874 | + "interrupting with SIGINT")) |
1875 | (options, args) = parser.parse_args() |
1876 | |
1877 | if os.getuid() != 0: |
1878 | - print _("You need to be root to run this application") |
1879 | + print(_("You need to be root to run this application")) |
1880 | sys.exit(1) |
1881 | |
1882 | # nice & ionce |
1883 | os.nice(19) |
1884 | - IONICE="/usr/bin/ionice" |
1885 | + IONICE = "/usr/bin/ionice" |
1886 | if os.path.exists(IONICE): |
1887 | with open(os.devnull, "w") as fstderr: |
1888 | - subprocess.call([IONICE, "-c3", "-p",str(os.getpid())], |
1889 | + subprocess.call([IONICE, "-c3", "-p", str(os.getpid())], |
1890 | stderr=fstderr) |
1891 | |
1892 | # ensure that we are not killed when the terminal goes away e.g. on |
1893 | |
1894 | === modified file 'unattended-upgrade-shutdown' |
1895 | --- unattended-upgrade-shutdown 2012-04-26 11:40:46 +0000 |
1896 | +++ unattended-upgrade-shutdown 2012-10-05 14:59:30 +0000 |
1897 | @@ -1,4 +1,4 @@ |
1898 | -#!/usr/bin/python |
1899 | +#!/usr/bin/python3 |
1900 | # Copyright (c) 2009 Canonical Ltd |
1901 | # |
1902 | # AUTHOR: |
1903 | @@ -141,8 +141,8 @@ |
1904 | os.kill(pid, signal.SIGUSR1) |
1905 | # show log |
1906 | log_progress() |
1907 | - time.sleep(5) |
1908 | - if (time.time() - start_time) > options.delay*60: |
1909 | + time.sleep(5) |
1910 | + if (time.time() - start_time) > options.delay*60: |
1911 | logging.warning(_("Giving up on lockfile after %s delay") % options.delay) |
1912 | sys.exit(1) |
1913 |