|
30 | 30 | import asyncio |
31 | 31 | import concurrent.futures |
32 | 32 | import dataclasses |
33 | | -import logging |
34 | 33 | import json |
| 34 | +import logging |
35 | 35 | import os |
36 | 36 | import statistics |
37 | 37 | import subprocess |
38 | 38 | import time |
| 39 | +import yaml |
| 40 | +from datetime import datetime, timezone |
39 | 41 |
|
40 | 42 | from deepmerge import Merger |
41 | 43 | import qubesadmin |
@@ -249,6 +251,30 @@ def get_time(): |
249 | 251 | return time.clock_gettime(time.CLOCK_MONOTONIC) |
250 | 252 |
|
251 | 253 |
|
| 254 | +def hcl() -> dict: |
| 255 | + completed_process = subprocess.run( |
| 256 | + ["qubes-hcl-report", "--yaml-only"], capture_output=True, check=True |
| 257 | + ) |
| 258 | + report = yaml.safe_load(completed_process.stdout) |
| 259 | + data = { |
| 260 | + "hcl-qubes": report["versions"][0]["qubes"].rstrip(), |
| 261 | + "hcl-xen": report["versions"][0]["xen"].rstrip(), |
| 262 | + "hcl-kernel": report["versions"][0]["kernel"].rstrip(), |
| 263 | + "hcl-memory": int(report["memory"].rstrip()), |
| 264 | + } |
| 265 | + if os.environ.get("QUBES_TEST_PERF_HWINFO"): |
| 266 | + data.update( |
| 267 | + { |
| 268 | + "hcl-certified": report["certified"].rstrip() != "no", |
| 269 | + "hcl-brand": report["brand"].rstrip(), |
| 270 | + "hcl-model": report["model"].rstrip(), |
| 271 | + "hcl-bios": report["bios"].rstrip(), |
| 272 | + "hcl-cpu": report["cpu"].rstrip(), |
| 273 | + } |
| 274 | + ) |
| 275 | + return data |
| 276 | + |
| 277 | + |
252 | 278 | class TestRun: |
253 | 279 | def __init__(self, dom0, dvm, vm1, vm2): |
254 | 280 | self.dom0 = dom0 |
@@ -537,13 +563,52 @@ def report_result(self, test, result): |
537 | 563 | else: |
538 | 564 | total_time = result |
539 | 565 | mean = round(total_time / self.iterations, ROUND_PRECISION) |
| 566 | + |
540 | 567 | data.update( |
541 | 568 | { |
542 | 569 | "iterations": self.iterations, |
543 | 570 | "mean": mean, |
544 | 571 | "total": total_time, |
| 572 | + "date": datetime.now(timezone.utc).strftime( |
| 573 | + "%Y-%m-%dT%H:%M:%S" |
| 574 | + ), |
545 | 575 | } |
546 | 576 | ) |
| 577 | + |
| 578 | + template_properties = {} |
| 579 | + int_properties = [ |
| 580 | + "memory", |
| 581 | + "maxmem", |
| 582 | + "vcpus", |
| 583 | + "qrexec_timeout", |
| 584 | + "shutdown_timeout", |
| 585 | + ] |
| 586 | + wanted_properties = [*int_properties, "kernel", "kernelopts"] |
| 587 | + for prop in wanted_properties: |
| 588 | + val = getattr(self.vm1, prop, "") |
| 589 | + if prop in int_properties: |
| 590 | + val = int(val or 0) |
| 591 | + template_properties[prop] = val |
| 592 | + data.update(template_properties) |
| 593 | + |
| 594 | + template_features = {} |
| 595 | + int_features = ["os-version"] |
| 596 | + wanted_features = [ |
| 597 | + "template-buildtime", |
| 598 | + "last-update", |
| 599 | + "os", |
| 600 | + "os-distribution", |
| 601 | + *int_features, |
| 602 | + ] |
| 603 | + for feature in wanted_features: |
| 604 | + val = self.vm1.features.check_with_template(feature, "") |
| 605 | + if feature in int_features: |
| 606 | + val = int(val or 0) |
| 607 | + template_features[feature] = val |
| 608 | + data.update(template_features) |
| 609 | + |
| 610 | + data.update(hcl()) |
| 611 | + |
547 | 612 | pretty_mean = f"{mean:.{ROUND_PRECISION}f}" |
548 | 613 | pretty_total_time = f"{total_time:.{ROUND_PRECISION}f}" |
549 | 614 | pretty_items = "iterations=" + str(self.iterations) |
@@ -659,7 +724,9 @@ def run_test(self, test: TestConfig): |
659 | 724 | def main(): |
660 | 725 | parser = argparse.ArgumentParser( |
661 | 726 | epilog="You can set QUBES_TEST_PERF_FILE env variable to a path where " |
662 | | - "machine-readable results should be saved." |
| 727 | + "machine-readable results should be saved. If you want to share a " |
| 728 | + "detailed result containing hardware information, set " |
| 729 | + "QUBES_TEST_PERF_HWINFO to a non empty value." |
663 | 730 | ) |
664 | 731 | parser.add_argument("--dvm", required=True) |
665 | 732 | parser.add_argument("--vm1", required=True) |
|
0 commit comments