~barry/ubuntu-system-image/citrain302

« back to all changes in this revision

Viewing changes to systemimage/main.py

  • Committer: CI bot
  • Date: 2014-07-23 23:07:29 UTC
  • mfrom: (232.1.6 citrain231)
  • Revision ID: ps-jenkins@lists.canonical.com-20140723230729-efe2ckz8xxqdt5uu
* New upstream release.
  - LP: #1207860 - Support factory resets.  system-image-cli
    --factory-reset and a new D-Bus API method FactoryReset() are added.
  - LP: #1262256 - Data file checksums are passed to
    ubuntu-download-manager where available.
  - LP: #1286542 - Certain duplicate destinations are allowed, if they
    have matching source urls and checksums.
  - LP: #1301995 - When system-image-{cli,dbus} is run as non-root, use
    a fallback location for the log file if the system log file isn't
    writable.
  - LP: #1251291 - system-image-cli --list-channels lists all the
    available channels, including aliases.
  - LP: #1279028 - system-image-cli --no-reboot downloads all files and
    prepares for recovery, but does not actually issue a reboot.
  - LP: #1249347 - system-image-cli --switch <channel> is a convenient
    alias for system-image-cli -b 0 -c <channel>.
  - LP: #1294273 - Added --show-settings, --get, --set, and --del
    options for viewing, changing, and setting all the internal database
    settings.
  - LP: #1271684 - Improve memory usage when verifying file checksums.
    Given by Michael Vogt.
  - LP: #1274131 - In the UpdatePaused signal, return a percentage value
    that's closer to reality than hardcoding it to 0.
  - LP: #1280169 - New D-Bus API method .Information() which is like
    .Info() except that it returns extended information details, as a
    mapping of strings to strings.  These details include a
    last_check_date which is the ISO 8601 timestamp of the last time an
    UpdateAvailableStatus signal was sent.
  - LP: #1339157 - Set the GSM flag in ubuntu-download-manager based on
    the current s-i download setting.
  - LP: #1340882 - The system-image-dbus(8) manpage now describes the
    full D-Bus API.
  - LP: #1273354 - Fix the D-Bus mock service so that the downloading
    flag for UpdateAvailableStatus will correctly return true when
    checking twice under manual downloads.
  - LP: #1342183 - Pay down some tech-debt.
* d/watch, d/upstream/signing-key.asc: Added Barry's GPG signing key so
  that uscan will verify the signature of the download.
* d/control: Updated Build-Depends.
* d/rules:
  - Updated, and add --buildsystem=pybuild.
  - Fix 'nocheck' test short-circuiting.
* d/tests:
  - control: Update dependencies and restrictions.  The smoketest test
    should not include the system-image-dev package, for a more
    realistic simulation of the installed enviroment.
  - dryrun: New schroot-compatible limited test suite.  The existing
    smoketest test requires isolation-container so isn't compatible with
    schroot.
  - smoketest-noreboot: Added full update test, with no reboot.
* New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
from systemimage.config import config
34
34
from systemimage.helpers import last_update_date, makedirs, version_detail
35
35
from systemimage.logging import initialize
 
36
from systemimage.reboot import factory_reset
 
37
from systemimage.settings import Settings
36
38
from systemimage.state import State
37
39
from textwrap import dedent
38
40
 
78
80
                                full updates or only delta updates.  The
79
81
                                argument to this option must be either `full`
80
82
                                or `delta`""")
 
83
    parser.add_argument('-g', '--no-reboot',
 
84
                        default=False, action='store_true',
 
85
                        help="""Download (i.e. "get") all the data files and
 
86
                                prepare for updating, but don't actually
 
87
                                reboot the device into recovery to apply the
 
88
                                update""")
81
89
    parser.add_argument('-i', '--info',
82
90
                        default=False, action='store_true',
83
91
                        help="""Show some information about the current
90
98
    parser.add_argument('-v', '--verbose',
91
99
                        default=0, action='count',
92
100
                        help='Increase verbosity')
 
101
    parser.add_argument('--list-channels',
 
102
                        default=False, action='store_true',
 
103
                        help="""List all available channels, then exit""")
 
104
    parser.add_argument('--factory-reset',
 
105
                        default=False, action='store_true',
 
106
                        help="""Perform a destructive factory reset and
 
107
                                reboot.  WARNING: this will wipe all user data
 
108
                                on the device!""")
 
109
    parser.add_argument('--switch',
 
110
                        default=None, action='store', metavar='CHANNEL',
 
111
                        help="""Switch to the given channel.  This is
 
112
                                equivalent to `-c CHANNEL -b 0`.""")
 
113
    # Settings options.
 
114
    parser.add_argument('--show-settings',
 
115
                        default=False, action='store_true',
 
116
                        help="""Show all settings as key=value pairs,
 
117
                                then exit""")
 
118
    parser.add_argument('--set',
 
119
                        default=[], action='append', metavar='KEY=VAL',
 
120
                        help="""Set a key and value in the settings, adding
 
121
                                the key if it doesn't yet exist, or overriding
 
122
                                its value if the key already exists.  Multiple
 
123
                                --set arguments can be given.""")
 
124
    parser.add_argument('--get',
 
125
                        default=[], action='append', metavar='KEY',
 
126
                        help="""Get the value for a key.  If the key does not
 
127
                                exist, a default value is returned.  Multiple
 
128
                                --get arguments can be given.""")
 
129
    parser.add_argument('--del',
 
130
                        default=[], action='append',
 
131
                        metavar='KEY', dest='delete',
 
132
                        help="""Delete the key and its value.  It is a no-op
 
133
                                if the key does not exist.  Multiple
 
134
                                --del arguments can be given.""")
93
135
 
94
136
    args = parser.parse_args(sys.argv[1:])
95
137
    try:
105
147
    except FileNotFoundError:
106
148
        pass
107
149
 
 
150
    # Perform a factory reset.
 
151
    if args.factory_reset:
 
152
        factory_reset()
 
153
        # We should never get here, except possibly during the testing
 
154
        # process, so just return as normal.
 
155
        return 0
 
156
 
 
157
    # Handle all settings arguments.  They are mutually exclusive.
 
158
    if sum(bool(arg) for arg in
 
159
           (args.set, args.get, args.delete, args.show_settings)) > 1:
 
160
        parser.error('Cannot mix and match settings arguments')
 
161
        assert 'parser.error() does not return'
 
162
 
 
163
    if args.show_settings:
 
164
        rows = sorted(Settings())
 
165
        for row in rows:
 
166
            print('{}={}'.format(*row))
 
167
        return 0
 
168
    if args.get:
 
169
        settings = Settings()
 
170
        for key in args.get:
 
171
            print(settings.get(key))
 
172
        return 0
 
173
    if args.set:
 
174
        settings = Settings()
 
175
        for keyval in args.set:
 
176
            key, val = keyval.split('=', 1)
 
177
            settings.set(key, val)
 
178
        return 0
 
179
    if args.delete:
 
180
        settings = Settings()
 
181
        for key in args.delete:
 
182
            settings.delete(key)
 
183
        return 0
 
184
 
108
185
    # Sanity check -f/--filter.
109
186
    if args.filter is None:
110
187
        candidate_filter = None
124
201
    # We assume the cache_partition already exists, as does the /etc directory
125
202
    # (i.e. where the archive master key lives).
126
203
 
127
 
    # Command line overrides.
 
204
    # Command line overrides.  Process --switch first since if both it and
 
205
    # -c/-b are given, the latter take precedence.
 
206
    if args.switch is not None:
 
207
        config.build_number = 0
 
208
        config.channel = args.switch
128
209
    if args.build is not None:
129
210
        try:
130
211
            config.build_number = int(args.build)
168
249
            print('version {}: {}'.format(key, details[key]))
169
250
        return 0
170
251
 
 
252
    if args.list_channels:
 
253
        state = State()
 
254
        try:
 
255
            state.run_thru('get_channel')
 
256
        except Exception:
 
257
            log.exception('system-image-cli exception')
 
258
            return 1
 
259
        print('Available channels:')
 
260
        for key in sorted(state.channels):
 
261
            alias = state.channels[key].get('alias')
 
262
            if alias is None:
 
263
                print('    {}'.format(key))
 
264
            else:
 
265
                print('    {} (alias for: {})'.format(key, alias))
 
266
        return 0
 
267
 
171
268
    # We can either run the API directly or through DBus.
172
269
    if args.dbus:
173
270
        client = DBusClient()
237
334
        log.info('running state machine [{}/{}]',
238
335
                 config.channel, config.device)
239
336
        try:
240
 
            list(state)
 
337
            if args.no_reboot:
 
338
                state.run_until('reboot')
 
339
            else:
 
340
                list(state)
241
341
        except KeyboardInterrupt:
242
342
            return 0
243
343
        except Exception:
245
345
            return 1
246
346
        else:
247
347
            return 0
 
348
        finally:
 
349
            log.info('state machine finished')
248
350
 
249
351
 
250
352
if __name__ == '__main__':