Merge lp:~barry/ubuntu-system-image/citrain-250u1 into lp:~ubuntu-managed-branches/ubuntu-system-image/system-image

Proposed by Barry Warsaw
Status: Merged
Approved by: Ken VanDine
Approved revision: 241
Merged at revision: 239
Proposed branch: lp:~barry/ubuntu-system-image/citrain-250u1
Merge into: lp:~ubuntu-managed-branches/ubuntu-system-image/system-image
Diff against target: 497 lines (+84/-184)
14 files modified
NEWS.rst (+7/-0)
PKG-INFO (+1/-1)
dbus-manpage.rst (+15/-6)
debian/changelog (+9/-0)
setup.cfg (+1/-1)
system_image.egg-info/PKG-INFO (+1/-1)
system_image.egg-info/SOURCES.txt (+0/-1)
systemimage/bindings.py (+0/-98)
systemimage/dbus.py (+10/-2)
systemimage/main.py (+0/-27)
systemimage/testing/dbus.py (+3/-1)
systemimage/testing/nose.py (+0/-1)
systemimage/tests/test_dbus.py (+36/-44)
systemimage/version.txt (+1/-1)
To merge this branch: bzr merge lp:~barry/ubuntu-system-image/citrain-250u1
Reviewer Review Type Date Requested Status
Ubuntu CI managed package branches Pending
Review via email: mp+236403@code.launchpad.net

Commit message

Fixes for LP: #1369717 and LP: #1370586

Description of the change

Fixes for LP: #1369717 and LP: #1370586

To post a comment you must log in.
241. By Barry Warsaw

Unrelease

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS.rst'
2--- NEWS.rst 2014-09-17 13:41:31 +0000
3+++ NEWS.rst 2014-09-29 18:55:39 +0000
4@@ -2,6 +2,13 @@
5 NEWS for system-image updater
6 =============================
7
8+2.5 (2014-XX-XX)
9+================
10+ * Remove the previously deprecated `system-image-cli --dbus` command line
11+ switch. (LP: #1369717)
12+ * Add a `target_build_number` key to the mapping returned by the
13+ `.Information()` D-Bus method. (LP: #1370586)
14+
15 2.4 (2014-09-16)
16 ================
17 * The channel.ini file can override the device name by setting
18
19=== modified file 'PKG-INFO'
20--- PKG-INFO 2014-09-17 02:59:15 +0000
21+++ PKG-INFO 2014-09-29 18:55:39 +0000
22@@ -1,6 +1,6 @@
23 Metadata-Version: 1.0
24 Name: system-image
25-Version: 2.4
26+Version: 2.5
27 Summary: Ubuntu System Image Based Upgrades
28 Home-page: UNKNOWN
29 Author: Barry Warsaw
30
31=== modified file 'dbus-manpage.rst'
32--- dbus-manpage.rst 2014-07-23 22:51:19 +0000
33+++ dbus-manpage.rst 2014-09-29 18:55:39 +0000
34@@ -128,19 +128,28 @@
35 This is a **synchronous** call which returns an extensible mapping of
36 UTF-8 keys to UTF-8 values. The following keys are currently defined:
37
38- * *current_build_number* - the current build number as an integer.
39- * *device_name* - the name of the device type.
40- * *channel_name* - the channel the device is currently on.
41- * *last_update_date* - the last time this device was updated as a
42+ * *current_build_number* - The current build number as an integer.
43+ * *target_build_number* - If an update is known to be available, this will
44+ be the build number that an update will leave the device at. If no
45+ `CheckForUpdate()` has been previously performed, then the
46+ *target_build_number* will be "-1". If a previous check has been
47+ performed, but no update is available (i.e., the device is already at
48+ the latest version), then *target_build_number* will be the same as
49+ *current_build_number*.
50+ * *device_name* - The name of the device type.
51+ * *channel_name* - The channel the device is currently on.
52+ * *last_update_date* - The last time this device was updated as a
53 datetime, e.g. "YYYY-MM-DDTHH:MM:SS"
54- * *version_detail* - a string containing a comma-separated list of
55+ * *version_detail* - A string containing a comma-separated list of
56 key-value pairs providing additional component version details,
57 e.g. "ubuntu=123,mako=456,custom=789".
58- * *last_check_date* - the last time a ``CheckForUpdate()`` call was
59+ * *last_check_date* - The last time a ``CheckForUpdate()`` call was
60 performed.
61
62 *New in system-image 2.3*
63
64+ *New in system-image 2.5: target_build_number*
65+
66 ``FactoryReset()``
67 This is a **synchronous** call which wipes the data partition and issue a
68 reboot to recovery. A ``Rebooting`` signal may be sent, depending on
69
70=== modified file 'debian/changelog'
71--- debian/changelog 2014-09-17 17:56:46 +0000
72+++ debian/changelog 2014-09-29 18:55:39 +0000
73@@ -1,3 +1,12 @@
74+system-image (2.5-0ubuntu1) UNRELEASED; urgency=medium
75+
76+ * New upstream release.
77+ - LP: #1369717 - Remove `system-image-cli --dbus` command line switch.
78+ - LP: #1370586 - Add a `target_build_number` key to the mapping
79+ returned by the `.Information()` D-Bus method.
80+
81+ -- Barry Warsaw <barry@ubuntu.com> Fri, 26 Sep 2014 10:36:13 -0400
82+
83 system-image (2.4-0ubuntu1) utopic; urgency=medium
84
85 [ Barry Warsaw ]
86
87=== modified file 'setup.cfg'
88--- setup.cfg 2014-09-17 13:41:31 +0000
89+++ setup.cfg 2014-09-29 18:55:39 +0000
90@@ -4,7 +4,7 @@
91 logging-filter = systemimage
92
93 [egg_info]
94+tag_svn_revision = 0
95 tag_build =
96 tag_date = 0
97-tag_svn_revision = 0
98
99
100=== modified file 'system_image.egg-info/PKG-INFO'
101--- system_image.egg-info/PKG-INFO 2014-09-17 02:59:15 +0000
102+++ system_image.egg-info/PKG-INFO 2014-09-29 18:55:39 +0000
103@@ -1,6 +1,6 @@
104 Metadata-Version: 1.0
105 Name: system-image
106-Version: 2.4
107+Version: 2.5
108 Summary: Ubuntu System Image Based Upgrades
109 Home-page: UNKNOWN
110 Author: Barry Warsaw
111
112=== modified file 'system_image.egg-info/SOURCES.txt'
113--- system_image.egg-info/SOURCES.txt 2014-09-17 02:59:15 +0000
114+++ system_image.egg-info/SOURCES.txt 2014-09-29 18:55:39 +0000
115@@ -18,7 +18,6 @@
116 systemimage/__init__.py
117 systemimage/api.py
118 systemimage/bag.py
119-systemimage/bindings.py
120 systemimage/candidates.py
121 systemimage/channel.py
122 systemimage/config.py
123
124=== removed file 'systemimage/bindings.py'
125--- systemimage/bindings.py 2014-09-17 13:41:31 +0000
126+++ systemimage/bindings.py 1970-01-01 00:00:00 +0000
127@@ -1,98 +0,0 @@
128-# Copyright (C) 2013-2014 Canonical Ltd.
129-# Author: Barry Warsaw <barry@ubuntu.com>
130-
131-# This program is free software: you can redistribute it and/or modify
132-# it under the terms of the GNU General Public License as published by
133-# the Free Software Foundation; version 3 of the License.
134-#
135-# This program is distributed in the hope that it will be useful,
136-# but WITHOUT ANY WARRANTY; without even the implied warranty of
137-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
138-# GNU General Public License for more details.
139-#
140-# You should have received a copy of the GNU General Public License
141-# along with this program. If not, see <http://www.gnu.org/licenses/>.
142-
143-"""Helpers for when the command line script is used as a DBus client."""
144-
145-
146-__all__ = [
147- 'DBusClient',
148- 'UASRecord',
149- ]
150-
151-
152-import dbus
153-import logging
154-
155-from collections import namedtuple
156-from systemimage.reactor import Reactor
157-
158-log = logging.getLogger('systemimage')
159-
160-
161-# Use a namedtuple for more convenient argument unpacking.
162-UASRecord = namedtuple('UASRecord',
163- 'is_available downloading available_version update_size '
164- 'last_update_date error_reason')
165-
166-
167-class DBusClient(Reactor):
168- """Python bindings to be used as a DBus client."""
169-
170- def __init__(self):
171- super().__init__(dbus.SystemBus())
172- service = self._bus.get_object('com.canonical.SystemImage', '/Service')
173- self.iface = dbus.Interface(service, 'com.canonical.SystemImage')
174- self.react_to('UpdateAvailableStatus')
175- self.react_to('UpdateDownloaded')
176- self.react_to('UpdateFailed')
177- self.failed = False
178- self.is_available = False
179- self.downloaded = False
180-
181- def _do_UpdateAvailableStatus(self, signal, path, *args):
182- payload = UASRecord(*args)
183- if payload.error_reason != '': # pragma: no cover
184- # Cancel the download, set the failed flag and log the reason.
185- log.error('CheckForUpdate returned an error: {}',
186- payload.error_reason)
187- self.failed = True
188- self.quit()
189- return
190- if not payload.is_available:
191- log.info('No update available')
192- self.quit()
193- return
194- if not payload.downloading: # pragma: no cover
195- # We should be in auto download mode, so why aren't we downloading
196- # the update? Do it manually.
197- log.info('Update available, downloading manually')
198- self.iface.DownloadUpdate()
199- self.is_available = True
200-
201- def _do_UpdateDownloaded(self, signal, path):
202- self.downloaded = True
203- self.quit()
204-
205- def _do_UpdateFailed(self, signal, path,
206- consecutive_failure_count, last_reason):
207- log.error('UpdateFailed: {}', last_reason)
208- self.failed = True
209- self.quit()
210-
211- def check_for_update(self):
212- # Switch to auto-download mode for this run.
213- old_value = self.iface.GetSetting('auto_download')
214- self.iface.SetSetting('auto_download', '2')
215- self.schedule(self.iface.CheckForUpdate)
216- self.run()
217- self.iface.SetSetting('auto_download', old_value)
218-
219- def _do_Rebooting(self, signal, path, status):
220- self.quit()
221-
222- def reboot(self):
223- self.react_to('Rebooting')
224- self.schedule(self.iface.ApplyUpdate)
225- self.run()
226
227=== modified file 'systemimage/dbus.py'
228--- systemimage/dbus.py 2014-09-17 13:41:31 +0000
229+++ systemimage/dbus.py 2014-09-29 18:55:39 +0000
230@@ -334,14 +334,22 @@
231 def Information(self):
232 self._loop.keepalive()
233 settings = Settings()
234- return dict(
235- current_build_number=str(config.build_number),
236+ current_build_number = str(config.build_number)
237+ response = dict(
238+ current_build_number=current_build_number,
239 device_name=config.device,
240 channel_name=config.channel,
241 last_update_date=last_update_date(),
242 version_detail=getattr(config.service, 'version_detail', ''),
243 last_check_date=settings.get('last_check_date'),
244 )
245+ if self._update is None:
246+ response['target_build_number'] = '-1'
247+ elif not self._update.is_available:
248+ response['target_build_number'] = current_build_number
249+ else:
250+ response['target_build_number'] = str(self._update.version)
251+ return response
252
253 @log_and_exit
254 @method('com.canonical.SystemImage', in_signature='ss')
255
256=== modified file 'systemimage/main.py'
257--- systemimage/main.py 2014-09-17 13:41:31 +0000
258+++ systemimage/main.py 2014-09-29 18:55:39 +0000
259@@ -25,11 +25,9 @@
260 import sys
261 import logging
262 import argparse
263-import warnings
264
265 from dbus.mainloop.glib import DBusGMainLoop
266 from pkg_resources import resource_string as resource_bytes
267-from systemimage.bindings import DBusClient
268 from systemimage.candidates import delta_filter, full_filter
269 from systemimage.config import config
270 from systemimage.helpers import last_update_date, makedirs, version_detail
271@@ -72,9 +70,6 @@
272 parser.add_argument('-d', '--device',
273 default=None, action='store',
274 help='Override the device name just this once')
275- parser.add_argument('--dbus',
276- default=False, action='store_true',
277- help='Run in D-Bus client mode.')
278 parser.add_argument('-f', '--filter',
279 default=None, action='store',
280 help="""Filter the candidate paths to contain only
281@@ -266,28 +261,6 @@
282 print(' {} (alias for: {})'.format(key, alias))
283 return 0
284
285- # 2014-09-15 BAW: --dbus is deprecated (LP: #1369714) and will be removed
286- # in system-image 2.5 (LP: #1369717).
287- if args.dbus: # pragma: no cover
288- print('WARNING: --dbus is deprecated and will be removed soon',
289- file=sys.stderr)
290- warnings.warn('--dbus is deprecated and will be removed soon',
291- DeprecationWarning)
292- client = DBusClient()
293- client.check_for_update()
294- if not client.is_available:
295- log.info('No update is available')
296- return 0
297- if not client.downloaded:
298- log.info('No update was downloaded')
299- return 1
300- if client.failed:
301- log.info('Update failed')
302- return 2
303- client.reboot()
304- # We probably won't get here..
305- return 0
306-
307 # When verbosity is at 1, logging every progress signal from
308 # ubuntu-download-manager would be way too noisy. OTOH, not printing
309 # anything leads some folks to think the process is just hung, since it
310
311=== modified file 'systemimage/testing/dbus.py'
312--- systemimage/testing/dbus.py 2014-09-17 13:41:31 +0000
313+++ systemimage/testing/dbus.py 2014-09-29 18:55:39 +0000
314@@ -334,6 +334,7 @@
315 self._updated = '2099-08-01 04:45:45'
316 self._version = 'ubuntu=123,mako=456,custom=789'
317 self._checked = '2099-08-01 04:45:00'
318+ self._target = 53
319
320 @log_and_exit
321 @method('com.canonical.SystemImage')
322@@ -354,7 +355,8 @@
323 channel_name=self._channel,
324 last_update_date=self._updated,
325 version_detail=self._version,
326- last_check_date=self._checked)
327+ last_check_date=self._checked,
328+ target_build_number=str(self._target))
329
330
331 class _Crasher(Service):
332
333=== modified file 'systemimage/testing/nose.py'
334--- systemimage/testing/nose.py 2014-09-17 13:41:31 +0000
335+++ systemimage/testing/nose.py 2014-09-29 18:55:39 +0000
336@@ -22,7 +22,6 @@
337
338 import re
339 import atexit
340-import logging
341
342 from dbus.mainloop.glib import DBusGMainLoop
343 from nose2.events import Plugin
344
345=== modified file 'systemimage/tests/test_dbus.py'
346--- systemimage/tests/test_dbus.py 2014-09-17 13:41:31 +0000
347+++ systemimage/tests/test_dbus.py 2014-09-29 18:55:39 +0000
348@@ -20,7 +20,6 @@
349 'TestDBusCheckForUpdate',
350 'TestDBusCheckForUpdateToUnwritablePartition',
351 'TestDBusCheckForUpdateWithBrokenIndex',
352- 'TestDBusClient',
353 'TestDBusDownload',
354 'TestDBusFactoryReset',
355 'TestDBusGetSet',
356@@ -51,11 +50,11 @@
357 import unittest
358
359 from contextlib import ExitStack, suppress
360+from collections import namedtuple
361 from datetime import datetime
362 from dbus.exceptions import DBusException
363 from functools import partial
364 from pathlib import Path
365-from systemimage.bindings import DBusClient, UASRecord
366 from systemimage.config import Configuration
367 from systemimage.helpers import MiB, atomic, safe_remove
368 from systemimage.reactor import Reactor
369@@ -66,6 +65,12 @@
370 from systemimage.testing.nose import SystemImagePlugin
371
372
373+# Use a namedtuple for more convenient argument unpacking.
374+UASRecord = namedtuple('UASRecord',
375+ 'is_available downloading available_version update_size '
376+ 'last_update_date error_reason')
377+
378+
379 class SignalCapturingReactor(Reactor):
380 def __init__(self, *signals):
381 super().__init__(dbus.SystemBus())
382@@ -1097,48 +1102,6 @@
383 self.assertIsNotNone(reactor.status)
384
385
386-class TestDBusClient(_LiveTesting):
387- """Test the DBus client (used with --dbus)."""
388-
389- def setUp(self):
390- super().setUp()
391- self._client = DBusClient()
392-
393- def test_check_for_update(self):
394- # There is an update available.
395- self._client.check_for_update()
396- self.assertTrue(self._client.is_available)
397- self.assertTrue(self._client.downloaded)
398-
399- def test_check_for_no_update(self):
400- # There is no update available.
401- self._touch_build(1701)
402- self._client.check_for_update()
403- self.assertFalse(self._client.is_available)
404- self.assertFalse(self._client.downloaded)
405-
406- def test_update_failed(self):
407- # For some reason <wink>, the update fails.
408- #
409- # Cause the update to fail by deleting a file from the server.
410- os.remove(os.path.join(SystemImagePlugin.controller.serverdir,
411- '4/5/6.txt.asc'))
412- self._client.check_for_update()
413- self.assertTrue(self._client.is_available)
414- self.assertFalse(self._client.downloaded)
415- self.assertTrue(self._client.failed)
416-
417- def test_reboot(self):
418- # After a successful update, we can reboot.
419- self._client.check_for_update()
420- self.assertTrue(self._client.is_available)
421- self.assertTrue(self._client.downloaded)
422- self._client.reboot()
423- with open(self.reboot_log, encoding='utf-8') as fp:
424- reboot = fp.read()
425- self.assertEqual(reboot, '/sbin/reboot -f recovery')
426-
427-
428 class TestDBusRegressions(_LiveTesting):
429 """Test that various regressions have been fixed."""
430
431@@ -1355,9 +1318,11 @@
432 'device_name',
433 'last_check_date',
434 'last_update_date',
435+ 'target_build_number',
436 'version_detail',
437 ])
438 self.assertEqual(response['current_build_number'], '45')
439+ self.assertEqual(response['target_build_number'], '53')
440 self.assertEqual(response['device_name'], 'nexus11')
441 self.assertEqual(response['channel_name'], 'daily-proposed')
442 self.assertEqual(response['last_update_date'], '2099-08-01 04:45:45')
443@@ -1388,6 +1353,7 @@
444 self.assertEqual(response['last_update_date'], '2022-08-01 04:45:45')
445 self.assertEqual(response['version_detail'], '')
446 self.assertEqual(response['last_check_date'], '')
447+ self.assertEqual(response['target_build_number'], '-1')
448
449 def test_information_no_details(self):
450 # .Information() where there is no channel.ini with version details,
451@@ -1414,6 +1380,7 @@
452 self.assertEqual(response['last_update_date'], '2022-08-01 04:45:45')
453 self.assertEqual(response['version_detail'], '')
454 self.assertEqual(response['last_check_date'], '2055-08-01 21:12:00')
455+ self.assertEqual(response['target_build_number'], '1600')
456
457 def test_information(self):
458 # .Information() where there is a channel.ini with version details,
459@@ -1453,6 +1420,31 @@
460 # in a robust way. E.g. what if we just happen to be at 12:59:59 on
461 # December 31st? Let's at least make sure it has a sane format.
462 self.assertRegex(response['last_check_date'], '2055-08-01 21:12:01')
463+ self.assertEqual(response['target_build_number'], '1600')
464+
465+ def test_information_no_update_available(self):
466+ # .Information() where we know that no update is available, gives us a
467+ # target build number equal to the current build number.
468+ self._touch_build(1701)
469+ reactor = SignalCapturingReactor('UpdateAvailableStatus')
470+ reactor.run(self.iface.CheckForUpdate)
471+ signal = reactor.signals[0]
472+ self.assertEqual(signal.available_version, '')
473+ response = self.iface.Information()
474+ self.assertEqual(response['target_build_number'], '1701')
475+
476+ def test_information_workflow(self):
477+ # At first, .Information() won't know whether there is an update
478+ # available or not. Then we check, and it tells us there is one.
479+ self._touch_build(45)
480+ response = self.iface.Information()
481+ self.assertEqual(response['target_build_number'], '-1')
482+ reactor = SignalCapturingReactor('UpdateAvailableStatus')
483+ reactor.run(self.iface.CheckForUpdate)
484+ signal = reactor.signals[0]
485+ self.assertEqual(signal.available_version, '1600')
486+ response = self.iface.Information()
487+ self.assertEqual(response['target_build_number'], '1600')
488
489
490 class TestLiveDBusInfoWithChannelIni(_LiveTesting):
491
492=== modified file 'systemimage/version.txt'
493--- systemimage/version.txt 2014-09-17 13:41:31 +0000
494+++ systemimage/version.txt 2014-09-29 18:55:39 +0000
495@@ -1,1 +1,1 @@
496-2.4
497+2.5

Subscribers

People subscribed via source and target branches