Skip to content

Commit 7aef3a1

Browse files
committed
Merge branch 'install-rpu'
2 parents 2530265 + c966f62 commit 7aef3a1

15 files changed

+334
-20
lines changed

Diff for: conftest.py

+1
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ def setup_host(hostname_or_ip, *, config=None):
169169
vif = host_vm.vifs()[0]
170170
mac_address = vif.param_get('MAC')
171171
logging.info("Nested host has MAC %s", mac_address)
172+
pxe.arp_clear_for(mac_address)
172173

173174
host_vm.start()
174175
wait_for(host_vm.is_running, "Wait for nested host VM running")

Diff for: data.py-dist

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ HOSTS_IP_CONFIG = {
4343
'HOSTS': {
4444
# 'DEFAULT': '192.16.0.1',
4545
# 'host2': '192.16.0.2',
46+
# 'host3': '192.16.0.3',
4647
},
4748
# 'NETMASK': '255.255.0.0',
4849
# 'GATEWAY': '192.16.0.254',

Diff for: jobs.py

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import argparse
44
import json
5+
import logging
56
import subprocess
67
import sys
78
from lib.commands import ssh
@@ -487,6 +488,8 @@
487488
# running quicktest on zfsvol generates dangling TAP devices that are hard to
488489
# cleanup. Bug needs to be fixed before enabling quicktest on zfsvol.
489490
"tests/storage/zfsvol/test_zfsvol_sr.py::TestZfsvolVm::test_quicktest",
491+
# not meant to be run from jobs.py (yet)
492+
"tests/install/test_pool.py",
490493
]
491494

492495
# Returns the vm filename or None if a host_version is passed and matches the one specified
@@ -710,6 +713,7 @@ def action_run(args):
710713
sys.exit(1)
711714

712715
def main():
716+
logging.basicConfig(format='[%(levelname)s] %(message)s', level=logging.DEBUG)
713717
parser = argparse.ArgumentParser(description="Manage test jobs")
714718
parser.add_argument("-v", "--host-version", help="host version to match VM filters.")
715719
subparsers = parser.add_subparsers(dest="action", metavar="action")

Diff for: lib/commands.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,14 @@ def _ellide_log_lines(log):
6262
def _ssh(hostname_or_ip, cmd, check, simple_output, suppress_fingerprint_warnings,
6363
background, target_os, decode, options):
6464
opts = list(options)
65-
opts.append('-o "BatchMode yes"')
65+
opts.append('-o BatchMode=yes')
6666
if suppress_fingerprint_warnings:
6767
# Suppress warnings and questions related to host key fingerprints
6868
# because on a test network IPs get reused, VMs are reinstalled, etc.
6969
# Based on https://unix.stackexchange.com/a/365976/257493
70-
opts.append('-o "StrictHostKeyChecking no"')
71-
opts.append('-o "LogLevel ERROR"')
72-
opts.append('-o "UserKnownHostsFile /dev/null"')
70+
opts.extend(['-o StrictHostKeyChecking=no',
71+
'-o LogLevel=ERROR',
72+
'-o UserKnownHostsFile=/dev/null'])
7373

7474
command = " ".join(cmd)
7575
if background and target_os != "windows":
@@ -216,7 +216,7 @@ def local_cmd(cmd, check=True, decode=True):
216216

217217
errorcode_msg = "" if res.returncode == 0 else " - Got error code: %s" % res.returncode
218218
command = " ".join(cmd)
219-
logging.debug(f"[local] {command}{errorcode_msg}{_ellide_log_lines(output_for_logs)}")
219+
logging.debug(f"[local] {command}{errorcode_msg}, output: {_ellide_log_lines(output_for_logs)}")
220220

221221
if res.returncode and check:
222222
raise LocalCommandFailed(res.returncode, output_for_logs, command)

Diff for: lib/host.py

+11
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,17 @@ def yum_restore_saved_state(self):
434434
self.saved_packages_list = None
435435
self.saved_rollback_id = None
436436

437+
def shutdown(self, verify=False):
438+
logging.info("Shutdown host %s" % self)
439+
try:
440+
self.ssh(['shutdown'])
441+
except commands.SSHCommandFailed as e:
442+
# ssh connection may get killed by the shutdown and terminate with an error code
443+
if "closed by remote host" not in e.stdout:
444+
raise
445+
if verify:
446+
wait_for_not(self.is_enabled, "Wait for host down")
447+
437448
def reboot(self, verify=False):
438449
logging.info("Reboot host %s" % self)
439450
try:

Diff for: lib/installer.py

+53-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import logging
2+
import os
23
import time
34
import xml.etree.ElementTree as ET
45

5-
from lib.commands import ssh, SSHCommandFailed
6+
from lib import pxe
7+
from lib.commands import local_cmd, scp, ssh, SSHCommandFailed
68
from lib.common import wait_for
79

810
# FIXME should only be used for <7.0
@@ -143,6 +145,56 @@ def monitor_upgrade(*, ip):
143145
).returncode == 1,
144146
"Wait for installer to terminate")
145147

148+
# FIXME essentially duplicates vm_booted_with_installer fixture
149+
def perform_upgrade(*, iso, host_vm, host):
150+
vif = host_vm.vifs()[0]
151+
mac_address = vif.param_get('MAC')
152+
logging.info("Host VM has MAC %s", mac_address)
153+
154+
try:
155+
remote_iso = host.pool.push_iso(iso)
156+
host_vm.insert_cd(os.path.basename(remote_iso))
157+
158+
try:
159+
pxe.arp_clear_for(mac_address)
160+
161+
host_vm.start()
162+
wait_for(host_vm.is_running, "Wait for host VM running")
163+
164+
# catch host-vm IP address
165+
wait_for(lambda: pxe.arp_addresses_for(mac_address),
166+
"Wait for DHCP server to see Host VM in ARP tables",
167+
timeout_secs=10 * 60)
168+
ips = pxe.arp_addresses_for(mac_address)
169+
logging.info("Host VM has IPs %s", ips)
170+
assert len(ips) == 1
171+
host_vm.ip = ips[0]
172+
173+
# host may not be up if ARP cache was filled
174+
wait_for(lambda: local_cmd(["ping", "-c1", host_vm.ip], check=False),
175+
"Wait for host up", timeout_secs=10 * 60, retry_delay_secs=10)
176+
wait_for(lambda: local_cmd(["nc", "-zw5", host_vm.ip, "22"], check=False),
177+
"Wait for ssh up on host", timeout_secs=10 * 60, retry_delay_secs=5)
178+
179+
yield host_vm
180+
181+
logging.info("Shutting down Host VM")
182+
poweroff(host_vm.ip)
183+
wait_for(host_vm.is_halted, "Wait for host VM halted")
184+
185+
except Exception as e:
186+
logging.critical("caught exception %s", e)
187+
host_vm.shutdown(force=True)
188+
raise
189+
except KeyboardInterrupt:
190+
logging.warning("keyboard interrupt")
191+
host_vm.shutdown(force=True)
192+
raise
193+
194+
host_vm.eject_cd()
195+
finally:
196+
host.pool.remove_iso(remote_iso)
197+
146198
def monitor_restore(*, ip):
147199
# wait for "yum install" phase to start
148200
wait_for(lambda: ssh(ip, ["grep",

Diff for: lib/pxe.py

+7
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,10 @@ def arp_addresses_for(mac_address):
4545
)
4646
candidate_ips = output.splitlines()
4747
return candidate_ips
48+
49+
def arp_clear_for(mac_address):
50+
for stray_ip in arp_addresses_for(mac_address):
51+
output = ssh(
52+
PXE_CONFIG_SERVER,
53+
['arp', '-d', stray_ip]
54+
)

Diff for: scripts/gen-indirect-installs.sh

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# creation of reference installations to be used for basis of upgrade tests
5+
6+
# * needs at least --hosts=$NEST
7+
# * ch821 and xs8 needs ISO in the cache
8+
9+
. $(dirname $0)/lib.bash
10+
11+
TESTCLASS="tests/install/test.py::TestNested"
12+
for conf in uefi-75+821.1-iso-ext; do
13+
IFS=- read fw versions media sr < <(echo "$conf")
14+
IFS=+ read origversion stepversion < <(echo "$versions")
15+
TESTS=(
16+
$TESTCLASS::test_install[$fw-$origversion-$media-$sr]
17+
$TESTCLASS::test_tune_firstboot[None-$fw-$origversion-host1-$media-$sr]
18+
$TESTCLASS::test_boot_inst[$fw-$origversion-host1-$media-$sr]
19+
20+
$TESTCLASS::test_upgrade[$fw-$origversion-$stepversion-host1-$media-$sr]
21+
$TESTCLASS::test_boot_upg[$fw-$origversion-$stepversion-host1-$media-$sr]
22+
23+
#$TESTCLASS::test_upgrade[$fw-$origversion-$stepversion-83nightly-host1-$media-$sr]
24+
)
25+
run_pytest "$conf" \
26+
--log-file=test-genref-$conf.log \
27+
--reruns=5 --only-rerun=TimeoutError \
28+
"$@" \
29+
"${TESTS[@]}"
30+
done
31+
32+
report_failures

Diff for: scripts/lib.bash

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ run_pytest() {
4646

4747
# reference configurations, to be upgraded to nightly
4848

49+
# FIXME this is also where we take the list to create all ref
50+
# installs, 75/76 should be separated
4951
REFVERSIONS=(
5052
83rc1 83b2 83b1
5153
821.1 81 80

Diff for: tests/install/conftest.py

+43-2
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,22 @@ def installer_iso(request):
112112
@pytest.fixture(scope='function')
113113
def install_disk(request):
114114
firmware = request.getfixturevalue("firmware")
115-
yield {"uefi": "nvme0n1", "bios": "sda"}[firmware]
115+
if firmware.startswith("uefi"):
116+
yield "nvme0n1"
117+
elif firmware.startswith("bios"):
118+
yield "sda"
119+
else:
120+
assert False, f"unknown firmware {firmware!r}"
121+
122+
@pytest.fixture(scope='function')
123+
def answerfile_maybe_tweak_parttable(request, answerfile):
124+
firmware = request.getfixturevalue("firmware")
125+
if firmware.endswith("+dell"):
126+
answerfile.top_append(dict(TAG="script", stage="installation-start",
127+
type="url", CONTENTS="file:///root/preinstall-utilitypart.sh"))
128+
if firmware.endswith("+mbr"):
129+
answerfile.top_append(dict(TAG="script", stage="installation-start",
130+
type="url", CONTENTS="file:///root/preinstall-mbrparttable.sh"))
116131

117132
# Remasters the ISO sepecified by `installer_iso` mark, with:
118133
# - network and ssh support activated, and .ssh/authorized_key so tests can
@@ -127,7 +142,7 @@ def install_disk(request):
127142
# in contexts where the same IP is reused by successively different MACs
128143
# (when cloning VMs from cache)
129144
@pytest.fixture(scope='function')
130-
def remastered_iso(installer_iso, answerfile):
145+
def remastered_iso(installer_iso, answerfile, install_disk):
131146
iso_file = installer_iso['iso']
132147
unsigned = installer_iso['unsigned']
133148

@@ -226,6 +241,30 @@ def remastered_iso(installer_iso, answerfile):
226241
chmod +x "$INSTALLIMG/etc/init.d/S12test-pingpxe"
227242
fi
228243
244+
cat > "$INSTALLIMG/root/preinstall-utilitypart.sh" <<'EOF'
245+
#!/bin/sh
246+
set -ex
247+
248+
# Dell utility partition
249+
sgdisk --zap-all /dev/{install_disk}
250+
sfdisk /dev/{install_disk} << 'EOP'
251+
unit: sectors
252+
p1 : start= 2048, size= 32768, Id=de
253+
EOP
254+
EOF
255+
256+
cat > "$INSTALLIMG/root/preinstall-mbrparttable.sh" <<'EOF'
257+
#!/bin/sh
258+
set -ex
259+
260+
# Dell utility partition
261+
sgdisk --zap-all /dev/{install_disk}
262+
sfdisk /dev/{install_disk} << 'EOP'
263+
unit: sectors
264+
p1 : start= 2048, size= 32768, Id=83
265+
EOP
266+
EOF
267+
229268
cat > "$INSTALLIMG/root/postinstall.sh" <<'EOF'
230269
#!/bin/sh
231270
set -ex
@@ -295,6 +334,8 @@ def vm_booted_with_installer(host, remastered_iso, create_vms):
295334
host_vm.insert_cd(os.path.basename(remote_iso))
296335

297336
try:
337+
pxe.arp_clear_for(mac_address)
338+
298339
host_vm.start()
299340
wait_for(host_vm.is_running, "Wait for host VM running")
300341

Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
tests/install/test_pool.py::test_pool_rpu[uefi-821.1-83nightly]

Diff for: tests/install/test-sequences/uefi-82-nosr+pool.lst

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
tests/install/test.py::TestNested::test_tune_firstboot[None-uefi-821.1-host2-iso-nosr]
2+
tests/install/test.py::TestNested::test_boot_inst[uefi-821.1-host2-iso-nosr]

Diff for: tests/install/test-sequences/uefi-82-nosr.lst

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
tests/install/test.py::TestNested::test_install[uefi-821.1-iso-nosr]
2+
tests/install/test.py::TestNested::test_tune_firstboot[None-uefi-821.1-host1-iso-nosr]
3+
tests/install/test.py::TestNested::test_boot_inst[uefi-821.1-host1-iso-nosr]

0 commit comments

Comments
 (0)