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