diff --git a/tests/lib/Qemu.py b/tests/lib/Qemu.py index ea71851..0c637a9 100644 --- a/tests/lib/Qemu.py +++ b/tests/lib/Qemu.py @@ -299,6 +299,12 @@ class QemuMonitor(): READ_TIMEOUT = 2 CONNECT_RETRIES = 60 + def __new__(cls, qemu): + # only 1 monitor per qemu machine + if qemu.monitor is None: + qemu.monitor = super().__new__(cls) + return qemu.monitor + def __init__(self, qemu): self.socket = None assert qemu.qcmd.monitor_file != None, "Monitor socket file is undefined" @@ -312,11 +318,13 @@ def __init__(self, qemu): break except Exception as e: # give some time to make sure socket file is available - print(f'Try to connect to qemu : {qemu.qcmd.monitor_file} : {e}') time.sleep(1) self.socket.settimeout(self.READ_TIMEOUT) + # wait for prompt + print(f'Connected : {qemu.qcmd.monitor_file}, wait for prompt.') + self.wait_prompt() - def recv(self): + def recv_data(self): msg = '' try: while True: @@ -327,6 +335,22 @@ def recv(self): msg += recv_data.decode('utf-8') except: pass + return msg + + def wait_prompt(self): + msg = self.recv_data() + assert self.DELIMITER_STRING in msg, f'Fail on wait for monitor prompt : {msg}' + + def recv(self): + """ + Return an array of messages from qemu process + separated by the prompt string (qemu) + Example: + (qemu) running + (qemu) rebooting + will result in the returned value : [' running', ' rebooting'] + """ + msg = self.recv_data() return msg.split(self.DELIMITER_STRING) def send_command(self, cmd): @@ -481,7 +505,6 @@ class QemuMachineService: # to run the guest manually qemu_run_script = """ #!/bin/bash -echo "To connect to the VM : ssh -p {fwd_port} root@localhost" {cmd_str} """ @@ -511,6 +534,10 @@ def __init__(self, ) self.qcmd.add_image(self.image_path) self.qcmd.add_monitor() + # monitor client associated to this machine + # since there could be only one client, we keep track + # of this client instance in the qemu machine object + self.monitor = None self.qcmd.add_qmp() if QemuMachineService.QEMU_MACHINE_PORT_FWD not in service_blacklist: self.fwd_port = util.tcp_port_available() @@ -606,7 +633,7 @@ def communicate(self): """ Wait for qemu to exit """ - self.out, self.err = self.proc.communicate() + self.out, self.err = self.proc.communicate(timeout=60) if self.proc.returncode != 0: print(self.err.decode()) return self.out, self.err @@ -622,17 +649,19 @@ def stop(self): # self.proc.returncode == None -> not yet terminated - # try to shutdown the VM properly, this is important to avoid - # rootfs corruption if we want to run the guest again - mon = QemuMonitor(self) - mon.powerdown() try: + # try to shutdown the VM properly, this is important to avoid + # rootfs corruption if we want to run the guest again + # catch exception and ignore it since we are stopping .... no need to fail the test + mon = QemuMonitor(self) + mon.powerdown() + self.communicate() return except Exception as e: pass - print('Qemu process did not shutdown properly, terminate it ...') + print(f'Qemu process did not shutdown properly, terminate it ... ({self.workdir_name})') # terminate qemu process (SIGTERM) try: self.proc.terminate() @@ -671,8 +700,7 @@ def write_cmd_to_file(self, fname : str): cmd_str += f'\"{el}\" ' else: cmd_str += f'{el} ' - script_contents = qemu_run_script.format(fwd_port=self.fwd_port, - cmd_str=cmd_str) + script_contents = qemu_run_script.format(cmd_str=cmd_str) run_script.write(script_contents) f = pathlib.Path(fname) f.chmod(f.stat().st_mode | stat.S_IEXEC) diff --git a/tests/tests/test_stress_boot.py b/tests/tests/test_stress_boot.py index 6a219b3..b592a6c 100644 --- a/tests/tests/test_stress_boot.py +++ b/tests/tests/test_stress_boot.py @@ -22,7 +22,7 @@ import util -def test_boot(): +def test_stress_boot(): """ Boot in loop """ diff --git a/tests/tests/test_stress_resources.py b/tests/tests/test_stress_resources.py index a83e2a6..2f26186 100644 --- a/tests/tests/test_stress_resources.py +++ b/tests/tests/test_stress_resources.py @@ -21,7 +21,7 @@ import Qemu import util -def test_huge_resource_vm(qm): +def test_stress_huge_resource_vm(qm): """ Test huge resources (Intel Case ID 007) """ @@ -34,11 +34,12 @@ def test_huge_resource_vm(qm): qm.qcmd.plugins['memory'].memory = '%dG' % (huge_mem_gb) qm.run() - ssh = Qemu.QemuSSH(qm) + # huge guest memory -> increase the timeout to give more time to guest to boot + ssh = Qemu.QemuSSH(qm, timeout=100) qm.stop() -def test_memory_limit_resource_vm(qm): +def test_stress_memory_limit_resource_vm(qm): """ Test memory limit resource (No Intel Case) """ @@ -54,7 +55,7 @@ def test_memory_limit_resource_vm(qm): qm.stop() -def test_max_vcpus(qm): +def test_stress_max_vcpus(qm): """ Test max vcpus (No Intel Case ID) """ @@ -65,12 +66,12 @@ def test_max_vcpus(qm): qm.qcmd.plugins['cpu'].nb_cores = num_cpus qm.run() - ssh = Qemu.QemuSSH(qm) + ssh = Qemu.QemuSSH(qm, timeout=100) qm.stop() -def test_max_guests(): +def test_stress_max_guests(): """ Test max guests (No Intel Case ID) """ diff --git a/tests/tox.ini b/tests/tox.ini index 2afe3a5..3045f8a 100644 --- a/tests/tox.ini +++ b/tests/tox.ini @@ -24,36 +24,40 @@ commands_pre = [testenv:test_guest] commands = - python3 -m pytest -s -v --junitxml=test_guest_report.xml -k test_guest + python3 -m pytest -s -v --junitxml=test_guest_report.xml --ignore=tests/guest -k test_guest [testenv:test_host] commands = - python3 -m pytest -s -v --junitxml=test_host_report.xml -k test_host + python3 -m pytest -s -v --junitxml=test_host_report.xml --ignore=tests/guest -k test_host [testenv:test_boot] commands = - python3 -m pytest -s -v --junitxml=test_boot_report.xml -k test_boot + python3 -m pytest -s -v --junitxml=test_boot_report.xml --ignore=tests/guest -k test_boot [testenv:test_perf] commands = - python3 -m pytest -s -v --junitxml=test_perf_report.xml -k test_perf + python3 -m pytest -s -v --junitxml=test_perf_report.xml --ignore=tests/guest -k test_perf [testenv:test_quote] commands = - python3 -m pytest -s -v --junitxml=test_quote_report.xml -k test_quote + python3 -m pytest -s -v --junitxml=test_quote_report.xml --ignore=tests/guest -k test_quote [testenv:test_stress] commands = - python3 -m pytest -s -v --junitxml=test_stress_report.xml -k test_stress + python3 -m pytest -s -v --junitxml=test_stress_report.xml --ignore=tests/guest -k test_stress + +[testenv:test_all_except_perf] +commands = + python3 -m pytest -s -v --junitxml=test_all_report.xml --ignore=tests/guest -k 'not test_perf' [testenv:test_all] commands = - python3 -m pytest -s -v --junitxml=test_all_report.xml + python3 -m pytest -s -v --junitxml=test_all_report.xml --ignore=tests/guest [testenv:test_specify] commands = - python3 -m pytest -s -v --junitxml=test_specify_report.xml -k {posargs} + python3 -m pytest -s -v --junitxml=test_specify_report.xml --ignore=tests/guest -k {posargs} [testenv:collect_tests] commands = - python3 -m pytest -s -v --collect-only -k {posargs} + python3 -m pytest -s -v --collect-only --ignore=tests/guest -k {posargs}