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