Skip to content

Commit 1eeea32

Browse files
committed
Merge branch 'install-rpu'
2 parents c4b1b62 + 4fe2e17 commit 1eeea32

15 files changed

+366
-32
lines changed

conftest.py

Lines changed: 1 addition & 0 deletions
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")

data.py-dist

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,18 @@ OTHER_GUEST_TOOLS = {
104104
},
105105
}
106106

107+
# IP addresses for hosts to be installed
108+
# NOTE: do NOT set an IP for host1, it is assumed to use DEFAULT
109+
HOSTS_IP_CONFIG = {
110+
'HOSTS': {
111+
# 'DEFAULT': '192.16.0.1',
112+
# 'host2': '192.16.0.2',
113+
},
114+
# 'NETMASK': '255.255.0.0',
115+
# 'GATEWAY': '192.16.0.254',
116+
# 'DNS': '192.16.0.254',
117+
}
118+
107119
# Tools
108120
TOOLS: Dict[str, str] = {
109121
# "iso-remaster": "/home/user/src/xcpng/xcp/scripts/iso-remaster/iso-remaster.sh",

jobs.py

Lines changed: 4 additions & 0 deletions
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
@@ -500,6 +501,8 @@
500501
# running quicktest on zfsvol generates dangling TAP devices that are hard to
501502
# cleanup. Bug needs to be fixed before enabling quicktest on zfsvol.
502503
"tests/storage/zfsvol/test_zfsvol_sr.py::TestZfsvolVm::test_quicktest",
504+
# not meant to be run from jobs.py (yet)
505+
"tests/install/test_pool.py",
503506
]
504507

505508
# Returns the vm filename or None if a host_version is passed and matches the one specified
@@ -723,6 +726,7 @@ def action_run(args):
723726
sys.exit(1)
724727

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

lib/commands.py

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

7575
if isinstance(cmd, str):
7676
command = cmd
@@ -220,7 +220,7 @@ def local_cmd(cmd, check=True, decode=True):
220220

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

225225
if res.returncode and check:
226226
raise LocalCommandFailed(res.returncode, output_for_logs, command)

lib/host.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,17 @@ def yum_restore_saved_state(self):
468468
self.saved_packages_list = None
469469
self.saved_rollback_id = None
470470

471+
def shutdown(self, verify=False):
472+
logging.info("Shutdown host %s" % self)
473+
try:
474+
self.ssh(['shutdown'])
475+
except commands.SSHCommandFailed as e:
476+
# ssh connection may get killed by the shutdown and terminate with an error code
477+
if "closed by remote host" not in e.stdout:
478+
raise
479+
if verify:
480+
wait_for_not(self.is_enabled, "Wait for host down")
481+
471482
def reboot(self, verify=False):
472483
logging.info("Reboot host %s" % self)
473484
try:

lib/installer.py

Lines changed: 53 additions & 1 deletion
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",

lib/pxe.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,10 @@ def arp_addresses_for(mac_address):
4242
)
4343
candidate_ips = output.splitlines()
4444
return candidate_ips
45+
46+
def arp_clear_for(mac_address):
47+
for stray_ip in arp_addresses_for(mac_address):
48+
output = ssh(
49+
PXE_CONFIG_SERVER,
50+
['arp', '-d', stray_ip]
51+
)

scripts/gen-indirect-installs.sh

Lines changed: 32 additions & 0 deletions
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

scripts/lib.bash

Lines changed: 2 additions & 0 deletions
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
830
5153
821.1 81 80

tests/install/conftest.py

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from lib.installer import AnswerFile
1111
from lib.commands import local_cmd
1212

13-
from data import (ISO_IMAGES, ISO_IMAGES_BASE, ISO_IMAGES_CACHE,
13+
from data import (ISO_IMAGES, ISO_IMAGES_BASE, ISO_IMAGES_CACHE, HOSTS_IP_CONFIG,
1414
ARP_SERVER, TEST_SSH_PUBKEY, TOOLS)
1515

1616
# Return true if the version of the ISO doesn't support the source type.
@@ -71,8 +71,14 @@ def answerfile(request):
7171
answerfile_def.top_append(
7272
dict(TAG="admin-interface",
7373
name="eth0",
74-
proto="dhcp",
75-
),
74+
proto="static",
75+
CONTENTS=(
76+
dict(TAG='ipaddr', CONTENTS=HOSTS_IP_CONFIG['HOSTS']['DEFAULT']),
77+
dict(TAG='subnet', CONTENTS=HOSTS_IP_CONFIG['NETMASK']),
78+
dict(TAG='gateway', CONTENTS=HOSTS_IP_CONFIG['GATEWAY']),
79+
)),
80+
dict(TAG="name-server",
81+
CONTENTS=HOSTS_IP_CONFIG['DNS']),
7682
)
7783

7884
yield answerfile_def
@@ -105,7 +111,22 @@ def installer_iso(request):
105111
@pytest.fixture(scope='function')
106112
def install_disk(request):
107113
firmware = request.getfixturevalue("firmware")
108-
yield {"uefi": "nvme0n1", "bios": "sda"}[firmware]
114+
if firmware.startswith("uefi"):
115+
yield "nvme0n1"
116+
elif firmware.startswith("bios"):
117+
yield "sda"
118+
else:
119+
assert False, f"unknown firmware {firmware!r}"
120+
121+
@pytest.fixture(scope='function')
122+
def answerfile_maybe_tweak_parttable(request, answerfile):
123+
firmware = request.getfixturevalue("firmware")
124+
if firmware.endswith("+dell"):
125+
answerfile.top_append(dict(TAG="script", stage="installation-start",
126+
type="url", CONTENTS="file:///root/preinstall-utilitypart.sh"))
127+
if firmware.endswith("+mbr"):
128+
answerfile.top_append(dict(TAG="script", stage="installation-start",
129+
type="url", CONTENTS="file:///root/preinstall-mbrparttable.sh"))
109130

110131
# Remasters the ISO sepecified by `installer_iso` mark, with:
111132
# - network and ssh support activated, and .ssh/authorized_key so tests can
@@ -120,7 +141,7 @@ def install_disk(request):
120141
# in contexts where the same IP is reused by successively different MACs
121142
# (when cloning VMs from cache)
122143
@pytest.fixture(scope='function')
123-
def remastered_iso(installer_iso, answerfile):
144+
def remastered_iso(installer_iso, answerfile, install_disk):
124145
iso_file = installer_iso['iso']
125146
unsigned = installer_iso['unsigned']
126147

@@ -219,6 +240,30 @@ def remastered_iso(installer_iso, answerfile):
219240
chmod +x "$INSTALLIMG/etc/init.d/S12test-pingpxe"
220241
fi
221242
243+
cat > "$INSTALLIMG/root/preinstall-utilitypart.sh" <<'EOF'
244+
#!/bin/sh
245+
set -ex
246+
247+
# Dell utility partition
248+
sgdisk --zap-all /dev/{install_disk}
249+
sfdisk /dev/{install_disk} << 'EOP'
250+
unit: sectors
251+
p1 : start= 2048, size= 32768, Id=de
252+
EOP
253+
EOF
254+
255+
cat > "$INSTALLIMG/root/preinstall-mbrparttable.sh" <<'EOF'
256+
#!/bin/sh
257+
set -ex
258+
259+
# Dell utility partition
260+
sgdisk --zap-all /dev/{install_disk}
261+
sfdisk /dev/{install_disk} << 'EOP'
262+
unit: sectors
263+
p1 : start= 2048, size= 32768, Id=83
264+
EOP
265+
EOF
266+
222267
cat > "$INSTALLIMG/root/postinstall.sh" <<'EOF'
223268
#!/bin/sh
224269
set -ex
@@ -288,6 +333,8 @@ def vm_booted_with_installer(host, create_vms, remastered_iso):
288333
host_vm.insert_cd(os.path.basename(remote_iso))
289334

290335
try:
336+
pxe.arp_clear_for(mac_address)
337+
291338
host_vm.start()
292339
wait_for(host_vm.is_running, "Wait for host VM running")
293340

0 commit comments

Comments
 (0)