Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@ heavy memory load use:
$ nix run -L .#tests.x86_64-linux.long_migration_with_load.driver
```

### Obtaining debug logs

To obtain debug logs from failing test cases automatically, set the
`DBG_LOG_DIR` environment variable:

```bash
DBG_LOG_DIR="./logs" nix run .#tests.x86_64-linux.default.driver
```

After the run is over, you can find relevant Libvirt and Cloud Hypervisor logs
in the `DBG_LOG_DIR`.

## Using a Custom Libvirt or Cloud Hypervisor

To test against a specific version or local build, you should update your
Expand Down
35 changes: 21 additions & 14 deletions tests/testscript.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from functools import partial
import libvirt # type: ignore
import os
import textwrap
import time
import unittest
Expand All @@ -13,9 +14,9 @@
from nixos_test_stubs import start_all, computeVM, controllerVM # type: ignore


class PrintLogsOnErrorTestCase(unittest.TestCase):
class SaveLogsOnErrorTestCase(unittest.TestCase):
"""
Custom TestCase class that prints interesting logs in error case.
Custom TestCase class that saves interesting logs in error case.
"""

def run(self, result=None):
Expand All @@ -26,31 +27,37 @@ def run(self, result=None):
original_addFailure = result.addFailure

def custom_addError(test, err):
self.print_logs(f"Error in {test._testMethodName}")
self.save_logs(test, f"Error in {test._testMethodName}")
original_addError(test, err)

def custom_addFailure(test, err):
self.print_logs(f"Failure in {test._testMethodName}")
self.save_logs(test, f"Failure in {test._testMethodName}")
original_addFailure(test, err)

result.addError = custom_addError
result.addFailure = custom_addFailure

return super().run(result)

def print_machine_log(self, machine, path):
status, out = machine.execute(f"cat {path}")
if status != 0:
print(f"Could not retrieve logs: {machine.name}:{path}")
return
print(f"\nLog {machine.name}:{path}:\n{out}\n")
def save_machine_log(self, machine, log_path, dst_path):
try:
machine.copy_from_vm(log_path, dst_path)
# Non-existing logs lead to an Exception that we ignore
except Exception:
pass

def print_logs(self, message):
def save_logs(self, test, message):
print(f"{message}")

if "DBG_LOG_DIR" not in os.environ:
return

for machine in [controllerVM, computeVM]:
self.print_machine_log(machine, "/var/log/libvirt/ch/testvm.log")
self.print_machine_log(machine, "/var/log/libvirt/libvirtd.log")
dst_path = os.path.join(
os.environ["DBG_LOG_DIR"], f"{test._testMethodName}", f"{machine.name}"
)
self.save_machine_log(machine, "/var/log/libvirt/ch/testvm.log", dst_path)
self.save_machine_log(machine, "/var/log/libvirt/libvirtd.log", dst_path)


class CommandGuard:
Expand Down Expand Up @@ -79,7 +86,7 @@ def __exit__(self, exc_type, exc_val, exc_tb):
self._finilizer()


class LibvirtTests(PrintLogsOnErrorTestCase):
class LibvirtTests(SaveLogsOnErrorTestCase):
@classmethod
def setUpClass(cls):
start_all()
Expand Down