|
@@ -86,14 +86,17 @@ def _console_interaction(test, success_message, failure_message,
|
|
|
assert not keep_sending or send_string
|
|
|
if vm is None:
|
|
|
vm = test.vm
|
|
|
- console = vm.console_socket.makefile()
|
|
|
+ console = vm.console_socket.makefile(mode='rb', encoding='utf-8')
|
|
|
console_logger = logging.getLogger('console')
|
|
|
while True:
|
|
|
if send_string:
|
|
|
vm.console_socket.sendall(send_string.encode())
|
|
|
if not keep_sending:
|
|
|
send_string = None # send only once
|
|
|
- msg = console.readline().strip()
|
|
|
+ try:
|
|
|
+ msg = console.readline().decode().strip()
|
|
|
+ except UnicodeDecodeError:
|
|
|
+ msg = None
|
|
|
if not msg:
|
|
|
continue
|
|
|
console_logger.debug(msg)
|
|
@@ -210,6 +213,9 @@ def setUp(self):
|
|
|
self.arch = self.params.get('arch',
|
|
|
default=self._get_unique_tag_val('arch'))
|
|
|
|
|
|
+ self.cpu = self.params.get('cpu',
|
|
|
+ default=self._get_unique_tag_val('cpu'))
|
|
|
+
|
|
|
self.machine = self.params.get('machine',
|
|
|
default=self._get_unique_tag_val('machine'))
|
|
|
|
|
@@ -219,9 +225,13 @@ def setUp(self):
|
|
|
if self.qemu_bin is None:
|
|
|
self.cancel("No QEMU binary defined or found in the build tree")
|
|
|
|
|
|
- def _new_vm(self, *args):
|
|
|
+ def _new_vm(self, name, *args):
|
|
|
self._sd = tempfile.TemporaryDirectory(prefix="avo_qemu_sock_")
|
|
|
- vm = QEMUMachine(self.qemu_bin, sock_dir=self._sd.name)
|
|
|
+ vm = QEMUMachine(self.qemu_bin, base_temp_dir=self.workdir,
|
|
|
+ sock_dir=self._sd.name, log_dir=self.logdir)
|
|
|
+ self.log.debug('QEMUMachine "%s" created', name)
|
|
|
+ self.log.debug('QEMUMachine "%s" temp_dir: %s', name, vm.temp_dir)
|
|
|
+ self.log.debug('QEMUMachine "%s" log_dir: %s', name, vm.log_dir)
|
|
|
if args:
|
|
|
vm.add_args(*args)
|
|
|
return vm
|
|
@@ -234,11 +244,34 @@ def get_vm(self, *args, name=None):
|
|
|
if not name:
|
|
|
name = str(uuid.uuid4())
|
|
|
if self._vms.get(name) is None:
|
|
|
- self._vms[name] = self._new_vm(*args)
|
|
|
+ self._vms[name] = self._new_vm(name, *args)
|
|
|
+ if self.cpu is not None:
|
|
|
+ self._vms[name].add_args('-cpu', self.cpu)
|
|
|
if self.machine is not None:
|
|
|
self._vms[name].set_machine(self.machine)
|
|
|
return self._vms[name]
|
|
|
|
|
|
+ def set_vm_arg(self, arg, value):
|
|
|
+ """
|
|
|
+ Set an argument to list of extra arguments to be given to the QEMU
|
|
|
+ binary. If the argument already exists then its value is replaced.
|
|
|
+
|
|
|
+ :param arg: the QEMU argument, such as "-cpu" in "-cpu host"
|
|
|
+ :type arg: str
|
|
|
+ :param value: the argument value, such as "host" in "-cpu host"
|
|
|
+ :type value: str
|
|
|
+ """
|
|
|
+ if not arg or not value:
|
|
|
+ return
|
|
|
+ if arg not in self.vm.args:
|
|
|
+ self.vm.args.extend([arg, value])
|
|
|
+ else:
|
|
|
+ idx = self.vm.args.index(arg) + 1
|
|
|
+ if idx < len(self.vm.args):
|
|
|
+ self.vm.args[idx] = value
|
|
|
+ else:
|
|
|
+ self.vm.args.append(value)
|
|
|
+
|
|
|
def tearDown(self):
|
|
|
for vm in self._vms.values():
|
|
|
vm.shutdown()
|
|
@@ -299,6 +332,103 @@ def ssh_command(self, command):
|
|
|
f'Guest command failed: {command}')
|
|
|
return stdout_lines, stderr_lines
|
|
|
|
|
|
+class LinuxDistro:
|
|
|
+ """Represents a Linux distribution
|
|
|
+
|
|
|
+ Holds information of known distros.
|
|
|
+ """
|
|
|
+ #: A collection of known distros and their respective image checksum
|
|
|
+ KNOWN_DISTROS = {
|
|
|
+ 'fedora': {
|
|
|
+ '31': {
|
|
|
+ 'x86_64':
|
|
|
+ {'checksum': ('e3c1b309d9203604922d6e255c2c5d09'
|
|
|
+ '8a309c2d46215d8fc026954f3c5c27a0'),
|
|
|
+ 'pxeboot_url': ('https://archives.fedoraproject.org/'
|
|
|
+ 'pub/archive/fedora/linux/releases/31/'
|
|
|
+ 'Everything/x86_64/os/images/pxeboot/'),
|
|
|
+ 'kernel_params': ('root=UUID=b1438b9b-2cab-4065-a99a-'
|
|
|
+ '08a96687f73c ro no_timer_check '
|
|
|
+ 'net.ifnames=0 console=tty1 '
|
|
|
+ 'console=ttyS0,115200n8'),
|
|
|
+ },
|
|
|
+ 'aarch64':
|
|
|
+ {'checksum': ('1e18d9c0cf734940c4b5d5ec592facae'
|
|
|
+ 'd2af0ad0329383d5639c997fdf16fe49'),
|
|
|
+ 'pxeboot_url': 'https://archives.fedoraproject.org/'
|
|
|
+ 'pub/archive/fedora/linux/releases/31/'
|
|
|
+ 'Everything/aarch64/os/images/pxeboot/',
|
|
|
+ 'kernel_params': ('root=UUID=b6950a44-9f3c-4076-a9c2-'
|
|
|
+ '355e8475b0a7 ro earlyprintk=pl011,0x9000000'
|
|
|
+ ' ignore_loglevel no_timer_check'
|
|
|
+ ' printk.time=1 rd_NO_PLYMOUTH'
|
|
|
+ ' console=ttyAMA0'),
|
|
|
+ },
|
|
|
+ 'ppc64':
|
|
|
+ {'checksum': ('7c3528b85a3df4b2306e892199a9e1e4'
|
|
|
+ '3f991c506f2cc390dc4efa2026ad2f58')},
|
|
|
+ 's390x':
|
|
|
+ {'checksum': ('4caaab5a434fd4d1079149a072fdc789'
|
|
|
+ '1e354f834d355069ca982fdcaf5a122d')},
|
|
|
+ },
|
|
|
+ '32': {
|
|
|
+ 'aarch64':
|
|
|
+ {'checksum': ('b367755c664a2d7a26955bbfff985855'
|
|
|
+ 'adfa2ca15e908baf15b4b176d68d3967'),
|
|
|
+ 'pxeboot_url': ('http://dl.fedoraproject.org/pub/fedora/linux/'
|
|
|
+ 'releases/32/Server/aarch64/os/images/'
|
|
|
+ 'pxeboot/'),
|
|
|
+ 'kernel_params': ('root=UUID=3df75b65-be8d-4db4-8655-'
|
|
|
+ '14d95c0e90c5 ro no_timer_check net.ifnames=0'
|
|
|
+ ' console=tty1 console=ttyS0,115200n8'),
|
|
|
+ },
|
|
|
+ },
|
|
|
+ '33': {
|
|
|
+ 'aarch64':
|
|
|
+ {'checksum': ('e7f75cdfd523fe5ac2ca9eeece68edc1'
|
|
|
+ 'a81f386a17f969c1d1c7c87031008a6b'),
|
|
|
+ 'pxeboot_url': ('http://dl.fedoraproject.org/pub/fedora/linux/'
|
|
|
+ 'releases/33/Server/aarch64/os/images/'
|
|
|
+ 'pxeboot/'),
|
|
|
+ 'kernel_params': ('root=UUID=d20b3ffa-6397-4a63-a734-'
|
|
|
+ '1126a0208f8a ro no_timer_check net.ifnames=0'
|
|
|
+ ' console=tty1 console=ttyS0,115200n8'
|
|
|
+ ' console=tty0'),
|
|
|
+ },
|
|
|
+ },
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ def __init__(self, name, version, arch):
|
|
|
+ self.name = name
|
|
|
+ self.version = version
|
|
|
+ self.arch = arch
|
|
|
+ try:
|
|
|
+ info = self.KNOWN_DISTROS.get(name).get(version).get(arch)
|
|
|
+ except AttributeError:
|
|
|
+ # Unknown distro
|
|
|
+ info = None
|
|
|
+ self._info = info or {}
|
|
|
+
|
|
|
+ @property
|
|
|
+ def checksum(self):
|
|
|
+ """Gets the cloud-image file checksum"""
|
|
|
+ return self._info.get('checksum', None)
|
|
|
+
|
|
|
+ @checksum.setter
|
|
|
+ def checksum(self, value):
|
|
|
+ self._info['checksum'] = value
|
|
|
+
|
|
|
+ @property
|
|
|
+ def pxeboot_url(self):
|
|
|
+ """Gets the repository url where pxeboot files can be found"""
|
|
|
+ return self._info.get('pxeboot_url', None)
|
|
|
+
|
|
|
+ @property
|
|
|
+ def default_kernel_params(self):
|
|
|
+ """Gets the default kernel parameters"""
|
|
|
+ return self._info.get('kernel_params', None)
|
|
|
+
|
|
|
|
|
|
class LinuxTest(Test, LinuxSSHMixIn):
|
|
|
"""Facilitates having a cloud-image Linux based available.
|
|
@@ -308,12 +438,39 @@ class LinuxTest(Test, LinuxSSHMixIn):
|
|
|
"""
|
|
|
|
|
|
timeout = 900
|
|
|
- chksum = None
|
|
|
+ distro = None
|
|
|
username = 'root'
|
|
|
password = 'password'
|
|
|
|
|
|
+ def _set_distro(self):
|
|
|
+ distro_name = self.params.get(
|
|
|
+ 'distro',
|
|
|
+ default=self._get_unique_tag_val('distro'))
|
|
|
+ if not distro_name:
|
|
|
+ distro_name = 'fedora'
|
|
|
+
|
|
|
+ distro_version = self.params.get(
|
|
|
+ 'distro_version',
|
|
|
+ default=self._get_unique_tag_val('distro_version'))
|
|
|
+ if not distro_version:
|
|
|
+ distro_version = '31'
|
|
|
+
|
|
|
+ self.distro = LinuxDistro(distro_name, distro_version, self.arch)
|
|
|
+
|
|
|
+ # The distro checksum behaves differently than distro name and
|
|
|
+ # version. First, it does not respect a tag with the same
|
|
|
+ # name, given that it's not expected to be used for filtering
|
|
|
+ # (distro name versions are the natural choice). Second, the
|
|
|
+ # order of precedence is: parameter, attribute and then value
|
|
|
+ # from KNOWN_DISTROS.
|
|
|
+ distro_checksum = self.params.get('distro_checksum',
|
|
|
+ default=None)
|
|
|
+ if distro_checksum:
|
|
|
+ self.distro.checksum = distro_checksum
|
|
|
+
|
|
|
def setUp(self, ssh_pubkey=None, network_device_type='virtio-net'):
|
|
|
super(LinuxTest, self).setUp()
|
|
|
+ self._set_distro()
|
|
|
self.vm.add_args('-smp', '2')
|
|
|
self.vm.add_args('-m', '1024')
|
|
|
# The following network device allows for SSH connections
|
|
@@ -351,12 +508,14 @@ def download_boot(self):
|
|
|
self.log.info('Downloading/preparing boot image')
|
|
|
# Fedora 31 only provides ppc64le images
|
|
|
image_arch = self.arch
|
|
|
- if image_arch == 'ppc64':
|
|
|
- image_arch = 'ppc64le'
|
|
|
+ if self.distro.name == 'fedora':
|
|
|
+ if image_arch == 'ppc64':
|
|
|
+ image_arch = 'ppc64le'
|
|
|
+
|
|
|
try:
|
|
|
boot = vmimage.get(
|
|
|
- 'fedora', arch=image_arch, version='31',
|
|
|
- checksum=self.chksum,
|
|
|
+ self.distro.name, arch=image_arch, version=self.distro.version,
|
|
|
+ checksum=self.distro.checksum,
|
|
|
algorithm='sha256',
|
|
|
cache_dir=self.cache_dirs[0],
|
|
|
snapshot_dir=self.workdir)
|