Message ID | 20210203172357.1422425-15-crosa@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Acceptance Test: introduce base class for Linux based tests | expand |
On 2/3/21 2:23 PM, Cleber Rosa wrote: > This is basically the infrastructure around "boot_linux.py" tests, but > now made into a base class for general use. > > Signed-off-by: Cleber Rosa <crosa@redhat.com> > --- > tests/acceptance/avocado_qemu/__init__.py | 87 +++++++++++++++++++++ > tests/acceptance/boot_linux.py | 94 ++--------------------- > tests/acceptance/virtiofs_submounts.py | 6 +- > 3 files changed, 94 insertions(+), 93 deletions(-) Reviewed-by: Wainer dos Santos Moschetta <wainersm@redhat.com> > > diff --git a/tests/acceptance/avocado_qemu/__init__.py b/tests/acceptance/avocado_qemu/__init__.py > index bf54e419da..b06692a59d 100644 > --- a/tests/acceptance/avocado_qemu/__init__.py > +++ b/tests/acceptance/avocado_qemu/__init__.py > @@ -16,6 +16,13 @@ import tempfile > > import avocado > > +from avocado.utils import cloudinit > +from avocado.utils import datadrainer > +from avocado.utils import network > +from avocado.utils import vmimage > +from avocado.utils.path import find_command > + > + > #: The QEMU build root directory. It may also be the source directory > #: if building from the source dir, but it's safer to use BUILD_DIR for > #: that purpose. Be aware that if this code is moved outside of a source > @@ -206,3 +213,83 @@ class Test(avocado.Test): > expire=expire, > find_only=find_only, > cancel_on_missing=cancel_on_missing) > + > + > +class LinuxTest(Test): > + """Facilitates having a cloud-image Linux based available. > + > + For tests that indend to interact with guests, this is a better choice > + to start with than the more vanilla `Test` class. > + """ > + > + timeout = 900 > + chksum = None > + > + def setUp(self, ssh_pubkey=None): > + super(LinuxTest, self).setUp() > + self.vm.add_args('-smp', '2') > + self.vm.add_args('-m', '1024') > + self.set_up_boot() > + self.set_up_cloudinit(ssh_pubkey) > + > + def download_boot(self): > + self.log.debug('Looking for and selecting a qemu-img binary to be ' > + 'used to create the bootable snapshot image') > + # If qemu-img has been built, use it, otherwise the system wide one > + # will be used. If none is available, the test will cancel. > + qemu_img = os.path.join(BUILD_DIR, 'qemu-img') > + if not os.path.exists(qemu_img): > + qemu_img = find_command('qemu-img', False) > + if qemu_img is False: > + self.cancel('Could not find "qemu-img", which is required to ' > + 'create the bootable image') > + vmimage.QEMU_IMG = qemu_img > + > + self.log.info('Downloading/preparing boot image') > + # Fedora 31 only provides ppc64le images > + image_arch = self.arch > + if image_arch == 'ppc64': > + image_arch = 'ppc64le' > + try: > + boot = vmimage.get( > + 'fedora', arch=image_arch, version='31', > + checksum=self.chksum, > + algorithm='sha256', > + cache_dir=self.cache_dirs[0], > + snapshot_dir=self.workdir) > + except: > + self.cancel('Failed to download/prepare boot image') > + return boot.path > + > + def prepare_cloudinit(self, ssh_pubkey=None): > + self.log.info('Preparing cloudinit image') > + try: > + cloudinit_iso = os.path.join(self.workdir, 'cloudinit.iso') > + self.phone_home_port = network.find_free_port() > + cloudinit.iso(cloudinit_iso, self.name, > + username='root', > + password='password', > + # QEMU's hard coded usermode router address > + phone_home_host='10.0.2.2', > + phone_home_port=self.phone_home_port, > + authorized_key=ssh_pubkey) > + except Exception: > + self.cancel('Failed to prepare the cloudinit image') > + return cloudinit_iso > + > + def set_up_boot(self): > + path = self.download_boot() > + self.vm.add_args('-drive', 'file=%s' % path) > + > + def set_up_cloudinit(self, ssh_pubkey=None): > + cloudinit_iso = self.prepare_cloudinit(ssh_pubkey) > + self.vm.add_args('-drive', 'file=%s,format=raw' % cloudinit_iso) > + > + def launch_and_wait(self): > + self.vm.set_console() > + self.vm.launch() > + console_drainer = datadrainer.LineLogger(self.vm.console_socket.fileno(), > + logger=self.log.getChild('console')) > + console_drainer.start() > + self.log.info('VM launched, waiting for boot confirmation from guest') > + cloudinit.wait_for_phone_home(('0.0.0.0', self.phone_home_port), self.name) > diff --git a/tests/acceptance/boot_linux.py b/tests/acceptance/boot_linux.py > index bcd923bb4a..14e89d020d 100644 > --- a/tests/acceptance/boot_linux.py > +++ b/tests/acceptance/boot_linux.py > @@ -10,16 +10,11 @@ > > import os > > -from avocado_qemu import Test, BUILD_DIR > +from avocado_qemu import LinuxTest, BUILD_DIR > > from qemu.accel import kvm_available > from qemu.accel import tcg_available > > -from avocado.utils import cloudinit > -from avocado.utils import network > -from avocado.utils import vmimage > -from avocado.utils import datadrainer > -from avocado.utils.path import find_command > from avocado import skipIf > > ACCEL_NOT_AVAILABLE_FMT = "%s accelerator does not seem to be available" > @@ -27,86 +22,7 @@ KVM_NOT_AVAILABLE = ACCEL_NOT_AVAILABLE_FMT % "KVM" > TCG_NOT_AVAILABLE = ACCEL_NOT_AVAILABLE_FMT % "TCG" > > > -class BootLinuxBase(Test): > - def download_boot(self): > - self.log.debug('Looking for and selecting a qemu-img binary to be ' > - 'used to create the bootable snapshot image') > - # If qemu-img has been built, use it, otherwise the system wide one > - # will be used. If none is available, the test will cancel. > - qemu_img = os.path.join(BUILD_DIR, 'qemu-img') > - if not os.path.exists(qemu_img): > - qemu_img = find_command('qemu-img', False) > - if qemu_img is False: > - self.cancel('Could not find "qemu-img", which is required to ' > - 'create the bootable image') > - vmimage.QEMU_IMG = qemu_img > - > - self.log.info('Downloading/preparing boot image') > - # Fedora 31 only provides ppc64le images > - image_arch = self.arch > - if image_arch == 'ppc64': > - image_arch = 'ppc64le' > - try: > - boot = vmimage.get( > - 'fedora', arch=image_arch, version='31', > - checksum=self.chksum, > - algorithm='sha256', > - cache_dir=self.cache_dirs[0], > - snapshot_dir=self.workdir) > - except: > - self.cancel('Failed to download/prepare boot image') > - return boot.path > - > - def prepare_cloudinit(self, ssh_pubkey=None): > - self.log.info('Preparing cloudinit image') > - try: > - cloudinit_iso = os.path.join(self.workdir, 'cloudinit.iso') > - self.phone_home_port = network.find_free_port() > - cloudinit.iso(cloudinit_iso, self.name, > - username='root', > - password='password', > - # QEMU's hard coded usermode router address > - phone_home_host='10.0.2.2', > - phone_home_port=self.phone_home_port, > - authorized_key=ssh_pubkey) > - except Exception: > - self.cancel('Failed to prepare the cloudinit image') > - return cloudinit_iso > - > -class BootLinux(BootLinuxBase): > - """ > - Boots a Linux system, checking for a successful initialization > - """ > - > - timeout = 900 > - chksum = None > - > - def setUp(self, ssh_pubkey=None): > - super(BootLinux, self).setUp() > - self.vm.add_args('-smp', '2') > - self.vm.add_args('-m', '1024') > - self.set_up_boot() > - self.set_up_cloudinit(ssh_pubkey) > - > - def set_up_boot(self): > - path = self.download_boot() > - self.vm.add_args('-drive', 'file=%s' % path) > - > - def set_up_cloudinit(self, ssh_pubkey=None): > - cloudinit_iso = self.prepare_cloudinit(ssh_pubkey) > - self.vm.add_args('-drive', 'file=%s,format=raw' % cloudinit_iso) > - > - def launch_and_wait(self): > - self.vm.set_console() > - self.vm.launch() > - console_drainer = datadrainer.LineLogger(self.vm.console_socket.fileno(), > - logger=self.log.getChild('console')) > - console_drainer.start() > - self.log.info('VM launched, waiting for boot confirmation from guest') > - cloudinit.wait_for_phone_home(('0.0.0.0', self.phone_home_port), self.name) > - > - > -class BootLinuxX8664(BootLinux): > +class BootLinuxX8664(LinuxTest): > """ > :avocado: tags=arch:x86_64 > """ > @@ -154,7 +70,7 @@ class BootLinuxX8664(BootLinux): > self.launch_and_wait() > > > -class BootLinuxAarch64(BootLinux): > +class BootLinuxAarch64(LinuxTest): > """ > :avocado: tags=arch:aarch64 > :avocado: tags=machine:virt > @@ -212,7 +128,7 @@ class BootLinuxAarch64(BootLinux): > self.launch_and_wait() > > > -class BootLinuxPPC64(BootLinux): > +class BootLinuxPPC64(LinuxTest): > """ > :avocado: tags=arch:ppc64 > """ > @@ -230,7 +146,7 @@ class BootLinuxPPC64(BootLinux): > self.launch_and_wait() > > > -class BootLinuxS390X(BootLinux): > +class BootLinuxS390X(LinuxTest): > """ > :avocado: tags=arch:s390x > """ > diff --git a/tests/acceptance/virtiofs_submounts.py b/tests/acceptance/virtiofs_submounts.py > index 1e745f15a2..25ea54b6ff 100644 > --- a/tests/acceptance/virtiofs_submounts.py > +++ b/tests/acceptance/virtiofs_submounts.py > @@ -5,15 +5,13 @@ import subprocess > import time > > from avocado import skipUnless > -from avocado_qemu import Test, BUILD_DIR > +from avocado_qemu import LinuxTest, BUILD_DIR > from avocado_qemu import wait_for_console_pattern > from avocado.utils import ssh > > from qemu.accel import kvm_available > from qemu.utils import get_info_usernet_hostfwd_port > > -from boot_linux import BootLinux > - > > def run_cmd(args): > subp = subprocess.Popen(args, > @@ -72,7 +70,7 @@ def has_cmds(*cmds): > return (True, '') > > > -class VirtiofsSubmountsTest(BootLinux): > +class VirtiofsSubmountsTest(LinuxTest): > """ > :avocado: tags=arch:x86_64 > :avocado: tags=accel:kvm
On Wed, Feb 3, 2021 at 2:24 PM Cleber Rosa <crosa@redhat.com> wrote: > > This is basically the infrastructure around "boot_linux.py" tests, but > now made into a base class for general use. > > Signed-off-by: Cleber Rosa <crosa@redhat.com> > --- > tests/acceptance/avocado_qemu/__init__.py | 87 +++++++++++++++++++++ > tests/acceptance/boot_linux.py | 94 ++--------------------- > tests/acceptance/virtiofs_submounts.py | 6 +- > 3 files changed, 94 insertions(+), 93 deletions(-) > > diff --git a/tests/acceptance/avocado_qemu/__init__.py b/tests/acceptance/avocado_qemu/__init__.py > index bf54e419da..b06692a59d 100644 > --- a/tests/acceptance/avocado_qemu/__init__.py > +++ b/tests/acceptance/avocado_qemu/__init__.py I found it not so intuitive to have the base class defined here. I see the number of base classes for the tests growing in the future. A common place for base classes for tests would be better, just like the `qemu.utils` you are defining somewhere else. Anyway, this is a design decision that can be changed later, so Reviewed-by: Willian Rampazzo <willianr@redhat.com>
On Mon, Feb 15, 2021 at 04:06:45PM -0300, Willian Rampazzo wrote: > On Wed, Feb 3, 2021 at 2:24 PM Cleber Rosa <crosa@redhat.com> wrote: > > > > This is basically the infrastructure around "boot_linux.py" tests, but > > now made into a base class for general use. > > > > Signed-off-by: Cleber Rosa <crosa@redhat.com> > > --- > > tests/acceptance/avocado_qemu/__init__.py | 87 +++++++++++++++++++++ > > tests/acceptance/boot_linux.py | 94 ++--------------------- > > tests/acceptance/virtiofs_submounts.py | 6 +- > > 3 files changed, 94 insertions(+), 93 deletions(-) > > > > diff --git a/tests/acceptance/avocado_qemu/__init__.py b/tests/acceptance/avocado_qemu/__init__.py > > index bf54e419da..b06692a59d 100644 > > --- a/tests/acceptance/avocado_qemu/__init__.py > > +++ b/tests/acceptance/avocado_qemu/__init__.py > > I found it not so intuitive to have the base class defined here. I see > the number of base classes for the tests growing in the future. A > common place for base classes for tests would be better, just like the > `qemu.utils` you are defining somewhere else. Anyway, this is a design > decision that can be changed later, so > Hi Willian, I tend to agree, and my medium/long term vision is similar. What I expect to be able to do soon (this is connected to John's work) is to have "avocado_qemu" as something like "qemu.testing.functional" which describe its Avocado (and other) dependencies. A "qemu.test.other" could describe its own dependencies (which may not include Avocado). > Reviewed-by: Willian Rampazzo <willianr@redhat.com> > > Thanks for the review, - Cleber.
diff --git a/tests/acceptance/avocado_qemu/__init__.py b/tests/acceptance/avocado_qemu/__init__.py index bf54e419da..b06692a59d 100644 --- a/tests/acceptance/avocado_qemu/__init__.py +++ b/tests/acceptance/avocado_qemu/__init__.py @@ -16,6 +16,13 @@ import tempfile import avocado +from avocado.utils import cloudinit +from avocado.utils import datadrainer +from avocado.utils import network +from avocado.utils import vmimage +from avocado.utils.path import find_command + + #: The QEMU build root directory. It may also be the source directory #: if building from the source dir, but it's safer to use BUILD_DIR for #: that purpose. Be aware that if this code is moved outside of a source @@ -206,3 +213,83 @@ class Test(avocado.Test): expire=expire, find_only=find_only, cancel_on_missing=cancel_on_missing) + + +class LinuxTest(Test): + """Facilitates having a cloud-image Linux based available. + + For tests that indend to interact with guests, this is a better choice + to start with than the more vanilla `Test` class. + """ + + timeout = 900 + chksum = None + + def setUp(self, ssh_pubkey=None): + super(LinuxTest, self).setUp() + self.vm.add_args('-smp', '2') + self.vm.add_args('-m', '1024') + self.set_up_boot() + self.set_up_cloudinit(ssh_pubkey) + + def download_boot(self): + self.log.debug('Looking for and selecting a qemu-img binary to be ' + 'used to create the bootable snapshot image') + # If qemu-img has been built, use it, otherwise the system wide one + # will be used. If none is available, the test will cancel. + qemu_img = os.path.join(BUILD_DIR, 'qemu-img') + if not os.path.exists(qemu_img): + qemu_img = find_command('qemu-img', False) + if qemu_img is False: + self.cancel('Could not find "qemu-img", which is required to ' + 'create the bootable image') + vmimage.QEMU_IMG = qemu_img + + self.log.info('Downloading/preparing boot image') + # Fedora 31 only provides ppc64le images + image_arch = self.arch + if image_arch == 'ppc64': + image_arch = 'ppc64le' + try: + boot = vmimage.get( + 'fedora', arch=image_arch, version='31', + checksum=self.chksum, + algorithm='sha256', + cache_dir=self.cache_dirs[0], + snapshot_dir=self.workdir) + except: + self.cancel('Failed to download/prepare boot image') + return boot.path + + def prepare_cloudinit(self, ssh_pubkey=None): + self.log.info('Preparing cloudinit image') + try: + cloudinit_iso = os.path.join(self.workdir, 'cloudinit.iso') + self.phone_home_port = network.find_free_port() + cloudinit.iso(cloudinit_iso, self.name, + username='root', + password='password', + # QEMU's hard coded usermode router address + phone_home_host='10.0.2.2', + phone_home_port=self.phone_home_port, + authorized_key=ssh_pubkey) + except Exception: + self.cancel('Failed to prepare the cloudinit image') + return cloudinit_iso + + def set_up_boot(self): + path = self.download_boot() + self.vm.add_args('-drive', 'file=%s' % path) + + def set_up_cloudinit(self, ssh_pubkey=None): + cloudinit_iso = self.prepare_cloudinit(ssh_pubkey) + self.vm.add_args('-drive', 'file=%s,format=raw' % cloudinit_iso) + + def launch_and_wait(self): + self.vm.set_console() + self.vm.launch() + console_drainer = datadrainer.LineLogger(self.vm.console_socket.fileno(), + logger=self.log.getChild('console')) + console_drainer.start() + self.log.info('VM launched, waiting for boot confirmation from guest') + cloudinit.wait_for_phone_home(('0.0.0.0', self.phone_home_port), self.name) diff --git a/tests/acceptance/boot_linux.py b/tests/acceptance/boot_linux.py index bcd923bb4a..14e89d020d 100644 --- a/tests/acceptance/boot_linux.py +++ b/tests/acceptance/boot_linux.py @@ -10,16 +10,11 @@ import os -from avocado_qemu import Test, BUILD_DIR +from avocado_qemu import LinuxTest, BUILD_DIR from qemu.accel import kvm_available from qemu.accel import tcg_available -from avocado.utils import cloudinit -from avocado.utils import network -from avocado.utils import vmimage -from avocado.utils import datadrainer -from avocado.utils.path import find_command from avocado import skipIf ACCEL_NOT_AVAILABLE_FMT = "%s accelerator does not seem to be available" @@ -27,86 +22,7 @@ KVM_NOT_AVAILABLE = ACCEL_NOT_AVAILABLE_FMT % "KVM" TCG_NOT_AVAILABLE = ACCEL_NOT_AVAILABLE_FMT % "TCG" -class BootLinuxBase(Test): - def download_boot(self): - self.log.debug('Looking for and selecting a qemu-img binary to be ' - 'used to create the bootable snapshot image') - # If qemu-img has been built, use it, otherwise the system wide one - # will be used. If none is available, the test will cancel. - qemu_img = os.path.join(BUILD_DIR, 'qemu-img') - if not os.path.exists(qemu_img): - qemu_img = find_command('qemu-img', False) - if qemu_img is False: - self.cancel('Could not find "qemu-img", which is required to ' - 'create the bootable image') - vmimage.QEMU_IMG = qemu_img - - self.log.info('Downloading/preparing boot image') - # Fedora 31 only provides ppc64le images - image_arch = self.arch - if image_arch == 'ppc64': - image_arch = 'ppc64le' - try: - boot = vmimage.get( - 'fedora', arch=image_arch, version='31', - checksum=self.chksum, - algorithm='sha256', - cache_dir=self.cache_dirs[0], - snapshot_dir=self.workdir) - except: - self.cancel('Failed to download/prepare boot image') - return boot.path - - def prepare_cloudinit(self, ssh_pubkey=None): - self.log.info('Preparing cloudinit image') - try: - cloudinit_iso = os.path.join(self.workdir, 'cloudinit.iso') - self.phone_home_port = network.find_free_port() - cloudinit.iso(cloudinit_iso, self.name, - username='root', - password='password', - # QEMU's hard coded usermode router address - phone_home_host='10.0.2.2', - phone_home_port=self.phone_home_port, - authorized_key=ssh_pubkey) - except Exception: - self.cancel('Failed to prepare the cloudinit image') - return cloudinit_iso - -class BootLinux(BootLinuxBase): - """ - Boots a Linux system, checking for a successful initialization - """ - - timeout = 900 - chksum = None - - def setUp(self, ssh_pubkey=None): - super(BootLinux, self).setUp() - self.vm.add_args('-smp', '2') - self.vm.add_args('-m', '1024') - self.set_up_boot() - self.set_up_cloudinit(ssh_pubkey) - - def set_up_boot(self): - path = self.download_boot() - self.vm.add_args('-drive', 'file=%s' % path) - - def set_up_cloudinit(self, ssh_pubkey=None): - cloudinit_iso = self.prepare_cloudinit(ssh_pubkey) - self.vm.add_args('-drive', 'file=%s,format=raw' % cloudinit_iso) - - def launch_and_wait(self): - self.vm.set_console() - self.vm.launch() - console_drainer = datadrainer.LineLogger(self.vm.console_socket.fileno(), - logger=self.log.getChild('console')) - console_drainer.start() - self.log.info('VM launched, waiting for boot confirmation from guest') - cloudinit.wait_for_phone_home(('0.0.0.0', self.phone_home_port), self.name) - - -class BootLinuxX8664(BootLinux): +class BootLinuxX8664(LinuxTest): """ :avocado: tags=arch:x86_64 """ @@ -154,7 +70,7 @@ class BootLinuxX8664(BootLinux): self.launch_and_wait() -class BootLinuxAarch64(BootLinux): +class BootLinuxAarch64(LinuxTest): """ :avocado: tags=arch:aarch64 :avocado: tags=machine:virt @@ -212,7 +128,7 @@ class BootLinuxAarch64(BootLinux): self.launch_and_wait() -class BootLinuxPPC64(BootLinux): +class BootLinuxPPC64(LinuxTest): """ :avocado: tags=arch:ppc64 """ @@ -230,7 +146,7 @@ class BootLinuxPPC64(BootLinux): self.launch_and_wait() -class BootLinuxS390X(BootLinux): +class BootLinuxS390X(LinuxTest): """ :avocado: tags=arch:s390x """ diff --git a/tests/acceptance/virtiofs_submounts.py b/tests/acceptance/virtiofs_submounts.py index 1e745f15a2..25ea54b6ff 100644 --- a/tests/acceptance/virtiofs_submounts.py +++ b/tests/acceptance/virtiofs_submounts.py @@ -5,15 +5,13 @@ import subprocess import time from avocado import skipUnless -from avocado_qemu import Test, BUILD_DIR +from avocado_qemu import LinuxTest, BUILD_DIR from avocado_qemu import wait_for_console_pattern from avocado.utils import ssh from qemu.accel import kvm_available from qemu.utils import get_info_usernet_hostfwd_port -from boot_linux import BootLinux - def run_cmd(args): subp = subprocess.Popen(args, @@ -72,7 +70,7 @@ def has_cmds(*cmds): return (True, '') -class VirtiofsSubmountsTest(BootLinux): +class VirtiofsSubmountsTest(LinuxTest): """ :avocado: tags=arch:x86_64 :avocado: tags=accel:kvm
This is basically the infrastructure around "boot_linux.py" tests, but now made into a base class for general use. Signed-off-by: Cleber Rosa <crosa@redhat.com> --- tests/acceptance/avocado_qemu/__init__.py | 87 +++++++++++++++++++++ tests/acceptance/boot_linux.py | 94 ++--------------------- tests/acceptance/virtiofs_submounts.py | 6 +- 3 files changed, 94 insertions(+), 93 deletions(-)