Merge ~chad.smith/cloud-init:ubuntu/xenial into cloud-init:ubuntu/xenial
- Git
- lp:~chad.smith/cloud-init
- ubuntu/xenial
- Merge into ubuntu/xenial
Proposed by
Chad Smith
Status: | Merged | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 59d8c5e0f514782bf853a414d905ddb569bb1fff | ||||||||||||
Proposed branch: | ~chad.smith/cloud-init:ubuntu/xenial | ||||||||||||
Merge into: | cloud-init:ubuntu/xenial | ||||||||||||
Diff against target: |
767 lines (+204/-315) 18 files modified
cloudinit/config/cc_growpart.py (+2/-1) cloudinit/config/cc_resizefs.py (+3/-3) cloudinit/config/cc_ubuntu_advantage.py (+1/-1) cloudinit/net/network_state.py (+8/-0) cloudinit/sources/DataSourceNoCloud.py (+23/-17) cloudinit/util.py (+13/-9) config/cloud.cfg.tmpl (+2/-2) debian/changelog (+7/-0) debian/patches/ubuntu-advantage-revert-tip.patch (+5/-255) tests/unittests/test_datasource/test_azure.py (+0/-24) tests/unittests/test_datasource/test_nocloud.py (+18/-0) tests/unittests/test_distros/test_freebsd.py (+45/-0) tests/unittests/test_ds_identify.py (+20/-0) tests/unittests/test_handler/test_handler_resizefs.py (+1/-1) tests/unittests/test_net.py (+46/-0) tools/ds-identify (+8/-0) tools/render-cloudcfg (+1/-1) tools/run-container (+1/-1) |
||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Server Team CI bot | continuous-integration | Needs Fixing | |
cloud-init Commiters | Pending | ||
Review via email:
|
Commit message
Refresh patches due to drift in cc_ubuntu_
new-upstream-
Description of the change
To post a comment you must log in.
Revision history for this message

Server Team CI bot (server-team-bot) wrote : | # |
review:
Needs Fixing
(continuous-integration)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/cloudinit/config/cc_growpart.py b/cloudinit/config/cc_growpart.py |
2 | index bafca9d..564f376 100644 |
3 | --- a/cloudinit/config/cc_growpart.py |
4 | +++ b/cloudinit/config/cc_growpart.py |
5 | @@ -215,7 +215,8 @@ def device_part_info(devpath): |
6 | # FreeBSD doesn't know of sysfs so just get everything we need from |
7 | # the device, like /dev/vtbd0p2. |
8 | if util.is_FreeBSD(): |
9 | - m = re.search('^(/dev/.+)p([0-9])$', devpath) |
10 | + freebsd_part = "/dev/" + util.find_freebsd_part(devpath) |
11 | + m = re.search('^(/dev/.+)p([0-9])$', freebsd_part) |
12 | return (m.group(1), m.group(2)) |
13 | |
14 | if not os.path.exists(syspath): |
15 | diff --git a/cloudinit/config/cc_resizefs.py b/cloudinit/config/cc_resizefs.py |
16 | index 076b9d5..afd2e06 100644 |
17 | --- a/cloudinit/config/cc_resizefs.py |
18 | +++ b/cloudinit/config/cc_resizefs.py |
19 | @@ -81,7 +81,7 @@ def _resize_xfs(mount_point, devpth): |
20 | |
21 | |
22 | def _resize_ufs(mount_point, devpth): |
23 | - return ('growfs', '-y', devpth) |
24 | + return ('growfs', '-y', mount_point) |
25 | |
26 | |
27 | def _resize_zfs(mount_point, devpth): |
28 | @@ -101,7 +101,7 @@ def _can_skip_resize_ufs(mount_point, devpth): |
29 | """ |
30 | # dumpfs -m / |
31 | # newfs command for / (/dev/label/rootfs) |
32 | - newfs -O 2 -U -a 4 -b 32768 -d 32768 -e 4096 -f 4096 -g 16384 |
33 | + newfs -L rootf -O 2 -U -a 4 -b 32768 -d 32768 -e 4096 -f 4096 -g 16384 |
34 | -h 64 -i 8192 -j -k 6408 -m 8 -o time -s 58719232 /dev/label/rootf |
35 | """ |
36 | cur_fs_sz = None |
37 | @@ -110,7 +110,7 @@ def _can_skip_resize_ufs(mount_point, devpth): |
38 | for line in dumpfs_res.splitlines(): |
39 | if not line.startswith('#'): |
40 | newfs_cmd = shlex.split(line) |
41 | - opt_value = 'O:Ua:s:b:d:e:f:g:h:i:jk:m:o:' |
42 | + opt_value = 'O:Ua:s:b:d:e:f:g:h:i:jk:m:o:L:' |
43 | optlist, _args = getopt.getopt(newfs_cmd[1:], opt_value) |
44 | for o, a in optlist: |
45 | if o == "-s": |
46 | diff --git a/cloudinit/config/cc_ubuntu_advantage.py b/cloudinit/config/cc_ubuntu_advantage.py |
47 | index f488123..f846e9a 100644 |
48 | --- a/cloudinit/config/cc_ubuntu_advantage.py |
49 | +++ b/cloudinit/config/cc_ubuntu_advantage.py |
50 | @@ -36,7 +36,7 @@ schema = { |
51 | """), |
52 | 'distros': distros, |
53 | 'examples': [dedent("""\ |
54 | - # Attach the machine to a Ubuntu Advantage support contract with a |
55 | + # Attach the machine to an Ubuntu Advantage support contract with a |
56 | # UA contract token obtained from %s. |
57 | ubuntu_advantage: |
58 | token: <ua_contract_token> |
59 | diff --git a/cloudinit/net/network_state.py b/cloudinit/net/network_state.py |
60 | index 4d19f56..3702130 100644 |
61 | --- a/cloudinit/net/network_state.py |
62 | +++ b/cloudinit/net/network_state.py |
63 | @@ -707,6 +707,14 @@ class NetworkStateInterpreter(object): |
64 | item_params = dict((key, value) for (key, value) in |
65 | item_cfg.items() if key not in |
66 | NETWORK_V2_KEY_FILTER) |
67 | + # we accept the fixed spelling, but write the old for compatability |
68 | + # Xenial does not have an updated netplan which supports the |
69 | + # correct spelling. LP: #1756701 |
70 | + params = item_params['parameters'] |
71 | + grat_value = params.pop('gratuitous-arp', None) |
72 | + if grat_value: |
73 | + params['gratuitious-arp'] = grat_value |
74 | + |
75 | v1_cmd = { |
76 | 'type': cmd_type, |
77 | 'name': item_name, |
78 | diff --git a/cloudinit/sources/DataSourceNoCloud.py b/cloudinit/sources/DataSourceNoCloud.py |
79 | index fcf5d58..8a9e5dd 100644 |
80 | --- a/cloudinit/sources/DataSourceNoCloud.py |
81 | +++ b/cloudinit/sources/DataSourceNoCloud.py |
82 | @@ -35,6 +35,26 @@ class DataSourceNoCloud(sources.DataSource): |
83 | root = sources.DataSource.__str__(self) |
84 | return "%s [seed=%s][dsmode=%s]" % (root, self.seed, self.dsmode) |
85 | |
86 | + def _get_devices(self, label): |
87 | + if util.is_FreeBSD(): |
88 | + devlist = [ |
89 | + p for p in ['/dev/msdosfs/' + label, '/dev/iso9660/' + label] |
90 | + if os.path.exists(p)] |
91 | + else: |
92 | + # Query optical drive to get it in blkid cache for 2.6 kernels |
93 | + util.find_devs_with(path="/dev/sr0") |
94 | + util.find_devs_with(path="/dev/sr1") |
95 | + |
96 | + fslist = util.find_devs_with("TYPE=vfat") |
97 | + fslist.extend(util.find_devs_with("TYPE=iso9660")) |
98 | + |
99 | + label_list = util.find_devs_with("LABEL=%s" % label.upper()) |
100 | + label_list.extend(util.find_devs_with("LABEL=%s" % label.lower())) |
101 | + |
102 | + devlist = list(set(fslist) & set(label_list)) |
103 | + devlist.sort(reverse=True) |
104 | + return devlist |
105 | + |
106 | def _get_data(self): |
107 | defaults = { |
108 | "instance-id": "nocloud", |
109 | @@ -99,20 +119,7 @@ class DataSourceNoCloud(sources.DataSource): |
110 | |
111 | label = self.ds_cfg.get('fs_label', "cidata") |
112 | if label is not None: |
113 | - # Query optical drive to get it in blkid cache for 2.6 kernels |
114 | - util.find_devs_with(path="/dev/sr0") |
115 | - util.find_devs_with(path="/dev/sr1") |
116 | - |
117 | - fslist = util.find_devs_with("TYPE=vfat") |
118 | - fslist.extend(util.find_devs_with("TYPE=iso9660")) |
119 | - |
120 | - label_list = util.find_devs_with("LABEL=%s" % label.upper()) |
121 | - label_list.extend(util.find_devs_with("LABEL=%s" % label.lower())) |
122 | - |
123 | - devlist = list(set(fslist) & set(label_list)) |
124 | - devlist.sort(reverse=True) |
125 | - |
126 | - for dev in devlist: |
127 | + for dev in self._get_devices(label): |
128 | try: |
129 | LOG.debug("Attempting to use data from %s", dev) |
130 | |
131 | @@ -120,9 +127,8 @@ class DataSourceNoCloud(sources.DataSource): |
132 | seeded = util.mount_cb(dev, _pp2d_callback, |
133 | pp2d_kwargs) |
134 | except ValueError: |
135 | - if dev in label_list: |
136 | - LOG.warning("device %s with label=%s not a" |
137 | - "valid seed.", dev, label) |
138 | + LOG.warning("device %s with label=%s not a" |
139 | + "valid seed.", dev, label) |
140 | continue |
141 | |
142 | mydata = _merge_new_seed(mydata, seeded) |
143 | diff --git a/cloudinit/util.py b/cloudinit/util.py |
144 | index ea4199c..aa23b3f 100644 |
145 | --- a/cloudinit/util.py |
146 | +++ b/cloudinit/util.py |
147 | @@ -2337,17 +2337,21 @@ def parse_mtab(path): |
148 | return None |
149 | |
150 | |
151 | -def find_freebsd_part(label_part): |
152 | - if label_part.startswith("/dev/label/"): |
153 | - target_label = label_part[5:] |
154 | - (label_part, _err) = subp(['glabel', 'status', '-s']) |
155 | - for labels in label_part.split("\n"): |
156 | +def find_freebsd_part(fs): |
157 | + splitted = fs.split('/') |
158 | + if len(splitted) == 3: |
159 | + return splitted[2] |
160 | + elif splitted[2] in ['label', 'gpt', 'ufs']: |
161 | + target_label = fs[5:] |
162 | + (part, _err) = subp(['glabel', 'status', '-s']) |
163 | + for labels in part.split("\n"): |
164 | items = labels.split() |
165 | - if len(items) > 0 and items[0].startswith(target_label): |
166 | - label_part = items[2] |
167 | + if len(items) > 0 and items[0] == target_label: |
168 | + part = items[2] |
169 | break |
170 | - label_part = str(label_part) |
171 | - return label_part |
172 | + return str(part) |
173 | + else: |
174 | + LOG.warning("Unexpected input in find_freebsd_part: %s", fs) |
175 | |
176 | |
177 | def get_path_dev_freebsd(path, mnt_list): |
178 | diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl |
179 | index 25db43e..684c747 100644 |
180 | --- a/config/cloud.cfg.tmpl |
181 | +++ b/config/cloud.cfg.tmpl |
182 | @@ -32,8 +32,8 @@ preserve_hostname: false |
183 | |
184 | {% if variant in ["freebsd"] %} |
185 | # This should not be required, but leave it in place until the real cause of |
186 | -# not beeing able to find -any- datasources is resolved. |
187 | -datasource_list: ['ConfigDrive', 'Azure', 'OpenStack', 'Ec2'] |
188 | +# not finding -any- datasources is resolved. |
189 | +datasource_list: ['NoCloud', 'ConfigDrive', 'Azure', 'OpenStack', 'Ec2'] |
190 | {% endif %} |
191 | # Example datasource config |
192 | # datasource: |
193 | diff --git a/debian/changelog b/debian/changelog |
194 | index 270b0f3..e14ee1c 100644 |
195 | --- a/debian/changelog |
196 | +++ b/debian/changelog |
197 | @@ -1,3 +1,10 @@ |
198 | +cloud-init (19.1-1-gbaa47854-0ubuntu1~16.04.2) UNRELEASED; urgency=medium |
199 | + |
200 | + * refresh patches: |
201 | + + debian/patches/ubuntu-advantage-revert-tip.patch |
202 | + |
203 | + -- Chad Smith <chad.smith@canonical.com> Tue, 04 Jun 2019 14:59:14 -0600 |
204 | + |
205 | cloud-init (19.1-1-gbaa47854-0ubuntu1~16.04.1) xenial; urgency=medium |
206 | |
207 | * debian/patches/ubuntu-advantage-revert-tip.patch |
208 | diff --git a/debian/patches/ubuntu-advantage-revert-tip.patch b/debian/patches/ubuntu-advantage-revert-tip.patch |
209 | index 08bdc81..5f1e043 100644 |
210 | --- a/debian/patches/ubuntu-advantage-revert-tip.patch |
211 | +++ b/debian/patches/ubuntu-advantage-revert-tip.patch |
212 | @@ -9,257 +9,9 @@ Forwarded: not-needed |
213 | Last-Update: 2019-05-10 |
214 | --- |
215 | This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ |
216 | -Index: cloud-init/cloudinit/config/cc_ubuntu_advantage.py |
217 | -=================================================================== |
218 | ---- cloud-init.orig/cloudinit/config/cc_ubuntu_advantage.py |
219 | -+++ cloud-init/cloudinit/config/cc_ubuntu_advantage.py |
220 | -@@ -1,143 +1,150 @@ |
221 | -+# Copyright (C) 2018 Canonical Ltd. |
222 | -+# |
223 | - # This file is part of cloud-init. See LICENSE file for license information. |
224 | - |
225 | --"""ubuntu_advantage: Configure Ubuntu Advantage support services""" |
226 | -+"""Ubuntu advantage: manage ubuntu-advantage offerings from Canonical.""" |
227 | - |
228 | -+import sys |
229 | - from textwrap import dedent |
230 | - |
231 | --import six |
232 | -- |
233 | -+from cloudinit import log as logging |
234 | - from cloudinit.config.schema import ( |
235 | - get_schema_doc, validate_cloudconfig_schema) |
236 | --from cloudinit import log as logging |
237 | - from cloudinit.settings import PER_INSTANCE |
238 | -+from cloudinit.subp import prepend_base_command |
239 | - from cloudinit import util |
240 | - |
241 | - |
242 | --UA_URL = 'https://ubuntu.com/advantage' |
243 | -- |
244 | - distros = ['ubuntu'] |
245 | -+frequency = PER_INSTANCE |
246 | -+ |
247 | -+LOG = logging.getLogger(__name__) |
248 | - |
249 | - schema = { |
250 | - 'id': 'cc_ubuntu_advantage', |
251 | - 'name': 'Ubuntu Advantage', |
252 | -- 'title': 'Configure Ubuntu Advantage support services', |
253 | -+ 'title': 'Install, configure and manage ubuntu-advantage offerings', |
254 | - 'description': dedent("""\ |
255 | -- Attach machine to an existing Ubuntu Advantage support contract and |
256 | -- enable or disable support services such as Livepatch, ESM, |
257 | -- FIPS and FIPS Updates. When attaching a machine to Ubuntu Advantage, |
258 | -- one can also specify services to enable. When the 'enable' |
259 | -- list is present, any named service will be enabled and all absent |
260 | -- services will remain disabled. |
261 | -- |
262 | -- Note that when enabling FIPS or FIPS updates you will need to schedule |
263 | -- a reboot to ensure the machine is running the FIPS-compliant kernel. |
264 | -- See :ref:`Power State Change` for information on how to configure |
265 | -- cloud-init to perform this reboot. |
266 | -+ This module provides configuration options to setup ubuntu-advantage |
267 | -+ subscriptions. |
268 | -+ |
269 | -+ .. note:: |
270 | -+ Both ``commands`` value can be either a dictionary or a list. If |
271 | -+ the configuration provided is a dictionary, the keys are only used |
272 | -+ to order the execution of the commands and the dictionary is |
273 | -+ merged with any vendor-data ubuntu-advantage configuration |
274 | -+ provided. If a ``commands`` is provided as a list, any vendor-data |
275 | -+ ubuntu-advantage ``commands`` are ignored. |
276 | -+ |
277 | -+ Ubuntu-advantage ``commands`` is a dictionary or list of |
278 | -+ ubuntu-advantage commands to run on the deployed machine. |
279 | -+ These commands can be used to enable or disable subscriptions to |
280 | -+ various ubuntu-advantage products. See 'man ubuntu-advantage' for more |
281 | -+ information on supported subcommands. |
282 | -+ |
283 | -+ .. note:: |
284 | -+ Each command item can be a string or list. If the item is a list, |
285 | -+ 'ubuntu-advantage' can be omitted and it will automatically be |
286 | -+ inserted as part of the command. |
287 | - """), |
288 | - 'distros': distros, |
289 | - 'examples': [dedent("""\ |
290 | -- # Attach the machine to a Ubuntu Advantage support contract with a |
291 | -- # UA contract token obtained from %s. |
292 | -- ubuntu_advantage: |
293 | -- token: <ua_contract_token> |
294 | -- """ % UA_URL), dedent("""\ |
295 | -- # Attach the machine to an Ubuntu Advantage support contract enabling |
296 | -- # only fips and esm services. Services will only be enabled if |
297 | -- # the environment supports said service. Otherwise warnings will |
298 | -- # be logged for incompatible services specified. |
299 | -+ # Enable Extended Security Maintenance using your service auth token |
300 | -+ ubuntu-advantage: |
301 | -+ commands: |
302 | -+ 00: ubuntu-advantage enable-esm <token> |
303 | -+ """), dedent("""\ |
304 | -+ # Enable livepatch by providing your livepatch token |
305 | - ubuntu-advantage: |
306 | -- token: <ua_contract_token> |
307 | -- enable: |
308 | -- - fips |
309 | -- - esm |
310 | -+ commands: |
311 | -+ 00: ubuntu-advantage enable-livepatch <livepatch-token> |
312 | -+ |
313 | - """), dedent("""\ |
314 | -- # Attach the machine to an Ubuntu Advantage support contract and enable |
315 | -- # the FIPS service. Perform a reboot once cloud-init has |
316 | -- # completed. |
317 | -- power_state: |
318 | -- mode: reboot |
319 | -+ # Convenience: the ubuntu-advantage command can be omitted when |
320 | -+ # specifying commands as a list and 'ubuntu-advantage' will |
321 | -+ # automatically be prepended. |
322 | -+ # The following commands are equivalent |
323 | - ubuntu-advantage: |
324 | -- token: <ua_contract_token> |
325 | -- enable: |
326 | -- - fips |
327 | -- """)], |
328 | -+ commands: |
329 | -+ 00: ['enable-livepatch', 'my-token'] |
330 | -+ 01: ['ubuntu-advantage', 'enable-livepatch', 'my-token'] |
331 | -+ 02: ubuntu-advantage enable-livepatch my-token |
332 | -+ 03: 'ubuntu-advantage enable-livepatch my-token' |
333 | -+ """)], |
334 | - 'frequency': PER_INSTANCE, |
335 | - 'type': 'object', |
336 | - 'properties': { |
337 | -- 'ubuntu_advantage': { |
338 | -+ 'ubuntu-advantage': { |
339 | - 'type': 'object', |
340 | - 'properties': { |
341 | -- 'enable': { |
342 | -- 'type': 'array', |
343 | -- 'items': {'type': 'string'}, |
344 | -- }, |
345 | -- 'token': { |
346 | -- 'type': 'string', |
347 | -- 'description': ( |
348 | -- 'A contract token obtained from %s.' % UA_URL) |
349 | -+ 'commands': { |
350 | -+ 'type': ['object', 'array'], # Array of strings or dict |
351 | -+ 'items': { |
352 | -+ 'oneOf': [ |
353 | -+ {'type': 'array', 'items': {'type': 'string'}}, |
354 | -+ {'type': 'string'}] |
355 | -+ }, |
356 | -+ 'additionalItems': False, # Reject non-string & non-list |
357 | -+ 'minItems': 1, |
358 | -+ 'minProperties': 1, |
359 | - } |
360 | - }, |
361 | -- 'required': ['token'], |
362 | -- 'additionalProperties': False |
363 | -+ 'additionalProperties': False, # Reject keys not in schema |
364 | -+ 'required': ['commands'] |
365 | - } |
366 | - } |
367 | - } |
368 | - |
369 | -+# TODO schema for 'assertions' and 'commands' are too permissive at the moment. |
370 | -+# Once python-jsonschema supports schema draft 6 add support for arbitrary |
371 | -+# object keys with 'patternProperties' constraint to validate string values. |
372 | -+ |
373 | - __doc__ = get_schema_doc(schema) # Supplement python help() |
374 | - |
375 | --LOG = logging.getLogger(__name__) |
376 | -+UA_CMD = "ubuntu-advantage" |
377 | - |
378 | - |
379 | --def configure_ua(token=None, enable=None): |
380 | -- """Call ua commandline client to attach or enable services.""" |
381 | -- error = None |
382 | -- if not token: |
383 | -- error = ('ubuntu_advantage: token must be provided') |
384 | -- LOG.error(error) |
385 | -- raise RuntimeError(error) |
386 | -- |
387 | -- if enable is None: |
388 | -- enable = [] |
389 | -- elif isinstance(enable, six.string_types): |
390 | -- LOG.warning('ubuntu_advantage: enable should be a list, not' |
391 | -- ' a string; treating as a single enable') |
392 | -- enable = [enable] |
393 | -- elif not isinstance(enable, list): |
394 | -- LOG.warning('ubuntu_advantage: enable should be a list, not' |
395 | -- ' a %s; skipping enabling services', |
396 | -- type(enable).__name__) |
397 | -- enable = [] |
398 | -+def run_commands(commands): |
399 | -+ """Run the commands provided in ubuntu-advantage:commands config. |
400 | - |
401 | -- attach_cmd = ['ua', 'attach', token] |
402 | -- LOG.debug('Attaching to Ubuntu Advantage. %s', ' '.join(attach_cmd)) |
403 | -- try: |
404 | -- util.subp(attach_cmd) |
405 | -- except util.ProcessExecutionError as e: |
406 | -- msg = 'Failure attaching Ubuntu Advantage:\n{error}'.format( |
407 | -- error=str(e)) |
408 | -- util.logexc(LOG, msg) |
409 | -- raise RuntimeError(msg) |
410 | -- enable_errors = [] |
411 | -- for service in enable: |
412 | -+ Commands are run individually. Any errors are collected and reported |
413 | -+ after attempting all commands. |
414 | -+ |
415 | -+ @param commands: A list or dict containing commands to run. Keys of a |
416 | -+ dict will be used to order the commands provided as dict values. |
417 | -+ """ |
418 | -+ if not commands: |
419 | -+ return |
420 | -+ LOG.debug('Running user-provided ubuntu-advantage commands') |
421 | -+ if isinstance(commands, dict): |
422 | -+ # Sort commands based on dictionary key |
423 | -+ commands = [v for _, v in sorted(commands.items())] |
424 | -+ elif not isinstance(commands, list): |
425 | -+ raise TypeError( |
426 | -+ 'commands parameter was not a list or dict: {commands}'.format( |
427 | -+ commands=commands)) |
428 | -+ |
429 | -+ fixed_ua_commands = prepend_base_command('ubuntu-advantage', commands) |
430 | -+ |
431 | -+ cmd_failures = [] |
432 | -+ for command in fixed_ua_commands: |
433 | -+ shell = isinstance(command, str) |
434 | - try: |
435 | -- cmd = ['ua', 'enable', service] |
436 | -- util.subp(cmd, capture=True) |
437 | -+ util.subp(command, shell=shell, status_cb=sys.stderr.write) |
438 | - except util.ProcessExecutionError as e: |
439 | -- enable_errors.append((service, e)) |
440 | -- if enable_errors: |
441 | -- for service, error in enable_errors: |
442 | -- msg = 'Failure enabling "{service}":\n{error}'.format( |
443 | -- service=service, error=str(error)) |
444 | -- util.logexc(LOG, msg) |
445 | -- raise RuntimeError( |
446 | -- 'Failure enabling Ubuntu Advantage service(s): {}'.format( |
447 | -- ', '.join('"{}"'.format(service) |
448 | -- for service, _ in enable_errors))) |
449 | -+ cmd_failures.append(str(e)) |
450 | -+ if cmd_failures: |
451 | -+ msg = ( |
452 | -+ 'Failures running ubuntu-advantage commands:\n' |
453 | -+ '{cmd_failures}'.format( |
454 | -+ cmd_failures=cmd_failures)) |
455 | -+ util.logexc(LOG, msg) |
456 | -+ raise RuntimeError(msg) |
457 | - |
458 | - |
459 | - def maybe_install_ua_tools(cloud): |
460 | - """Install ubuntu-advantage-tools if not present.""" |
461 | -- if util.which('ua'): |
462 | -+ if util.which('ubuntu-advantage'): |
463 | - return |
464 | - try: |
465 | - cloud.distro.update_package_sources() |
466 | -@@ -152,28 +159,14 @@ def maybe_install_ua_tools(cloud): |
467 | +--- a/cloudinit/config/cc_ubuntu_advantage.py |
468 | ++++ b/cloudinit/config/cc_ubuntu_advantage.py |
469 | +@@ -152,28 +152,14 @@ def maybe_install_ua_tools(cloud): |
470 | |
471 | |
472 | def handle(name, cfg, cloud, log, args): |
473 | @@ -294,10 +46,8 @@ Index: cloud-init/cloudinit/config/cc_ubuntu_advantage.py |
474 | + run_commands(cfgin.get('commands', [])) |
475 | |
476 | # vi: ts=4 expandtab |
477 | -Index: cloud-init/cloudinit/config/tests/test_ubuntu_advantage.py |
478 | -=================================================================== |
479 | ---- cloud-init.orig/cloudinit/config/tests/test_ubuntu_advantage.py |
480 | -+++ cloud-init/cloudinit/config/tests/test_ubuntu_advantage.py |
481 | +--- a/cloudinit/config/tests/test_ubuntu_advantage.py |
482 | ++++ b/cloudinit/config/tests/test_ubuntu_advantage.py |
483 | @@ -1,7 +1,10 @@ |
484 | # This file is part of cloud-init. See LICENSE file for license information. |
485 | |
486 | diff --git a/tests/unittests/test_datasource/test_azure.py b/tests/unittests/test_datasource/test_azure.py |
487 | index 427ab7e..afb614e 100644 |
488 | --- a/tests/unittests/test_datasource/test_azure.py |
489 | +++ b/tests/unittests/test_datasource/test_azure.py |
490 | @@ -6,7 +6,6 @@ from cloudinit import url_helper |
491 | from cloudinit.sources import ( |
492 | UNSET, DataSourceAzure as dsaz, InvalidMetaDataException) |
493 | from cloudinit.util import (b64e, decode_binary, load_file, write_file, |
494 | - find_freebsd_part, get_path_dev_freebsd, |
495 | MountFailedError, json_dumps, load_json) |
496 | from cloudinit.version import version_string as vs |
497 | from cloudinit.tests.helpers import ( |
498 | @@ -391,29 +390,6 @@ scbus-1 on xpt0 bus 0 |
499 | dev = ds.get_resource_disk_on_freebsd(1) |
500 | self.assertEqual("da1", dev) |
501 | |
502 | - @mock.patch('cloudinit.util.subp') |
503 | - def test_find_freebsd_part_on_Azure(self, mock_subp): |
504 | - glabel_out = ''' |
505 | -gptid/fa52d426-c337-11e6-8911-00155d4c5e47 N/A da0p1 |
506 | - label/rootfs N/A da0p2 |
507 | - label/swap N/A da0p3 |
508 | -''' |
509 | - mock_subp.return_value = (glabel_out, "") |
510 | - res = find_freebsd_part("/dev/label/rootfs") |
511 | - self.assertEqual("da0p2", res) |
512 | - |
513 | - def test_get_path_dev_freebsd_on_Azure(self): |
514 | - mnt_list = ''' |
515 | -/dev/label/rootfs / ufs rw 1 1 |
516 | -devfs /dev devfs rw,multilabel 0 0 |
517 | -fdescfs /dev/fd fdescfs rw 0 0 |
518 | -/dev/da1s1 /mnt/resource ufs rw 2 2 |
519 | -''' |
520 | - with mock.patch.object(os.path, 'exists', |
521 | - return_value=True): |
522 | - res = get_path_dev_freebsd('/etc', mnt_list) |
523 | - self.assertIsNotNone(res) |
524 | - |
525 | @mock.patch(MOCKPATH + '_is_platform_viable') |
526 | def test_call_is_platform_viable_seed(self, m_is_platform_viable): |
527 | """Check seed_dir using _is_platform_viable and return False.""" |
528 | diff --git a/tests/unittests/test_datasource/test_nocloud.py b/tests/unittests/test_datasource/test_nocloud.py |
529 | index b785362..18bea0b 100644 |
530 | --- a/tests/unittests/test_datasource/test_nocloud.py |
531 | +++ b/tests/unittests/test_datasource/test_nocloud.py |
532 | @@ -278,6 +278,24 @@ class TestNoCloudDataSource(CiTestCase): |
533 | self.assertEqual(netconf, dsrc.network_config) |
534 | self.assertNotIn(gateway, str(dsrc.network_config)) |
535 | |
536 | + @mock.patch("cloudinit.util.blkid") |
537 | + def test_nocloud_get_devices_freebsd(self, m_is_lxd, fake_blkid): |
538 | + populate_dir(os.path.join(self.paths.seed_dir, "nocloud"), |
539 | + {'user-data': b"ud", 'meta-data': "instance-id: IID\n"}) |
540 | + |
541 | + sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}} |
542 | + |
543 | + self.mocks.enter_context( |
544 | + mock.patch.object(util, 'is_FreeBSD', return_value=True)) |
545 | + |
546 | + self.mocks.enter_context( |
547 | + mock.patch.object(os.path, 'exists', return_value=True)) |
548 | + |
549 | + dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths) |
550 | + ret = dsrc._get_devices('foo') |
551 | + self.assertEqual(['/dev/msdosfs/foo', '/dev/iso9660/foo'], ret) |
552 | + fake_blkid.assert_not_called() |
553 | + |
554 | |
555 | class TestParseCommandLineData(CiTestCase): |
556 | |
557 | diff --git a/tests/unittests/test_distros/test_freebsd.py b/tests/unittests/test_distros/test_freebsd.py |
558 | new file mode 100644 |
559 | index 0000000..8af253a |
560 | --- /dev/null |
561 | +++ b/tests/unittests/test_distros/test_freebsd.py |
562 | @@ -0,0 +1,45 @@ |
563 | +# This file is part of cloud-init. See LICENSE file for license information. |
564 | + |
565 | +from cloudinit.util import (find_freebsd_part, get_path_dev_freebsd) |
566 | +from cloudinit.tests.helpers import (CiTestCase, mock) |
567 | + |
568 | +import os |
569 | + |
570 | + |
571 | +class TestDeviceLookUp(CiTestCase): |
572 | + |
573 | + @mock.patch('cloudinit.util.subp') |
574 | + def test_find_freebsd_part_label(self, mock_subp): |
575 | + glabel_out = ''' |
576 | +gptid/fa52d426-c337-11e6-8911-00155d4c5e47 N/A da0p1 |
577 | + label/rootfs N/A da0p2 |
578 | + label/swap N/A da0p3 |
579 | +''' |
580 | + mock_subp.return_value = (glabel_out, "") |
581 | + res = find_freebsd_part("/dev/label/rootfs") |
582 | + self.assertEqual("da0p2", res) |
583 | + |
584 | + @mock.patch('cloudinit.util.subp') |
585 | + def test_find_freebsd_part_gpt(self, mock_subp): |
586 | + glabel_out = ''' |
587 | + gpt/bootfs N/A vtbd0p1 |
588 | +gptid/3f4cbe26-75da-11e8-a8f2-002590ec6166 N/A vtbd0p1 |
589 | + gpt/swapfs N/A vtbd0p2 |
590 | + gpt/rootfs N/A vtbd0p3 |
591 | + iso9660/cidata N/A vtbd2 |
592 | +''' |
593 | + mock_subp.return_value = (glabel_out, "") |
594 | + res = find_freebsd_part("/dev/gpt/rootfs") |
595 | + self.assertEqual("vtbd0p3", res) |
596 | + |
597 | + def test_get_path_dev_freebsd_label(self): |
598 | + mnt_list = ''' |
599 | +/dev/label/rootfs / ufs rw 1 1 |
600 | +devfs /dev devfs rw,multilabel 0 0 |
601 | +fdescfs /dev/fd fdescfs rw 0 0 |
602 | +/dev/da1s1 /mnt/resource ufs rw 2 2 |
603 | +''' |
604 | + with mock.patch.object(os.path, 'exists', |
605 | + return_value=True): |
606 | + res = get_path_dev_freebsd('/etc', mnt_list) |
607 | + self.assertIsNotNone(res) |
608 | diff --git a/tests/unittests/test_ds_identify.py b/tests/unittests/test_ds_identify.py |
609 | index 8c18aa1..7575223 100644 |
610 | --- a/tests/unittests/test_ds_identify.py |
611 | +++ b/tests/unittests/test_ds_identify.py |
612 | @@ -435,6 +435,14 @@ class TestDsIdentify(DsIdentifyBase): |
613 | """Open Telecom identification.""" |
614 | self._test_ds_found('OpenStack-OpenTelekom') |
615 | |
616 | + def test_openstack_asset_tag_nova(self): |
617 | + """OpenStack identification via asset tag OpenStack Nova.""" |
618 | + self._test_ds_found('OpenStack-AssetTag-Nova') |
619 | + |
620 | + def test_openstack_asset_tag_copute(self): |
621 | + """OpenStack identification via asset tag OpenStack Compute.""" |
622 | + self._test_ds_found('OpenStack-AssetTag-Compute') |
623 | + |
624 | def test_openstack_on_non_intel_is_maybe(self): |
625 | """On non-Intel, openstack without dmi info is maybe. |
626 | |
627 | @@ -759,6 +767,18 @@ VALID_CFG = { |
628 | 'files': {P_CHASSIS_ASSET_TAG: 'OpenTelekomCloud\n'}, |
629 | 'mocks': [MOCK_VIRT_IS_XEN], |
630 | }, |
631 | + 'OpenStack-AssetTag-Nova': { |
632 | + # VMware vSphere can't modify product-name, LP: #1669875 |
633 | + 'ds': 'OpenStack', |
634 | + 'files': {P_CHASSIS_ASSET_TAG: 'OpenStack Nova\n'}, |
635 | + 'mocks': [MOCK_VIRT_IS_XEN], |
636 | + }, |
637 | + 'OpenStack-AssetTag-Compute': { |
638 | + # VMware vSphere can't modify product-name, LP: #1669875 |
639 | + 'ds': 'OpenStack', |
640 | + 'files': {P_CHASSIS_ASSET_TAG: 'OpenStack Compute\n'}, |
641 | + 'mocks': [MOCK_VIRT_IS_XEN], |
642 | + }, |
643 | 'OVF-seed': { |
644 | 'ds': 'OVF', |
645 | 'files': { |
646 | diff --git a/tests/unittests/test_handler/test_handler_resizefs.py b/tests/unittests/test_handler/test_handler_resizefs.py |
647 | index 3518784..db9a041 100644 |
648 | --- a/tests/unittests/test_handler/test_handler_resizefs.py |
649 | +++ b/tests/unittests/test_handler/test_handler_resizefs.py |
650 | @@ -147,7 +147,7 @@ class TestResizefs(CiTestCase): |
651 | def test_resize_ufs_cmd_return(self): |
652 | mount_point = '/' |
653 | devpth = '/dev/sda2' |
654 | - self.assertEqual(('growfs', '-y', devpth), |
655 | + self.assertEqual(('growfs', '-y', mount_point), |
656 | _resize_ufs(mount_point, devpth)) |
657 | |
658 | @mock.patch('cloudinit.util.is_container', return_value=False) |
659 | diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py |
660 | index e85e964..b936bc9 100644 |
661 | --- a/tests/unittests/test_net.py |
662 | +++ b/tests/unittests/test_net.py |
663 | @@ -407,6 +407,37 @@ network: |
664 | - maas |
665 | """ |
666 | |
667 | +NETPLAN_BOND_GRAT_ARP = """ |
668 | +network: |
669 | + bonds: |
670 | + bond0: |
671 | + interfaces: |
672 | + - ens3 |
673 | + macaddress: 68:05:ca:64:d3:6c |
674 | + mtu: 9000 |
675 | + parameters: |
676 | + gratuitious-arp: 1 |
677 | + bond1: |
678 | + interfaces: |
679 | + - ens4 |
680 | + macaddress: 68:05:ca:64:d3:6d |
681 | + mtu: 9000 |
682 | + parameters: |
683 | + gratuitous-arp: 2 |
684 | + ethernets: |
685 | + ens3: |
686 | + dhcp4: false |
687 | + dhcp6: false |
688 | + match: |
689 | + macaddress: 52:54:00:ab:cd:ef |
690 | + ens4: |
691 | + dhcp4: false |
692 | + dhcp6: false |
693 | + match: |
694 | + macaddress: 52:54:00:11:22:ff |
695 | + version: 2 |
696 | +""" |
697 | + |
698 | NETPLAN_DHCP_FALSE = """ |
699 | version: 2 |
700 | ethernets: |
701 | @@ -3589,6 +3620,21 @@ class TestNetplanRoundTrip(CiTestCase): |
702 | entry['expected_netplan'].splitlines(), |
703 | files['/etc/netplan/50-cloud-init.yaml'].splitlines()) |
704 | |
705 | + def test_render_output_supports_both_grat_arp_spelling(self): |
706 | + entry = { |
707 | + 'yaml': NETPLAN_BOND_GRAT_ARP, |
708 | + 'expected_netplan': NETPLAN_BOND_GRAT_ARP.replace('gratuitous', |
709 | + 'gratuitious'), |
710 | + } |
711 | + network_config = yaml.load(entry['yaml']).get('network') |
712 | + files = self._render_and_read(network_config=network_config) |
713 | + print(entry['expected_netplan']) |
714 | + print('-- expected ^ | v rendered --') |
715 | + print(files['/etc/netplan/50-cloud-init.yaml']) |
716 | + self.assertEqual( |
717 | + entry['expected_netplan'].splitlines(), |
718 | + files['/etc/netplan/50-cloud-init.yaml'].splitlines()) |
719 | + |
720 | |
721 | class TestEniRoundTrip(CiTestCase): |
722 | |
723 | diff --git a/tools/ds-identify b/tools/ds-identify |
724 | index 6518901..e16708f 100755 |
725 | --- a/tools/ds-identify |
726 | +++ b/tools/ds-identify |
727 | @@ -979,6 +979,14 @@ dscheck_OpenStack() { |
728 | return ${DS_FOUND} |
729 | fi |
730 | |
731 | + # LP: #1669875 : allow identification of OpenStack by asset tag |
732 | + if dmi_chassis_asset_tag_matches "$nova"; then |
733 | + return ${DS_FOUND} |
734 | + fi |
735 | + if dmi_chassis_asset_tag_matches "$compute"; then |
736 | + return ${DS_FOUND} |
737 | + fi |
738 | + |
739 | # LP: #1715241 : arch other than intel are not identified properly. |
740 | case "$DI_UNAME_MACHINE" in |
741 | i?86|x86_64) :;; |
742 | diff --git a/tools/render-cloudcfg b/tools/render-cloudcfg |
743 | index 8b7cb87..0957c32 100755 |
744 | --- a/tools/render-cloudcfg |
745 | +++ b/tools/render-cloudcfg |
746 | @@ -4,7 +4,7 @@ import argparse |
747 | import os |
748 | import sys |
749 | |
750 | -VARIANTS = ["bsd", "centos", "fedora", "rhel", "suse", "ubuntu", "unknown"] |
751 | +VARIANTS = ["freebsd", "centos", "fedora", "rhel", "suse", "ubuntu", "unknown"] |
752 | |
753 | if "avoid-pep8-E402-import-not-top-of-file": |
754 | _tdir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) |
755 | diff --git a/tools/run-container b/tools/run-container |
756 | index 852f4d1..1d24e15 100755 |
757 | --- a/tools/run-container |
758 | +++ b/tools/run-container |
759 | @@ -373,7 +373,7 @@ wait_for_boot() { |
760 | inside "$name" sh -c "echo proxy=$http_proxy >> /etc/yum.conf" |
761 | inside "$name" sed -i s/enabled=1/enabled=0/ \ |
762 | /etc/yum/pluginconf.d/fastestmirror.conf |
763 | - inside "$name" sh -c "sed -i '/^#baseurl=/s/#//' /etc/yum.repos.d/*.repo" |
764 | + inside "$name" sh -c "sed -i '/^#baseurl=/s/#// ; s/^mirrorlist/#mirrorlist/' /etc/yum.repos.d/*.repo" |
765 | else |
766 | debug 1 "do not know how to configure proxy on $OS_NAME" |
767 | fi |
FAILED: Continuous integration, rev:d12794c5048 cecdc4887c7bd49 6794cb6fad029c /jenkins. ubuntu. com/server/ job/cloud- init-ci/ 732/
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
FAILED: Ubuntu LTS: Build
Click here to trigger a rebuild: /jenkins. ubuntu. com/server/ job/cloud- init-ci/ 732/rebuild
https:/