Merge ~paride/curtin:20.1-29-g81144052-0ubuntu1 into curtin:ubuntu/devel
- Git
- lp:~paride/curtin
- 20.1-29-g81144052-0ubuntu1
- Merge into ubuntu/devel
Proposed by
Paride Legovini
Status: | Merged |
---|---|
Merged at revision: | 602618759f4ab30847599de23b598339a1c99ebc |
Proposed branch: | ~paride/curtin:20.1-29-g81144052-0ubuntu1 |
Merge into: | curtin:ubuntu/devel |
Diff against target: |
4246 lines (+1378/-939) 84 files modified
Makefile (+1/-1) curtin/__init__.py (+4/-0) curtin/block/__init__.py (+16/-1) curtin/block/dasd.py (+2/-2) curtin/block/multipath.py (+1/-1) curtin/commands/block_meta.py (+8/-3) curtin/commands/curthooks.py (+130/-16) curtin/commands/install_grub.py (+1/-1) curtin/commands/swap.py (+4/-1) curtin/distro.py (+23/-7) curtin/net/deps.py (+4/-1) curtin/swap.py (+79/-5) debian/changelog (+44/-0) dev/null (+0/-7) doc/topics/config.rst (+58/-1) examples/tests/basic.yaml (+4/-0) examples/tests/basic_scsi.yaml (+4/-0) examples/tests/network_v2_ovs.yaml (+3/-32) examples/tests/nvme_bcache.yaml (+2/-4) examples/tests/preserve-partition-wipe-vg.yaml (+0/-1) examples/tests/raid5boot.yaml (+1/-1) helpers/common (+0/-578) requirements.txt (+3/-0) tests/data/multipath-nvme.txt (+1/-0) tests/unittests/helpers.py (+18/-0) tests/unittests/test_block.py (+12/-0) tests/unittests/test_block_multipath.py (+14/-0) tests/unittests/test_commands_block_meta.py (+145/-5) tests/unittests/test_curthooks.py (+340/-52) tests/unittests/test_distro.py (+27/-6) tests/unittests/test_feature.py (+6/-0) tests/vmtests/__init__.py (+100/-22) tests/vmtests/releases.py (+9/-0) tests/vmtests/test_apt_config_cmd.py (+5/-1) tests/vmtests/test_basic.py (+23/-10) tests/vmtests/test_basic_dasd.py (+2/-2) tests/vmtests/test_bcache_basic.py (+2/-2) tests/vmtests/test_bcache_bug1718699.py (+2/-2) tests/vmtests/test_bcache_ceph.py (+6/-2) tests/vmtests/test_bcache_partitions.py (+2/-2) tests/vmtests/test_fs_battery.py (+2/-2) tests/vmtests/test_iscsi.py (+2/-2) tests/vmtests/test_journald_reporter.py (+2/-2) tests/vmtests/test_lvm.py (+2/-2) tests/vmtests/test_lvm_iscsi.py (+2/-2) tests/vmtests/test_lvm_raid.py (+4/-4) tests/vmtests/test_lvm_root.py (+17/-4) tests/vmtests/test_mdadm_bcache.py (+39/-30) tests/vmtests/test_mdadm_iscsi.py (+2/-2) tests/vmtests/test_multipath.py (+2/-2) tests/vmtests/test_multipath_lvm.py (+7/-2) tests/vmtests/test_network.py (+2/-2) tests/vmtests/test_network_alias.py (+2/-2) tests/vmtests/test_network_bonding.py (+2/-2) tests/vmtests/test_network_bridging.py (+2/-2) tests/vmtests/test_network_disabled.py (+17/-0) tests/vmtests/test_network_ipv6.py (+5/-1) tests/vmtests/test_network_ipv6_static.py (+2/-2) tests/vmtests/test_network_ipv6_vlan.py (+6/-6) tests/vmtests/test_network_mtu.py (+7/-15) tests/vmtests/test_network_ovs.py (+2/-3) tests/vmtests/test_network_static.py (+2/-2) tests/vmtests/test_network_static_routes.py (+4/-4) tests/vmtests/test_network_vlan.py (+3/-4) tests/vmtests/test_nvme.py (+3/-4) tests/vmtests/test_panic.py (+5/-0) tests/vmtests/test_pollinate_useragent.py (+2/-2) tests/vmtests/test_preserve.py (+2/-2) tests/vmtests/test_preserve_bcache.py (+2/-2) tests/vmtests/test_preserve_lvm.py (+2/-2) tests/vmtests/test_preserve_partition_wipe_vg.py (+5/-4) tests/vmtests/test_preserve_raid.py (+2/-2) tests/vmtests/test_raid5_bcache.py (+5/-5) tests/vmtests/test_reuse_lvm_member.py (+4/-4) tests/vmtests/test_reuse_msdos_partitions.py (+4/-4) tests/vmtests/test_reuse_raid_member.py (+6/-6) tests/vmtests/test_reuse_uefi_esp.py (+10/-10) tests/vmtests/test_simple.py (+11/-4) tests/vmtests/test_uefi_basic.py (+9/-4) tests/vmtests/test_zfsroot.py (+4/-5) tools/curtainer (+43/-7) tools/jenkins-runner (+14/-2) tools/run-pep8 (+1/-1) tools/vmtest-remove-release (+1/-1) |
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Server Team CI bot | continuous-integration | Approve | |
Ryan Harper (community) | Approve | ||
Review via email: mp+390692@code.launchpad.net |
Commit message
releasing curtin version 20.1-29-
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 : | # |
PASSED: Continuous integration, rev:602618759f4
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
review:
Approve
(continuous-integration)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/Makefile b/Makefile |
2 | index 68a3ad3..187132c 100644 |
3 | --- a/Makefile |
4 | +++ b/Makefile |
5 | @@ -9,7 +9,7 @@ ifeq ($(COVERAGE), 1) |
6 | endif |
7 | CURTIN_VMTEST_IMAGE_SYNC ?= False |
8 | export CURTIN_VMTEST_IMAGE_SYNC |
9 | -noseopts ?= -vv --nologcapture |
10 | +noseopts ?= -vv |
11 | pylintopts ?= --rcfile=pylintrc --errors-only |
12 | target_dirs ?= curtin tests tools |
13 | |
14 | diff --git a/curtin/__init__.py b/curtin/__init__.py |
15 | index 2e1a0ed..092020b 100644 |
16 | --- a/curtin/__init__.py |
17 | +++ b/curtin/__init__.py |
18 | @@ -8,6 +8,8 @@ KERNEL_CMDLINE_COPY_TO_INSTALL_SEP = "---" |
19 | # can determine which features are supported. Each entry should have |
20 | # a consistent meaning. |
21 | FEATURES = [ |
22 | + # curtin supports creating swapfiles on btrfs, if possible |
23 | + 'BTRFS_SWAPFILE', |
24 | # curtin can apply centos networking via centos_apply_network_config |
25 | 'CENTOS_APPLY_NETWORK_CONFIG', |
26 | # curtin can configure centos storage devices and boot devices |
27 | @@ -32,6 +34,8 @@ FEATURES = [ |
28 | 'APT_CONFIG_V1', |
29 | # has version module |
30 | 'HAS_VERSION_MODULE', |
31 | + # uefi_reoder has fallback support if BootCurrent is missing |
32 | + 'UEFI_REORDER_FALLBACK_SUPPORT', |
33 | ] |
34 | |
35 | __version__ = "20.1" |
36 | diff --git a/curtin/block/__init__.py b/curtin/block/__init__.py |
37 | index 35e3a64..10b8b9e 100644 |
38 | --- a/curtin/block/__init__.py |
39 | +++ b/curtin/block/__init__.py |
40 | @@ -1,5 +1,5 @@ |
41 | # This file is part of curtin. See LICENSE file for copyright and license info. |
42 | - |
43 | +import re |
44 | from contextlib import contextmanager |
45 | import errno |
46 | import itertools |
47 | @@ -67,6 +67,19 @@ def dev_path(devname): |
48 | return '/dev/' + devname |
49 | |
50 | |
51 | +def md_path(mdname): |
52 | + """ Convert device name to path in /dev/md """ |
53 | + full_mdname = dev_path(mdname) |
54 | + if full_mdname.startswith('/dev/md/'): |
55 | + return full_mdname |
56 | + elif re.match(r'/dev/md\d+$', full_mdname): |
57 | + return full_mdname |
58 | + elif '/' in mdname: |
59 | + raise ValueError("Invalid RAID device name: {}".format(mdname)) |
60 | + else: |
61 | + return '/dev/md/{}'.format(mdname) |
62 | + |
63 | + |
64 | def path_to_kname(path): |
65 | """ |
66 | converts a path in /dev or a path in /sys/block to the device kname, |
67 | @@ -840,6 +853,8 @@ def _get_dev_disk_by_prefix(prefix): |
68 | '/dev/sda1': '/dev/disk/<prefix>/virtio-aaaa-part1', |
69 | } |
70 | """ |
71 | + if not os.path.exists(prefix): |
72 | + return {} |
73 | return { |
74 | os.path.realpath(bypfx): bypfx |
75 | for bypfx in [os.path.join(prefix, path) |
76 | diff --git a/curtin/block/dasd.py b/curtin/block/dasd.py |
77 | index 682f9d3..b7008f6 100644 |
78 | --- a/curtin/block/dasd.py |
79 | +++ b/curtin/block/dasd.py |
80 | @@ -269,9 +269,9 @@ def _valid_device_id(device_id): |
81 | if not (0 <= int(dsn, 16) < 256): |
82 | raise ValueError("device_id invalid: dsn not in 0-255: '%s'" % dsn) |
83 | |
84 | - if not (0 <= int(dev.lower(), 16) < 65535): |
85 | + if not (0 <= int(dev.lower(), 16) <= 65535): |
86 | raise ValueError( |
87 | - "device_id invalid: devno not in 0-0x10000: '%s'" % dev) |
88 | + "device_id invalid: devno not in 0-0xffff: '%s'" % dev) |
89 | |
90 | return True |
91 | |
92 | diff --git a/curtin/block/multipath.py b/curtin/block/multipath.py |
93 | index 9c7f510..7ad1791 100644 |
94 | --- a/curtin/block/multipath.py |
95 | +++ b/curtin/block/multipath.py |
96 | @@ -7,7 +7,7 @@ from curtin import udev |
97 | SHOW_PATHS_FMT = ("device='%d' serial='%z' multipath='%m' host_wwpn='%N' " |
98 | "target_wwnn='%n' host_wwpn='%R' target_wwpn='%r' " |
99 | "host_adapter='%a'") |
100 | -SHOW_MAPS_FMT = "name=%n multipath='%w' sysfs='%d' paths='%N'" |
101 | +SHOW_MAPS_FMT = "name='%n' multipath='%w' sysfs='%d' paths='%N'" |
102 | |
103 | |
104 | def _extract_mpath_data(cmd, show_verb): |
105 | diff --git a/curtin/commands/block_meta.py b/curtin/commands/block_meta.py |
106 | index ff0f2e9..dee73b1 100644 |
107 | --- a/curtin/commands/block_meta.py |
108 | +++ b/curtin/commands/block_meta.py |
109 | @@ -502,7 +502,7 @@ def get_path_to_storage_volume(volume, storage_config): |
110 | elif vol.get('type') == "raid": |
111 | # For raid partitions, block device is at /dev/mdX |
112 | name = vol.get('name') |
113 | - volume_path = os.path.join("/dev", name) |
114 | + volume_path = block.md_path(name) |
115 | |
116 | elif vol.get('type') == "bcache": |
117 | # For bcache setups, the only reliable way to determine the name of the |
118 | @@ -1485,7 +1485,7 @@ def raid_handler(info, storage_config): |
119 | devices = info.get('devices') |
120 | raidlevel = info.get('raidlevel') |
121 | spare_devices = info.get('spare_devices') |
122 | - md_devname = block.dev_path(info.get('name')) |
123 | + md_devname = block.md_path(info.get('name')) |
124 | preserve = config.value_as_boolean(info.get('preserve')) |
125 | if not devices: |
126 | raise ValueError("devices for raid must be specified") |
127 | @@ -1744,7 +1744,12 @@ def get_device_paths_from_storage_config(storage_config): |
128 | dpaths = [] |
129 | for (k, v) in storage_config.items(): |
130 | if v.get('type') in ['disk', 'partition']: |
131 | - if config.value_as_boolean(v.get('wipe')): |
132 | + wipe = config.value_as_boolean(v.get('wipe')) |
133 | + preserve = config.value_as_boolean(v.get('preserve')) |
134 | + if v.get('type') == 'disk' and all([wipe, preserve]): |
135 | + msg = 'type:disk id=%s has both wipe and preserve' % v['id'] |
136 | + raise RuntimeError(msg) |
137 | + if wipe: |
138 | try: |
139 | # skip paths that do not exit, nothing to wipe |
140 | dpath = get_path_to_storage_volume(k, storage_config) |
141 | diff --git a/curtin/commands/curthooks.py b/curtin/commands/curthooks.py |
142 | index d66afa7..4cf7301 100644 |
143 | --- a/curtin/commands/curthooks.py |
144 | +++ b/curtin/commands/curthooks.py |
145 | @@ -85,6 +85,8 @@ do_initrd = yes |
146 | link_in_boot = {inboot} |
147 | """ |
148 | |
149 | +UEFI_BOOT_ENTRY_IS_NETWORK = r'.*(Network|PXE|NIC|Ethernet|LAN|IP4|IP6)+.*' |
150 | + |
151 | |
152 | def do_apt_config(cfg, target): |
153 | cfg = apt_config.translate_old_apt_features(cfg) |
154 | @@ -411,6 +413,7 @@ def install_kernel(cfg, target): |
155 | def uefi_remove_old_loaders(grubcfg, target): |
156 | """Removes the old UEFI loaders from efibootmgr.""" |
157 | efi_output = util.get_efibootmgr(target) |
158 | + LOG.debug('UEFI remove old olders efi output:\n%s', efi_output) |
159 | current_uefi_boot = efi_output.get('current', None) |
160 | old_efi_entries = { |
161 | entry: info |
162 | @@ -437,18 +440,90 @@ def uefi_remove_old_loaders(grubcfg, target): |
163 | "should be removed.", info['name']) |
164 | |
165 | |
166 | -def uefi_reorder_loaders(grubcfg, target): |
167 | +def uefi_boot_entry_is_network(boot_entry_name): |
168 | + """ |
169 | + Return boolean if boot entry name looks like a known network entry. |
170 | + """ |
171 | + return re.match(UEFI_BOOT_ENTRY_IS_NETWORK, |
172 | + boot_entry_name, re.IGNORECASE) is not None |
173 | + |
174 | + |
175 | +def _reorder_new_entry(boot_order, efi_output, efi_orig=None, variant=None): |
176 | + """ |
177 | + Reorder the EFI boot menu as follows |
178 | + |
179 | + 1. All PXE/Network boot entries |
180 | + 2. The newly installed entry variant (ubuntu/centos) |
181 | + 3. The other items in the boot order that are not in [1, 2] |
182 | + |
183 | + returns a list of bootnum strings |
184 | + """ |
185 | + |
186 | + if not boot_order: |
187 | + raise RuntimeError('boot_order is not a list') |
188 | + |
189 | + if efi_orig is None: |
190 | + raise RuntimeError('Missing efi_orig boot dictionary') |
191 | + |
192 | + if variant is None: |
193 | + variant = "" |
194 | + |
195 | + net_boot = [] |
196 | + other = [] |
197 | + target = [] |
198 | + |
199 | + LOG.debug("UEFI previous boot order: %s", efi_orig['order']) |
200 | + LOG.debug("UEFI current boot order: %s", boot_order) |
201 | + new_entries = list(set(boot_order).difference(set(efi_orig['order']))) |
202 | + if new_entries: |
203 | + LOG.debug("UEFI Found new boot entries: %s", new_entries) |
204 | + LOG.debug('UEFI Looking for installed entry variant=%s', variant.lower()) |
205 | + for bootnum in boot_order: |
206 | + entry = efi_output['entries'][bootnum] |
207 | + if uefi_boot_entry_is_network(entry['name']): |
208 | + net_boot.append(bootnum) |
209 | + else: |
210 | + if entry['name'].lower() == variant.lower(): |
211 | + target.append(bootnum) |
212 | + else: |
213 | + other.append(bootnum) |
214 | + |
215 | + if net_boot: |
216 | + LOG.debug("UEFI found netboot entries: %s", net_boot) |
217 | + if other: |
218 | + LOG.debug("UEFI found other entries: %s", other) |
219 | + if target: |
220 | + LOG.debug("UEFI found target entry: %s", target) |
221 | + else: |
222 | + LOG.debug("UEFI Did not find an entry with variant=%s", |
223 | + variant.lower()) |
224 | + new_order = net_boot + target + other |
225 | + if boot_order == new_order: |
226 | + LOG.debug("UEFI Current and Previous bootorders match") |
227 | + return new_order |
228 | + |
229 | + |
230 | +def uefi_reorder_loaders(grubcfg, target, efi_orig=None, variant=None): |
231 | """Reorders the UEFI BootOrder to place BootCurrent first. |
232 | |
233 | The specifically doesn't try to do to much. The order in which grub places |
234 | a new EFI loader is up to grub. This only moves the BootCurrent to the |
235 | front of the BootOrder. |
236 | + |
237 | + In some systems, BootCurrent may not be set/present. In this case |
238 | + curtin will attempt to place the new boot entry created when grub |
239 | + is installed after the the previous first entry (before we installed grub). |
240 | + |
241 | """ |
242 | if grubcfg.get('reorder_uefi', True): |
243 | efi_output = util.get_efibootmgr(target=target) |
244 | + LOG.debug('UEFI efibootmgr output after install:\n%s', efi_output) |
245 | currently_booted = efi_output.get('current', None) |
246 | boot_order = efi_output.get('order', []) |
247 | - if currently_booted: |
248 | + new_boot_order = None |
249 | + force_fallback_reorder = config.value_as_boolean( |
250 | + grubcfg.get('reorder_uefi_force_fallback', False)) |
251 | + if currently_booted and force_fallback_reorder is False: |
252 | if currently_booted in boot_order: |
253 | boot_order.remove(currently_booted) |
254 | boot_order = [currently_booted] + boot_order |
255 | @@ -456,6 +531,23 @@ def uefi_reorder_loaders(grubcfg, target): |
256 | LOG.debug( |
257 | "Setting currently booted %s as the first " |
258 | "UEFI loader.", currently_booted) |
259 | + else: |
260 | + reason = ( |
261 | + "config 'reorder_uefi_force_fallback' is True" if |
262 | + force_fallback_reorder else "missing 'BootCurrent' value") |
263 | + LOG.debug("Using fallback UEFI reordering: " + reason) |
264 | + if len(boot_order) < 2: |
265 | + LOG.debug( |
266 | + 'UEFI BootOrder has less than 2 entries, cannot reorder') |
267 | + return |
268 | + # look at efi entries before we added one to find the new addition |
269 | + new_order = _reorder_new_entry( |
270 | + copy.deepcopy(boot_order), efi_output, efi_orig, variant) |
271 | + if new_order != boot_order: |
272 | + new_boot_order = ','.join(new_order) |
273 | + else: |
274 | + LOG.debug("UEFI No changes to boot order.") |
275 | + if new_boot_order: |
276 | LOG.debug( |
277 | "New UEFI boot order: %s", new_boot_order) |
278 | with util.ChrootableTarget(target) as in_chroot: |
279 | @@ -465,25 +557,44 @@ def uefi_reorder_loaders(grubcfg, target): |
280 | LOG.debug("Currently booted UEFI loader might no longer boot.") |
281 | |
282 | |
283 | -def uefi_remove_duplicate_entries(grubcfg, target): |
284 | +def uefi_remove_duplicate_entries(grubcfg, target, to_remove=None): |
285 | + if not grubcfg.get('remove_duplicate_entries', True): |
286 | + LOG.debug("Skipped removing duplicate UEFI boot entries per config.") |
287 | + return |
288 | + if to_remove is None: |
289 | + to_remove = uefi_find_duplicate_entries(grubcfg, target) |
290 | + |
291 | + # check so we don't run ChrootableTarget code unless we have things to do |
292 | + if to_remove: |
293 | + with util.ChrootableTarget(target) as in_chroot: |
294 | + for bootnum, entry in to_remove: |
295 | + LOG.debug('Removing duplicate EFI entry (%s, %s)', |
296 | + bootnum, entry) |
297 | + in_chroot.subp(['efibootmgr', '--bootnum=%s' % bootnum, |
298 | + '--delete-bootnum']) |
299 | + |
300 | + |
301 | +def uefi_find_duplicate_entries(grubcfg, target, efi_output=None): |
302 | seen = set() |
303 | to_remove = [] |
304 | - efi_output = util.get_efibootmgr(target=target) |
305 | + if efi_output is None: |
306 | + efi_output = util.get_efibootmgr(target=target) |
307 | entries = efi_output.get('entries', {}) |
308 | + current_bootnum = efi_output.get('current', None) |
309 | + # adding BootCurrent to seen first allows us to remove any other duplicate |
310 | + # entry of BootCurrent. |
311 | + if current_bootnum: |
312 | + seen.add(tuple(entries[current_bootnum].items())) |
313 | for bootnum in sorted(entries): |
314 | + if bootnum == current_bootnum: |
315 | + continue |
316 | entry = entries[bootnum] |
317 | t = tuple(entry.items()) |
318 | if t not in seen: |
319 | seen.add(t) |
320 | else: |
321 | to_remove.append((bootnum, entry)) |
322 | - if to_remove: |
323 | - with util.ChrootableTarget(target) as in_chroot: |
324 | - for bootnum, entry in to_remove: |
325 | - LOG.debug('Removing duplicate EFI entry (%s, %s)', |
326 | - bootnum, entry) |
327 | - in_chroot.subp(['efibootmgr', '--bootnum=%s' % bootnum, |
328 | - '--delete-bootnum']) |
329 | + return to_remove |
330 | |
331 | |
332 | def _debconf_multiselect(package, variable, choices): |
333 | @@ -557,7 +668,7 @@ def uefi_find_grub_device_ids(sconfig): |
334 | esp_partitions.append(item_id) |
335 | continue |
336 | |
337 | - if item['type'] == 'mount' and item['path'] == '/boot/efi': |
338 | + if item['type'] == 'mount' and item.get('path') == '/boot/efi': |
339 | if primary_esp: |
340 | LOG.debug('Ignoring duplicate mounted primary ESP: %s', |
341 | item_id) |
342 | @@ -592,7 +703,7 @@ def uefi_find_grub_device_ids(sconfig): |
343 | return grub_device_ids |
344 | |
345 | |
346 | -def setup_grub(cfg, target, osfamily=DISTROS.debian): |
347 | +def setup_grub(cfg, target, osfamily=DISTROS.debian, variant=None): |
348 | # target is the path to the mounted filesystem |
349 | |
350 | # FIXME: these methods need moving to curtin.block |
351 | @@ -692,13 +803,14 @@ def setup_grub(cfg, target, osfamily=DISTROS.debian): |
352 | |
353 | update_nvram = grubcfg.get('update_nvram', True) |
354 | if uefi_bootable and update_nvram: |
355 | + efi_orig_output = util.get_efibootmgr(target) |
356 | uefi_remove_old_loaders(grubcfg, target) |
357 | |
358 | install_grub(instdevs, target, uefi=uefi_bootable, grubcfg=grubcfg) |
359 | |
360 | if uefi_bootable and update_nvram: |
361 | + uefi_reorder_loaders(grubcfg, target, efi_orig_output, variant) |
362 | uefi_remove_duplicate_entries(grubcfg, target) |
363 | - uefi_reorder_loaders(grubcfg, target) |
364 | |
365 | |
366 | def update_initramfs(target=None, all_kernels=False): |
367 | @@ -900,6 +1012,7 @@ def add_swap(cfg, target, fstab): |
368 | fname = swapcfg.get('filename', None) |
369 | size = swapcfg.get('size', None) |
370 | maxsize = swapcfg.get('maxsize', None) |
371 | + force = swapcfg.get('force', False) |
372 | |
373 | if size: |
374 | size = util.human2bytes(str(size)) |
375 | @@ -907,7 +1020,7 @@ def add_swap(cfg, target, fstab): |
376 | maxsize = util.human2bytes(str(maxsize)) |
377 | |
378 | swap.setup_swapfile(target=target, fstab=fstab, swapfile=fname, size=size, |
379 | - maxsize=maxsize) |
380 | + maxsize=maxsize, force=force) |
381 | |
382 | |
383 | def detect_and_handle_multipath(cfg, target, osfamily=DISTROS.debian): |
384 | @@ -1733,7 +1846,8 @@ def builtin_curthooks(cfg, target, state): |
385 | name=stack_prefix + '/install-grub', |
386 | reporting_enabled=True, level="INFO", |
387 | description="installing grub to target devices"): |
388 | - setup_grub(cfg, target, osfamily=osfamily) |
389 | + setup_grub(cfg, target, osfamily=osfamily, |
390 | + variant=distro_info.variant) |
391 | |
392 | |
393 | def curthooks(args): |
394 | diff --git a/curtin/commands/install_grub.py b/curtin/commands/install_grub.py |
395 | index 777aa35..5f8311f 100644 |
396 | --- a/curtin/commands/install_grub.py |
397 | +++ b/curtin/commands/install_grub.py |
398 | @@ -346,7 +346,7 @@ def install_grub(devices, target, uefi=None, grubcfg=None): |
399 | |
400 | LOG.debug("installing grub to target=%s devices=%s [replace_defaults=%s]", |
401 | target, devices, grubcfg.get('replace_default')) |
402 | - update_nvram = config.value_as_boolean(grubcfg.get('update_nvram', False)) |
403 | + update_nvram = config.value_as_boolean(grubcfg.get('update_nvram', True)) |
404 | distroinfo = distro.get_distroinfo(target=target) |
405 | target_arch = distro.get_architecture(target=target) |
406 | rhel_ver = (distro.rpm_get_dist_id(target) |
407 | diff --git a/curtin/commands/swap.py b/curtin/commands/swap.py |
408 | index f2381e6..089cd73 100644 |
409 | --- a/curtin/commands/swap.py |
410 | +++ b/curtin/commands/swap.py |
411 | @@ -40,7 +40,7 @@ def swap_main(args): |
412 | |
413 | swap.setup_swapfile(target=state['target'], fstab=state['fstab'], |
414 | swapfile=args.swapfile, size=size, |
415 | - maxsize=args.maxsize) |
416 | + maxsize=args.maxsize, force=args.force) |
417 | sys.exit(2) |
418 | |
419 | |
420 | @@ -54,6 +54,9 @@ CMD_ARGUMENTS = ( |
421 | 'default is env[TARGET_MOUNT_POINT]'), |
422 | 'action': 'store', 'metavar': 'TARGET', |
423 | 'default': os.environ.get('TARGET_MOUNT_POINT')}), |
424 | + (('-F', '--force'), |
425 | + {'help': 'force creating of swapfile even if it may fail (btrfs,xfs)', |
426 | + 'default': False, 'action': 'store_true'}), |
427 | (('-s', '--size'), |
428 | {'help': 'size of swap file (eg: 1G, 1500M, 1024K, 100000. def: "auto")', |
429 | 'default': None, 'action': 'store'}), |
430 | diff --git a/curtin/distro.py b/curtin/distro.py |
431 | index 43b0c19..82a4dd5 100644 |
432 | --- a/curtin/distro.py |
433 | +++ b/curtin/distro.py |
434 | @@ -264,7 +264,7 @@ def apt_update(target=None, env=None, force=False, comment=None, |
435 | |
436 | |
437 | def run_apt_command(mode, args=None, opts=None, env=None, target=None, |
438 | - execute=True, allow_daemons=False): |
439 | + execute=True, allow_daemons=False, clean=True): |
440 | defopts = ['--quiet', '--assume-yes', |
441 | '--option=Dpkg::options::=--force-unsafe-io', |
442 | '--option=Dpkg::Options::=--force-confold'] |
443 | @@ -289,7 +289,11 @@ def run_apt_command(mode, args=None, opts=None, env=None, target=None, |
444 | |
445 | apt_update(target, env=env, comment=' '.join(cmd)) |
446 | with ChrootableTarget(target, allow_daemons=allow_daemons) as inchroot: |
447 | - return inchroot.subp(cmd, env=env) |
448 | + cmd_rv = inchroot.subp(cmd, env=env) |
449 | + if clean and mode in ['dist-upgrade', 'install', 'upgrade']: |
450 | + inchroot.subp(['apt-get', 'clean']) |
451 | + |
452 | + return cmd_rv |
453 | |
454 | |
455 | def run_yum_command(mode, args=None, opts=None, env=None, target=None, |
456 | @@ -472,6 +476,7 @@ def parse_dpkg_version(raw, name=None, semx=None): |
457 | as the upstream version. |
458 | |
459 | returns a dictionary with fields: |
460 | + 'epoch' |
461 | 'major' (int), 'minor' (int), 'micro' (int), |
462 | 'semantic_version' (int), |
463 | 'extra' (string), 'raw' (string), 'upstream' (string), |
464 | @@ -484,12 +489,20 @@ def parse_dpkg_version(raw, name=None, semx=None): |
465 | if semx is None: |
466 | semx = (10000, 100, 1) |
467 | |
468 | - if "-" in raw: |
469 | - upstream = raw.rsplit('-', 1)[0] |
470 | + raw_offset = 0 |
471 | + if ':' in raw: |
472 | + epoch, _, upstream = raw.partition(':') |
473 | + raw_offset = len(epoch) + 1 |
474 | else: |
475 | - # this is a native package, package version treated as upstream. |
476 | + epoch = 0 |
477 | upstream = raw |
478 | |
479 | + if "-" in raw[raw_offset:]: |
480 | + upstream = raw[raw_offset:].rsplit('-', 1)[0] |
481 | + else: |
482 | + # this is a native package, package version treated as upstream. |
483 | + upstream = raw[raw_offset:] |
484 | + |
485 | match = re.search(r'[^0-9.]', upstream) |
486 | if match: |
487 | extra = upstream[match.start():] |
488 | @@ -498,8 +511,10 @@ def parse_dpkg_version(raw, name=None, semx=None): |
489 | upstream_base = upstream |
490 | extra = None |
491 | |
492 | - toks = upstream_base.split(".", 2) |
493 | - if len(toks) == 3: |
494 | + toks = upstream_base.split(".", 3) |
495 | + if len(toks) == 4: |
496 | + major, minor, micro, extra = toks |
497 | + elif len(toks) == 3: |
498 | major, minor, micro = toks |
499 | elif len(toks) == 2: |
500 | major, minor, micro = (toks[0], toks[1], 0) |
501 | @@ -507,6 +522,7 @@ def parse_dpkg_version(raw, name=None, semx=None): |
502 | major, minor, micro = (toks[0], 0, 0) |
503 | |
504 | version = { |
505 | + 'epoch': int(epoch), |
506 | 'major': int(major), |
507 | 'minor': int(minor), |
508 | 'micro': int(micro), |
509 | diff --git a/curtin/net/deps.py b/curtin/net/deps.py |
510 | index f912d1d..b78654d 100644 |
511 | --- a/curtin/net/deps.py |
512 | +++ b/curtin/net/deps.py |
513 | @@ -34,10 +34,13 @@ def network_config_required_packages(network_config, mapping=None): |
514 | if cfgtype == 'version': |
515 | continue |
516 | dev_configs.add(cfgtype) |
517 | - # the renderer type may trigger package adds |
518 | + # subkeys under the type may trigger package adds |
519 | for entry, entry_cfg in cfg.items(): |
520 | if entry_cfg.get('renderer'): |
521 | dev_configs.add(entry_cfg.get('renderer')) |
522 | + else: |
523 | + for sub_entry, sub_cfg in entry_cfg.items(): |
524 | + dev_configs.add(sub_entry) |
525 | |
526 | needed_packages = [] |
527 | for dev_type in dev_configs: |
528 | diff --git a/curtin/swap.py b/curtin/swap.py |
529 | index d3f29dc..11e95c4 100644 |
530 | --- a/curtin/swap.py |
531 | +++ b/curtin/swap.py |
532 | @@ -5,6 +5,8 @@ import resource |
533 | |
534 | from .log import LOG |
535 | from . import util |
536 | +from curtin import paths |
537 | +from curtin import distro |
538 | |
539 | |
540 | def suggested_swapsize(memsize=None, maxsize=None, fsys=None): |
541 | @@ -51,7 +53,62 @@ def suggested_swapsize(memsize=None, maxsize=None, fsys=None): |
542 | return maxsize |
543 | |
544 | |
545 | -def setup_swapfile(target, fstab=None, swapfile=None, size=None, maxsize=None): |
546 | +def get_fstype(target, source): |
547 | + target_source = paths.target_path(target, source) |
548 | + try: |
549 | + out, _ = util.subp(['findmnt', '--noheading', '--target', |
550 | + target_source, '-o', 'FSTYPE'], capture=True) |
551 | + except util.ProcessExecutionError as exc: |
552 | + LOG.warning('Failed to query %s fstype, findmnt returned error: %s', |
553 | + target_source, exc) |
554 | + return None |
555 | + |
556 | + if out: |
557 | + """ |
558 | + $ findmnt --noheading --target /btrfs -o FSTYPE |
559 | + btrfs |
560 | + """ |
561 | + return out.splitlines()[-1] |
562 | + |
563 | + return None |
564 | + |
565 | + |
566 | +def get_target_kernel_version(target): |
567 | + pkg_ver = None |
568 | + |
569 | + distro_info = distro.get_distroinfo(target=target) |
570 | + if not distro_info: |
571 | + raise RuntimeError('Failed to determine target distro') |
572 | + osfamily = distro_info.family |
573 | + if osfamily == distro.DISTROS.debian: |
574 | + try: |
575 | + # check in-target version |
576 | + pkg_ver = distro.get_package_version('linux-image-generic', |
577 | + target=target) |
578 | + except Exception as e: |
579 | + LOG.warn( |
580 | + "failed reading linux-image-generic package version, %s", e) |
581 | + return pkg_ver |
582 | + |
583 | + |
584 | +def can_use_swapfile(target, fstype): |
585 | + if fstype is None: |
586 | + raise RuntimeError( |
587 | + 'Unknown target filesystem type, may not support swapfiles') |
588 | + if fstype in ['btrfs', 'xfs']: |
589 | + # check kernel version |
590 | + pkg_ver = get_target_kernel_version(target) |
591 | + if not pkg_ver: |
592 | + raise RuntimeError('Failed to read target kernel version') |
593 | + if fstype == 'btrfs' and pkg_ver['major'] < 5: |
594 | + raise RuntimeError( |
595 | + 'btrfs requiers kernel version 5.0+ to use swapfiles') |
596 | + elif fstype in ['zfs']: |
597 | + raise RuntimeError('ZFS cannot use swapfiles') |
598 | + |
599 | + |
600 | +def setup_swapfile(target, fstab=None, swapfile=None, size=None, maxsize=None, |
601 | + force=False): |
602 | if size is None: |
603 | size = suggested_swapsize(fsys=target, maxsize=maxsize) |
604 | |
605 | @@ -65,6 +122,24 @@ def setup_swapfile(target, fstab=None, swapfile=None, size=None, maxsize=None): |
606 | if not swapfile.startswith("/"): |
607 | swapfile = "/" + swapfile |
608 | |
609 | + # query the directory in which swapfile will reside |
610 | + fstype = get_fstype(target, os.path.dirname(swapfile)) |
611 | + try: |
612 | + can_use_swapfile(target, fstype) |
613 | + except RuntimeError as err: |
614 | + if force: |
615 | + LOG.warning('swapfile may not work: %s', err) |
616 | + else: |
617 | + LOG.debug('Not creating swap: %s', err) |
618 | + return |
619 | + |
620 | + allocate_cmd = 'fallocate -l "${2}M" "$1"' |
621 | + # fallocate uses IOCTLs to allocate space in a filesystem, however it's not |
622 | + # clear (from curtin's POV) that it creates non-sparse files as required by |
623 | + # mkswap so we'll skip fallocate for now and use dd. |
624 | + if fstype in ['btrfs', 'xfs']: |
625 | + allocate_cmd = 'dd if=/dev/zero "of=$1" bs=1M "count=$2"' |
626 | + |
627 | mbsize = str(int(size / (2 ** 20))) |
628 | msg = "creating swap file '%s' of %sMB" % (swapfile, mbsize) |
629 | fpath = os.path.sep.join([target, swapfile]) |
630 | @@ -73,10 +148,9 @@ def setup_swapfile(target, fstab=None, swapfile=None, size=None, maxsize=None): |
631 | with util.LogTimer(LOG.debug, msg): |
632 | util.subp( |
633 | ['sh', '-c', |
634 | - ('rm -f "$1" && umask 0066 && ' |
635 | - '{ fallocate -l "${2}M" "$1" || ' |
636 | - ' dd if=/dev/zero "of=$1" bs=1M "count=$2"; } && ' |
637 | - 'mkswap "$1" || { r=$?; rm -f "$1"; exit $r; }'), |
638 | + ('rm -f "$1" && umask 0066 && truncate -s 0 "$1" && ' |
639 | + '{ chattr +C "$1" || true; } && ') + allocate_cmd + |
640 | + (' && mkswap "$1" || { r=$?; rm -f "$1"; exit $r; }'), |
641 | 'setup_swap', fpath, mbsize]) |
642 | except Exception: |
643 | LOG.warn("failed %s" % msg) |
644 | diff --git a/debian/changelog b/debian/changelog |
645 | index e1a75e1..265d939 100644 |
646 | --- a/debian/changelog |
647 | +++ b/debian/changelog |
648 | @@ -1,3 +1,47 @@ |
649 | +curtin (20.1-29-g81144052-0ubuntu1) groovy; urgency=medium |
650 | + |
651 | + * New upstream snapshot. |
652 | + - vmtest: Fix multiple issues with vmtest on master |
653 | + - Refactor uefi_remove_duplicates into find/remove functions for reuse |
654 | + - distro: run apt-get clean after dist-upgrade, install, upgrade |
655 | + - curthooks: UEFI remove dupes: don't remove BootCurrent, config option |
656 | + (LP: #1894217) |
657 | + - Pin the dependency on pyrsistent [Paride Legovini] |
658 | + - restore default of grub.update_nvram to True in install_grub |
659 | + [Michael Hudson-Doyle] |
660 | + - block: disk_to_byid_path handle missing /dev/disk/by-id directory |
661 | + (LP: #1876258) |
662 | + - UEFI: Handle missing BootCurrent entry when reordering UEFI entries |
663 | + (LP: #1789650) |
664 | + - dasd: fix off-by-one device_id devno range check [Paride Legovini] |
665 | + - curthooks: uefi_find_grub_device_ids handle type:mount without path |
666 | + (LP: #1892242) |
667 | + - netplan openvswitch yaml changed (LP: #1891608) |
668 | + - tools/curtainer: do not wait for snapd.seeded.service |
669 | + - tools/curtainer: enable using ubuntu-minimal images |
670 | + - vmtests: add Groovy [Paride Legovini] |
671 | + - Drop the Eoan vmtests (EOL) [Paride Legovini] |
672 | + - tools: rename remove-vmtest-release to vmtest-remove-release |
673 | + - Snooze the tests failing because of LP: #1861941 for two more months |
674 | + [Paride Legovini] |
675 | + - LP: #1671951 is Fix Released => Drop the PPA [Paride Legovini] |
676 | + - swaps: handle swapfiles on btrfs (LP: #1884161) |
677 | + - curtainer: fail is masking of zfs-mount or zfs-share fails |
678 | + [Paride Legovini] |
679 | + - multipath: handle multipath nvme name fields correctly (LP: #1878041) |
680 | + - curtainer: mask the zfs-mount and zfs-share services [Paride Legovini] |
681 | + - tools/jenkins-runner: shuffle test-cases to randomize load |
682 | + [Paride Legovini] |
683 | + - Add Trusty/UEFI/HWE-X vmtest, drop realpath add, drop shell code |
684 | + - LP: #1881977 - Install realpath on Trusty UEFI. [Lee Trager] |
685 | + - vmtests: fix PreservePartitionWipeVg storage config |
686 | + - Fix mdraid name creates broken configuration |
687 | + [James Falcon] (LP: #1803933) |
688 | + - vmtests: update skiptests |
689 | + - vmtest: allow installed centos images to reboot (LP: #1881011) |
690 | + |
691 | + -- Paride Legovini <paride.legovini@canonical.com> Mon, 14 Sep 2020 17:53:15 +0200 |
692 | + |
693 | curtin (20.1-0ubuntu1) groovy; urgency=medium |
694 | |
695 | * New upstream release. |
696 | diff --git a/doc/topics/config.rst b/doc/topics/config.rst |
697 | index 72cd683..ec8a109 100644 |
698 | --- a/doc/topics/config.rst |
699 | +++ b/doc/topics/config.rst |
700 | @@ -226,6 +226,42 @@ not provided, Curtin will set the value to 'console'. If the ``terminal`` |
701 | value is 'unmodified' then Curtin will not set any value at all and will |
702 | use Grub defaults. |
703 | |
704 | +**reorder_uefi**: *<boolean: default True>* |
705 | + |
706 | +Curtin is typically used with MAAS where the systems are configured to boot |
707 | +from the network leaving MAAS in control. On UEFI systems, after installing |
708 | +a bootloader the systems BootOrder may be updated to boot from the new entry. |
709 | +This breaks MAAS control over the system as all subsequent reboots of the node |
710 | +will no longer boot over the network. Therefore, if ``reorder_uefi`` is True |
711 | +curtin will modify the UEFI BootOrder settings to place the currently booted |
712 | +entry (BootCurrent) to the first option after installing the new target OS into |
713 | +the UEFI boot menu. The result is that the system will boot from the same |
714 | +device that it booted to run curtin; for MAAS this will be a network device. |
715 | + |
716 | +On some UEFI systems the BootCurrent entry may not be present. This can |
717 | +cause a system to not boot to the same device that it was previously booting. |
718 | +If BootCurrent is not present, curtin will update the BootOrder such that |
719 | +all Network related entries are placed before the newly installed boot entry and |
720 | +all other entries are placed at the end. This enables the system to network |
721 | +boot first and on failure will boot the most recently installed entry. |
722 | + |
723 | +This setting is ignored if *update_nvram* is False. |
724 | + |
725 | +**reorder_uefi_force_fallback**: *<boolean: default False>* |
726 | + |
727 | +The fallback reodering mechanism is only active if BootCurrent is not present |
728 | +in the efibootmgr output. The fallback reordering method may be enabled |
729 | +even if BootCurrent is present if *reorder_uefi_force_fallback* is True. |
730 | + |
731 | +This setting is ignored if *update_nvram* or *reorder_uefi* are False. |
732 | + |
733 | +**remove_duplicate_entries**: <*boolean: default True>* |
734 | + |
735 | +When curtin updates UEFI NVRAM it will remove duplicate entries that are |
736 | +present in the UEFI menu. If you do not wish for curtin to remove duplicate |
737 | +entries setting *remove_duplicate_entries* to False. |
738 | + |
739 | +This setting is ignored if *update_nvram* is False. |
740 | |
741 | **Example**:: |
742 | |
743 | @@ -235,6 +271,7 @@ use Grub defaults. |
744 | replace_linux_default: False |
745 | update_nvram: True |
746 | terminal: serial |
747 | + remove_duplicate_entries: True |
748 | |
749 | **Default terminal value, GRUB_TERMINAL=console**:: |
750 | |
751 | @@ -264,6 +301,12 @@ use Grub defaults. |
752 | probe_additional_os: True |
753 | terminal: unmodified |
754 | |
755 | +**Enable Fallback UEFI Reordering**:: |
756 | + |
757 | + grub: |
758 | + reorder_uefi: true |
759 | + reorder_uefi_force_fallback: true |
760 | + |
761 | |
762 | http_proxy |
763 | ~~~~~~~~~~ |
764 | @@ -752,13 +795,27 @@ Configure the max size of the swapfile, defaults to 8GB |
765 | Configure the exact size of the swapfile. Setting ``size`` to 0 will |
766 | disable swap. |
767 | |
768 | +**force**: *<boolean>* |
769 | + |
770 | +Force the creation of swapfile even if curtin detects it may not work. |
771 | +In some target filesystems, e.g. btrfs, xfs, zfs, the use of a swap file has |
772 | +restrictions. If curtin detects that there may be issues it will refuse |
773 | +to create the swapfile. Users can force creation of a swapfile by passing |
774 | +``force: true``. A forced swapfile may not be used by the target OS and could |
775 | +log cause an error. |
776 | + |
777 | **Example**:: |
778 | |
779 | swap: |
780 | filename: swap.img |
781 | - size: None |
782 | + size: 1GB |
783 | maxsize: 4GB |
784 | |
785 | + swap: |
786 | + filename: btrfs_swapfile.img |
787 | + size: 1GB |
788 | + force: true |
789 | + |
790 | |
791 | system_upgrade |
792 | ~~~~~~~~~~~~~~ |
793 | diff --git a/examples/tests/basic.yaml b/examples/tests/basic.yaml |
794 | index 71730c0..82f5ad1 100644 |
795 | --- a/examples/tests/basic.yaml |
796 | +++ b/examples/tests/basic.yaml |
797 | @@ -1,4 +1,8 @@ |
798 | showtrace: true |
799 | +swap: |
800 | + filename: /btrfs/btrfsswap.img |
801 | + size: 1GB |
802 | + maxsize: 1GB |
803 | storage: |
804 | version: 1 |
805 | config: |
806 | diff --git a/examples/tests/basic_scsi.yaml b/examples/tests/basic_scsi.yaml |
807 | index 51f5236..fd28bbe 100644 |
808 | --- a/examples/tests/basic_scsi.yaml |
809 | +++ b/examples/tests/basic_scsi.yaml |
810 | @@ -1,4 +1,8 @@ |
811 | showtrace: true |
812 | +swap: |
813 | + filename: /btrfs/btrfsswap.img |
814 | + size: 1GB |
815 | + maxsize: 1GB |
816 | storage: |
817 | version: 1 |
818 | config: |
819 | diff --git a/examples/tests/network_v2_ovs.yaml b/examples/tests/network_v2_ovs.yaml |
820 | index 6d1dc3d..0d063ce 100644 |
821 | --- a/examples/tests/network_v2_ovs.yaml |
822 | +++ b/examples/tests/network_v2_ovs.yaml |
823 | @@ -8,35 +8,6 @@ network: |
824 | match: |
825 | macaddress: '52:54:00:12:34:00' |
826 | set-name: eth0 |
827 | - eth1: |
828 | - match: |
829 | - macaddress: '52:54:00:12:34:02' |
830 | - set-name: eth1 |
831 | - eth2: |
832 | - match: |
833 | - macaddress: '52:54:00:12:34:04' |
834 | - set-name: eth2 |
835 | - openvswitch: |
836 | - bridges: |
837 | - br-int: |
838 | - fail-mode: secure |
839 | - datapath_type: system |
840 | - stp: false |
841 | - rstp: false |
842 | - mcast-snooping: false |
843 | - controller: |
844 | - addresses: |
845 | - - tcp:127.0.0.1:6653 |
846 | - protocols: |
847 | - - OpenFlow10 |
848 | - - OpenFlow12 |
849 | - - OpenFlow13 |
850 | - ports: |
851 | - patch-tun: |
852 | - type: patch |
853 | - options: |
854 | - peer: patch-int |
855 | - eth1: |
856 | - tag: 2 |
857 | - eth2: |
858 | - tag: 2 |
859 | + bridges: |
860 | + br-empty: |
861 | + openvswitch: {} |
862 | diff --git a/examples/tests/nvme_bcache.yaml b/examples/tests/nvme_bcache.yaml |
863 | index 4fefd94..ed705c4 100644 |
864 | --- a/examples/tests/nvme_bcache.yaml |
865 | +++ b/examples/tests/nvme_bcache.yaml |
866 | @@ -1,8 +1,7 @@ |
867 | showtrace: true |
868 | storage: |
869 | config: |
870 | - - grub_device: true |
871 | - id: sda |
872 | + - id: sda |
873 | model: LOGICAL VOLUME |
874 | name: sda |
875 | ptable: gpt |
876 | @@ -23,7 +22,7 @@ storage: |
877 | type: disk |
878 | wipe: superblock |
879 | - device: sda |
880 | - flag: boot |
881 | + grub_device: true |
882 | id: sda-part1 |
883 | name: sda-part1 |
884 | number: 1 |
885 | @@ -33,7 +32,6 @@ storage: |
886 | uuid: 9f0fda16-c096-4cee-82ac-4f5f294253a2 |
887 | wipe: superblock |
888 | - device: sda |
889 | - flag: boot |
890 | id: sda-part2 |
891 | name: sda-part2 |
892 | number: 2 |
893 | diff --git a/examples/tests/preserve-partition-wipe-vg.yaml b/examples/tests/preserve-partition-wipe-vg.yaml |
894 | index 97686e1..27a4235 100644 |
895 | --- a/examples/tests/preserve-partition-wipe-vg.yaml |
896 | +++ b/examples/tests/preserve-partition-wipe-vg.yaml |
897 | @@ -38,7 +38,6 @@ storage: |
898 | grub_device: true |
899 | type: disk |
900 | id: disk-sda |
901 | - wipe: superblock |
902 | - serial: disk-b |
903 | name: disk-b |
904 | grub_device: false |
905 | diff --git a/examples/tests/raid5boot.yaml b/examples/tests/raid5boot.yaml |
906 | index b1df21d..d8afe7f 100644 |
907 | --- a/examples/tests/raid5boot.yaml |
908 | +++ b/examples/tests/raid5boot.yaml |
909 | @@ -42,7 +42,7 @@ storage: |
910 | size: 3GB |
911 | device: sdc |
912 | - id: mddevice |
913 | - name: md0 |
914 | + name: os-raid1 |
915 | type: raid |
916 | raidlevel: 5 |
917 | devices: |
918 | diff --git a/helpers/common b/helpers/common |
919 | index 5638d39..4afb6a1 100644 |
920 | --- a/helpers/common |
921 | +++ b/helpers/common |
922 | @@ -29,19 +29,6 @@ EOF |
923 | [ $# -eq 0 ] || echo "$@" |
924 | } |
925 | |
926 | -grub_install_usage() { |
927 | - cat <<EOF |
928 | -Usage: ${0##*/} [ options ] mount-point target-dev |
929 | - |
930 | - perform grub-install with mount-point onto target-dev. |
931 | - |
932 | - options: |
933 | - --uefi install grub-efi instead of grub-pc |
934 | - --update-nvram request grub to update nvram |
935 | -EOF |
936 | - [ $# -eq 0 ] || echo "$@" |
937 | -} |
938 | - |
939 | cleanup() { |
940 | if [ -d "$TEMP_D" ]; then |
941 | rm -Rf "$TEMP_D" |
942 | @@ -480,569 +467,4 @@ getsize() { |
943 | fi |
944 | } |
945 | |
946 | -is_md() { |
947 | - case "${1##*/}" in |
948 | - md[0-9]) return 0;; |
949 | - esac |
950 | - return 1 |
951 | -} |
952 | - |
953 | -get_carryover_params() { |
954 | - local cmdline=" $1 " extra="" lead="" carry_extra="" carry_lead="" |
955 | - # return a string to append to installed systems boot parameters |
956 | - # it may include a '--' after a '---' |
957 | - # see LP: 1402042 for some history here. |
958 | - # this is similar to 'user-params' from d-i |
959 | - local preferred_sep="---" # KERNEL_CMDLINE_COPY_TO_INSTALL_SEP |
960 | - local legacy_sep="--" |
961 | - case "$cmdline" in |
962 | - *\ ${preferred_sep}\ *) |
963 | - extra=${cmdline#* ${preferred_sep} } |
964 | - lead=${cmdline%% ${preferred_sep} *} |
965 | - ;; |
966 | - *\ ${legacy_sep}\ *) |
967 | - extra="${cmdline#* ${legacy_sep} }" |
968 | - lead=${cmdline%% ${legacy_sep} *} |
969 | - ;; |
970 | - *) |
971 | - extra="" |
972 | - lead="$cmdline" |
973 | - ;; |
974 | - esac |
975 | - |
976 | - if [ -n "$extra" ]; then |
977 | - carry_extra=$(set -f; |
978 | - c=""; |
979 | - for p in $extra; do |
980 | - case "$p" in |
981 | - (BOOTIF=*|initrd=*|BOOT_IMAGE=*) continue;; |
982 | - esac |
983 | - c="$c $p"; |
984 | - done |
985 | - echo "${c# }" |
986 | - ) |
987 | - fi |
988 | - |
989 | - # these get copied even if they werent after the separator |
990 | - local padded=" $carry_extra " |
991 | - carry_lead=$(set -f; |
992 | - padded=" ${carry_extra} " |
993 | - c="" |
994 | - for p in $lead; do |
995 | - # skip any that are already in carry_extra |
996 | - [ "${padded#* $p }" != "$padded" ] && continue |
997 | - case "$p" in |
998 | - (console=*) c="$c $p";; |
999 | - esac |
1000 | - done |
1001 | - echo "${c# }" |
1002 | - ) |
1003 | - [ -n "${carry_lead}" -a -n "${carry_extra}" ] && |
1004 | - carry_lead="${carry_lead} " |
1005 | - _RET="${carry_lead}${carry_extra}" |
1006 | -} |
1007 | - |
1008 | -shell_config_update() { |
1009 | - # shell_config_update(file, name, value) |
1010 | - # update variable 'name' setting value to 'val' in shell syntax 'file'. |
1011 | - # if 'name' is not present, then append declaration. |
1012 | - local file="$1" name="$2" val="$3" |
1013 | - if ! [ -f "$file" ] || ! grep -q "^$name=" "$file"; then |
1014 | - debug 2 "appending to $file shell $name=\"$val\"" |
1015 | - echo "$name=\"$val\"" >> "$file" |
1016 | - return |
1017 | - fi |
1018 | - local cand="" del="" |
1019 | - for cand in "|" "," "/"; do |
1020 | - [ "${val#*${del}}" = "${val}" ] && del="$cand" && break |
1021 | - done |
1022 | - [ -n "$del" ] || { |
1023 | - error "Couldn't find a sed delimiter for '$val'"; |
1024 | - return 1; |
1025 | - } |
1026 | - |
1027 | - sed -i -e "s${del}^$name=.*${del}$name=\"$val\"${del}" "$file" || |
1028 | - { error "Failed editing '$file' to set $name=$val"; return 1; } |
1029 | - debug 2 "updated $file to set $name=\"$val\"" |
1030 | - return 0 |
1031 | -} |
1032 | - |
1033 | -apply_grub_cmdline_linux_default() { |
1034 | - local mp="$1" newargs="$2" edg="${3:-etc/default/grub}" |
1035 | - local gcld="GRUB_CMDLINE_LINUX_DEFAULT" |
1036 | - debug 1 "setting $gcld to '$newargs' in $edg" |
1037 | - shell_config_update "$mp/$edg" "$gcld" "$newargs" || { |
1038 | - error "Failed to set '$gcld=$newargs' in $edg" |
1039 | - return 1 |
1040 | - } |
1041 | -} |
1042 | - |
1043 | -get_parent_disk() { |
1044 | - # Look up the parent /dev path via sysfs. Using the partition |
1045 | - # kname (nvme0n1p1), construct a /sys/class/block path, use |
1046 | - # realpath to resolve this to an absolute path which includes |
1047 | - # the parent: |
1048 | - # /sys/devices/pci0000:00/*/*/nvme/nvme0/nvme0n1/nvme0n1p1 |
1049 | - # dirname to extract the parent, then read the 'dev' entry |
1050 | - # /sys/devices/pci0000:00/*/*/nvme/nvme0/nvme0n1/dev |
1051 | - # which contains the MAJOR:MINOR value and construct a /dev/block |
1052 | - # path which is a symbolic link that udev constructs that points |
1053 | - # to the real device name and use realpath to return the absolute path. |
1054 | - # /dev/block/259:0 -> ../nvme0n1 |
1055 | - local devpath="${1}" |
1056 | - local kname=$(basename "$devpath") |
1057 | - local syspath=$(realpath "/sys/class/block/$kname") |
1058 | - local disksyspath=$(dirname "$syspath") |
1059 | - local diskmajmin=$(cat "${disksyspath}/dev") |
1060 | - local diskdevpath=$(realpath "/dev/block/${diskmajmin}") |
1061 | - echo $diskdevpath |
1062 | -} |
1063 | - |
1064 | -install_grub() { |
1065 | - local long_opts="uefi,update-nvram,os-family:" |
1066 | - local getopt_out="" mp_efi="" |
1067 | - getopt_out=$(getopt --name "${0##*/}" \ |
1068 | - --options "" --long "${long_opts}" -- "$@") && |
1069 | - eval set -- "${getopt_out}" |
1070 | - |
1071 | - local uefi=0 update_nvram=0 os_family="" |
1072 | - |
1073 | - while [ $# -ne 0 ]; do |
1074 | - cur="$1"; next="$2"; |
1075 | - case "$cur" in |
1076 | - --os-family) os_family=${next};; |
1077 | - --uefi) uefi=$((${uefi}+1));; |
1078 | - --update-nvram) update_nvram=$((${update_nvram}+1));; |
1079 | - --) shift; break;; |
1080 | - esac |
1081 | - shift; |
1082 | - done |
1083 | - |
1084 | - [ $# -lt 2 ] && { grub_install_usage "must provide mount-point and target-dev" 1>&2; return 1; } |
1085 | - |
1086 | - local mp="$1" |
1087 | - local cmdline tmp r="" |
1088 | - shift |
1089 | - local grubdevs |
1090 | - grubdevs=( "$@" ) |
1091 | - if [ "${#grubdevs[@]}" = "1" -a "${grubdevs[0]}" = "none" ]; then |
1092 | - grubdevs=( ) |
1093 | - fi |
1094 | - debug 1 "grubdevs: [${grubdevs[@]}]" |
1095 | - |
1096 | - # find the mp device |
1097 | - local mp_dev="" fstype="" |
1098 | - mp_dev=$(awk -v "MP=$mp" '$2 == MP { print $1 }' /proc/mounts) || { |
1099 | - error "unable to determine device for mount $mp"; |
1100 | - return 1; |
1101 | - } |
1102 | - debug 1 "/proc/mounts shows $mp_dev is mounted at $mp" |
1103 | - |
1104 | - fstype=$(awk -v MP=$mp '$2 == MP { print $3 }' /proc/mounts) || { |
1105 | - error "unable to fstype for mount $mp"; |
1106 | - return 1; |
1107 | - } |
1108 | - |
1109 | - [ -z "$mp_dev" ] && { |
1110 | - error "did not find '$mp' in /proc/mounts" |
1111 | - cat /proc/mounts 1>&2 |
1112 | - return 1 |
1113 | - } |
1114 | - # check if parsed mount point is a block device |
1115 | - # error unless fstype is zfs, where entry will not point to block device. |
1116 | - if ! [ -b "$mp_dev" ] && [ "$fstype" != "zfs" ]; then |
1117 | - # error unless mp is zfs, entry doesn't point to block devs |
1118 | - error "$mp_dev ($fstype) is not a block device!"; return 1; |
1119 | - fi |
1120 | - |
1121 | - local os_variant="" |
1122 | - if [ -e "${mp}/etc/os-release" ]; then |
1123 | - os_variant=$(chroot "$mp" \ |
1124 | - /bin/sh -c 'echo $(. /etc/os-release; echo $ID)') |
1125 | - else |
1126 | - # Centos6 doesn't have os-release, so check for centos/redhat release |
1127 | - # looks like: CentOS release 6.9 (Final) |
1128 | - for rel in $(ls ${mp}/etc/*-release); do |
1129 | - os_variant=$(awk '{print tolower($1)}' $rel) |
1130 | - [ -n "$os_variant" ] && break |
1131 | - done |
1132 | - fi |
1133 | - [ $? != 0 ] && |
1134 | - { error "Failed to read ID from $mp/etc/os-release"; return 1; } |
1135 | - |
1136 | - local rhel_ver="" |
1137 | - case $os_variant in |
1138 | - debian|ubuntu) os_family="debian";; |
1139 | - centos|rhel) |
1140 | - os_family="redhat" |
1141 | - rhel_ver=$(chroot "$mp" rpm -E '%rhel') |
1142 | - ;; |
1143 | - esac |
1144 | - |
1145 | - # ensure we have both settings, family and variant are needed |
1146 | - [ -n "${os_variant}" -a -n "${os_family}" ] || |
1147 | - { error "Failed to determine os variant and family"; return 1; } |
1148 | - |
1149 | - # get target arch |
1150 | - local target_arch="" r="1" |
1151 | - case $os_family in |
1152 | - debian) |
1153 | - target_arch=$(chroot "$mp" dpkg --print-architecture) |
1154 | - r=$? |
1155 | - ;; |
1156 | - redhat) |
1157 | - target_arch=$(chroot "$mp" rpm -E '%_arch') |
1158 | - r=$? |
1159 | - ;; |
1160 | - esac |
1161 | - [ $r -eq 0 ] || { |
1162 | - error "failed to get target architecture [$r]" |
1163 | - return 1; |
1164 | - } |
1165 | - |
1166 | - # grub is not the bootloader you are looking for |
1167 | - if [ "${target_arch}" = "s390x" ]; then |
1168 | - return 0; |
1169 | - fi |
1170 | - |
1171 | - # set correct grub package |
1172 | - local grub_name="" |
1173 | - local grub_target="" |
1174 | - case "$target_arch" in |
1175 | - i386|amd64) |
1176 | - # debian |
1177 | - grub_name="grub-pc" |
1178 | - grub_target="i386-pc" |
1179 | - ;; |
1180 | - x86_64) |
1181 | - case $rhel_ver in |
1182 | - 6) grub_name="grub";; |
1183 | - 7|8) grub_name="grub2-pc";; |
1184 | - *) |
1185 | - error "Unknown rhel_ver [$rhel_ver]"; |
1186 | - return 1; |
1187 | - ;; |
1188 | - esac |
1189 | - grub_target="i386-pc" |
1190 | - ;; |
1191 | - esac |
1192 | - if [ "${target_arch#ppc64}" != "${target_arch}" ]; then |
1193 | - grub_name="grub-ieee1275" |
1194 | - grub_target="powerpc-ieee1275" |
1195 | - elif [ "$uefi" -ge 1 ]; then |
1196 | - grub_name="grub-efi-$target_arch" |
1197 | - case "$target_arch" in |
1198 | - x86_64) |
1199 | - # centos 7+, no centos6 support |
1200 | - # grub2-efi-x64 installs a signed grub bootloader while |
1201 | - # curtin uses grub2-efi-x64-modules to generate grubx64.efi. |
1202 | - # Either works just check that one of them is installed. |
1203 | - grub_name="grub2-efi-x64 grub2-efi-x64-modules" |
1204 | - grub_target="x86_64-efi" |
1205 | - ;; |
1206 | - amd64) |
1207 | - grub_target="x86_64-efi";; |
1208 | - arm64) |
1209 | - grub_target="arm64-efi";; |
1210 | - esac |
1211 | - fi |
1212 | - |
1213 | - # check that the grub package is installed |
1214 | - local r=$? |
1215 | - case $os_family in |
1216 | - debian) |
1217 | - tmp=$(chroot "$mp" dpkg-query --show \ |
1218 | - --showformat='${Status}\n' $grub_name) |
1219 | - r=$? |
1220 | - ;; |
1221 | - redhat) |
1222 | - tmp=$(chroot "$mp" rpm -q \ |
1223 | - --queryformat='install ok installed\n' $grub_name) |
1224 | - r=$? |
1225 | - ;; |
1226 | - esac |
1227 | - if [ $r -ne 0 -a $r -ne 1 ]; then |
1228 | - error "failed to check if $grub_name installed"; |
1229 | - return 1; |
1230 | - fi |
1231 | - # Check that any of the packages in $grub_name are installed. If |
1232 | - # grub_name contains multiple packages, as it does for CentOS 7+, |
1233 | - # only one package has to be installed for this to pass. |
1234 | - if ! echo $tmp | grep -q 'install ok installed'; then |
1235 | - debug 1 "$grub_name not installed, not doing anything" |
1236 | - return 1 |
1237 | - fi |
1238 | - |
1239 | - local grub_d="etc/default/grub.d" |
1240 | - # ubuntu writes to /etc/default/grub.d/50-curtin-settings.cfg |
1241 | - # to avoid tripping prompts on upgrade LP: #564853 |
1242 | - local mygrub_cfg="$grub_d/50-curtin-settings.cfg" |
1243 | - case $os_family in |
1244 | - redhat) |
1245 | - grub_d="etc/default" |
1246 | - mygrub_cfg="etc/default/grub";; |
1247 | - esac |
1248 | - [ -d "$mp/$grub_d" ] || mkdir -p "$mp/$grub_d" || |
1249 | - { error "Failed to create $grub_d"; return 1; } |
1250 | - |
1251 | - # LP: #1179940 . The 50-cloudig-settings.cfg file is written by the cloud |
1252 | - # images build and defines/override some settings. Disable it. |
1253 | - local cicfg="$grub_d/50-cloudimg-settings.cfg" |
1254 | - if [ -f "$mp/$cicfg" ]; then |
1255 | - debug 1 "moved $cicfg out of the way" |
1256 | - mv "$mp/$cicfg" "$mp/$cicfg.disabled" |
1257 | - fi |
1258 | - |
1259 | - # get the user provided / carry-over kernel arguments |
1260 | - local newargs="" |
1261 | - read cmdline < /proc/cmdline && |
1262 | - get_carryover_params "$cmdline" && newargs="$_RET" || { |
1263 | - error "Failed to get carryover parrameters from cmdline"; |
1264 | - return 1; |
1265 | - } |
1266 | - # always append rd.auto=1 for centos |
1267 | - case $os_family in |
1268 | - redhat) |
1269 | - newargs="${newargs:+${newargs} }rd.auto=1";; |
1270 | - esac |
1271 | - debug 1 "carryover command line params '$newargs'" |
1272 | - |
1273 | - if [ "${REPLACE_GRUB_LINUX_DEFAULT:-1}" != "0" ]; then |
1274 | - apply_grub_cmdline_linux_default "$mp" "$newargs" || { |
1275 | - error "Failed to apply grub cmdline." |
1276 | - return 1 |
1277 | - } |
1278 | - fi |
1279 | - |
1280 | - if [ "${DISABLE_OS_PROBER:-1}" == "1" ]; then |
1281 | - { |
1282 | - echo "# Curtin disable grub os prober that might find other OS installs." |
1283 | - echo "GRUB_DISABLE_OS_PROBER=true" |
1284 | - } >> "$mp/$mygrub_cfg" |
1285 | - fi |
1286 | - |
1287 | - if [ -n "${GRUB_TERMINAL}" ]; then |
1288 | - { |
1289 | - echo "# Curtin configured GRUB_TERMINAL value" |
1290 | - echo "GRUB_TERMINAL=${GRUB_TERMINAL}" |
1291 | - } >> "$mp/$mygrub_cfg" |
1292 | - fi |
1293 | - |
1294 | - debug 1 "processing grubdevs values for expansion if needed" |
1295 | - local short="" bd="" grubdev grubdevs_new="" |
1296 | - grubdevs_new=() |
1297 | - for grubdev in "${grubdevs[@]}"; do |
1298 | - if is_md "$grubdev"; then |
1299 | - debug 1 "$grubdev is raid, find members" |
1300 | - short=${grubdev##*/} |
1301 | - for bd in "/sys/block/$short/slaves/"/*; do |
1302 | - [ -d "$bd" ] || continue |
1303 | - bd=${bd##*/} |
1304 | - bd="/dev/${bd%[0-9]}" # FIXME: part2bd |
1305 | - debug 1 "Add dev $bd to grubdevs_new" |
1306 | - grubdevs_new[${#grubdevs_new[@]}]="$bd" |
1307 | - done |
1308 | - else |
1309 | - debug 1 "Found dev [$grubdev] add to grubdevs_new" |
1310 | - grubdevs_new[${#grubdevs_new[@]}]="$grubdev" |
1311 | - fi |
1312 | - done |
1313 | - grubdevs=( "${grubdevs_new[@]}" ) |
1314 | - debug 1 "updated grubdevs: [${grubdevs[@]}]" |
1315 | - |
1316 | - if [ "$uefi" -ge 1 ]; then |
1317 | - nvram="--no-nvram" |
1318 | - if [ "$update_nvram" -ge 1 ]; then |
1319 | - nvram="" |
1320 | - fi |
1321 | - debug 1 "number of entries in grubdevs_new: ${#grubdevs[@]}" |
1322 | - if [ "${#grubdevs_new[@]}" -eq 1 ] && [ -b "${grubdevs_new[0]}" ]; then |
1323 | - debug 1 "Found a single entry in grubdevs, ${grubdevs_new[0]}" |
1324 | - # Currently UEFI can only be pointed to one system partition. If |
1325 | - # for some reason multiple install locations are given only use the |
1326 | - # first. |
1327 | - efi_dev="${grubdevs_new[0]}" |
1328 | - debug 1 "efi_dev=[${efi_dev}]" |
1329 | - elif [ "${#grubdevs_new[@]}" -gt 1 ]; then |
1330 | - error "Only one grub device supported on UEFI!" |
1331 | - exit 1 |
1332 | - else |
1333 | - debug 1 "no storage config, parsing /proc/mounts with awk" |
1334 | - # If no storage configuration was given try to determine the system |
1335 | - # partition. |
1336 | - efi_dev=$(awk -v "MP=${mp}/boot/efi" '$2 == MP { print $1 }' /proc/mounts) |
1337 | - debug 1 "efi_dev=[${efi_dev}]" |
1338 | - [ -n "$efi_dev" ] || { |
1339 | - error "Failed to find efi device from parsing /proc/mounts" |
1340 | - return 1 |
1341 | - } |
1342 | - |
1343 | - fi |
1344 | - # The partition number of block device name need to be determined here |
1345 | - # so both getting the UEFI device from Curtin config and discovering it |
1346 | - # work. |
1347 | - efi_part_num=$(cat /sys/class/block/$(basename $efi_dev)/partition) |
1348 | - debug 1 "efi_part_num: $efi_part_num" |
1349 | - [ -n "${efi_part_num}" ] || { |
1350 | - error "Failed to determine $efi_dev partition number" |
1351 | - return 1 |
1352 | - } |
1353 | - efi_disk=$(get_parent_disk "$efi_dev") |
1354 | - debug 1 "efi_disk: [$efi_disk]" |
1355 | - [ -b "${efi_disk}" ] || { |
1356 | - error "${efi_disk} is not a valid block device" |
1357 | - return 1 |
1358 | - } |
1359 | - debug 1 "curtin uefi: installing ${grub_name} to: /boot/efi" |
1360 | - chroot "$mp" env DEBIAN_FRONTEND=noninteractive sh -exc ' |
1361 | - echo "before grub-install efiboot settings" |
1362 | - efibootmgr -v || echo "WARN: efibootmgr exited $?" |
1363 | - bootid="$4" |
1364 | - efi_disk="$5" |
1365 | - efi_part_num="$6" |
1366 | - grubpost="" |
1367 | - grubmulti="/usr/lib/grub/grub-multi-install" |
1368 | - case $bootid in |
1369 | - debian|ubuntu) |
1370 | - grubcmd="grub-install" |
1371 | - if [ -e "${grubmulti}" ]; then |
1372 | - grubcmd="${grubmulti}" |
1373 | - fi |
1374 | - dpkg-reconfigure "$1" |
1375 | - update-grub |
1376 | - ;; |
1377 | - centos|redhat|rhel) |
1378 | - grubcmd="grub2-install" |
1379 | - # RHEL uses redhat instead of the os_variant rhel for the bootid. |
1380 | - if [ "$bootid" = "rhel" ]; then |
1381 | - bootid="redhat" |
1382 | - fi |
1383 | - if [ -f /boot/efi/EFI/$bootid/grubx64.efi ]; then |
1384 | - grubpost="grub2-mkconfig -o /boot/efi/EFI/$bootid/grub.cfg" |
1385 | - else |
1386 | - grubpost="grub2-mkconfig -o /boot/grub2/grub.cfg" |
1387 | - fi |
1388 | - ;; |
1389 | - *) |
1390 | - echo "Unsupported OS: $bootid" 1>&2 |
1391 | - exit 1 |
1392 | - ;; |
1393 | - esac |
1394 | - # grub-install in 12.04 does not contain --no-nvram, --target, |
1395 | - # or --efi-directory |
1396 | - target="--target=$2" |
1397 | - no_nvram="$3" |
1398 | - efi_dir="--efi-directory=/boot/efi" |
1399 | - gi_out=$($grubcmd --help 2>&1) |
1400 | - echo "$gi_out" | grep -q -- "$no_nvram" || no_nvram="" |
1401 | - echo "$gi_out" | grep -q -- "--target" || target="" |
1402 | - echo "$gi_out" | grep -q -- "--efi-directory" || efi_dir="" |
1403 | - |
1404 | - # Do not overwrite grubx64.efi if it already exists. grub-install |
1405 | - # generates grubx64.efi and overwrites any existing binary in |
1406 | - # /boot/efi/EFI/$bootid. This binary is not signed and will cause |
1407 | - # secure boot to fail. |
1408 | - # |
1409 | - # CentOS, RHEL, Fedora ship the signed boot loader in the package |
1410 | - # grub2-efi-x64 which installs the signed boot loader to |
1411 | - # /boot/efi/EFI/$bootid/grubx64.efi. All Curtin has to do is |
1412 | - # configure the firmware. This mirrors what Anaconda does. |
1413 | - # |
1414 | - # Debian and Ubuntu come with a patched version of grub which |
1415 | - # add the install flag --uefi-secure-boot which is enabled by |
1416 | - # default. When enabled if a signed version of grub exists on |
1417 | - # the filesystem it will be copied into /boot/efi/EFI/$bootid. |
1418 | - # Stock Ubuntu images do not ship with anything in /boot. Those |
1419 | - # files are generated by installing a kernel and grub. |
1420 | - echo "Dumping /boot/efi contents" |
1421 | - find /boot/efi |
1422 | - echo "Checking for existing EFI grub entry on ESP" |
1423 | - if [ "$grubcmd" = "grub2-install" -a -f /boot/efi/EFI/$bootid/grubx64.efi ]; then |
1424 | - if [ -z "$no_nvram" ]; then |
1425 | - # UEFI firmware should be pointed to the shim if available to |
1426 | - # enable secure boot. |
1427 | - for boot_uefi in \ |
1428 | - /boot/efi/EFI/$bootid/shimx64.efi \ |
1429 | - /boot/efi/EFI/BOOT/BOOTX64.EFI \ |
1430 | - /boot/efi/EFI/$bootid/grubx64.efi; do |
1431 | - if [ -f $boot_uefi ]; then |
1432 | - break |
1433 | - fi |
1434 | - done |
1435 | - loader=$(echo ${boot_uefi##/boot/efi} | sed "s|/|\\\|g") |
1436 | - efibootmgr --create --write-signature --label $bootid \ |
1437 | - --disk $efi_disk --part $efi_part_num --loader $loader |
1438 | - rc=$? |
1439 | - [ "$rc" != "0" ] && { exit $rc; } |
1440 | - else |
1441 | - echo "skip EFI entry creation due to \"$no_nvram\" flag" |
1442 | - fi |
1443 | - else |
1444 | - echo "No previous EFI grub entry found on ESP, use $grubcmd" |
1445 | - if [ "${grubcmd}" = "${grubmulti}" ]; then |
1446 | - $grubcmd |
1447 | - else |
1448 | - $grubcmd $target $efi_dir \ |
1449 | - --bootloader-id=$bootid --recheck $no_nvram |
1450 | - fi |
1451 | - fi |
1452 | - [ -z "$grubpost" ] || $grubpost;' \ |
1453 | - -- "$grub_name" "$grub_target" "$nvram" "$os_variant" "$efi_disk" "$efi_part_num" </dev/null || |
1454 | - { error "failed to install grub!"; return 1; } |
1455 | - |
1456 | - chroot "$mp" sh -exc ' |
1457 | - echo "after grub-install efiboot settings" |
1458 | - efibootmgr -v || echo "WARN: efibootmgr exited $?" |
1459 | - ' -- </dev/null || |
1460 | - { error "failed to list efi boot entries!"; return 1; } |
1461 | - else |
1462 | - # Note: dpkg-reconfigure calls grub-install on ppc64 |
1463 | - # this means that using '--no-nvram' below ends up |
1464 | - # failing very oddly. This is because grub's post-inst |
1465 | - # runs grub-install with no target. That ends up |
1466 | - # updating nvram badly, and then the grub-install would |
1467 | - # not fix it because of the no-nvram there. |
1468 | - debug 1 "curtin non-uefi: installing ${grub_name} to: ${grubdevs[*]}" |
1469 | - chroot "$mp" env DEBIAN_FRONTEND=noninteractive sh -exc ' |
1470 | - pkg=$1; shift; |
1471 | - bootid=$1; shift; |
1472 | - bootver=$1; shift; |
1473 | - grubpost="" |
1474 | - case $bootid in |
1475 | - debian|ubuntu) |
1476 | - grubcmd="grub-install" |
1477 | - dpkg-reconfigure "$pkg" |
1478 | - update-grub |
1479 | - ;; |
1480 | - centos|redhat|rhel) |
1481 | - case $bootver in |
1482 | - 6) grubcmd="grub-install";; |
1483 | - 7|8) grubcmd="grub2-install" |
1484 | - grubpost="grub2-mkconfig -o /boot/grub2/grub.cfg";; |
1485 | - *) |
1486 | - echo "Unknown rhel_ver [$bootver]" |
1487 | - exit 1 |
1488 | - esac |
1489 | - ;; |
1490 | - *) |
1491 | - echo "Unsupported OS: $bootid"; 1>&2 |
1492 | - exit 1 |
1493 | - ;; |
1494 | - esac |
1495 | - for d in "$@"; do |
1496 | - echo $grubcmd "$d"; |
1497 | - $grubcmd "$d" || exit; done |
1498 | - [ -z "$grubpost" ] || $grubpost;' \ |
1499 | - -- "${grub_name}" "${os_variant}" "${rhel_ver}" "${grubdevs[@]}" </dev/null || |
1500 | - { error "failed to install grub!"; return 1; } |
1501 | - fi |
1502 | - |
1503 | - if [ -n "${mp_efi}" ]; then |
1504 | - umount "$mp_efi" || |
1505 | - { error "failed to unmount $mp_efi"; return 1; } |
1506 | - fi |
1507 | - |
1508 | - return |
1509 | -} |
1510 | - |
1511 | # vi: ts=4 expandtab syntax=sh |
1512 | diff --git a/helpers/install-grub b/helpers/install-grub |
1513 | deleted file mode 100755 |
1514 | index e1bfb23..0000000 |
1515 | --- a/helpers/install-grub |
1516 | +++ /dev/null |
1517 | @@ -1,7 +0,0 @@ |
1518 | -#!/bin/bash |
1519 | -# This file is part of curtin. See LICENSE file for copyright and license info. |
1520 | - |
1521 | -[ "${0%/*}" = "$0" ] && . ./common || . "${0%/*}/common" |
1522 | -install_grub "$@" |
1523 | - |
1524 | -# vi: ts=4 expandtab syntax=sh |
1525 | diff --git a/requirements.txt b/requirements.txt |
1526 | index 9066728..6afa3b8 100644 |
1527 | --- a/requirements.txt |
1528 | +++ b/requirements.txt |
1529 | @@ -2,3 +2,6 @@ pyyaml |
1530 | oauthlib |
1531 | # For validation of storate configuration format |
1532 | jsonschema |
1533 | +# Dependency of jsonschema. |
1534 | +# Version 0.16.0 is the latest version supporting Python < 3.5. |
1535 | +pyrsistent==0.16.0 |
1536 | diff --git a/tests/data/multipath-nvme.txt b/tests/data/multipath-nvme.txt |
1537 | new file mode 100644 |
1538 | index 0000000..30b59e4 |
1539 | --- /dev/null |
1540 | +++ b/tests/data/multipath-nvme.txt |
1541 | @@ -0,0 +1 @@ |
1542 | +name='nqn.1994-11.com.samsung:nvme:PM1725a:HHHL:S3RVNA0J300208 :nsid.1' multipath='eui.335256304a3002080025384100000001' sysfs='nvme0n1' paths='1' |
1543 | diff --git a/tests/unittests/helpers.py b/tests/unittests/helpers.py |
1544 | index 2f5e51a..64a79ca 100644 |
1545 | --- a/tests/unittests/helpers.py |
1546 | +++ b/tests/unittests/helpers.py |
1547 | @@ -2,11 +2,13 @@ |
1548 | |
1549 | import imp |
1550 | import importlib |
1551 | +import logging |
1552 | import mock |
1553 | import os |
1554 | import random |
1555 | import shutil |
1556 | import string |
1557 | +import sys |
1558 | import tempfile |
1559 | from unittest import TestCase, skipIf |
1560 | from contextlib import contextmanager |
1561 | @@ -55,6 +57,7 @@ def skipUnlessJsonSchema(): |
1562 | class CiTestCase(TestCase): |
1563 | """Common testing class which all curtin unit tests subclass.""" |
1564 | |
1565 | + with_logs = False |
1566 | allowed_subp = False |
1567 | SUBP_SHELL_TRUE = "shell=True" |
1568 | |
1569 | @@ -69,6 +72,21 @@ class CiTestCase(TestCase): |
1570 | |
1571 | def setUp(self): |
1572 | super(CiTestCase, self).setUp() |
1573 | + if self.with_logs: |
1574 | + # Create a log handler so unit tests can search expected logs. |
1575 | + self.logger = logging.getLogger() |
1576 | + if sys.version_info[0] == 2: |
1577 | + import StringIO |
1578 | + self.logs = StringIO.StringIO() |
1579 | + else: |
1580 | + import io |
1581 | + self.logs = io.StringIO() |
1582 | + formatter = logging.Formatter('%(levelname)s: %(message)s') |
1583 | + handler = logging.StreamHandler(self.logs) |
1584 | + handler.setFormatter(formatter) |
1585 | + self.old_handlers = self.logger.handlers |
1586 | + self.logger.handlers = [handler] |
1587 | + |
1588 | if self.allowed_subp is True: |
1589 | util.subp = _real_subp |
1590 | else: |
1591 | diff --git a/tests/unittests/test_block.py b/tests/unittests/test_block.py |
1592 | index c62c153..78e331d 100644 |
1593 | --- a/tests/unittests/test_block.py |
1594 | +++ b/tests/unittests/test_block.py |
1595 | @@ -179,6 +179,18 @@ class TestBlock(CiTestCase): |
1596 | byid_path = block.disk_to_byid_path('/dev/sdb') |
1597 | self.assertEqual(mapping.get('/dev/sdb'), byid_path) |
1598 | |
1599 | + @mock.patch("curtin.block.os.path.exists") |
1600 | + def test__get_dev_disk_by_prefix_returns_empty_dict(self, m_exists): |
1601 | + """ _get_disk_by_prefix returns empty dict prefix dir does not exit """ |
1602 | + m_exists.return_value = False |
1603 | + self.assertEqual({}, block._get_dev_disk_by_prefix("/dev/disk/by-id")) |
1604 | + |
1605 | + @mock.patch("curtin.block.os.path.exists") |
1606 | + def test_disk_to_byid_returns_none_if_disk_byid_missing(self, m_exists): |
1607 | + """ disk_to_byid path returns None if /dev/disk/by-id is missing """ |
1608 | + m_exists.return_value = False |
1609 | + self.assertEqual(None, block.disk_to_byid_path('/dev/sdb')) |
1610 | + |
1611 | |
1612 | class TestSysBlockPath(CiTestCase): |
1613 | @mock.patch("curtin.block.get_blockdev_for_partition") |
1614 | diff --git a/tests/unittests/test_block_multipath.py b/tests/unittests/test_block_multipath.py |
1615 | index 2101eae..96cbcba 100644 |
1616 | --- a/tests/unittests/test_block_multipath.py |
1617 | +++ b/tests/unittests/test_block_multipath.py |
1618 | @@ -39,6 +39,20 @@ class TestMultipath(CiTestCase): |
1619 | multipath.show_maps()) |
1620 | self.m_subp.assert_called_with(expected, capture=True) |
1621 | |
1622 | + def test_show_maps_nvme(self): |
1623 | + """verify show_maps extracts mulitpath map data correctly.""" |
1624 | + NVME_MP = multipath.util.load_file('tests/data/multipath-nvme.txt') |
1625 | + self.m_subp.return_value = (NVME_MP, "") |
1626 | + expected = ['multipathd', 'show', 'maps', 'raw', 'format', |
1627 | + multipath.SHOW_MAPS_FMT] |
1628 | + self.assertEqual([ |
1629 | + {'name': |
1630 | + ('nqn.1994-11.com.samsung:nvme:PM1725a:HHHL:S3RVNA0J300208 ' |
1631 | + ':nsid.1'), |
1632 | + 'multipath': 'eui.335256304a3002080025384100000001', |
1633 | + 'sysfs': 'nvme0n1', 'paths': '1'}], multipath.show_maps()) |
1634 | + self.m_subp.assert_called_with(expected, capture=True) |
1635 | + |
1636 | def test_is_mpath_device_true(self): |
1637 | """is_mpath_device returns true if dev DM_UUID starts with mpath-""" |
1638 | self.m_udev.udevadm_info.return_value = {'DM_UUID': 'mpath-mpatha-foo'} |
1639 | diff --git a/tests/unittests/test_commands_block_meta.py b/tests/unittests/test_commands_block_meta.py |
1640 | index b768cdc..d954296 100644 |
1641 | --- a/tests/unittests/test_commands_block_meta.py |
1642 | +++ b/tests/unittests/test_commands_block_meta.py |
1643 | @@ -1779,6 +1779,7 @@ class TestRaidHandler(CiTestCase): |
1644 | def setUp(self): |
1645 | super(TestRaidHandler, self).setUp() |
1646 | |
1647 | + orig_md_path = block_meta.block.md_path |
1648 | basepath = 'curtin.commands.block_meta.' |
1649 | self.add_patch(basepath + 'get_path_to_storage_volume', 'm_getpath') |
1650 | self.add_patch(basepath + 'util', 'm_util') |
1651 | @@ -1787,6 +1788,10 @@ class TestRaidHandler(CiTestCase): |
1652 | self.add_patch(basepath + 'block', 'm_block') |
1653 | self.add_patch(basepath + 'udevadm_settle', 'm_uset') |
1654 | |
1655 | + # The behavior of this function is being directly tested in |
1656 | + # these tests, so we can't mock it |
1657 | + self.m_block.md_path = orig_md_path |
1658 | + |
1659 | self.target = "my_target" |
1660 | self.config = { |
1661 | 'storage': { |
1662 | @@ -1850,12 +1855,40 @@ class TestRaidHandler(CiTestCase): |
1663 | block_meta.extract_storage_ordered_dict(self.config)) |
1664 | self.m_util.load_command_environment.return_value = {'fstab': None} |
1665 | |
1666 | + def test_md_name(self): |
1667 | + input_to_result = [ |
1668 | + ('md1', '/dev/md1'), |
1669 | + ('os-raid1', '/dev/md/os-raid1'), |
1670 | + ('md/os-raid1', '/dev/md/os-raid1'), |
1671 | + ('/dev/md1', '/dev/md1'), |
1672 | + ('/dev/md/os-raid1', '/dev/md/os-raid1'), |
1673 | + ('bad/path', ValueError) |
1674 | + ] |
1675 | + for index, test in enumerate(input_to_result): |
1676 | + param, expected = test |
1677 | + self.storage_config['mddevice']['name'] = param |
1678 | + try: |
1679 | + block_meta.raid_handler(self.storage_config['mddevice'], |
1680 | + self.storage_config) |
1681 | + except ValueError: |
1682 | + if param in ['bad/path']: |
1683 | + continue |
1684 | + else: |
1685 | + raise |
1686 | + |
1687 | + actual = self.m_mdadm.mdadm_create.call_args_list[index][0][0] |
1688 | + self.assertEqual( |
1689 | + expected, |
1690 | + actual, |
1691 | + "Expected {} to result in mdadm being called with {}. " |
1692 | + "mdadm instead called with {}".format(param, expected, actual) |
1693 | + ) |
1694 | + |
1695 | def test_raid_handler(self): |
1696 | """ raid_handler creates raid device. """ |
1697 | devices = [self.random_string(), self.random_string(), |
1698 | self.random_string()] |
1699 | md_devname = '/dev/' + self.storage_config['mddevice']['name'] |
1700 | - self.m_block.dev_path.return_value = '/dev/md0' |
1701 | self.m_getpath.side_effect = iter(devices) |
1702 | block_meta.raid_handler(self.storage_config['mddevice'], |
1703 | self.storage_config) |
1704 | @@ -1868,7 +1901,6 @@ class TestRaidHandler(CiTestCase): |
1705 | |
1706 | devices = [self.random_string(), self.random_string(), |
1707 | self.random_string()] |
1708 | - self.m_block.dev_path.return_value = '/dev/md0' |
1709 | self.m_getpath.side_effect = iter(devices) |
1710 | m_verify.return_value = True |
1711 | self.storage_config['mddevice']['preserve'] = True |
1712 | @@ -1882,7 +1914,6 @@ class TestRaidHandler(CiTestCase): |
1713 | devices = [self.random_string(), self.random_string(), |
1714 | self.random_string()] |
1715 | md_devname = '/dev/' + self.storage_config['mddevice']['name'] |
1716 | - self.m_block.dev_path.return_value = '/dev/md0' |
1717 | self.m_getpath.side_effect = iter(devices) |
1718 | self.m_mdadm.md_check.return_value = True |
1719 | self.storage_config['mddevice']['preserve'] = True |
1720 | @@ -1898,7 +1929,6 @@ class TestRaidHandler(CiTestCase): |
1721 | devices = [self.random_string(), self.random_string(), |
1722 | self.random_string()] |
1723 | md_devname = '/dev/' + self.storage_config['mddevice']['name'] |
1724 | - self.m_block.dev_path.return_value = '/dev/md0' |
1725 | self.m_getpath.side_effect = iter(devices) |
1726 | self.m_mdadm.md_check.side_effect = iter([False, True]) |
1727 | self.storage_config['mddevice']['preserve'] = True |
1728 | @@ -1916,7 +1946,6 @@ class TestRaidHandler(CiTestCase): |
1729 | devices = [self.random_string(), self.random_string(), |
1730 | self.random_string()] |
1731 | md_devname = '/dev/' + self.storage_config['mddevice']['name'] |
1732 | - self.m_block.dev_path.return_value = '/dev/md0' |
1733 | self.m_getpath.side_effect = iter(devices) |
1734 | self.m_mdadm.md_check.side_effect = iter([False, False]) |
1735 | self.storage_config['mddevice']['preserve'] = True |
1736 | @@ -2557,4 +2586,115 @@ class TestVerifyPtableFlag(CiTestCase): |
1737 | sfdisk_info=self.sfdisk_info_dos) |
1738 | |
1739 | |
1740 | +class TestGetDevicePathsFromStorageConfig(CiTestCase): |
1741 | + |
1742 | + def setUp(self): |
1743 | + super(TestGetDevicePathsFromStorageConfig, self).setUp() |
1744 | + base = 'curtin.commands.block_meta.' |
1745 | + self.add_patch(base + 'get_path_to_storage_volume', 'mock_getpath') |
1746 | + self.add_patch(base + 'os.path.exists', 'm_exists') |
1747 | + self.m_exists.return_value = True |
1748 | + self.mock_getpath.side_effect = self._getpath |
1749 | + self.prefix = '/test/dev/' |
1750 | + self.config = { |
1751 | + 'storage': { |
1752 | + 'version': 1, |
1753 | + 'config': [ |
1754 | + {'id': 'sda', |
1755 | + 'type': 'disk', |
1756 | + 'name': 'main_disk', |
1757 | + 'ptable': 'gpt', |
1758 | + 'serial': 'disk-a'}, |
1759 | + {'id': 'disk-sda-part-1', |
1760 | + 'type': 'partition', |
1761 | + 'device': 'sda', |
1762 | + 'name': 'bios_boot', |
1763 | + 'number': 1, |
1764 | + 'size': '1M', |
1765 | + 'flag': 'bios_grub'}, |
1766 | + {'id': 'disk-sda-part-2', |
1767 | + 'type': 'partition', |
1768 | + 'device': 'sda', |
1769 | + 'number': 2, |
1770 | + 'size': '5GB'}, |
1771 | + ], |
1772 | + } |
1773 | + } |
1774 | + self.disk1 = self.config['storage']['config'][0] |
1775 | + self.part1 = self.config['storage']['config'][1] |
1776 | + self.part2 = self.config['storage']['config'][2] |
1777 | + self.sconfig = self._sconfig(self.config) |
1778 | + |
1779 | + def _sconfig(self, config): |
1780 | + return block_meta.extract_storage_ordered_dict(config) |
1781 | + |
1782 | + def _getpath(self, item_id, _sconfig): |
1783 | + return self.prefix + item_id |
1784 | + |
1785 | + def test_devpath_selects_disks_partitions_with_wipe_setting(self): |
1786 | + self.disk1['wipe'] = 'superblock' |
1787 | + self.part1['wipe'] = 'superblock' |
1788 | + self.sconfig = self._sconfig(self.config) |
1789 | + |
1790 | + expected_devpaths = [ |
1791 | + self.prefix + self.disk1['id'], self.prefix + self.part1['id']] |
1792 | + result = block_meta.get_device_paths_from_storage_config(self.sconfig) |
1793 | + self.assertEqual(sorted(expected_devpaths), sorted(result)) |
1794 | + self.assertEqual([ |
1795 | + call(self.disk1['id'], self.sconfig), |
1796 | + call(self.part1['id'], self.sconfig)], |
1797 | + self.mock_getpath.call_args_list) |
1798 | + self.assertEqual( |
1799 | + sorted([call(devpath) for devpath in expected_devpaths]), |
1800 | + sorted(self.m_exists.call_args_list)) |
1801 | + |
1802 | + def test_devpath_raises_exception_if_wipe_and_preserve_set(self): |
1803 | + self.disk1['wipe'] = 'superblock' |
1804 | + self.disk1['preserve'] = True |
1805 | + self.sconfig = self._sconfig(self.config) |
1806 | + |
1807 | + with self.assertRaises(RuntimeError): |
1808 | + block_meta.get_device_paths_from_storage_config(self.sconfig) |
1809 | + self.assertEqual([], self.mock_getpath.call_args_list) |
1810 | + self.assertEqual([], self.m_exists.call_args_list) |
1811 | + |
1812 | + def test_devpath_check_boolean_value_if_wipe_and_preserve_set(self): |
1813 | + self.disk1['wipe'] = 'superblock' |
1814 | + self.disk1['preserve'] = False |
1815 | + self.sconfig = self._sconfig(self.config) |
1816 | + |
1817 | + expected_devpaths = [self.prefix + self.disk1['id']] |
1818 | + result = block_meta.get_device_paths_from_storage_config(self.sconfig) |
1819 | + self.assertEqual(expected_devpaths, result) |
1820 | + self.assertEqual( |
1821 | + [call(self.disk1['id'], self.sconfig)], |
1822 | + self.mock_getpath.call_args_list) |
1823 | + self.assertEqual( |
1824 | + sorted([call(devpath) for devpath in expected_devpaths]), |
1825 | + sorted(self.m_exists.call_args_list)) |
1826 | + |
1827 | + def test_devpath_check_preserved_devices_skipped(self): |
1828 | + self.disk1['preserve'] = True |
1829 | + self.sconfig = self._sconfig(self.config) |
1830 | + |
1831 | + result = block_meta.get_device_paths_from_storage_config(self.sconfig) |
1832 | + self.assertEqual([], result) |
1833 | + self.assertEqual([], self.mock_getpath.call_args_list) |
1834 | + self.assertEqual([], self.m_exists.call_args_list) |
1835 | + |
1836 | + def test_devpath_check_missing_path_devices_skipped(self): |
1837 | + self.disk1['wipe'] = 'superblock' |
1838 | + self.sconfig = self._sconfig(self.config) |
1839 | + |
1840 | + self.m_exists.return_value = False |
1841 | + result = block_meta.get_device_paths_from_storage_config(self.sconfig) |
1842 | + self.assertEqual([], result) |
1843 | + self.assertEqual( |
1844 | + [call(self.disk1['id'], self.sconfig)], |
1845 | + self.mock_getpath.call_args_list) |
1846 | + self.assertEqual( |
1847 | + [call(self.prefix + self.disk1['id'])], |
1848 | + self.m_exists.call_args_list) |
1849 | + |
1850 | + |
1851 | # vi: ts=4 expandtab syntax=python |
1852 | diff --git a/tests/unittests/test_curthooks.py b/tests/unittests/test_curthooks.py |
1853 | index 2349456..e5fead3 100644 |
1854 | --- a/tests/unittests/test_curthooks.py |
1855 | +++ b/tests/unittests/test_curthooks.py |
1856 | @@ -1,5 +1,6 @@ |
1857 | # This file is part of curtin. See LICENSE file for copyright and license info. |
1858 | |
1859 | +import copy |
1860 | import os |
1861 | from mock import call, patch |
1862 | import textwrap |
1863 | @@ -10,7 +11,7 @@ from curtin import distro |
1864 | from curtin import util |
1865 | from curtin import config |
1866 | from curtin.reporter import events |
1867 | -from .helpers import CiTestCase, dir2dict, populate_dir |
1868 | +from .helpers import CiTestCase, dir2dict, populate_dir, random |
1869 | |
1870 | |
1871 | class TestGetFlashKernelPkgs(CiTestCase): |
1872 | @@ -531,12 +532,55 @@ class TestSetupZipl(CiTestCase): |
1873 | content) |
1874 | |
1875 | |
1876 | +class EfiOutput(object): |
1877 | + |
1878 | + def __init__(self, current=None, order=None, entries=None): |
1879 | + self.entries = {} |
1880 | + if entries: |
1881 | + for entry in entries: |
1882 | + self.entries.update(entry) |
1883 | + self.current = current |
1884 | + self.order = order |
1885 | + if not order and self.entries: |
1886 | + self.order = sorted(self.entries.keys()) |
1887 | + |
1888 | + def add_entry(self, bootnum=None, name=None, path=None, current=False): |
1889 | + if not bootnum: |
1890 | + bootnum = "%04x" % random.randint(0, 1000) |
1891 | + if not name: |
1892 | + name = CiTestCase.random_string() |
1893 | + if not path: |
1894 | + path = '' |
1895 | + if bootnum not in self.entries: |
1896 | + self.entries[bootnum] = {'name': name, 'path': path} |
1897 | + if not self.order: |
1898 | + self.order = [] |
1899 | + self.order.append(bootnum) |
1900 | + if current: |
1901 | + self.current = bootnum |
1902 | + |
1903 | + def set_order(self, new_order): |
1904 | + self.order = new_order |
1905 | + |
1906 | + def as_dict(self): |
1907 | + output = {} |
1908 | + if self.current: |
1909 | + output['current'] = self.current |
1910 | + if self.order: |
1911 | + output['order'] = self.order |
1912 | + output['entries'] = self.entries |
1913 | + return output |
1914 | + |
1915 | + |
1916 | class TestSetupGrub(CiTestCase): |
1917 | |
1918 | + with_logs = True |
1919 | + |
1920 | def setUp(self): |
1921 | super(TestSetupGrub, self).setUp() |
1922 | self.target = self.tmp_dir() |
1923 | self.distro_family = distro.DISTROS.debian |
1924 | + self.variant = 'ubuntu' |
1925 | self.add_patch('curtin.distro.lsb_release', 'mock_lsb_release') |
1926 | self.mock_lsb_release.return_value = {'codename': 'xenial'} |
1927 | self.add_patch('curtin.util.is_uefi_bootable', |
1928 | @@ -556,7 +600,8 @@ class TestSetupGrub(CiTestCase): |
1929 | updated_cfg = { |
1930 | 'install_devices': ['/dev/vdb'] |
1931 | } |
1932 | - curthooks.setup_grub(cfg, self.target, osfamily=self.distro_family) |
1933 | + curthooks.setup_grub(cfg, self.target, osfamily=self.distro_family, |
1934 | + variant=self.variant) |
1935 | self.m_install_grub.assert_called_with( |
1936 | ['/dev/vdb'], self.target, uefi=False, grubcfg=updated_cfg) |
1937 | |
1938 | @@ -588,7 +633,8 @@ class TestSetupGrub(CiTestCase): |
1939 | }, |
1940 | } |
1941 | m_exists.return_value = True |
1942 | - curthooks.setup_grub(cfg, self.target, osfamily=self.distro_family) |
1943 | + curthooks.setup_grub(cfg, self.target, osfamily=self.distro_family, |
1944 | + variant=self.variant) |
1945 | self.m_install_grub.assert_called_with( |
1946 | ['/dev/vdb'], self.target, uefi=False, |
1947 | grubcfg={'install_devices': ['/dev/vdb']}) |
1948 | @@ -638,7 +684,8 @@ class TestSetupGrub(CiTestCase): |
1949 | } |
1950 | m_exists.return_value = True |
1951 | m_is_valid_device.side_effect = (False, True, False, True) |
1952 | - curthooks.setup_grub(cfg, self.target, osfamily=distro.DISTROS.redhat) |
1953 | + curthooks.setup_grub(cfg, self.target, osfamily=distro.DISTROS.redhat, |
1954 | + variant='centos') |
1955 | self.m_install_grub.assert_called_with( |
1956 | ['/dev/vdb1'], self.target, uefi=True, |
1957 | grubcfg={'update_nvram': False, 'install_devices': ['/dev/vdb1']} |
1958 | @@ -650,7 +697,8 @@ class TestSetupGrub(CiTestCase): |
1959 | 'install_devices': None, |
1960 | }, |
1961 | } |
1962 | - curthooks.setup_grub(cfg, self.target, osfamily=self.distro_family) |
1963 | + curthooks.setup_grub(cfg, self.target, osfamily=self.distro_family, |
1964 | + variant=self.variant) |
1965 | self.m_install_grub.assert_called_with( |
1966 | ['none'], self.target, uefi=False, |
1967 | grubcfg={'install_devices': None} |
1968 | @@ -681,7 +729,8 @@ class TestSetupGrub(CiTestCase): |
1969 | } |
1970 | } |
1971 | } |
1972 | - curthooks.setup_grub(cfg, self.target, osfamily=self.distro_family) |
1973 | + curthooks.setup_grub(cfg, self.target, osfamily=self.distro_family, |
1974 | + variant=self.variant) |
1975 | self.m_install_grub.assert_called_with( |
1976 | ['/dev/vdb'], self.target, uefi=True, grubcfg=cfg.get('grub') |
1977 | ) |
1978 | @@ -721,7 +770,8 @@ class TestSetupGrub(CiTestCase): |
1979 | } |
1980 | } |
1981 | self.mock_haspkg.return_value = False |
1982 | - curthooks.setup_grub(cfg, self.target, osfamily=self.distro_family) |
1983 | + curthooks.setup_grub(cfg, self.target, osfamily=self.distro_family, |
1984 | + variant=self.variant) |
1985 | |
1986 | expected_calls = [ |
1987 | call(['efibootmgr', '-B', '-b', '0001'], |
1988 | @@ -762,70 +812,304 @@ class TestSetupGrub(CiTestCase): |
1989 | } |
1990 | } |
1991 | self.mock_haspkg.return_value = False |
1992 | - curthooks.setup_grub(cfg, self.target, osfamily=self.distro_family) |
1993 | + curthooks.setup_grub(cfg, self.target, osfamily=self.distro_family, |
1994 | + variant=self.variant) |
1995 | self.assertEquals([ |
1996 | call(['efibootmgr', '-o', '0001,0000'], target=self.target)], |
1997 | self.mock_subp.call_args_list) |
1998 | |
1999 | + @patch.object(util.ChrootableTarget, "__enter__", new=lambda a: a) |
2000 | + def test_grub_install_uefi_reorders_no_current_new_entry(self): |
2001 | + self.add_patch('curtin.distro.install_packages', 'mock_install') |
2002 | + self.add_patch('curtin.distro.has_pkg_available', 'mock_haspkg') |
2003 | + self.add_patch('curtin.util.get_efibootmgr', 'mock_efibootmgr') |
2004 | + self.mock_is_uefi_bootable.return_value = True |
2005 | + cfg = { |
2006 | + 'grub': { |
2007 | + 'install_devices': ['/dev/vdb'], |
2008 | + 'update_nvram': True, |
2009 | + 'remove_old_uefi_loaders': False, |
2010 | + 'reorder_uefi': True, |
2011 | + }, |
2012 | + } |
2013 | + |
2014 | + # Single existing entry 0001 |
2015 | + efi_orig = EfiOutput() |
2016 | + efi_orig.add_entry(bootnum='0001', name='centos') |
2017 | |
2018 | -class TestUefiRemoveDuplicateEntries(CiTestCase): |
2019 | + # After install add a second entry, 0000 to the front of order |
2020 | + efi_post = copy.deepcopy(efi_orig) |
2021 | + efi_post.add_entry(bootnum='0000', name='ubuntu') |
2022 | + efi_post.set_order(['0000', '0001']) |
2023 | |
2024 | - def setUp(self): |
2025 | - super(TestUefiRemoveDuplicateEntries, self).setUp() |
2026 | - self.target = self.tmp_dir() |
2027 | - self.add_patch('curtin.util.get_efibootmgr', 'm_efibootmgr') |
2028 | - self.add_patch('curtin.util.subp', 'm_subp') |
2029 | + # After reorder we should have the target install first |
2030 | + efi_final = copy.deepcopy(efi_post) |
2031 | + |
2032 | + self.mock_efibootmgr.side_effect = iter([ |
2033 | + efi_orig.as_dict(), # collect original order before install |
2034 | + efi_orig.as_dict(), # remove_old_loaders query (no change) |
2035 | + efi_post.as_dict(), # efi table after grub install, (changed) |
2036 | + efi_final.as_dict(), # remove duplicates checks and finds reorder |
2037 | + # has changed |
2038 | + ]) |
2039 | + self.mock_haspkg.return_value = False |
2040 | + curthooks.setup_grub(cfg, self.target, osfamily=self.distro_family, |
2041 | + variant=self.variant) |
2042 | + logs = self.logs.getvalue() |
2043 | + print(logs) |
2044 | + self.assertEquals([], self.mock_subp.call_args_list) |
2045 | + self.assertIn("Using fallback UEFI reordering:", logs) |
2046 | + self.assertIn("missing 'BootCurrent' value", logs) |
2047 | + self.assertIn("Found new boot entries: ['0000']", logs) |
2048 | |
2049 | @patch.object(util.ChrootableTarget, "__enter__", new=lambda a: a) |
2050 | - def test_uefi_remove_duplicate_entries(self): |
2051 | + def test_grub_install_uefi_reorders_no_curr_same_size_order_no_match(self): |
2052 | + self.add_patch('curtin.distro.install_packages', 'mock_install') |
2053 | + self.add_patch('curtin.distro.has_pkg_available', 'mock_haspkg') |
2054 | + self.add_patch('curtin.util.get_efibootmgr', 'mock_efibootmgr') |
2055 | + self.add_patch('curtin.commands.curthooks.uefi_remove_old_loaders', |
2056 | + 'mock_remove_old_loaders') |
2057 | + self.mock_is_uefi_bootable.return_value = True |
2058 | cfg = { |
2059 | 'grub': { |
2060 | 'install_devices': ['/dev/vdb'], |
2061 | 'update_nvram': True, |
2062 | + 'remove_old_uefi_loaders': False, |
2063 | + 'reorder_uefi': True, |
2064 | }, |
2065 | } |
2066 | - self.m_efibootmgr.return_value = { |
2067 | - 'current': '0000', |
2068 | - 'entries': { |
2069 | - '0000': { |
2070 | - 'name': 'ubuntu', |
2071 | - 'path': ( |
2072 | - 'HD(1,GPT)/File(\\EFI\\ubuntu\\shimx64.efi)'), |
2073 | - }, |
2074 | - '0001': { |
2075 | - 'name': 'ubuntu', |
2076 | - 'path': ( |
2077 | - 'HD(1,GPT)/File(\\EFI\\ubuntu\\shimx64.efi)'), |
2078 | - }, |
2079 | - '0002': { # Is not a duplicate because of unique path |
2080 | - 'name': 'ubuntu', |
2081 | - 'path': ( |
2082 | - 'HD(2,GPT)/File(\\EFI\\ubuntu\\shimx64.efi)'), |
2083 | - }, |
2084 | - '0003': { # Is duplicate of 0000 |
2085 | - 'name': 'ubuntu', |
2086 | - 'path': ( |
2087 | - 'HD(1,GPT)/File(\\EFI\\ubuntu\\shimx64.efi)'), |
2088 | - }, |
2089 | - } |
2090 | + |
2091 | + # Existing Custom Ubuntu, usb and cd/dvd entry, booting Ubuntu |
2092 | + efi_orig = EfiOutput() |
2093 | + efi_orig.add_entry(bootnum='0001', name='Ubuntu Deluxe Edition') |
2094 | + efi_orig.add_entry(bootnum='0002', name='USB Device') |
2095 | + efi_orig.add_entry(bootnum='0000', name='CD/DVD') |
2096 | + efi_orig.set_order(['0001', '0002', '0000']) |
2097 | + |
2098 | + # after install existing ubuntu entry is reused, no change in order |
2099 | + efi_post = efi_orig |
2100 | + |
2101 | + # after reorder, no change is made due to the installed distro variant |
2102 | + # string 'ubuntu' is not found in the boot entries so we retain the |
2103 | + # original efi order. |
2104 | + efi_final = efi_post |
2105 | + |
2106 | + self.mock_efibootmgr.side_effect = iter([ |
2107 | + efi_orig.as_dict(), # collect original order before install |
2108 | + efi_orig.as_dict(), # remove_old_loaders query |
2109 | + efi_post.as_dict(), # reorder entries queries post install |
2110 | + efi_final.as_dict(), # remove duplicates checks and finds reorder |
2111 | + ]) |
2112 | + |
2113 | + self.mock_haspkg.return_value = False |
2114 | + curthooks.setup_grub(cfg, self.target, osfamily=self.distro_family, |
2115 | + variant=self.variant) |
2116 | + |
2117 | + logs = self.logs.getvalue() |
2118 | + print(logs) |
2119 | + self.assertEquals([], self.mock_subp.call_args_list) |
2120 | + self.assertIn("Using fallback UEFI reordering:", logs) |
2121 | + self.assertIn("missing 'BootCurrent' value", logs) |
2122 | + self.assertIn("Current and Previous bootorders match", logs) |
2123 | + self.assertIn("Looking for installed entry variant=", logs) |
2124 | + self.assertIn("Did not find an entry with variant=", logs) |
2125 | + self.assertIn("No changes to boot order.", logs) |
2126 | + |
2127 | + @patch.object(util.ChrootableTarget, "__enter__", new=lambda a: a) |
2128 | + def test_grub_install_uefi_reorders_force_fallback(self): |
2129 | + self.add_patch('curtin.distro.install_packages', 'mock_install') |
2130 | + self.add_patch('curtin.distro.has_pkg_available', 'mock_haspkg') |
2131 | + self.add_patch('curtin.util.get_efibootmgr', 'mock_efibootmgr') |
2132 | + self.mock_is_uefi_bootable.return_value = True |
2133 | + cfg = { |
2134 | + 'grub': { |
2135 | + 'install_devices': ['/dev/vdb'], |
2136 | + 'update_nvram': True, |
2137 | + 'remove_old_uefi_loaders': True, |
2138 | + 'reorder_uefi': True, |
2139 | + 'reorder_uefi_force_fallback': True, |
2140 | + }, |
2141 | } |
2142 | + # Single existing entry 0001 and set as current, which should avoid |
2143 | + # any fallback logic, but we're forcing fallback pack via config |
2144 | + efi_orig = EfiOutput() |
2145 | + efi_orig.add_entry(bootnum='0001', name='PXE', current=True) |
2146 | + print(efi_orig.as_dict()) |
2147 | + |
2148 | + # After install add a second entry, 0000 to the front of order |
2149 | + efi_post = copy.deepcopy(efi_orig) |
2150 | + efi_post.add_entry(bootnum='0000', name='ubuntu') |
2151 | + efi_post.set_order(['0000', '0001']) |
2152 | + print(efi_orig.as_dict()) |
2153 | + |
2154 | + # After reorder we should have the original boot entry 0001 as first |
2155 | + efi_final = copy.deepcopy(efi_post) |
2156 | + efi_final.set_order(['0001', '0000']) |
2157 | + |
2158 | + self.mock_efibootmgr.side_effect = iter([ |
2159 | + efi_orig.as_dict(), # collect original order before install |
2160 | + efi_orig.as_dict(), # remove_old_loaders query (no change) |
2161 | + efi_post.as_dict(), # efi table after grub install, (changed) |
2162 | + efi_final.as_dict(), # remove duplicates checks and finds reorder |
2163 | + # has changed |
2164 | + ]) |
2165 | |
2166 | - curthooks.uefi_remove_duplicate_entries(cfg, self.target) |
2167 | + self.mock_haspkg.return_value = False |
2168 | + curthooks.setup_grub(cfg, self.target, osfamily=self.distro_family, |
2169 | + variant=self.variant) |
2170 | + logs = self.logs.getvalue() |
2171 | + print(logs) |
2172 | self.assertEquals([ |
2173 | - call(['efibootmgr', '--bootnum=0001', '--delete-bootnum'], |
2174 | - target=self.target), |
2175 | - call(['efibootmgr', '--bootnum=0003', '--delete-bootnum'], |
2176 | - target=self.target) |
2177 | - ], self.m_subp.call_args_list) |
2178 | + call(['efibootmgr', '-o', '0001,0000'], target=self.target)], |
2179 | + self.mock_subp.call_args_list) |
2180 | + self.assertIn("Using fallback UEFI reordering:", logs) |
2181 | + self.assertIn("config 'reorder_uefi_force_fallback' is True", logs) |
2182 | |
2183 | @patch.object(util.ChrootableTarget, "__enter__", new=lambda a: a) |
2184 | - def test_uefi_remove_duplicate_entries_no_change(self): |
2185 | + def test_grub_install_uefi_reorders_network_first(self): |
2186 | + self.add_patch('curtin.distro.install_packages', 'mock_install') |
2187 | + self.add_patch('curtin.distro.has_pkg_available', 'mock_haspkg') |
2188 | + self.add_patch('curtin.util.get_efibootmgr', 'mock_efibootmgr') |
2189 | + self.mock_is_uefi_bootable.return_value = True |
2190 | cfg = { |
2191 | 'grub': { |
2192 | 'install_devices': ['/dev/vdb'], |
2193 | 'update_nvram': True, |
2194 | + 'remove_old_uefi_loaders': True, |
2195 | + 'reorder_uefi': True, |
2196 | + }, |
2197 | + } |
2198 | + |
2199 | + # Existing ubuntu, usb and cd/dvd entry, booting ubuntu |
2200 | + efi_orig = EfiOutput() |
2201 | + efi_orig.add_entry(bootnum='0001', name='centos') |
2202 | + efi_orig.add_entry(bootnum='0002', name='Network') |
2203 | + efi_orig.add_entry(bootnum='0003', name='PXE') |
2204 | + efi_orig.add_entry(bootnum='0004', name='LAN') |
2205 | + efi_orig.add_entry(bootnum='0000', name='CD/DVD') |
2206 | + efi_orig.set_order(['0001', '0002', '0003', '0004', '0000']) |
2207 | + print(efi_orig.as_dict()) |
2208 | + |
2209 | + # after install we add an ubuntu entry, and grub puts it first |
2210 | + efi_post = copy.deepcopy(efi_orig) |
2211 | + efi_post.add_entry(bootnum='0007', name='ubuntu') |
2212 | + efi_post.set_order(['0007'] + efi_orig.order) |
2213 | + print(efi_post.as_dict()) |
2214 | + |
2215 | + # reorder must place all network devices first, then ubuntu, and others |
2216 | + efi_final = copy.deepcopy(efi_post) |
2217 | + expected_order = ['0002', '0003', '0004', '0007', '0001', '0000'] |
2218 | + efi_final.set_order(expected_order) |
2219 | + |
2220 | + self.mock_efibootmgr.side_effect = iter([ |
2221 | + efi_orig.as_dict(), # collect original order before install |
2222 | + efi_orig.as_dict(), # remove_old_loaders query |
2223 | + efi_post.as_dict(), # reorder entries queries post install |
2224 | + efi_final.as_dict(), # remove duplicates checks and finds reorder |
2225 | + ]) |
2226 | + self.mock_haspkg.return_value = False |
2227 | + curthooks.setup_grub(cfg, self.target, osfamily=self.distro_family, |
2228 | + variant=self.variant) |
2229 | + logs = self.logs.getvalue() |
2230 | + print(logs) |
2231 | + print('Number of bootmgr calls: %s' % self.mock_efibootmgr.call_count) |
2232 | + self.assertEquals([ |
2233 | + call(['efibootmgr', '-o', '%s' % (",".join(expected_order))], |
2234 | + target=self.target)], |
2235 | + self.mock_subp.call_args_list) |
2236 | + self.assertIn("Using fallback UEFI reordering:", logs) |
2237 | + self.assertIn("missing 'BootCurrent' value", logs) |
2238 | + self.assertIn("Looking for installed entry variant=", logs) |
2239 | + self.assertIn("found netboot entries: ['0002', '0003', '0004']", logs) |
2240 | + self.assertIn("found other entries: ['0001', '0000']", logs) |
2241 | + self.assertIn("found target entry: ['0007']", logs) |
2242 | + |
2243 | + |
2244 | +class TestUefiRemoveDuplicateEntries(CiTestCase): |
2245 | + |
2246 | + efibootmgr_output = { |
2247 | + 'current': '0000', |
2248 | + 'entries': { |
2249 | + '0000': { |
2250 | + 'name': 'ubuntu', |
2251 | + 'path': ( |
2252 | + 'HD(1,GPT)/File(\\EFI\\ubuntu\\shimx64.efi)'), |
2253 | + }, |
2254 | + '0001': { # Is duplicate of 0000 |
2255 | + 'name': 'ubuntu', |
2256 | + 'path': ( |
2257 | + 'HD(1,GPT)/File(\\EFI\\ubuntu\\shimx64.efi)'), |
2258 | + }, |
2259 | + '0002': { # Is not a duplicate because of unique path |
2260 | + 'name': 'ubuntu', |
2261 | + 'path': ( |
2262 | + 'HD(2,GPT)/File(\\EFI\\ubuntu\\shimx64.efi)'), |
2263 | + }, |
2264 | + '0003': { # Is duplicate of 0000 |
2265 | + 'name': 'ubuntu', |
2266 | + 'path': ( |
2267 | + 'HD(1,GPT)/File(\\EFI\\ubuntu\\shimx64.efi)'), |
2268 | }, |
2269 | } |
2270 | + } |
2271 | + |
2272 | + def setUp(self): |
2273 | + super(TestUefiRemoveDuplicateEntries, self).setUp() |
2274 | + self.target = self.tmp_dir() |
2275 | + self.add_patch('curtin.util.get_efibootmgr', 'm_efibootmgr') |
2276 | + self.add_patch('curtin.util.subp', 'm_subp') |
2277 | + self.m_efibootmgr.return_value = copy.deepcopy(self.efibootmgr_output) |
2278 | + |
2279 | + @patch.object(util.ChrootableTarget, "__enter__", new=lambda a: a) |
2280 | + def test_uefi_remove_duplicate_entries(self): |
2281 | + grubcfg = {} |
2282 | + curthooks.uefi_remove_duplicate_entries(grubcfg, self.target) |
2283 | + self.assertEquals([ |
2284 | + call(['efibootmgr', '--bootnum=0001', '--delete-bootnum'], |
2285 | + target=self.target), |
2286 | + call(['efibootmgr', '--bootnum=0003', '--delete-bootnum'], |
2287 | + target=self.target) |
2288 | + ], self.m_subp.call_args_list) |
2289 | + |
2290 | + @patch.object(util.ChrootableTarget, "__enter__", new=lambda a: a) |
2291 | + def test_uefi_remove_duplicate_entries_no_bootcurrent(self): |
2292 | + grubcfg = {} |
2293 | + efiout = copy.deepcopy(self.efibootmgr_output) |
2294 | + del efiout['current'] |
2295 | + self.m_efibootmgr.return_value = efiout |
2296 | + curthooks.uefi_remove_duplicate_entries(grubcfg, self.target) |
2297 | + self.assertEquals([ |
2298 | + call(['efibootmgr', '--bootnum=0001', '--delete-bootnum'], |
2299 | + target=self.target), |
2300 | + call(['efibootmgr', '--bootnum=0003', '--delete-bootnum'], |
2301 | + target=self.target) |
2302 | + ], self.m_subp.call_args_list) |
2303 | + |
2304 | + @patch.object(util.ChrootableTarget, "__enter__", new=lambda a: a) |
2305 | + def test_uefi_remove_duplicate_entries_disabled(self): |
2306 | + grubcfg = { |
2307 | + 'remove_duplicate_entries': False, |
2308 | + } |
2309 | + curthooks.uefi_remove_duplicate_entries(grubcfg, self.target) |
2310 | + self.assertEquals([], self.m_subp.call_args_list) |
2311 | + |
2312 | + @patch.object(util.ChrootableTarget, "__enter__", new=lambda a: a) |
2313 | + def test_uefi_remove_duplicate_entries_skip_bootcurrent(self): |
2314 | + grubcfg = {} |
2315 | + efiout = copy.deepcopy(self.efibootmgr_output) |
2316 | + efiout['current'] = '0003' |
2317 | + self.m_efibootmgr.return_value = efiout |
2318 | + curthooks.uefi_remove_duplicate_entries(grubcfg, self.target) |
2319 | + self.assertEquals([ |
2320 | + call(['efibootmgr', '--bootnum=0000', '--delete-bootnum'], |
2321 | + target=self.target), |
2322 | + call(['efibootmgr', '--bootnum=0001', '--delete-bootnum'], |
2323 | + target=self.target), |
2324 | + ], self.m_subp.call_args_list) |
2325 | + |
2326 | + @patch.object(util.ChrootableTarget, "__enter__", new=lambda a: a) |
2327 | + def test_uefi_remove_duplicate_entries_no_change(self): |
2328 | + grubcfg = {} |
2329 | self.m_efibootmgr.return_value = { |
2330 | 'current': '0000', |
2331 | 'entries': { |
2332 | @@ -846,8 +1130,7 @@ class TestUefiRemoveDuplicateEntries(CiTestCase): |
2333 | }, |
2334 | } |
2335 | } |
2336 | - |
2337 | - curthooks.uefi_remove_duplicate_entries(cfg, self.target) |
2338 | + curthooks.uefi_remove_duplicate_entries(grubcfg, self.target) |
2339 | self.assertEquals([], self.m_subp.call_args_list) |
2340 | |
2341 | |
2342 | @@ -1110,9 +1393,8 @@ class TestDetectRequiredPackages(CiTestCase): |
2343 | {'type': 'static', 'address': '2001:1::1/64'}]}}, |
2344 | 2: { |
2345 | 'openvswitch': { |
2346 | - 'openvswitch': { |
2347 | - 'bridges': { |
2348 | - 'br-int': {'ports': {'eth15': {'tag': 2}}}}}}, |
2349 | + 'bridges': { |
2350 | + 'br-int': {'openvswitch': {}}}}, |
2351 | 'vlans': { |
2352 | 'vlans': { |
2353 | 'en-intra': {'id': 1, 'link': 'eno1', 'dhcp4': 'yes'}, |
2354 | @@ -1245,7 +1527,7 @@ class TestDetectRequiredPackages(CiTestCase): |
2355 | ({'network': { |
2356 | 'version': 2, |
2357 | 'items': ('openvswitch',)}}, |
2358 | - ('openvswitch-switch', )), |
2359 | + ('bridge-utils', 'openvswitch-switch', )), |
2360 | )) |
2361 | |
2362 | def test_network_v2_detect_renderers(self): |
2363 | @@ -1726,6 +2008,12 @@ class TestUefiFindGrubDeviceIds(CiTestCase): |
2364 | 'fstype': 'fat32', |
2365 | }, |
2366 | { |
2367 | + 'id': 'vdb-part2-swap_mount', |
2368 | + 'type': 'mount', |
2369 | + 'device': 'vdb-part2-swap_format', |
2370 | + 'options': '', |
2371 | + }, |
2372 | + { |
2373 | 'id': 'vdb-part1_mount', |
2374 | 'type': 'mount', |
2375 | 'device': 'vdb-part1_format', |
2376 | diff --git a/tests/unittests/test_distro.py b/tests/unittests/test_distro.py |
2377 | index eb62dd8..380680c 100644 |
2378 | --- a/tests/unittests/test_distro.py |
2379 | +++ b/tests/unittests/test_distro.py |
2380 | @@ -65,7 +65,7 @@ class TestParseDpkgVersion(CiTestCase): |
2381 | def test_simple_native_package_version(self): |
2382 | """dpkg versions must have a -. If not present expect value error.""" |
2383 | self.assertEqual( |
2384 | - {'major': 2, 'minor': 28, 'micro': 0, 'extra': None, |
2385 | + {'epoch': 0, 'major': 2, 'minor': 28, 'micro': 0, 'extra': None, |
2386 | 'raw': '2.28', 'upstream': '2.28', 'name': 'germinate', |
2387 | 'semantic_version': 22800}, |
2388 | distro.parse_dpkg_version('2.28', name='germinate')) |
2389 | @@ -73,7 +73,7 @@ class TestParseDpkgVersion(CiTestCase): |
2390 | def test_complex_native_package_version(self): |
2391 | dver = '1.0.106ubuntu2+really1.0.97ubuntu1' |
2392 | self.assertEqual( |
2393 | - {'major': 1, 'minor': 0, 'micro': 106, |
2394 | + {'epoch': 0, 'major': 1, 'minor': 0, 'micro': 106, |
2395 | 'extra': 'ubuntu2+really1.0.97ubuntu1', |
2396 | 'raw': dver, 'upstream': dver, 'name': 'debootstrap', |
2397 | 'semantic_version': 100106}, |
2398 | @@ -82,14 +82,14 @@ class TestParseDpkgVersion(CiTestCase): |
2399 | |
2400 | def test_simple_valid(self): |
2401 | self.assertEqual( |
2402 | - {'major': 1, 'minor': 2, 'micro': 3, 'extra': None, |
2403 | + {'epoch': 0, 'major': 1, 'minor': 2, 'micro': 3, 'extra': None, |
2404 | 'raw': '1.2.3-0', 'upstream': '1.2.3', 'name': 'foo', |
2405 | 'semantic_version': 10203}, |
2406 | distro.parse_dpkg_version('1.2.3-0', name='foo')) |
2407 | |
2408 | def test_simple_valid_with_semx(self): |
2409 | self.assertEqual( |
2410 | - {'major': 1, 'minor': 2, 'micro': 3, 'extra': None, |
2411 | + {'epoch': 0, 'major': 1, 'minor': 2, 'micro': 3, 'extra': None, |
2412 | 'raw': '1.2.3-0', 'upstream': '1.2.3', |
2413 | 'semantic_version': 123}, |
2414 | distro.parse_dpkg_version('1.2.3-0', semx=(100, 10, 1))) |
2415 | @@ -98,7 +98,8 @@ class TestParseDpkgVersion(CiTestCase): |
2416 | """upstream versions may have a hyphen.""" |
2417 | cver = '18.2-14-g6d48d265-0ubuntu1' |
2418 | self.assertEqual( |
2419 | - {'major': 18, 'minor': 2, 'micro': 0, 'extra': '-14-g6d48d265', |
2420 | + {'epoch': 0, 'major': 18, 'minor': 2, 'micro': 0, |
2421 | + 'extra': '-14-g6d48d265', |
2422 | 'raw': cver, 'upstream': '18.2-14-g6d48d265', |
2423 | 'name': 'cloud-init', 'semantic_version': 180200}, |
2424 | distro.parse_dpkg_version(cver, name='cloud-init')) |
2425 | @@ -107,11 +108,30 @@ class TestParseDpkgVersion(CiTestCase): |
2426 | """multipath tools has a + in it.""" |
2427 | mver = '0.5.0+git1.656f8865-5ubuntu2.5' |
2428 | self.assertEqual( |
2429 | - {'major': 0, 'minor': 5, 'micro': 0, 'extra': '+git1.656f8865', |
2430 | + {'epoch': 0, 'major': 0, 'minor': 5, 'micro': 0, |
2431 | + 'extra': '+git1.656f8865', |
2432 | 'raw': mver, 'upstream': '0.5.0+git1.656f8865', |
2433 | 'semantic_version': 500}, |
2434 | distro.parse_dpkg_version(mver)) |
2435 | |
2436 | + def test_package_with_epoch(self): |
2437 | + """xxd has epoch""" |
2438 | + mver = '2:8.1.2269-1ubuntu5' |
2439 | + self.assertEqual( |
2440 | + {'epoch': 2, 'major': 8, 'minor': 1, 'micro': 2269, |
2441 | + 'extra': None, 'raw': mver, 'upstream': '8.1.2269', |
2442 | + 'semantic_version': 82369}, |
2443 | + distro.parse_dpkg_version(mver)) |
2444 | + |
2445 | + def test_package_with_dot_in_extra(self): |
2446 | + """linux-image-generic has multiple dots in extra""" |
2447 | + mver = '5.4.0.37.40' |
2448 | + self.assertEqual( |
2449 | + {'epoch': 0, 'major': 5, 'minor': 4, 'micro': 0, |
2450 | + 'extra': '37.40', 'raw': mver, 'upstream': '5.4.0.37.40', |
2451 | + 'semantic_version': 50400}, |
2452 | + distro.parse_dpkg_version(mver)) |
2453 | + |
2454 | |
2455 | class TestDistros(CiTestCase): |
2456 | |
2457 | @@ -429,6 +449,7 @@ class TestSystemUpgrade(CiTestCase): |
2458 | auto_remove = apt_base + ['autoremove'] |
2459 | expected_calls = [ |
2460 | mock.call(apt_cmd, env=env, target=paths.target_path(target)), |
2461 | + mock.call(['apt-get', 'clean'], target=paths.target_path(target)), |
2462 | mock.call(auto_remove, env=env, target=paths.target_path(target)), |
2463 | ] |
2464 | which_calls = [mock.call('eatmydata', target=target)] |
2465 | diff --git a/tests/unittests/test_feature.py b/tests/unittests/test_feature.py |
2466 | index 7c55882..8690ad8 100644 |
2467 | --- a/tests/unittests/test_feature.py |
2468 | +++ b/tests/unittests/test_feature.py |
2469 | @@ -24,4 +24,10 @@ class TestExportsFeatures(CiTestCase): |
2470 | def test_has_centos_curthook_support(self): |
2471 | self.assertIn('CENTOS_CURTHOOK_SUPPORT', curtin.FEATURES) |
2472 | |
2473 | + def test_has_btrfs_swapfile_support(self): |
2474 | + self.assertIn('BTRFS_SWAPFILE', curtin.FEATURES) |
2475 | + |
2476 | + def test_has_uefi_reorder_fallback_support(self): |
2477 | + self.assertIn('UEFI_REORDER_FALLBACK_SUPPORT', curtin.FEATURES) |
2478 | + |
2479 | # vi: ts=4 expandtab syntax=python |
2480 | diff --git a/tests/vmtests/__init__.py b/tests/vmtests/__init__.py |
2481 | index 32cd5fd..0b19d8f 100644 |
2482 | --- a/tests/vmtests/__init__.py |
2483 | +++ b/tests/vmtests/__init__.py |
2484 | @@ -633,6 +633,7 @@ class VMBaseClass(TestCase): |
2485 | |
2486 | # these get set from base_vm_classes |
2487 | release = None |
2488 | + supported_releases = [] |
2489 | arch = None |
2490 | target_arch = None |
2491 | kflavor = None |
2492 | @@ -855,6 +856,13 @@ class VMBaseClass(TestCase): |
2493 | return {'kernel': {'fallback-package': package}} |
2494 | |
2495 | @classmethod |
2496 | + def is_unsupported_release(cls): |
2497 | + # allow unsupported releases opt-in to avoid the skiptest |
2498 | + if cls.release in cls.supported_releases: |
2499 | + return False |
2500 | + return is_unsupported_ubuntu(cls.release) |
2501 | + |
2502 | + @classmethod |
2503 | def skip_by_date(cls, *args, **kwargs): |
2504 | """skip_by_date wrapper. this way other modules do not have |
2505 | to add an import of skip_by_date to start skipping.""" |
2506 | @@ -883,7 +891,7 @@ class VMBaseClass(TestCase): |
2507 | "Class %s does not have required attrs set: %s" % |
2508 | (cls.__name__, missing)) |
2509 | |
2510 | - if is_unsupported_ubuntu(cls.release): |
2511 | + if cls.is_unsupported_release(): |
2512 | raise SkipTest('"%s" is unsupported release.' % cls.release) |
2513 | |
2514 | # check if we should skip due to host arch |
2515 | @@ -1372,8 +1380,10 @@ class VMBaseClass(TestCase): |
2516 | 'serial=%s' % os.path.basename(cls.td.output_disk)) |
2517 | target_disks.extend([output_disk]) |
2518 | |
2519 | + # centos requires a reboot after first boot to do selinux relabing |
2520 | + noreboot = ['--no-reboot'] if cls.target_distro != 'centos' else [] |
2521 | # create xkvm cmd |
2522 | - cmd = (["tools/xkvm", "-v", dowait, '--no-reboot'] + |
2523 | + cmd = (["tools/xkvm", "-v", dowait] + noreboot + |
2524 | uefi_flags + netdevs + |
2525 | cls.mpath_diskargs(target_disks + extra_disks + nvme_disks) + |
2526 | ["--disk=file=%s,if=virtio,media=cdrom" % cls.td.seed_disk] + |
2527 | @@ -1666,8 +1676,8 @@ class VMBaseClass(TestCase): |
2528 | if spec in line: |
2529 | fstab_entry = line |
2530 | self.assertIsNotNone(fstab_entry) |
2531 | - self.assertEqual(mp, fstab_entry.split(' ')[1]) |
2532 | - self.assertEqual(fsopts, fstab_entry.split(' ')[3]) |
2533 | + self.assertEqual(mp, fstab_entry.split()[1]) |
2534 | + self.assertEqual(fsopts, fstab_entry.split()[3]) |
2535 | found.append((spec, mp, fsopts)) |
2536 | |
2537 | self.assertEqual(sorted(expected), sorted(found)) |
2538 | @@ -1753,12 +1763,28 @@ class VMBaseClass(TestCase): |
2539 | for line in ls_byid.split('\n') |
2540 | if ("virtio-" + serial) in line.split() or |
2541 | ("scsi-" + serial) in line.split() or |
2542 | - ("wwn-" + serial) in line.split()] |
2543 | + ("wwn-" + serial) in line.split() or |
2544 | + (serial) in line.split()] |
2545 | + print("Looking for serial %s in 'ls_al_byid' content\n%s" % (serial, |
2546 | + ls_byid)) |
2547 | self.assertEqual(len(kname), 1) |
2548 | kname = kname.pop() |
2549 | self.assertIsNotNone(kname) |
2550 | return kname |
2551 | |
2552 | + def _mdname_to_kname(self, mdname): |
2553 | + # extract kname from /dev/md/ on /dev/<kname> |
2554 | + # parsing ls -al output on /dev/md/*: |
2555 | + # lrwxrwxrwx 1 root root 8 May 28 16:26 /dev/md/os-raid1 -> ../md127 |
2556 | + ls_dev_md = self.load_collect_file("ls_al_dev_md") |
2557 | + knames = [os.path.basename(line.split()[-1]) |
2558 | + for line in ls_dev_md.split('\n') |
2559 | + if mdname in line] |
2560 | + self.assertEqual(len(knames), 1) |
2561 | + kname = knames.pop() |
2562 | + self.assertIsNotNone(kname) |
2563 | + return kname |
2564 | + |
2565 | def _kname_to_bypath(self, kname): |
2566 | # extract path from /dev/disk/by-path on /dev/<kname> |
2567 | # parsing ls -al output on /dev/disk/by-path |
2568 | @@ -1787,6 +1813,36 @@ class VMBaseClass(TestCase): |
2569 | self.assertEqual(len(uuid), 36) |
2570 | return uuid |
2571 | |
2572 | + def _byuuid_to_kname(self, devpath): |
2573 | + # lookup kname via /dev/disk/by-uuid symlink |
2574 | + # parsing ls -al output on /dev/disk/by-uuid: |
2575 | + # lrwxrwxrwx 1 root root 9 Dec 4 20:02 |
2576 | + # d591e9e9-825a-4f0a-b280-3bfaf470b83c -> ../../vdg |
2577 | + uuid = os.path.basename(devpath) |
2578 | + self.assertIsNotNone(uuid) |
2579 | + print(uuid) |
2580 | + ls_uuid = self.load_collect_file("ls_al_byuuid") |
2581 | + kname = [line.split()[-1] for line in ls_uuid.split('\n') |
2582 | + if uuid in line.split()] |
2583 | + self.assertEqual(len(kname), 1) |
2584 | + kname = os.path.basename(kname.pop()) |
2585 | + return kname |
2586 | + |
2587 | + def _bypath_to_kname(self, devpath): |
2588 | + # lookup kname via /dev/disk/by-path symlink |
2589 | + # parsing ls -al output on /dev/disk/by-path: |
2590 | + # lrwxrwxrwx 1 root root 9 Dec 4 20:02 |
2591 | + # pci-0000:00:03.0-scsi-0:0:0:0-part3 -> ../../sda3 |
2592 | + dpath = os.path.basename(devpath) |
2593 | + self.assertIsNotNone(dpath) |
2594 | + print(dpath) |
2595 | + ls_bypath = self.load_collect_file("ls_al_bypath") |
2596 | + kname = [line.split()[-1] for line in ls_bypath.split('\n') |
2597 | + if dpath in line.split()] |
2598 | + self.assertEqual(len(kname), 1) |
2599 | + kname = os.path.basename(kname.pop()) |
2600 | + return kname |
2601 | + |
2602 | def _bcache_to_byuuid(self, kname): |
2603 | # extract bcache uuid from /dev/bcache/by-uuid on /dev/<kname> |
2604 | # parsing ls -al output on /dev/bcache/by-uuid |
2605 | @@ -1968,25 +2024,44 @@ class VMBaseClass(TestCase): |
2606 | |
2607 | @skip_if_flag('expected_failure') |
2608 | def test_swaps_used(self): |
2609 | - if not self.has_storage_config(): |
2610 | - raise SkipTest("This test does not use storage config.") |
2611 | |
2612 | - stgcfg = self.get_storage_config() |
2613 | - swap_ids = [d["id"] for d in stgcfg if d.get("fstype") == "swap"] |
2614 | - swap_mounts = [d for d in stgcfg if d.get("device") in swap_ids] |
2615 | - self.assertEqual(len(swap_ids), len(swap_mounts), |
2616 | - "number config swap fstypes != number swap mounts") |
2617 | + def find_fstab_swaps(): |
2618 | + swaps = [] |
2619 | + path = self.collect_path("fstab") |
2620 | + if not os.path.exists(path): |
2621 | + return swaps |
2622 | + for line in util.load_file(path).splitlines(): |
2623 | + if line.startswith("#"): |
2624 | + continue |
2625 | + (fs, mp, fstype, opts, dump, passno) = line.split() |
2626 | + if fstype == 'swap': |
2627 | + if fs.startswith('/dev/disk/by-uuid'): |
2628 | + swaps.append('/dev/' + self._byuuid_to_kname(fs)) |
2629 | + elif fs.startswith('/dev/disk/by-id'): |
2630 | + kname = self._serial_to_kname(os.path.basename(fs)) |
2631 | + swaps.append('/dev/' + kname) |
2632 | + elif fs.startswith('/dev/disk/by-path'): |
2633 | + swaps.append('/dev/' + self._bypath_to_kname(fs)) |
2634 | + else: |
2635 | + swaps.append(fs) |
2636 | + |
2637 | + return swaps |
2638 | + |
2639 | + # we don't yet have a skip_by_date on specific releases |
2640 | + if is_devel_release(self.target_release): |
2641 | + name = "test_swaps_used" |
2642 | + bug = "1894910" |
2643 | + fixby = "2020-10-15" |
2644 | + removeby = "2020-11-01" |
2645 | + raise SkipTest( |
2646 | + "skip_by_date({name}) LP: #{bug} " |
2647 | + "fixby={fixby} removeby={removeby}: ".format( |
2648 | + name=name, bug=bug, fixby=fixby, removeby=removeby)) |
2649 | |
2650 | - swaps_found = [] |
2651 | - for line in self.load_collect_file("proc-swaps").splitlines(): |
2652 | - fname, ttype, size, used, priority = line.split() |
2653 | - if ttype == "partition": |
2654 | - swaps_found.append( |
2655 | - {"fname": fname, ttype: "ttype", "size": int(size), |
2656 | - "used": int(used), "priority": int(priority)}) |
2657 | - self.assertEqual( |
2658 | - len(swap_mounts), len(swaps_found), |
2659 | - "Number swaps configured != number used") |
2660 | + expected_swaps = find_fstab_swaps() |
2661 | + proc_swaps = self.load_collect_file("proc-swaps") |
2662 | + for swap in expected_swaps: |
2663 | + self.assertIn(swap, proc_swaps) |
2664 | |
2665 | |
2666 | class PsuedoVMBaseClass(VMBaseClass): |
2667 | @@ -2085,6 +2160,9 @@ class PsuedoVMBaseClass(VMBaseClass): |
2668 | def test_kernel_img_conf(self): |
2669 | pass |
2670 | |
2671 | + def test_swaps_used(self): |
2672 | + pass |
2673 | + |
2674 | def _maybe_raise(self, exc): |
2675 | if self.allow_test_fails: |
2676 | raise exc |
2677 | diff --git a/tests/vmtests/releases.py b/tests/vmtests/releases.py |
2678 | index 3dcb415..11abcb8 100644 |
2679 | --- a/tests/vmtests/releases.py |
2680 | +++ b/tests/vmtests/releases.py |
2681 | @@ -185,6 +185,14 @@ class _FocalBase(_UbuntuBase): |
2682 | subarch = "ga-20.04" |
2683 | |
2684 | |
2685 | +class _GroovyBase(_UbuntuBase): |
2686 | + release = "groovy" |
2687 | + target_release = "groovy" |
2688 | + mem = "2048" |
2689 | + if _UbuntuBase.arch == "arm64": |
2690 | + subarch = "ga-20.04" |
2691 | + |
2692 | + |
2693 | class _Releases(object): |
2694 | trusty = _TrustyBase |
2695 | precise = _PreciseBase |
2696 | @@ -203,6 +211,7 @@ class _Releases(object): |
2697 | disco = _DiscoBase |
2698 | eoan = _EoanBase |
2699 | focal = _FocalBase |
2700 | + groovy = _GroovyBase |
2701 | |
2702 | |
2703 | class _CentosReleases(object): |
2704 | diff --git a/tests/vmtests/test_apt_config_cmd.py b/tests/vmtests/test_apt_config_cmd.py |
2705 | index 4e43882..874efad 100644 |
2706 | --- a/tests/vmtests/test_apt_config_cmd.py |
2707 | +++ b/tests/vmtests/test_apt_config_cmd.py |
2708 | @@ -41,7 +41,7 @@ class TestAptConfigCMD(VMBaseClass): |
2709 | self.check_file_regex("curtin-dev-ubuntu-test-archive-%s.list" % |
2710 | self.release, |
2711 | (r"http://ppa.launchpad.net/" |
2712 | - r"curtin-dev/test-archive/ubuntu" |
2713 | + r"curtin-dev/test-archive/ubuntu(/*)" |
2714 | r" %s main" % self.release)) |
2715 | |
2716 | def test_cmd_preserve_source(self): |
2717 | @@ -68,4 +68,8 @@ class FocalTestAptConfigCMDCMD(relbase.focal, TestAptConfigCMD): |
2718 | __test__ = True |
2719 | |
2720 | |
2721 | +class GroovyTestAptConfigCMDCMD(relbase.groovy, TestAptConfigCMD): |
2722 | + __test__ = True |
2723 | + |
2724 | + |
2725 | # vi: ts=4 expandtab syntax=python |
2726 | diff --git a/tests/vmtests/test_basic.py b/tests/vmtests/test_basic.py |
2727 | index e50318d..5723bc6 100644 |
2728 | --- a/tests/vmtests/test_basic.py |
2729 | +++ b/tests/vmtests/test_basic.py |
2730 | @@ -143,11 +143,16 @@ class TestBasicAbs(VMBaseClass): |
2731 | def get_fstab_expected(self): |
2732 | rootdev = self._serial_to_kname('disk-a') |
2733 | btrfsdev = self._serial_to_kname('disk-c') |
2734 | - return [ |
2735 | + expected = [ |
2736 | (self._kname_to_byuuid(rootdev + '1'), '/', 'defaults'), |
2737 | (self._kname_to_byuuid(rootdev + '2'), '/home', 'defaults'), |
2738 | - (self._kname_to_byuuid(btrfsdev), '/btrfs', 'defaults,noatime') |
2739 | + (self._kname_to_byuuid(btrfsdev), '/btrfs', 'defaults,noatime'), |
2740 | + (self._kname_to_byuuid(rootdev + '3'), 'none', 'sw'), |
2741 | ] |
2742 | + if self.target_release in ['focal']: |
2743 | + expected.append(('/btrfs/btrfsswap.img', 'none', 'sw')) |
2744 | + |
2745 | + return expected |
2746 | |
2747 | def test_whole_disk_uuid(self): |
2748 | self._test_whole_disk_uuid( |
2749 | @@ -250,11 +255,11 @@ class BionicTestBasic(relbase.bionic, TestBasicAbs): |
2750 | __test__ = True |
2751 | |
2752 | |
2753 | -class EoanTestBasic(relbase.eoan, TestBasicAbs): |
2754 | +class FocalTestBasic(relbase.focal, TestBasicAbs): |
2755 | __test__ = True |
2756 | |
2757 | |
2758 | -class FocalTestBasic(relbase.focal, TestBasicAbs): |
2759 | +class GroovyTestBasic(relbase.groovy, TestBasicAbs): |
2760 | __test__ = True |
2761 | |
2762 | |
2763 | @@ -307,14 +312,23 @@ class TestBasicScsiAbs(TestBasicAbs): |
2764 | home_kname = ( |
2765 | self._serial_to_kname('0x39cc071e72c64cc4-part2')) |
2766 | btrfs_kname = self._serial_to_kname('0x22dc58dc023c7008') |
2767 | + swap_kname = ( |
2768 | + self._serial_to_kname('0x39cc071e72c64cc4-part3')) |
2769 | |
2770 | map_func = self._kname_to_byuuid |
2771 | if self.arch == 's390x': |
2772 | map_func = self._kname_to_bypath |
2773 | |
2774 | - return [(map_func(root_kname), '/', 'defaults'), |
2775 | - (map_func(home_kname), '/home', 'defaults'), |
2776 | - (map_func(btrfs_kname), '/btrfs', 'defaults,noatime')] |
2777 | + expected = [ |
2778 | + (map_func(root_kname), '/', 'defaults'), |
2779 | + (map_func(home_kname), '/home', 'defaults'), |
2780 | + (map_func(btrfs_kname), '/btrfs', 'defaults,noatime'), |
2781 | + (map_func(swap_kname), 'none', 'sw')] |
2782 | + |
2783 | + if self.target_release in ['focal']: |
2784 | + expected.append(('/btrfs/btrfsswap.img', 'none', 'sw')) |
2785 | + |
2786 | + return expected |
2787 | |
2788 | @skip_if_arch('s390x') |
2789 | def test_whole_disk_uuid(self): |
2790 | @@ -340,7 +354,6 @@ class Centos70BionicTestScsiBasic(centos_relbase.centos70_bionic, |
2791 | __test__ = True |
2792 | |
2793 | |
2794 | -@VMBaseClass.skip_by_date("1859858", fixby="2020-03-06", install=False) |
2795 | class Centos70FocalTestScsiBasic(centos_relbase.centos70_focal, |
2796 | TestBasicScsiAbs, CentosTestBasicAbs): |
2797 | __test__ = True |
2798 | @@ -362,11 +375,11 @@ class BionicTestScsiBasic(relbase.bionic, TestBasicScsiAbs): |
2799 | __test__ = True |
2800 | |
2801 | |
2802 | -class EoanTestScsiBasic(relbase.eoan, TestBasicScsiAbs): |
2803 | +class FocalTestScsiBasic(relbase.focal, TestBasicScsiAbs): |
2804 | __test__ = True |
2805 | |
2806 | |
2807 | -class FocalTestScsiBasic(relbase.focal, TestBasicScsiAbs): |
2808 | +class GroovyTestScsiBasic(relbase.groovy, TestBasicScsiAbs): |
2809 | __test__ = True |
2810 | |
2811 | |
2812 | diff --git a/tests/vmtests/test_basic_dasd.py b/tests/vmtests/test_basic_dasd.py |
2813 | index 391bafc..d61e1b9 100644 |
2814 | --- a/tests/vmtests/test_basic_dasd.py |
2815 | +++ b/tests/vmtests/test_basic_dasd.py |
2816 | @@ -52,11 +52,11 @@ class BionicTestBasicDasd(relbase.bionic, TestBasicDasd): |
2817 | __test__ = True |
2818 | |
2819 | |
2820 | -class EoanTestBasicDasd(relbase.eoan, TestBasicDasd): |
2821 | +class FocalTestBasicDasd(relbase.focal, TestBasicDasd): |
2822 | __test__ = True |
2823 | |
2824 | |
2825 | -class FocalTestBasicDasd(relbase.focal, TestBasicDasd): |
2826 | +class GroovyTestBasicDasd(relbase.groovy, TestBasicDasd): |
2827 | __test__ = True |
2828 | |
2829 | |
2830 | diff --git a/tests/vmtests/test_bcache_basic.py b/tests/vmtests/test_bcache_basic.py |
2831 | index 54bac81..053225f 100644 |
2832 | --- a/tests/vmtests/test_bcache_basic.py |
2833 | +++ b/tests/vmtests/test_bcache_basic.py |
2834 | @@ -64,11 +64,11 @@ class BionicBcacheBasic(relbase.bionic, TestBcacheBasic): |
2835 | __test__ = True |
2836 | |
2837 | |
2838 | -class EoanBcacheBasic(relbase.eoan, TestBcacheBasic): |
2839 | +class FocalBcacheBasic(relbase.focal, TestBcacheBasic): |
2840 | __test__ = True |
2841 | |
2842 | |
2843 | -class FocalBcacheBasic(relbase.focal, TestBcacheBasic): |
2844 | +class GroovyBcacheBasic(relbase.groovy, TestBcacheBasic): |
2845 | __test__ = True |
2846 | |
2847 | |
2848 | diff --git a/tests/vmtests/test_bcache_bug1718699.py b/tests/vmtests/test_bcache_bug1718699.py |
2849 | index 8c29046..ebb99ab 100644 |
2850 | --- a/tests/vmtests/test_bcache_bug1718699.py |
2851 | +++ b/tests/vmtests/test_bcache_bug1718699.py |
2852 | @@ -19,11 +19,11 @@ class BionicTestBcacheBug1718699(relbase.bionic, TestBcacheBug1718699): |
2853 | __test__ = True |
2854 | |
2855 | |
2856 | -class EoanTestBcacheBug1718699(relbase.eoan, TestBcacheBug1718699): |
2857 | +class FocalTestBcacheBug1718699(relbase.focal, TestBcacheBug1718699): |
2858 | __test__ = True |
2859 | |
2860 | |
2861 | -class FocalTestBcacheBug1718699(relbase.focal, TestBcacheBug1718699): |
2862 | +class GroovyTestBcacheBug1718699(relbase.groovy, TestBcacheBug1718699): |
2863 | __test__ = True |
2864 | |
2865 | |
2866 | diff --git a/tests/vmtests/test_bcache_ceph.py b/tests/vmtests/test_bcache_ceph.py |
2867 | index d24994a..bff4dd4 100644 |
2868 | --- a/tests/vmtests/test_bcache_ceph.py |
2869 | +++ b/tests/vmtests/test_bcache_ceph.py |
2870 | @@ -75,11 +75,11 @@ class BionicTestBcacheCeph(relbase.bionic, TestBcacheCeph): |
2871 | __test__ = True |
2872 | |
2873 | |
2874 | -class EoanTestBcacheCeph(relbase.eoan, TestBcacheCeph): |
2875 | +class FocalTestBcacheCeph(relbase.focal, TestBcacheCeph): |
2876 | __test__ = True |
2877 | |
2878 | |
2879 | -class FocalTestBcacheCeph(relbase.focal, TestBcacheCeph): |
2880 | +class GroovyTestBcacheCeph(relbase.groovy, TestBcacheCeph): |
2881 | __test__ = True |
2882 | |
2883 | |
2884 | @@ -109,4 +109,8 @@ class FocalTestBcacheCephLvm(relbase.focal, TestBcacheCephLvm): |
2885 | __test__ = True |
2886 | |
2887 | |
2888 | +class GroovyTestBcacheCephLvm(relbase.groovy, TestBcacheCephLvm): |
2889 | + __test__ = True |
2890 | + |
2891 | + |
2892 | # vi: ts=4 expandtab syntax=python |
2893 | diff --git a/tests/vmtests/test_bcache_partitions.py b/tests/vmtests/test_bcache_partitions.py |
2894 | index f41e645..1ffea12 100644 |
2895 | --- a/tests/vmtests/test_bcache_partitions.py |
2896 | +++ b/tests/vmtests/test_bcache_partitions.py |
2897 | @@ -25,11 +25,11 @@ class BionicTestBcachePartitions(relbase.bionic, TestBcachePartitions): |
2898 | __test__ = True |
2899 | |
2900 | |
2901 | -class EoanTestBcachePartitions(relbase.eoan, TestBcachePartitions): |
2902 | +class FocalTestBcachePartitions(relbase.focal, TestBcachePartitions): |
2903 | __test__ = True |
2904 | |
2905 | |
2906 | -class FocalTestBcachePartitions(relbase.focal, TestBcachePartitions): |
2907 | +class GroovyTestBcachePartitions(relbase.groovy, TestBcachePartitions): |
2908 | __test__ = True |
2909 | |
2910 | |
2911 | diff --git a/tests/vmtests/test_fs_battery.py b/tests/vmtests/test_fs_battery.py |
2912 | index bd44905..7177fea 100644 |
2913 | --- a/tests/vmtests/test_fs_battery.py |
2914 | +++ b/tests/vmtests/test_fs_battery.py |
2915 | @@ -239,11 +239,11 @@ class BionicTestFsBattery(relbase.bionic, TestFsBattery): |
2916 | __test__ = True |
2917 | |
2918 | |
2919 | -class EoanTestFsBattery(relbase.eoan, TestFsBattery): |
2920 | +class FocalTestFsBattery(relbase.focal, TestFsBattery): |
2921 | __test__ = True |
2922 | |
2923 | |
2924 | -class FocalTestFsBattery(relbase.focal, TestFsBattery): |
2925 | +class GroovyTestFsBattery(relbase.groovy, TestFsBattery): |
2926 | __test__ = True |
2927 | |
2928 | |
2929 | diff --git a/tests/vmtests/test_iscsi.py b/tests/vmtests/test_iscsi.py |
2930 | index c99264c..f3406cd 100644 |
2931 | --- a/tests/vmtests/test_iscsi.py |
2932 | +++ b/tests/vmtests/test_iscsi.py |
2933 | @@ -72,11 +72,11 @@ class BionicTestIscsiBasic(relbase.bionic, TestBasicIscsiAbs): |
2934 | __test__ = True |
2935 | |
2936 | |
2937 | -class EoanTestIscsiBasic(relbase.eoan, TestBasicIscsiAbs): |
2938 | +class FocalTestIscsiBasic(relbase.focal, TestBasicIscsiAbs): |
2939 | __test__ = True |
2940 | |
2941 | |
2942 | -class FocalTestIscsiBasic(relbase.focal, TestBasicIscsiAbs): |
2943 | +class GroovyTestIscsiBasic(relbase.groovy, TestBasicIscsiAbs): |
2944 | __test__ = True |
2945 | |
2946 | |
2947 | diff --git a/tests/vmtests/test_journald_reporter.py b/tests/vmtests/test_journald_reporter.py |
2948 | index d29b4d4..ff003a5 100644 |
2949 | --- a/tests/vmtests/test_journald_reporter.py |
2950 | +++ b/tests/vmtests/test_journald_reporter.py |
2951 | @@ -32,11 +32,11 @@ class BionicTestJournaldReporter(relbase.bionic, TestJournaldReporter): |
2952 | __test__ = True |
2953 | |
2954 | |
2955 | -class EoanTestJournaldReporter(relbase.eoan, TestJournaldReporter): |
2956 | +class FocalTestJournaldReporter(relbase.focal, TestJournaldReporter): |
2957 | __test__ = True |
2958 | |
2959 | |
2960 | -class FocalTestJournaldReporter(relbase.focal, TestJournaldReporter): |
2961 | +class GroovyTestJournaldReporter(relbase.groovy, TestJournaldReporter): |
2962 | __test__ = True |
2963 | |
2964 | |
2965 | diff --git a/tests/vmtests/test_lvm.py b/tests/vmtests/test_lvm.py |
2966 | index a79a705..eb65c32 100644 |
2967 | --- a/tests/vmtests/test_lvm.py |
2968 | +++ b/tests/vmtests/test_lvm.py |
2969 | @@ -77,11 +77,11 @@ class BionicTestLvm(relbase.bionic, TestLvmAbs): |
2970 | __test__ = True |
2971 | |
2972 | |
2973 | -class EoanTestLvm(relbase.eoan, TestLvmAbs): |
2974 | +class FocalTestLvm(relbase.focal, TestLvmAbs): |
2975 | __test__ = True |
2976 | |
2977 | |
2978 | -class FocalTestLvm(relbase.focal, TestLvmAbs): |
2979 | +class GroovyTestLvm(relbase.groovy, TestLvmAbs): |
2980 | __test__ = True |
2981 | |
2982 | |
2983 | diff --git a/tests/vmtests/test_lvm_iscsi.py b/tests/vmtests/test_lvm_iscsi.py |
2984 | index 077b31a..e0b9606 100644 |
2985 | --- a/tests/vmtests/test_lvm_iscsi.py |
2986 | +++ b/tests/vmtests/test_lvm_iscsi.py |
2987 | @@ -95,11 +95,11 @@ class BionicTestIscsiLvm(relbase.bionic, TestLvmIscsiAbs): |
2988 | __test__ = True |
2989 | |
2990 | |
2991 | -class EoanTestIscsiLvm(relbase.eoan, TestLvmIscsiAbs): |
2992 | +class FocalTestIscsiLvm(relbase.focal, TestLvmIscsiAbs): |
2993 | __test__ = True |
2994 | |
2995 | |
2996 | -class FocalTestIscsiLvm(relbase.focal, TestLvmIscsiAbs): |
2997 | +class GroovyTestIscsiLvm(relbase.groovy, TestLvmIscsiAbs): |
2998 | __test__ = True |
2999 | |
3000 | |
3001 | diff --git a/tests/vmtests/test_lvm_raid.py b/tests/vmtests/test_lvm_raid.py |
3002 | index 8d42a1a..5fe7993 100644 |
3003 | --- a/tests/vmtests/test_lvm_raid.py |
3004 | +++ b/tests/vmtests/test_lvm_raid.py |
3005 | @@ -47,17 +47,17 @@ class TestLvmOverRaidAbs(TestMdadmAbs, TestLvmAbs): |
3006 | return self._test_pvs(dname_to_vg) |
3007 | |
3008 | |
3009 | -class FocalTestLvmOverRaid(relbase.focal, TestLvmOverRaidAbs): |
3010 | +class XenialGATestLvmOverRaid(relbase.xenial_ga, TestLvmOverRaidAbs): |
3011 | __test__ = True |
3012 | |
3013 | |
3014 | -class EoanTestLvmOverRaid(relbase.eoan, TestLvmOverRaidAbs): |
3015 | +class BionicTestLvmOverRaid(relbase.bionic, TestLvmOverRaidAbs): |
3016 | __test__ = True |
3017 | |
3018 | |
3019 | -class BionicTestLvmOverRaid(relbase.bionic, TestLvmOverRaidAbs): |
3020 | +class FocalTestLvmOverRaid(relbase.focal, TestLvmOverRaidAbs): |
3021 | __test__ = True |
3022 | |
3023 | |
3024 | -class XenialGATestLvmOverRaid(relbase.xenial_ga, TestLvmOverRaidAbs): |
3025 | +class GroovyTestLvmOverRaid(relbase.groovy, TestLvmOverRaidAbs): |
3026 | __test__ = True |
3027 | diff --git a/tests/vmtests/test_lvm_root.py b/tests/vmtests/test_lvm_root.py |
3028 | index 117406e..12b8ea8 100644 |
3029 | --- a/tests/vmtests/test_lvm_root.py |
3030 | +++ b/tests/vmtests/test_lvm_root.py |
3031 | @@ -94,6 +94,13 @@ class FocalTestLvmRootExt4(relbase.focal, TestLvmRootAbs): |
3032 | } |
3033 | |
3034 | |
3035 | +class GroovyTestLvmRootExt4(relbase.groovy, TestLvmRootAbs): |
3036 | + __test__ = True |
3037 | + conf_replace = { |
3038 | + '__ROOTFS_FORMAT__': 'ext4', |
3039 | + } |
3040 | + |
3041 | + |
3042 | class XenialTestLvmRootXfs(relbase.xenial, TestLvmRootAbs): |
3043 | __test__ = True |
3044 | conf_replace = { |
3045 | @@ -140,6 +147,14 @@ class FocalTestUefiLvmRootExt4(relbase.focal, TestUefiLvmRootAbs): |
3046 | } |
3047 | |
3048 | |
3049 | +class GroovyTestUefiLvmRootExt4(relbase.groovy, TestUefiLvmRootAbs): |
3050 | + __test__ = True |
3051 | + conf_replace = { |
3052 | + '__BOOTFS_FORMAT__': 'ext4', |
3053 | + '__ROOTFS_FORMAT__': 'ext4', |
3054 | + } |
3055 | + |
3056 | + |
3057 | class XenialTestUefiLvmRootXfs(relbase.xenial, TestUefiLvmRootAbs): |
3058 | __test__ = True |
3059 | conf_replace = { |
3060 | @@ -148,13 +163,11 @@ class XenialTestUefiLvmRootXfs(relbase.xenial, TestUefiLvmRootAbs): |
3061 | } |
3062 | |
3063 | |
3064 | -@VMBaseClass.skip_by_date("1652822", fixby="2020-06-01", install=False) |
3065 | class XenialTestUefiLvmRootXfsBootXfs(relbase.xenial, TestUefiLvmRootAbs): |
3066 | """This tests xfs root and xfs boot with uefi. |
3067 | |
3068 | - It is known broken (LP: #1652822) and unlikely to be fixed without pushing, |
3069 | - so we skip-by for a long time.""" |
3070 | - __test__ = True |
3071 | + It is known broken (LP: #1652822) and unlikely to be fixed.""" |
3072 | + __test__ = False |
3073 | conf_replace = { |
3074 | '__BOOTFS_FORMAT__': 'xfs', |
3075 | '__ROOTFS_FORMAT__': 'xfs', |
3076 | diff --git a/tests/vmtests/test_mdadm_bcache.py b/tests/vmtests/test_mdadm_bcache.py |
3077 | index 53637ae..5425221 100644 |
3078 | --- a/tests/vmtests/test_mdadm_bcache.py |
3079 | +++ b/tests/vmtests/test_mdadm_bcache.py |
3080 | @@ -26,6 +26,7 @@ class TestMdadmAbs(VMBaseClass): |
3081 | ls -al /dev/bcache* > lsal_dev_bcache_star |
3082 | ls -al /dev/bcache/by-uuid/ | cat >ls_al_bcache_byuuid |
3083 | ls -al /dev/bcache/by-label/ | cat >ls_al_bcache_bylabel |
3084 | + ls -al /dev/md/* | cat >ls_al_dev_md |
3085 | |
3086 | exit 0 |
3087 | """)] |
3088 | @@ -153,18 +154,18 @@ class BionicTestMdadmBcache(relbase.bionic, TestMdadmBcacheAbs): |
3089 | __test__ = True |
3090 | |
3091 | |
3092 | -class EoanTestMdadmBcache(relbase.eoan, TestMdadmBcacheAbs): |
3093 | - __test__ = True |
3094 | - |
3095 | - |
3096 | class FocalTestMdadmBcache(relbase.focal, TestMdadmBcacheAbs): |
3097 | __test__ = True |
3098 | |
3099 | - @TestMdadmBcacheAbs.skip_by_date("1861941", fixby="2020-04-15") |
3100 | + @TestMdadmBcacheAbs.skip_by_date("1861941", fixby="2020-09-15") |
3101 | def test_fstab(self): |
3102 | return super().test_fstab() |
3103 | |
3104 | |
3105 | +class GroovyTestMdadmBcache(relbase.groovy, TestMdadmBcacheAbs): |
3106 | + __test__ = True |
3107 | + |
3108 | + |
3109 | class TestMirrorbootAbs(TestMdadmAbs): |
3110 | # alternative config for more complex setup |
3111 | conf_file = "examples/tests/mirrorboot.yaml" |
3112 | @@ -202,11 +203,11 @@ class BionicTestMirrorboot(relbase.bionic, TestMirrorbootAbs): |
3113 | __test__ = True |
3114 | |
3115 | |
3116 | -class EoanTestMirrorboot(relbase.eoan, TestMirrorbootAbs): |
3117 | +class FocalTestMirrorboot(relbase.focal, TestMirrorbootAbs): |
3118 | __test__ = True |
3119 | |
3120 | |
3121 | -class FocalTestMirrorboot(relbase.focal, TestMirrorbootAbs): |
3122 | +class GroovyTestMirrorboot(relbase.groovy, TestMirrorbootAbs): |
3123 | __test__ = True |
3124 | |
3125 | |
3126 | @@ -250,13 +251,13 @@ class BionicTestMirrorbootPartitions(relbase.bionic, |
3127 | __test__ = True |
3128 | |
3129 | |
3130 | -class EoanTestMirrorbootPartitions(relbase.eoan, |
3131 | - TestMirrorbootPartitionsAbs): |
3132 | +class FocalTestMirrorbootPartitions(relbase.focal, |
3133 | + TestMirrorbootPartitionsAbs): |
3134 | __test__ = True |
3135 | |
3136 | |
3137 | -class FocalTestMirrorbootPartitions(relbase.focal, |
3138 | - TestMirrorbootPartitionsAbs): |
3139 | +class GroovyTestMirrorbootPartitions(relbase.groovy, |
3140 | + TestMirrorbootPartitionsAbs): |
3141 | __test__ = True |
3142 | |
3143 | |
3144 | @@ -309,6 +310,16 @@ class TestMirrorbootPartitionsUEFIAbs(TestMdadmAbs): |
3145 | self.assertIn( |
3146 | ('grub-pc', 'grub-efi/install_devices', choice), found_selections) |
3147 | |
3148 | + def test_backup_esp_matches_primary(self): |
3149 | + if self.target_distro != "ubuntu": |
3150 | + raise SkipTest("backup ESP supported only on Ubuntu") |
3151 | + if self.target_release in [ |
3152 | + "trusty", "xenial", "bionic", "cosmic", "disco", "eoan"]: |
3153 | + raise SkipTest("backup ESP supported only on >= Focal") |
3154 | + primary_esp = self.load_collect_file("diska-part1-efi.out") |
3155 | + backup_esp = self.load_collect_file("diskb-part1-efi.out") |
3156 | + self.assertEqual(primary_esp, backup_esp) |
3157 | + |
3158 | |
3159 | class Centos70TestMirrorbootPartitionsUEFI(centos_relbase.centos70_xenial, |
3160 | TestMirrorbootPartitionsUEFIAbs): |
3161 | @@ -335,19 +346,14 @@ class BionicTestMirrorbootPartitionsUEFI(relbase.bionic, |
3162 | __test__ = True |
3163 | |
3164 | |
3165 | -class EoanTestMirrorbootPartitionsUEFI(relbase.eoan, |
3166 | - TestMirrorbootPartitionsUEFIAbs): |
3167 | - __test__ = True |
3168 | - |
3169 | - |
3170 | class FocalTestMirrorbootPartitionsUEFI(relbase.focal, |
3171 | TestMirrorbootPartitionsUEFIAbs): |
3172 | __test__ = True |
3173 | |
3174 | - def test_backup_esp_matches_primary(self): |
3175 | - primary_esp = self.load_collect_file("diska-part1-efi.out") |
3176 | - backup_esp = self.load_collect_file("diskb-part1-efi.out") |
3177 | - self.assertEqual(primary_esp, backup_esp) |
3178 | + |
3179 | +class GroovyTestMirrorbootPartitionsUEFI(relbase.groovy, |
3180 | + TestMirrorbootPartitionsUEFIAbs): |
3181 | + __test__ = True |
3182 | |
3183 | |
3184 | class TestRaid5bootAbs(TestMdadmAbs): |
3185 | @@ -359,11 +365,14 @@ class TestRaid5bootAbs(TestMdadmAbs): |
3186 | ('main_disk', 2), |
3187 | ('second_disk', 1), |
3188 | ('third_disk', 1), |
3189 | - ('md0', 0)] |
3190 | + ('os-raid1', 0)] |
3191 | |
3192 | def get_fstab_expected(self): |
3193 | + kname = self._mdname_to_kname('os-raid1') |
3194 | return [ |
3195 | - (self._kname_to_uuid_devpath('md-uuid', 'md0'), '/', 'defaults'), |
3196 | + (self._kname_to_uuid_devpath('md-uuid', kname), |
3197 | + '/', |
3198 | + 'defaults'), |
3199 | ] |
3200 | |
3201 | |
3202 | @@ -387,11 +396,11 @@ class BionicTestRaid5boot(relbase.bionic, TestRaid5bootAbs): |
3203 | __test__ = True |
3204 | |
3205 | |
3206 | -class EoanTestRaid5boot(relbase.eoan, TestRaid5bootAbs): |
3207 | +class FocalTestRaid5boot(relbase.focal, TestRaid5bootAbs): |
3208 | __test__ = True |
3209 | |
3210 | |
3211 | -class FocalTestRaid5boot(relbase.focal, TestRaid5bootAbs): |
3212 | +class GroovyTestRaid5boot(relbase.groovy, TestRaid5bootAbs): |
3213 | __test__ = True |
3214 | |
3215 | |
3216 | @@ -448,11 +457,11 @@ class BionicTestRaid6boot(relbase.bionic, TestRaid6bootAbs): |
3217 | __test__ = True |
3218 | |
3219 | |
3220 | -class EoanTestRaid6boot(relbase.eoan, TestRaid6bootAbs): |
3221 | +class FocalTestRaid6boot(relbase.focal, TestRaid6bootAbs): |
3222 | __test__ = True |
3223 | |
3224 | |
3225 | -class FocalTestRaid6boot(relbase.focal, TestRaid6bootAbs): |
3226 | +class GroovyTestRaid6boot(relbase.groovy, TestRaid6bootAbs): |
3227 | __test__ = True |
3228 | |
3229 | |
3230 | @@ -495,11 +504,11 @@ class BionicTestRaid10boot(relbase.bionic, TestRaid10bootAbs): |
3231 | __test__ = True |
3232 | |
3233 | |
3234 | -class EoanTestRaid10boot(relbase.eoan, TestRaid10bootAbs): |
3235 | +class FocalTestRaid10boot(relbase.focal, TestRaid10bootAbs): |
3236 | __test__ = True |
3237 | |
3238 | |
3239 | -class FocalTestRaid10boot(relbase.focal, TestRaid10bootAbs): |
3240 | +class GroovyTestRaid10boot(relbase.groovy, TestRaid10bootAbs): |
3241 | __test__ = True |
3242 | |
3243 | |
3244 | @@ -599,11 +608,11 @@ class BionicTestAllindata(relbase.bionic, TestAllindataAbs): |
3245 | __test__ = True |
3246 | |
3247 | |
3248 | -class EoanTestAllindata(relbase.eoan, TestAllindataAbs): |
3249 | +class FocalTestAllindata(relbase.focal, TestAllindataAbs): |
3250 | __test__ = True |
3251 | |
3252 | |
3253 | -class FocalTestAllindata(relbase.focal, TestAllindataAbs): |
3254 | +class GroovyTestAllindata(relbase.groovy, TestAllindataAbs): |
3255 | __test__ = True |
3256 | |
3257 | |
3258 | diff --git a/tests/vmtests/test_mdadm_iscsi.py b/tests/vmtests/test_mdadm_iscsi.py |
3259 | index 26b1f71..7e6fbf6 100644 |
3260 | --- a/tests/vmtests/test_mdadm_iscsi.py |
3261 | +++ b/tests/vmtests/test_mdadm_iscsi.py |
3262 | @@ -50,11 +50,11 @@ class BionicTestIscsiMdadm(relbase.bionic, TestMdadmIscsiAbs): |
3263 | __test__ = True |
3264 | |
3265 | |
3266 | -class EoanTestIscsiMdadm(relbase.eoan, TestMdadmIscsiAbs): |
3267 | +class FocalTestIscsiMdadm(relbase.focal, TestMdadmIscsiAbs): |
3268 | __test__ = True |
3269 | |
3270 | |
3271 | -class FocalTestIscsiMdadm(relbase.focal, TestMdadmIscsiAbs): |
3272 | +class GroovyTestIscsiMdadm(relbase.groovy, TestMdadmIscsiAbs): |
3273 | __test__ = True |
3274 | |
3275 | |
3276 | diff --git a/tests/vmtests/test_multipath.py b/tests/vmtests/test_multipath.py |
3277 | index 7c7e621..6d9c5df 100644 |
3278 | --- a/tests/vmtests/test_multipath.py |
3279 | +++ b/tests/vmtests/test_multipath.py |
3280 | @@ -158,11 +158,11 @@ class BionicTestMultipathBasic(relbase.bionic, TestMultipathBasicAbs): |
3281 | __test__ = True |
3282 | |
3283 | |
3284 | -class EoanTestMultipathBasic(relbase.eoan, TestMultipathBasicAbs): |
3285 | +class FocalTestMultipathBasic(relbase.focal, TestMultipathBasicAbs): |
3286 | __test__ = True |
3287 | |
3288 | |
3289 | -class FocalTestMultipathBasic(relbase.focal, TestMultipathBasicAbs): |
3290 | +class GroovyTestMultipathBasic(relbase.groovy, TestMultipathBasicAbs): |
3291 | __test__ = True |
3292 | |
3293 | |
3294 | diff --git a/tests/vmtests/test_multipath_lvm.py b/tests/vmtests/test_multipath_lvm.py |
3295 | index 39b8587..c5a1e42 100644 |
3296 | --- a/tests/vmtests/test_multipath_lvm.py |
3297 | +++ b/tests/vmtests/test_multipath_lvm.py |
3298 | @@ -56,11 +56,11 @@ class BionicTestMultipathLvm(relbase.bionic, TestMultipathLvmAbs): |
3299 | __test__ = True |
3300 | |
3301 | |
3302 | -class EoanTestMultipathLvm(relbase.eoan, TestMultipathLvmAbs): |
3303 | +class FocalTestMultipathLvm(relbase.focal, TestMultipathLvmAbs): |
3304 | __test__ = True |
3305 | |
3306 | |
3307 | -class FocalTestMultipathLvm(relbase.focal, TestMultipathLvmAbs): |
3308 | +class GroovyTestMultipathLvm(relbase.groovy, TestMultipathLvmAbs): |
3309 | __test__ = True |
3310 | |
3311 | |
3312 | @@ -73,4 +73,9 @@ class FocalTestMultipathLvmPartWipe(relbase.focal, |
3313 | __test__ = True |
3314 | |
3315 | |
3316 | +class GroovyTestMultipathLvmPartWipe(relbase.groovy, |
3317 | + TestMultipathLvmPartWipeAbs): |
3318 | + __test__ = True |
3319 | + |
3320 | + |
3321 | # vi: ts=4 expandtab syntax=python |
3322 | diff --git a/tests/vmtests/test_network.py b/tests/vmtests/test_network.py |
3323 | index e6ea6e2..43a7c6b 100644 |
3324 | --- a/tests/vmtests/test_network.py |
3325 | +++ b/tests/vmtests/test_network.py |
3326 | @@ -474,11 +474,11 @@ class BionicTestNetworkBasic(relbase.bionic, TestNetworkBasicAbs): |
3327 | __test__ = True |
3328 | |
3329 | |
3330 | -class EoanTestNetworkBasic(relbase.eoan, TestNetworkBasicAbs): |
3331 | +class FocalTestNetworkBasic(relbase.focal, TestNetworkBasicAbs): |
3332 | __test__ = True |
3333 | |
3334 | |
3335 | -class FocalTestNetworkBasic(relbase.focal, TestNetworkBasicAbs): |
3336 | +class GroovyTestNetworkBasic(relbase.groovy, TestNetworkBasicAbs): |
3337 | __test__ = True |
3338 | |
3339 | |
3340 | diff --git a/tests/vmtests/test_network_alias.py b/tests/vmtests/test_network_alias.py |
3341 | index 68e7de4..bc1fb22 100644 |
3342 | --- a/tests/vmtests/test_network_alias.py |
3343 | +++ b/tests/vmtests/test_network_alias.py |
3344 | @@ -52,11 +52,11 @@ class BionicTestNetworkAlias(relbase.bionic, TestNetworkAliasAbs): |
3345 | __test__ = True |
3346 | |
3347 | |
3348 | -class EoanTestNetworkAlias(relbase.eoan, TestNetworkAliasAbs): |
3349 | +class FocalTestNetworkAlias(relbase.focal, TestNetworkAliasAbs): |
3350 | __test__ = True |
3351 | |
3352 | |
3353 | -class FocalTestNetworkAlias(relbase.focal, TestNetworkAliasAbs): |
3354 | +class GroovyTestNetworkAlias(relbase.groovy, TestNetworkAliasAbs): |
3355 | __test__ = True |
3356 | |
3357 | |
3358 | diff --git a/tests/vmtests/test_network_bonding.py b/tests/vmtests/test_network_bonding.py |
3359 | index 913c7ff..6c6dd6d 100644 |
3360 | --- a/tests/vmtests/test_network_bonding.py |
3361 | +++ b/tests/vmtests/test_network_bonding.py |
3362 | @@ -57,11 +57,11 @@ class BionicTestBonding(relbase.bionic, TestNetworkBondingAbs): |
3363 | __test__ = True |
3364 | |
3365 | |
3366 | -class EoanTestBonding(relbase.eoan, TestNetworkBondingAbs): |
3367 | +class FocalTestBonding(relbase.focal, TestNetworkBondingAbs): |
3368 | __test__ = True |
3369 | |
3370 | |
3371 | -class FocalTestBonding(relbase.focal, TestNetworkBondingAbs): |
3372 | +class GroovyTestBonding(relbase.groovy, TestNetworkBondingAbs): |
3373 | __test__ = True |
3374 | |
3375 | |
3376 | diff --git a/tests/vmtests/test_network_bridging.py b/tests/vmtests/test_network_bridging.py |
3377 | index daaade5..9ecd2f6 100644 |
3378 | --- a/tests/vmtests/test_network_bridging.py |
3379 | +++ b/tests/vmtests/test_network_bridging.py |
3380 | @@ -236,11 +236,11 @@ class BionicTestBridging(relbase.bionic, TestBridgeNetworkAbs): |
3381 | __test__ = True |
3382 | |
3383 | |
3384 | -class EoanTestBridging(relbase.eoan, TestBridgeNetworkAbs): |
3385 | +class FocalTestBridging(relbase.focal, TestBridgeNetworkAbs): |
3386 | __test__ = True |
3387 | |
3388 | |
3389 | -class FocalTestBridging(relbase.focal, TestBridgeNetworkAbs): |
3390 | +class GroovyTestBridging(relbase.groovy, TestBridgeNetworkAbs): |
3391 | __test__ = True |
3392 | |
3393 | |
3394 | diff --git a/tests/vmtests/test_network_disabled.py b/tests/vmtests/test_network_disabled.py |
3395 | index b19ca64..ea8dae2 100644 |
3396 | --- a/tests/vmtests/test_network_disabled.py |
3397 | +++ b/tests/vmtests/test_network_disabled.py |
3398 | @@ -57,6 +57,11 @@ class FocalCurtinDisableNetworkRendering(relbase.focal, |
3399 | __test__ = True |
3400 | |
3401 | |
3402 | +class GroovyCurtinDisableNetworkRendering(relbase.groovy, |
3403 | + CurtinDisableNetworkRendering): |
3404 | + __test__ = True |
3405 | + |
3406 | + |
3407 | class FocalCurtinDisableCloudInitNetworkingVersion1( |
3408 | relbase.focal, |
3409 | CurtinDisableCloudInitNetworkingVersion1 |
3410 | @@ -64,9 +69,21 @@ class FocalCurtinDisableCloudInitNetworkingVersion1( |
3411 | __test__ = True |
3412 | |
3413 | |
3414 | +class GroovyCurtinDisableCloudInitNetworkingVersion1( |
3415 | + relbase.groovy, |
3416 | + CurtinDisableCloudInitNetworkingVersion1 |
3417 | +): |
3418 | + __test__ = True |
3419 | + |
3420 | + |
3421 | class FocalCurtinDisableCloudInitNetworking(relbase.focal, |
3422 | CurtinDisableCloudInitNetworking): |
3423 | __test__ = True |
3424 | |
3425 | |
3426 | +class GroovyCurtinDisableCloudInitNetworking(relbase.groovy, |
3427 | + CurtinDisableCloudInitNetworking): |
3428 | + __test__ = True |
3429 | + |
3430 | + |
3431 | # vi: ts=4 expandtab syntax=python |
3432 | diff --git a/tests/vmtests/test_network_ipv6.py b/tests/vmtests/test_network_ipv6.py |
3433 | index 8f0dd54..50a139c 100644 |
3434 | --- a/tests/vmtests/test_network_ipv6.py |
3435 | +++ b/tests/vmtests/test_network_ipv6.py |
3436 | @@ -53,9 +53,13 @@ class BionicTestNetworkIPV6(relbase.bionic, TestNetworkIPV6Abs): |
3437 | __test__ = True |
3438 | |
3439 | |
3440 | -class EoanTestNetworkIPV6(relbase.eoan, TestNetworkIPV6Abs): |
3441 | +class GroovyTestNetworkIPV6(relbase.groovy, TestNetworkIPV6Abs): |
3442 | __test__ = True |
3443 | |
3444 | + @TestNetworkIPV6Abs.skip_by_date("1888726", "2020-10-15") |
3445 | + def test_ip_output(self): |
3446 | + return super().test_ip_output() |
3447 | + |
3448 | |
3449 | class Centos66TestNetworkIPV6(centos_relbase.centos66_xenial, |
3450 | CentosTestNetworkIPV6Abs): |
3451 | diff --git a/tests/vmtests/test_network_ipv6_static.py b/tests/vmtests/test_network_ipv6_static.py |
3452 | index 8a1ba2f..28ff697 100644 |
3453 | --- a/tests/vmtests/test_network_ipv6_static.py |
3454 | +++ b/tests/vmtests/test_network_ipv6_static.py |
3455 | @@ -23,11 +23,11 @@ class BionicTestNetworkIPV6Static(relbase.bionic, TestNetworkIPV6StaticAbs): |
3456 | __test__ = True |
3457 | |
3458 | |
3459 | -class EoanTestNetworkIPV6Static(relbase.eoan, TestNetworkIPV6StaticAbs): |
3460 | +class FocalTestNetworkIPV6Static(relbase.focal, TestNetworkIPV6StaticAbs): |
3461 | __test__ = True |
3462 | |
3463 | |
3464 | -class FocalTestNetworkIPV6Static(relbase.focal, TestNetworkIPV6StaticAbs): |
3465 | +class GroovyTestNetworkIPV6Static(relbase.groovy, TestNetworkIPV6StaticAbs): |
3466 | __test__ = True |
3467 | |
3468 | |
3469 | diff --git a/tests/vmtests/test_network_ipv6_vlan.py b/tests/vmtests/test_network_ipv6_vlan.py |
3470 | index 6d38621..a0bf267 100644 |
3471 | --- a/tests/vmtests/test_network_ipv6_vlan.py |
3472 | +++ b/tests/vmtests/test_network_ipv6_vlan.py |
3473 | @@ -22,17 +22,17 @@ class BionicTestNetworkIPV6Vlan(relbase.bionic, TestNetworkIPV6VlanAbs): |
3474 | __test__ = True |
3475 | |
3476 | |
3477 | -class EoanTestNetworkIPV6Vlan(relbase.eoan, TestNetworkIPV6VlanAbs): |
3478 | +class FocalTestNetworkIPV6Vlan(relbase.focal, TestNetworkIPV6VlanAbs): |
3479 | __test__ = True |
3480 | |
3481 | - @TestNetworkVlanAbs.skip_by_date("1846232", fixby="2020-03-10") |
3482 | - def test_ip_output(self): |
3483 | - return super().test_ip_output() |
3484 | - |
3485 | |
3486 | -class FocalTestNetworkIPV6Vlan(relbase.focal, TestNetworkIPV6VlanAbs): |
3487 | +class GroovyTestNetworkIPV6Vlan(relbase.groovy, TestNetworkIPV6VlanAbs): |
3488 | __test__ = True |
3489 | |
3490 | + @TestNetworkVlanAbs.skip_by_date("1888726", "2020-10-15") |
3491 | + def test_ip_output(self): |
3492 | + return super().test_ip_output() |
3493 | + |
3494 | |
3495 | class Centos66TestNetworkIPV6Vlan(centos_relbase.centos66_xenial, |
3496 | CentosTestNetworkIPV6VlanAbs): |
3497 | diff --git a/tests/vmtests/test_network_mtu.py b/tests/vmtests/test_network_mtu.py |
3498 | index bf13459..c70b9e0 100644 |
3499 | --- a/tests/vmtests/test_network_mtu.py |
3500 | +++ b/tests/vmtests/test_network_mtu.py |
3501 | @@ -137,6 +137,10 @@ class TestNetworkMtuAbs(TestNetworkIPV6Abs): |
3502 | self._check_iface_subnets('interface7') |
3503 | |
3504 | |
3505 | +class TestNetworkMtuNetworkdAbs(TestNetworkMtuAbs): |
3506 | + conf_file = "examples/tests/network_mtu_networkd.yaml" |
3507 | + |
3508 | + |
3509 | class CentosTestNetworkMtuAbs(TestNetworkMtuAbs): |
3510 | conf_file = "examples/tests/network_mtu.yaml" |
3511 | extra_collect_scripts = TestNetworkMtuAbs.extra_collect_scripts + [ |
3512 | @@ -181,28 +185,16 @@ class TestNetworkMtu(relbase.xenial, TestNetworkMtuAbs): |
3513 | __test__ = True |
3514 | |
3515 | |
3516 | -class BionicTestNetworkMtu(relbase.bionic, TestNetworkMtuAbs): |
3517 | - conf_file = "examples/tests/network_mtu_networkd.yaml" |
3518 | +class BionicTestNetworkMtu(relbase.bionic, TestNetworkMtuNetworkdAbs): |
3519 | __test__ = True |
3520 | - # Until systemd is released with the fix for LP:#1671951 |
3521 | - add_repos = "ppa:ddstreet/systemd" |
3522 | - upgrade_packages = "cloud-init,systemd" |
3523 | |
3524 | |
3525 | -class EoanTestNetworkMtu(relbase.eoan, TestNetworkMtuAbs): |
3526 | - conf_file = "examples/tests/network_mtu_networkd.yaml" |
3527 | +class FocalTestNetworkMtu(relbase.focal, TestNetworkMtuNetworkdAbs): |
3528 | __test__ = True |
3529 | - # Until systemd is released with the fix for LP:#1671951 |
3530 | - add_repos = "ppa:ddstreet/systemd" |
3531 | - upgrade_packages = "cloud-init,systemd" |
3532 | |
3533 | |
3534 | -class FocalTestNetworkMtu(relbase.focal, TestNetworkMtuAbs): |
3535 | - conf_file = "examples/tests/network_mtu_networkd.yaml" |
3536 | +class GroovyTestNetworkMtu(relbase.groovy, TestNetworkMtuNetworkdAbs): |
3537 | __test__ = True |
3538 | - # Until systemd is released with the fix for LP:#1671951 |
3539 | - add_repos = "ppa:ddstreet/systemd" |
3540 | - upgrade_packages = "cloud-init,systemd" |
3541 | |
3542 | |
3543 | class Centos66TestNetworkMtu(centos_relbase.centos66_xenial, |
3544 | diff --git a/tests/vmtests/test_network_ovs.py b/tests/vmtests/test_network_ovs.py |
3545 | index 3e23bd0..0cee17e 100644 |
3546 | --- a/tests/vmtests/test_network_ovs.py |
3547 | +++ b/tests/vmtests/test_network_ovs.py |
3548 | @@ -34,12 +34,11 @@ class BionicTestNetworkOvs(relbase.bionic, TestNetworkOvsAbs): |
3549 | __test__ = True |
3550 | |
3551 | |
3552 | -class EoanTestNetworkOvs(relbase.eoan, TestNetworkOvsAbs): |
3553 | +class FocalTestNetworkOvs(relbase.focal, TestNetworkOvsAbs): |
3554 | __test__ = True |
3555 | |
3556 | |
3557 | -class FocalTestNetworkOvs(relbase.focal, TestNetworkOvsAbs): |
3558 | +class GroovyTestNetworkOvs(relbase.groovy, TestNetworkOvsAbs): |
3559 | __test__ = True |
3560 | |
3561 | - |
3562 | # vi: ts=4 expandtab syntax=python |
3563 | diff --git a/tests/vmtests/test_network_static.py b/tests/vmtests/test_network_static.py |
3564 | index 80ff2cd..e0abd54 100644 |
3565 | --- a/tests/vmtests/test_network_static.py |
3566 | +++ b/tests/vmtests/test_network_static.py |
3567 | @@ -28,11 +28,11 @@ class BionicTestNetworkStatic(relbase.bionic, TestNetworkStaticAbs): |
3568 | __test__ = True |
3569 | |
3570 | |
3571 | -class EoanTestNetworkStatic(relbase.eoan, TestNetworkStaticAbs): |
3572 | +class FocalTestNetworkStatic(relbase.focal, TestNetworkStaticAbs): |
3573 | __test__ = True |
3574 | |
3575 | |
3576 | -class FocalTestNetworkStatic(relbase.focal, TestNetworkStaticAbs): |
3577 | +class GroovyTestNetworkStatic(relbase.groovy, TestNetworkStaticAbs): |
3578 | __test__ = True |
3579 | |
3580 | |
3581 | diff --git a/tests/vmtests/test_network_static_routes.py b/tests/vmtests/test_network_static_routes.py |
3582 | index dfcbffe..f99d9d5 100644 |
3583 | --- a/tests/vmtests/test_network_static_routes.py |
3584 | +++ b/tests/vmtests/test_network_static_routes.py |
3585 | @@ -28,13 +28,13 @@ class BionicTestNetworkStaticRoutes(relbase.bionic, |
3586 | __test__ = True |
3587 | |
3588 | |
3589 | -class EoanTestNetworkStaticRoutes(relbase.eoan, |
3590 | - TestNetworkStaticRoutesAbs): |
3591 | +class FocalTestNetworkStaticRoutes(relbase.focal, |
3592 | + TestNetworkStaticRoutesAbs): |
3593 | __test__ = True |
3594 | |
3595 | |
3596 | -class FocalTestNetworkStaticRoutes(relbase.focal, |
3597 | - TestNetworkStaticRoutesAbs): |
3598 | +class GroovyTestNetworkStaticRoutes(relbase.groovy, |
3599 | + TestNetworkStaticRoutesAbs): |
3600 | __test__ = True |
3601 | |
3602 | |
3603 | diff --git a/tests/vmtests/test_network_vlan.py b/tests/vmtests/test_network_vlan.py |
3604 | index cdd06c3..9f1094b 100644 |
3605 | --- a/tests/vmtests/test_network_vlan.py |
3606 | +++ b/tests/vmtests/test_network_vlan.py |
3607 | @@ -76,18 +76,17 @@ class BionicTestNetworkVlan(relbase.bionic, TestNetworkVlanAbs): |
3608 | __test__ = True |
3609 | |
3610 | |
3611 | -class EoanTestNetworkVlan(relbase.eoan, TestNetworkVlanAbs): |
3612 | +class FocalTestNetworkVlan(relbase.focal, TestNetworkVlanAbs): |
3613 | __test__ = True |
3614 | |
3615 | - @TestNetworkBaseTestsAbs.skip_by_date("1846232", fixby="2020-03-10") |
3616 | def test_ip_output(self): |
3617 | return super().test_ip_output() |
3618 | |
3619 | |
3620 | -class FocalTestNetworkVlan(relbase.focal, TestNetworkVlanAbs): |
3621 | +class GroovyTestNetworkVlan(relbase.groovy, TestNetworkVlanAbs): |
3622 | __test__ = True |
3623 | |
3624 | - @TestNetworkBaseTestsAbs.skip_by_date("1846232", fixby="2020-03-10") |
3625 | + @TestNetworkVlanAbs.skip_by_date("1888726", "2020-10-15") |
3626 | def test_ip_output(self): |
3627 | return super().test_ip_output() |
3628 | |
3629 | diff --git a/tests/vmtests/test_nvme.py b/tests/vmtests/test_nvme.py |
3630 | index ca36ca8..39f9f3c 100644 |
3631 | --- a/tests/vmtests/test_nvme.py |
3632 | +++ b/tests/vmtests/test_nvme.py |
3633 | @@ -73,7 +73,7 @@ class BionicTestNvme(relbase.bionic, TestNvmeAbs): |
3634 | __test__ = True |
3635 | |
3636 | |
3637 | -class EoanTestNvme(relbase.eoan, TestNvmeAbs): |
3638 | +class GroovyTestNvme(relbase.groovy, TestNvmeAbs): |
3639 | __test__ = True |
3640 | |
3641 | |
3642 | @@ -139,12 +139,11 @@ class BionicTestNvmeBcache(relbase.bionic, TestNvmeBcacheAbs): |
3643 | __test__ = True |
3644 | |
3645 | |
3646 | -class EoanTestNvmeBcache(relbase.eoan, TestNvmeBcacheAbs): |
3647 | +class FocalTestNvmeBcache(relbase.focal, TestNvmeBcacheAbs): |
3648 | __test__ = True |
3649 | |
3650 | |
3651 | -@TestNvmeBcacheAbs.skip_by_date("1861941", fixby="2020-04-15") |
3652 | -class FocalTestNvmeBcache(relbase.focal, TestNvmeBcacheAbs): |
3653 | +class GroovyTestNvmeBcache(relbase.groovy, TestNvmeBcacheAbs): |
3654 | __test__ = True |
3655 | |
3656 | |
3657 | diff --git a/tests/vmtests/test_panic.py b/tests/vmtests/test_panic.py |
3658 | index fe4005e..7b1fdbe 100644 |
3659 | --- a/tests/vmtests/test_panic.py |
3660 | +++ b/tests/vmtests/test_panic.py |
3661 | @@ -28,4 +28,9 @@ class TestInstallPanic(VMBaseClass): |
3662 | class FocalTestInstallPanic(relbase.focal, TestInstallPanic): |
3663 | __test__ = True |
3664 | |
3665 | + |
3666 | +class GroovyTestInstallPanic(relbase.groovy, TestInstallPanic): |
3667 | + __test__ = True |
3668 | + |
3669 | + |
3670 | # vi: ts=4 expandtab syntax=python |
3671 | diff --git a/tests/vmtests/test_pollinate_useragent.py b/tests/vmtests/test_pollinate_useragent.py |
3672 | index ff21f20..ed14719 100644 |
3673 | --- a/tests/vmtests/test_pollinate_useragent.py |
3674 | +++ b/tests/vmtests/test_pollinate_useragent.py |
3675 | @@ -61,11 +61,11 @@ class BionicTestPollinateUserAgent(relbase.bionic, TestPollinateUserAgent): |
3676 | __test__ = True |
3677 | |
3678 | |
3679 | -class EoanTestPollinateUserAgent(relbase.eoan, TestPollinateUserAgent): |
3680 | +class FocalTestPollinateUserAgent(relbase.focal, TestPollinateUserAgent): |
3681 | __test__ = True |
3682 | |
3683 | |
3684 | -class FocalTestPollinateUserAgent(relbase.focal, TestPollinateUserAgent): |
3685 | +class GroovyTestPollinateUserAgent(relbase.groovy, TestPollinateUserAgent): |
3686 | __test__ = True |
3687 | |
3688 | |
3689 | diff --git a/tests/vmtests/test_preserve.py b/tests/vmtests/test_preserve.py |
3690 | index f02ba6c..998218c 100644 |
3691 | --- a/tests/vmtests/test_preserve.py |
3692 | +++ b/tests/vmtests/test_preserve.py |
3693 | @@ -25,11 +25,11 @@ class BionicTestPreserve(relbase.bionic, TestPreserve): |
3694 | __test__ = True |
3695 | |
3696 | |
3697 | -class EoanTestPreserve(relbase.eoan, TestPreserve): |
3698 | +class FocalTestPreserve(relbase.focal, TestPreserve): |
3699 | __test__ = True |
3700 | |
3701 | |
3702 | -class FocalTestPreserve(relbase.focal, TestPreserve): |
3703 | +class GroovyTestPreserve(relbase.groovy, TestPreserve): |
3704 | __test__ = True |
3705 | |
3706 | |
3707 | diff --git a/tests/vmtests/test_preserve_bcache.py b/tests/vmtests/test_preserve_bcache.py |
3708 | index e2d2a34..bd91c5a 100644 |
3709 | --- a/tests/vmtests/test_preserve_bcache.py |
3710 | +++ b/tests/vmtests/test_preserve_bcache.py |
3711 | @@ -56,11 +56,11 @@ class BionicTestPreserveBcache(relbase.bionic, TestPreserveBcache): |
3712 | __test__ = True |
3713 | |
3714 | |
3715 | -class EoanTestPreserveBcache(relbase.eoan, TestPreserveBcache): |
3716 | +class FocalTestPreserveBcache(relbase.focal, TestPreserveBcache): |
3717 | __test__ = True |
3718 | |
3719 | |
3720 | -class FocalTestPreserveBcache(relbase.focal, TestPreserveBcache): |
3721 | +class GroovyTestPreserveBcache(relbase.groovy, TestPreserveBcache): |
3722 | __test__ = True |
3723 | |
3724 | |
3725 | diff --git a/tests/vmtests/test_preserve_lvm.py b/tests/vmtests/test_preserve_lvm.py |
3726 | index 90f15cb..0ed7ad4 100644 |
3727 | --- a/tests/vmtests/test_preserve_lvm.py |
3728 | +++ b/tests/vmtests/test_preserve_lvm.py |
3729 | @@ -69,11 +69,11 @@ class BionicTestLvmPreserve(relbase.bionic, TestLvmPreserveAbs): |
3730 | __test__ = True |
3731 | |
3732 | |
3733 | -class EoanTestLvmPreserve(relbase.eoan, TestLvmPreserveAbs): |
3734 | +class FocalTestLvmPreserve(relbase.focal, TestLvmPreserveAbs): |
3735 | __test__ = True |
3736 | |
3737 | |
3738 | -class FocalTestLvmPreserve(relbase.focal, TestLvmPreserveAbs): |
3739 | +class GroovyTestLvmPreserve(relbase.groovy, TestLvmPreserveAbs): |
3740 | __test__ = True |
3741 | |
3742 | |
3743 | diff --git a/tests/vmtests/test_preserve_partition_wipe_vg.py b/tests/vmtests/test_preserve_partition_wipe_vg.py |
3744 | index 96346ff..58b1f65 100644 |
3745 | --- a/tests/vmtests/test_preserve_partition_wipe_vg.py |
3746 | +++ b/tests/vmtests/test_preserve_partition_wipe_vg.py |
3747 | @@ -25,11 +25,11 @@ class BionicTestPreserveWipeLvm(relbase.bionic, TestPreserveWipeLvm): |
3748 | __test__ = True |
3749 | |
3750 | |
3751 | -class EoanTestPreserveWipeLvm(relbase.eoan, TestPreserveWipeLvm): |
3752 | +class FocalTestPreserveWipeLvm(relbase.focal, TestPreserveWipeLvm): |
3753 | __test__ = True |
3754 | |
3755 | |
3756 | -class FocalTestPreserveWipeLvm(relbase.focal, TestPreserveWipeLvm): |
3757 | +class GroovyTestPreserveWipeLvm(relbase.groovy, TestPreserveWipeLvm): |
3758 | __test__ = True |
3759 | |
3760 | |
3761 | @@ -48,11 +48,12 @@ class BionicTestPreserveWipeLvmSimple(relbase.bionic, |
3762 | __test__ = True |
3763 | |
3764 | |
3765 | -class EoanTestPreserveWipeLvmSimple(relbase.eoan, TestPreserveWipeLvmSimple): |
3766 | +class FocalTestPreserveWipeLvmSimple(relbase.focal, TestPreserveWipeLvmSimple): |
3767 | __test__ = True |
3768 | |
3769 | |
3770 | -class FocalTestPreserveWipeLvmSimple(relbase.focal, TestPreserveWipeLvmSimple): |
3771 | +class GroovyTestPreserveWipeLvmSimple(relbase.groovy, |
3772 | + TestPreserveWipeLvmSimple): |
3773 | __test__ = True |
3774 | |
3775 | |
3776 | diff --git a/tests/vmtests/test_preserve_raid.py b/tests/vmtests/test_preserve_raid.py |
3777 | index cf3a6bb..15f2f50 100644 |
3778 | --- a/tests/vmtests/test_preserve_raid.py |
3779 | +++ b/tests/vmtests/test_preserve_raid.py |
3780 | @@ -25,11 +25,11 @@ class BionicTestPreserveRAID(relbase.bionic, TestPreserveRAID): |
3781 | __test__ = True |
3782 | |
3783 | |
3784 | -class EoanTestPreserveRAID(relbase.eoan, TestPreserveRAID): |
3785 | +class FocalTestPreserveRAID(relbase.focal, TestPreserveRAID): |
3786 | __test__ = True |
3787 | |
3788 | |
3789 | -class FocalTestPreserveRAID(relbase.focal, TestPreserveRAID): |
3790 | +class GroovyTestPreserveRAID(relbase.groovy, TestPreserveRAID): |
3791 | __test__ = True |
3792 | |
3793 | |
3794 | diff --git a/tests/vmtests/test_raid5_bcache.py b/tests/vmtests/test_raid5_bcache.py |
3795 | index 7138a2c..3fdb217 100644 |
3796 | --- a/tests/vmtests/test_raid5_bcache.py |
3797 | +++ b/tests/vmtests/test_raid5_bcache.py |
3798 | @@ -88,16 +88,16 @@ class BionicTestRaid5Bcache(relbase.bionic, TestMdadmBcacheAbs): |
3799 | __test__ = True |
3800 | |
3801 | |
3802 | -class EoanTestRaid5Bcache(relbase.eoan, TestMdadmBcacheAbs): |
3803 | - __test__ = True |
3804 | - |
3805 | - |
3806 | class FocalTestRaid5Bcache(relbase.focal, TestMdadmBcacheAbs): |
3807 | __test__ = True |
3808 | |
3809 | - @TestMdadmBcacheAbs.skip_by_date("1861941", fixby="2020-04-15") |
3810 | + @TestMdadmBcacheAbs.skip_by_date("1861941", fixby="2020-09-15") |
3811 | def test_fstab(self): |
3812 | return super().test_fstab() |
3813 | |
3814 | |
3815 | +class GroovyTestRaid5Bcache(relbase.groovy, TestMdadmBcacheAbs): |
3816 | + __test__ = True |
3817 | + |
3818 | + |
3819 | # vi: ts=4 expandtab syntax=python |
3820 | diff --git a/tests/vmtests/test_reuse_lvm_member.py b/tests/vmtests/test_reuse_lvm_member.py |
3821 | index 749ea24..87afcfb 100644 |
3822 | --- a/tests/vmtests/test_reuse_lvm_member.py |
3823 | +++ b/tests/vmtests/test_reuse_lvm_member.py |
3824 | @@ -21,13 +21,13 @@ class BionicTestReuseLVMMemberPartition(relbase.bionic, |
3825 | __test__ = True |
3826 | |
3827 | |
3828 | -class EoanTestReuseLVMMemberPartition(relbase.eoan, |
3829 | - TestReuseLVMMemberPartition): |
3830 | +class FocalTestReuseLVMMemberPartition(relbase.focal, |
3831 | + TestReuseLVMMemberPartition): |
3832 | __test__ = True |
3833 | |
3834 | |
3835 | -class FocalTestReuseLVMMemberPartition(relbase.focal, |
3836 | - TestReuseLVMMemberPartition): |
3837 | +class GroovyTestReuseLVMMemberPartition(relbase.groovy, |
3838 | + TestReuseLVMMemberPartition): |
3839 | __test__ = True |
3840 | |
3841 | |
3842 | diff --git a/tests/vmtests/test_reuse_msdos_partitions.py b/tests/vmtests/test_reuse_msdos_partitions.py |
3843 | index f8e20d9..9f18d3c 100644 |
3844 | --- a/tests/vmtests/test_reuse_msdos_partitions.py |
3845 | +++ b/tests/vmtests/test_reuse_msdos_partitions.py |
3846 | @@ -18,13 +18,13 @@ class BionicTestReuseMSDOSPartitions(relbase.bionic, |
3847 | __test__ = True |
3848 | |
3849 | |
3850 | -class EoanTestReuseMSDOSPartitions(relbase.eoan, |
3851 | - TestReuseMSDOSPartitions): |
3852 | +class FocalTestReuseMSDOSPartitions(relbase.focal, |
3853 | + TestReuseMSDOSPartitions): |
3854 | __test__ = True |
3855 | |
3856 | |
3857 | -class FocalTestReuseMSDOSPartitions(relbase.focal, |
3858 | - TestReuseMSDOSPartitions): |
3859 | +class GroovyTestReuseMSDOSPartitions(relbase.groovy, |
3860 | + TestReuseMSDOSPartitions): |
3861 | __test__ = True |
3862 | |
3863 | |
3864 | diff --git a/tests/vmtests/test_reuse_raid_member.py b/tests/vmtests/test_reuse_raid_member.py |
3865 | index 425105f..7be98f3 100644 |
3866 | --- a/tests/vmtests/test_reuse_raid_member.py |
3867 | +++ b/tests/vmtests/test_reuse_raid_member.py |
3868 | @@ -28,11 +28,11 @@ class BionicTestReuseRAIDMember(relbase.bionic, TestReuseRAIDMember): |
3869 | __test__ = True |
3870 | |
3871 | |
3872 | -class EoanTestReuseRAIDMember(relbase.eoan, TestReuseRAIDMember): |
3873 | +class FocalTestReuseRAIDMember(relbase.focal, TestReuseRAIDMember): |
3874 | __test__ = True |
3875 | |
3876 | |
3877 | -class FocalTestReuseRAIDMember(relbase.focal, TestReuseRAIDMember): |
3878 | +class GroovyTestReuseRAIDMember(relbase.groovy, TestReuseRAIDMember): |
3879 | __test__ = True |
3880 | |
3881 | |
3882 | @@ -41,13 +41,13 @@ class BionicTestReuseRAIDMemberPartition(relbase.bionic, |
3883 | __test__ = True |
3884 | |
3885 | |
3886 | -class EoanTestReuseRAIDMemberPartition(relbase.eoan, |
3887 | - TestReuseRAIDMemberPartition): |
3888 | +class FocalTestReuseRAIDMemberPartition(relbase.focal, |
3889 | + TestReuseRAIDMemberPartition): |
3890 | __test__ = True |
3891 | |
3892 | |
3893 | -class FocalTestReuseRAIDMemberPartition(relbase.focal, |
3894 | - TestReuseRAIDMemberPartition): |
3895 | +class GroovyTestReuseRAIDMemberPartition(relbase.groovy, |
3896 | + TestReuseRAIDMemberPartition): |
3897 | __test__ = True |
3898 | |
3899 | |
3900 | diff --git a/tests/vmtests/test_reuse_uefi_esp.py b/tests/vmtests/test_reuse_uefi_esp.py |
3901 | index 1e99935..46e7ac7 100644 |
3902 | --- a/tests/vmtests/test_reuse_uefi_esp.py |
3903 | +++ b/tests/vmtests/test_reuse_uefi_esp.py |
3904 | @@ -3,17 +3,20 @@ |
3905 | from .test_uefi_basic import TestBasicAbs |
3906 | from .releases import base_vm_classes as relbase |
3907 | from .releases import centos_base_vm_classes as cent_rbase |
3908 | +from curtin.commands.curthooks import uefi_find_duplicate_entries |
3909 | +from curtin import util |
3910 | |
3911 | |
3912 | class TestUefiReuseEspAbs(TestBasicAbs): |
3913 | conf_file = "examples/tests/uefi_reuse_esp.yaml" |
3914 | |
3915 | def test_efiboot_menu_has_one_distro_entry(self): |
3916 | - efiboot_mgr_content = self.load_collect_file("efibootmgr.out") |
3917 | - distro_lines = [line for line in efiboot_mgr_content.splitlines() |
3918 | - if self.target_distro in line] |
3919 | - print(distro_lines) |
3920 | - self.assertEqual(1, len(distro_lines)) |
3921 | + efi_output = util.parse_efibootmgr( |
3922 | + self.load_collect_file("efibootmgr.out")) |
3923 | + duplicates = uefi_find_duplicate_entries( |
3924 | + grubcfg=None, target=None, efi_output=efi_output) |
3925 | + print(duplicates) |
3926 | + self.assertEqual(0, len(duplicates)) |
3927 | |
3928 | |
3929 | class Cent70TestUefiReuseEsp(cent_rbase.centos70_bionic, TestUefiReuseEspAbs): |
3930 | @@ -28,23 +31,20 @@ class XenialGATestUefiReuseEsp(relbase.xenial_ga, TestUefiReuseEspAbs): |
3931 | class BionicTestUefiReuseEsp(relbase.bionic, TestUefiReuseEspAbs): |
3932 | __test__ = True |
3933 | |
3934 | - @TestUefiReuseEspAbs.skip_by_date("1863015", fixby="2020-04-15") |
3935 | def test_efiboot_menu_has_one_distro_entry(self): |
3936 | return super().test_efiboot_menu_has_one_distro_entry() |
3937 | |
3938 | |
3939 | -class EoanTestUefiReuseEsp(relbase.eoan, TestUefiReuseEspAbs): |
3940 | +class FocalTestUefiReuseEsp(relbase.focal, TestUefiReuseEspAbs): |
3941 | __test__ = True |
3942 | |
3943 | - @TestUefiReuseEspAbs.skip_by_date("1863015", fixby="2020-04-15") |
3944 | def test_efiboot_menu_has_one_distro_entry(self): |
3945 | return super().test_efiboot_menu_has_one_distro_entry() |
3946 | |
3947 | |
3948 | -class FocalTestUefiReuseEsp(relbase.focal, TestUefiReuseEspAbs): |
3949 | +class GroovyTestUefiReuseEsp(relbase.groovy, TestUefiReuseEspAbs): |
3950 | __test__ = True |
3951 | |
3952 | - @TestUefiReuseEspAbs.skip_by_date("1863015", fixby="2020-04-15") |
3953 | def test_efiboot_menu_has_one_distro_entry(self): |
3954 | return super().test_efiboot_menu_has_one_distro_entry() |
3955 | |
3956 | diff --git a/tests/vmtests/test_simple.py b/tests/vmtests/test_simple.py |
3957 | index b34a6fc..9e71047 100644 |
3958 | --- a/tests/vmtests/test_simple.py |
3959 | +++ b/tests/vmtests/test_simple.py |
3960 | @@ -49,14 +49,14 @@ class BionicTestSimple(relbase.bionic, TestSimple): |
3961 | self.output_files_exist(["netplan.yaml"]) |
3962 | |
3963 | |
3964 | -class EoanTestSimple(relbase.eoan, TestSimple): |
3965 | +class FocalTestSimple(relbase.focal, TestSimple): |
3966 | __test__ = True |
3967 | |
3968 | def test_output_files_exist(self): |
3969 | self.output_files_exist(["netplan.yaml"]) |
3970 | |
3971 | |
3972 | -class FocalTestSimple(relbase.focal, TestSimple): |
3973 | +class GroovyTestSimple(relbase.groovy, TestSimple): |
3974 | __test__ = True |
3975 | |
3976 | def test_output_files_exist(self): |
3977 | @@ -105,14 +105,14 @@ class BionicTestSimpleStorage(relbase.bionic, TestSimpleStorage): |
3978 | self.output_files_exist(["netplan.yaml"]) |
3979 | |
3980 | |
3981 | -class EoanTestSimpleStorage(relbase.eoan, TestSimpleStorage): |
3982 | +class FocalTestSimpleStorage(relbase.focal, TestSimpleStorage): |
3983 | __test__ = True |
3984 | |
3985 | def test_output_files_exist(self): |
3986 | self.output_files_exist(["netplan.yaml"]) |
3987 | |
3988 | |
3989 | -class FocalTestSimpleStorage(relbase.focal, TestSimpleStorage): |
3990 | +class GroovyTestSimpleStorage(relbase.groovy, TestSimpleStorage): |
3991 | __test__ = True |
3992 | |
3993 | def test_output_files_exist(self): |
3994 | @@ -145,4 +145,11 @@ class FocalTestGrubNoDefaults(relbase.focal, TestGrubNoDefaults): |
3995 | self.output_files_exist(["netplan.yaml"]) |
3996 | |
3997 | |
3998 | +class GroovyTestGrubNoDefaults(relbase.groovy, TestGrubNoDefaults): |
3999 | + __test__ = True |
4000 | + |
4001 | + def test_output_files_exist(self): |
4002 | + self.output_files_exist(["netplan.yaml"]) |
4003 | + |
4004 | + |
4005 | # vi: ts=4 expandtab syntax=python |
4006 | diff --git a/tests/vmtests/test_uefi_basic.py b/tests/vmtests/test_uefi_basic.py |
4007 | index 90940dd..932c1c8 100644 |
4008 | --- a/tests/vmtests/test_uefi_basic.py |
4009 | +++ b/tests/vmtests/test_uefi_basic.py |
4010 | @@ -89,6 +89,11 @@ class PreciseHWETUefiTestBasic(relbase.precise_hwe_t, PreciseUefiTestBasic): |
4011 | __test__ = False |
4012 | |
4013 | |
4014 | +class TrustyHWEXUefiTestBasic(relbase.trusty_hwe_x, TestBasicAbs): |
4015 | + supported_releases = ['trusty'] # avoid unsupported release skiptest |
4016 | + __test__ = False |
4017 | + |
4018 | + |
4019 | class XenialGAUefiTestBasic(relbase.xenial_ga, TestBasicAbs): |
4020 | __test__ = True |
4021 | |
4022 | @@ -105,11 +110,11 @@ class BionicUefiTestBasic(relbase.bionic, TestBasicAbs): |
4023 | __test__ = True |
4024 | |
4025 | |
4026 | -class EoanUefiTestBasic(relbase.eoan, TestBasicAbs): |
4027 | +class FocalUefiTestBasic(relbase.focal, TestBasicAbs): |
4028 | __test__ = True |
4029 | |
4030 | |
4031 | -class FocalUefiTestBasic(relbase.focal, TestBasicAbs): |
4032 | +class GroovyUefiTestBasic(relbase.groovy, TestBasicAbs): |
4033 | __test__ = True |
4034 | |
4035 | |
4036 | @@ -128,12 +133,12 @@ class BionicUefiTestBasic4k(relbase.bionic, TestBasicAbs): |
4037 | disk_block_size = 4096 |
4038 | |
4039 | |
4040 | -class EoanUefiTestBasic4k(relbase.eoan, TestBasicAbs): |
4041 | +class FocalUefiTestBasic4k(relbase.focal, TestBasicAbs): |
4042 | __test__ = True |
4043 | disk_block_size = 4096 |
4044 | |
4045 | |
4046 | -class FocalUefiTestBasic4k(relbase.focal, TestBasicAbs): |
4047 | +class GroovyUefiTestBasic4k(relbase.groovy, TestBasicAbs): |
4048 | __test__ = True |
4049 | disk_block_size = 4096 |
4050 | |
4051 | diff --git a/tests/vmtests/test_zfsroot.py b/tests/vmtests/test_zfsroot.py |
4052 | index c9c73a3..952bf7b 100644 |
4053 | --- a/tests/vmtests/test_zfsroot.py |
4054 | +++ b/tests/vmtests/test_zfsroot.py |
4055 | @@ -96,12 +96,12 @@ class BionicTestZfsRoot(relbase.bionic, TestZfsRootAbs): |
4056 | __test__ = True |
4057 | |
4058 | |
4059 | -class EoanTestZfsRoot(relbase.eoan, TestZfsRootAbs): |
4060 | +class FocalTestZfsRoot(relbase.focal, TestZfsRootAbs): |
4061 | __test__ = True |
4062 | mem = 4096 |
4063 | |
4064 | |
4065 | -class FocalTestZfsRoot(relbase.focal, TestZfsRootAbs): |
4066 | +class GroovyTestZfsRoot(relbase.groovy, TestZfsRootAbs): |
4067 | __test__ = True |
4068 | mem = 4096 |
4069 | |
4070 | @@ -125,13 +125,12 @@ class BionicTestZfsRootFsType(relbase.bionic, TestZfsRootFsTypeAbs): |
4071 | __test__ = True |
4072 | |
4073 | |
4074 | -class EoanTestZfsRootFsType(relbase.eoan, TestZfsRootFsTypeAbs): |
4075 | +class FocalTestZfsRootFsType(relbase.focal, TestZfsRootFsTypeAbs): |
4076 | __test__ = True |
4077 | mem = 4096 |
4078 | |
4079 | |
4080 | -class FocalTestZfsRootFsType(relbase.focal, TestZfsRootFsTypeAbs): |
4081 | +class GroovyTestZfsRootFsType(relbase.groovy, TestZfsRootFsTypeAbs): |
4082 | __test__ = True |
4083 | - mem = 4096 |
4084 | |
4085 | # vi: ts=4 expandtab syntax=python |
4086 | diff --git a/tools/curtainer b/tools/curtainer |
4087 | index 466d719..b24884b 100755 |
4088 | --- a/tools/curtainer |
4089 | +++ b/tools/curtainer |
4090 | @@ -153,20 +153,35 @@ main() { |
4091 | fi |
4092 | getsource="${getsource%/}" |
4093 | |
4094 | - lxc launch "$src" "$name" || fail "failed lxc launch $src $name" |
4095 | + # launch container; mask snapd.seeded.service; not needed |
4096 | + { |
4097 | + lxc init "$src" "$name" && |
4098 | + lxc file push \ |
4099 | + /dev/null ${name}/etc/systemd/system/snapd.seeded.service && |
4100 | + lxc start ${name} |
4101 | + } || fail "failed lxc launch $src $name" |
4102 | CONTAINER=$name |
4103 | |
4104 | wait_for_ready "$name" $maxwait $VERBOSITY || |
4105 | fail "$name did not become ready after $maxwait" |
4106 | |
4107 | inside "$name" which eatmydata >/dev/null || eatmydata="" |
4108 | + release=$(inside $name lsb_release -sc) || |
4109 | + fail "$name did not have a lsb release codename" |
4110 | + |
4111 | + # curtin depends on zfsutils-linux via probert-storage, but zfsutils-linux |
4112 | + # can't be installed in an unprivileged container as it fails to start |
4113 | + # the zfs-mount and zfs-share services as /dev/zfs is missing. We do |
4114 | + # not actually need ZFS to work in the container, so the problem can be |
4115 | + # worked around by masking the services before the package is installed. |
4116 | + inside "$name" systemctl mask zfs-mount || fail "failed to mask zfs-mount" |
4117 | + inside "$name" systemctl mask zfs-share || fail "failed to mask zfs-share" |
4118 | |
4119 | if $proposed; then |
4120 | mirror=$(inside $name awk '$1 == "deb" { print $2; exit(0); }' \ |
4121 | - /etc/apt/sources.list) && |
4122 | - rel=$(inside $name lsb_release -sc) || |
4123 | + /etc/apt/sources.list) || |
4124 | fail "failed to get mirror in $name" |
4125 | - line="$mirror $rel-proposed main universe" |
4126 | + line="$mirror $release-proposed main universe" |
4127 | local fname="/etc/apt/sources.list.d/proposed.list" |
4128 | debug 1 "enabling proposed in $fname: deb $line" |
4129 | inside "$name" sh -c "echo deb $line > $fname" || |
4130 | @@ -179,9 +194,30 @@ main() { |
4131 | if $daily; then |
4132 | local daily_ppa="ppa:curtin-dev/daily" |
4133 | debug 1 "enabling daily: $daily_ppa" |
4134 | - inside "$name" add-apt-repository --enable-source --yes \ |
4135 | - "${daily_ppa}" || |
4136 | - fail "failed add-apt-repository for daily." |
4137 | + local addaptrepo="add-apt-repository" |
4138 | + inside "$name" which $addaptrepo >/dev/null || addaptrepo="" |
4139 | + if [ -n "${addaptrepo}" ]; then |
4140 | + inside "$name" ${addaptrepo} --enable-source --yes --no-update \ |
4141 | + "${daily_ppa}" || |
4142 | + fail "failed add-apt-repository for daily." |
4143 | + else |
4144 | + # https://launchpad.net/~curtin-dev/+archive/ubuntu/daily |
4145 | + local url="http://ppa.launchpad.net/curtin-dev/daily/ubuntu" |
4146 | + local lfile="/etc/apt/sources.list.d/curtin-daily-ppa.list" |
4147 | + local kfile="/etc/apt/trusted.gpg.d/curtin-daily-ppa.asc" |
4148 | + local key="0x1bc30f715a3b861247a81a5e55fe7c8c0165013e" |
4149 | + local keyserver="keyserver.ubuntu.com" |
4150 | + local keyurl="https://${keyserver}/pks/lookup?op=get&search=${key}" |
4151 | + inside "$name" sh -c " |
4152 | + echo deb $url $release main > $lfile && |
4153 | + wget -q \"$keyurl\" -O $kfile" || |
4154 | + fail "failed to add $daily_ppa repository manually" |
4155 | + if [ "$getsource" != "none" ]; then |
4156 | + inside "$name" sh -c " |
4157 | + echo deb-src $url $release main >> $lfile" || |
4158 | + fail "failed adding daily ppa deb-src to $lfile" |
4159 | + fi |
4160 | + fi |
4161 | fi |
4162 | |
4163 | line="Acquire::Languages \"none\";" |
4164 | diff --git a/tools/jenkins-runner b/tools/jenkins-runner |
4165 | index 253b722..375dc3c 100755 |
4166 | --- a/tools/jenkins-runner |
4167 | +++ b/tools/jenkins-runner |
4168 | @@ -5,6 +5,7 @@ topdir="${CURTIN_VMTEST_TOPDIR:-${WORKSPACE:-$PWD}/output}" |
4169 | pkeep=${CURTIN_VMTEST_KEEP_DATA_PASS:-logs,collect} |
4170 | fkeep=${CURTIN_VMTEST_KEEP_DATA_FAIL:-logs,collect} |
4171 | reuse=${CURTIN_VMTEST_REUSE_TOPDIR:-0} |
4172 | +shuffle=${CURTIN_VMTEST_SHUFFLE_TESTS:-1} |
4173 | declare -i ltimeout=${CURTIN_VMTEST_IMAGE_LOCK_TIMEOUT:-"-1"} |
4174 | export CURTIN_VMTEST_TAR_DISKS=${CURTIN_VMTEST_TAR_DISKS:-0} |
4175 | export CURTIN_VMTEST_REUSE_TOPDIR=$reuse |
4176 | @@ -14,6 +15,7 @@ export CURTIN_VMTEST_KEEP_DATA_FAIL=$fkeep |
4177 | export CURTIN_VMTEST_TOPDIR="$topdir" |
4178 | export CURTIN_VMTEST_LOG="${CURTIN_VMTEST_LOG:-$topdir/debug.log}" |
4179 | export CURTIN_VMTEST_PARALLEL=${CURTIN_VMTEST_PARALLEL:-0} |
4180 | +export CURTIN_VMTEST_SHUFFLE_TESTS=$shuffle |
4181 | export IMAGE_DIR=${IMAGE_DIR:-/srv/images} |
4182 | |
4183 | # empty TGT_* variables in current env to avoid killing a pid we didn't start. |
4184 | @@ -50,6 +52,15 @@ if [ "$reuse" != "1" ]; then |
4185 | mkdir -p "$topdir" || fail "failed mkdir $topdir" |
4186 | fi |
4187 | |
4188 | +# Use 'shuf' to randomize test case execution order |
4189 | +if [ "$shuffle" == "1" ]; then |
4190 | + SHUFFLE="shuf" |
4191 | +else |
4192 | + # when disabled just repeat the input to output |
4193 | + SHUFFLE="tee" |
4194 | +fi |
4195 | + |
4196 | + |
4197 | start_s=$(date +%s) |
4198 | parallel=${CURTIN_VMTEST_PARALLEL} |
4199 | ntfilters=( ) |
4200 | @@ -83,9 +94,10 @@ if [ "${#tests[@]}" -ne 0 -a "${#ntfilters[@]}" -ne 0 ]; then |
4201 | error "test arguments provided were: ${#tests[*]}" |
4202 | fail |
4203 | elif [ "${#tests[@]}" -eq 0 -a "${#ntfilters[@]}" -eq 0 ]; then |
4204 | - tests=( tests/vmtests ) |
4205 | + # run filter without args to enumerate all tests and maybe shuffle |
4206 | + tests=( $(./tools/vmtest-filter | ${SHUFFLE}) ) |
4207 | elif [ "${#ntfilters[@]}" -ne 0 ]; then |
4208 | - tests=( $(./tools/vmtest-filter "${ntfilters[@]}") ) |
4209 | + tests=( $(./tools/vmtest-filter "${ntfilters[@]}" | ${SHUFFLE}) ) |
4210 | if [ "${#tests[@]}" -eq 0 ]; then |
4211 | error "Failed to find any tests with filter(s): \"${ntfilters[*]}\"" |
4212 | fail "Try testing filters with: ./tools/vmtest-filter ${ntfilters[*]}" |
4213 | diff --git a/tools/run-pep8 b/tools/run-pep8 |
4214 | index c27a96c..227129c 100755 |
4215 | --- a/tools/run-pep8 |
4216 | +++ b/tools/run-pep8 |
4217 | @@ -9,10 +9,10 @@ pycheck_dirs=( |
4218 | "tools/block-discover-to-config" |
4219 | "tools/curtin-log-print" |
4220 | "tools/noproxy" |
4221 | - "tools/remove-vmtest-release" |
4222 | "tools/schema-validate-storage" |
4223 | "tools/ssh-keys-list" |
4224 | "tools/vmtest-filter" |
4225 | + "tools/vmtest-remove-release" |
4226 | "tools/vmtest-sync-images" |
4227 | "tools/webserv" |
4228 | "tools/write-curtin" |
4229 | diff --git a/tools/remove-vmtest-release b/tools/vmtest-remove-release |
4230 | similarity index 97% |
4231 | rename from tools/remove-vmtest-release |
4232 | rename to tools/vmtest-remove-release |
4233 | old mode 100644 |
4234 | new mode 100755 |
4235 | index 8ab9b2e..d2c5f83 |
4236 | --- a/tools/remove-vmtest-release |
4237 | +++ b/tools/vmtest-remove-release |
4238 | @@ -36,7 +36,7 @@ def clean_file(fname, distro): |
4239 | |
4240 | if __name__ == "__main__": |
4241 | parser = argparse.ArgumentParser( |
4242 | - prog="remove-vmtest-release", |
4243 | + prog="vmtest-remove-release", |
4244 | description="Tool to remove vmtest classes by distro release") |
4245 | parser.add_argument('--distro-release', '-d', |
4246 | action='store', required=True) |
LGTM!
(crispyboi) curtin % git fetch upstream //git.launchpad .net/curtin .81144052 master -> upstream/master ubuntu/ devel git/uss- tableflip/ git/uss- tableflip ~/work/ git/curtin/ release/ curtin com:CanonicalLt d/uss-tableflip .575fd654 master -> origin/master lp-attach- file | 2 +- sru-changelog- format | 69 +++++++ +++++++ +++++++ +++++++ +++++++ ------- ------- ------- ------- ------ git/curtin/ release/ curtin git/uss- tableflip/ scripts/ new-upstream- snapshot g81144052- 0ubuntu1) UNRELEASED; urgency=medium duplicates into find/remove functions for reuse grub_device_ ids handle type:mount without path service vmtest- release to vmtest- remove- release
X11 forwarding request failed on channel 0
remote: Enumerating objects: 110, done.
remote: Counting objects: 100% (110/110), done.
remote: Compressing objects: 100% (76/76), done.
remote: Total 76 (delta 62), reused 0 (delta 0)
Unpacking objects: 100% (76/76), 14.69 KiB | 214.00 KiB/s, done.
From git+ssh:
1304d3ea.
(crispyboi) curtin % git bn
ubuntu/devel
(crispyboi) curtin % git reset --hard upstream/
HEAD is now at 34894cc7 releasing curtin version 20.1-0ubuntu1
(crispyboi) curtin % pushd ~/work/
~/work/
(crispyboi) uss-tableflip % git bn
master
(crispyboi) uss-tableflip % git pull
X11 forwarding request failed on channel 0
remote: Enumerating objects: 21, done.
remote: Counting objects: 100% (21/21), done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 21 (delta 14), reused 17 (delta 14), pack-reused 0
Unpacking objects: 100% (21/21), 3.44 KiB | 251.00 KiB/s, done.
From github.
c0641f9c.
Updating c0641f9c..575fd654
Fast-forward
scripts/cla-query | 9 +++------
scripts/log2dch | 10 +++++++++-
scripts/
scripts/
4 files changed, 48 insertions(+), 42 deletions(-)
(crispyboi) uss-tableflip % popd
~/work/
(crispyboi) curtin % ~/work/
updating remote upstream for default commitish upstream/master.
X11 forwarding request failed on channel 0
diff --git a/debian/changelog b/debian/changelog
index e1a75e18..ba612827 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,47 @@
+curtin (20.1-29-
+
+ * New upstream snapshot.
+ - vmtest: Fix multiple issues with vmtest on master
+ - Refactor uefi_remove_
+ - distro: run apt-get clean after dist-upgrade, install, upgrade
+ - curthooks: UEFI remove dupes: don't remove BootCurrent, config option
+ (LP: #1894217)
+ - Pin the dependency on pyrsistent [Paride Legovini]
+ - restore default of grub.update_nvram to True in install_grub
+ [Michael Hudson-Doyle]
+ - block: disk_to_byid_path handle missing /dev/disk/by-id directory
+ (LP: #1876258)
+ - UEFI: Handle missing BootCurrent entry when reordering UEFI entries
+ (LP: #1789650)
+ - dasd: fix off-by-one device_id devno range check [Paride Legovini]
+ - curthooks: uefi_find_
+ (LP: #1892242)
+ - netplan openvswitch yaml changed (LP: #1891608)
+ - tools/curtainer: do not wait for snapd.seeded.
+ - tools/curtainer: enable using ubuntu-minimal images
+ - vmtests: add Groovy [Paride Legovini]
+ - Drop the Eoan vmtests (EOL) [Paride Legovini]
+ - tools: rename remove-
+ - Snooze the tests failing because...