-
Notifications
You must be signed in to change notification settings - Fork 6
feat: add snphost config/commit test module #241
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
amd-aliem
wants to merge
1
commit into
AMDEPYC:main
Choose a base branch
from
amd-aliem:config-commit-test
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
48 changes: 33 additions & 15 deletions
48
...sr/local/lib/scripts/generate_sev_certificate/sev_certificate/generate_sev_certificate.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,41 @@ | ||
| import sys | ||
| import subprocess | ||
| import os | ||
| import emoji as em | ||
| import textwrap | ||
| import re | ||
| import json | ||
|
|
||
| # Import user-defined modules located at sibling directory in the parent folder | ||
| from sev_certificate_version_3_0_0_0 import SEV_Certificate as sev_certificate_v_3_0_0_0 | ||
| from sev_certificate_version_3_0_0_0 import SEV_Certificate as SEV_Certificate_v3_0_0_0 | ||
| from sev_certificate_version import SEV_Certificate as SEV_Certificate_structured | ||
|
|
||
| sev_report = '' | ||
| FAIL_MARKER = em.emojize(':cross_mark:') | ||
|
|
||
| # Get SEV Certificate Version 3.0.0-0 | ||
| sev_report_v_3_0_0_0 = sev_certificate_v_3_0_0_0() | ||
| sev_report += sev_report_v_3_0_0_0.generate_sev_certificate() | ||
| # Certification levels in ascending order. | ||
| # v3.0.0-0 uses its own class (service-based status extraction). | ||
| # All subsequent levels use the structured JSON class, just with different version strings. | ||
| levels = [ | ||
| SEV_Certificate_v3_0_0_0(), | ||
| SEV_Certificate_structured("3.0.0-1"), | ||
| ] | ||
|
|
||
| # Print SEV Certificate into the console | ||
| print(sev_report) | ||
| combined = '' | ||
| highest_passed = None | ||
|
|
||
| # Write certificate to file | ||
| sev_report_v_3_0_0_0.write_sev_certificate(sev_report, "~/sev_certificate_v3.0.0-0.txt") | ||
| for cert in levels: | ||
| content = cert.generate_sev_certificate() | ||
| combined += content | ||
| if FAIL_MARKER not in content: | ||
| highest_passed = cert.sev_version | ||
|
|
||
| print(combined) | ||
|
|
||
| # Write one combined cert named after highest achieved level | ||
| if highest_passed: | ||
| output_file = os.path.expanduser(f"~/sev_certificate_v{highest_passed}.txt") | ||
| else: | ||
| output_file = os.path.expanduser("~/sev_certificate.txt") | ||
|
|
||
| with open(output_file, "w") as f: | ||
| f.write(combined) | ||
|
|
||
| print(f"Certificate saved to: {output_file}") | ||
| if highest_passed: | ||
| print(f"Highest achieved level: {highest_passed}") | ||
| else: | ||
| print("No certification level achieved") | ||
92 changes: 92 additions & 0 deletions
92
...usr/local/lib/scripts/generate_sev_certificate/sev_certificate/sev_certificate_version.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| import subprocess | ||
| import json | ||
| import emoji as em | ||
|
|
||
| test_status_emojis = { | ||
| 'pass': em.emojize(':check_mark_button:'), | ||
| 'fail': em.emojize(':cross_mark:'), | ||
| 'skip': em.emojize(':fast_forward:', language='alias'), | ||
| } | ||
|
|
||
|
|
||
| class SEV_Certificate: | ||
| """Generic certificate generator for structured JSON test results. | ||
|
|
||
| Parses step/summary JSON lines from journald, filtered by SEV_VERSION | ||
| and grouped by SEV_TEST_GROUP. Works for any certification level that | ||
| uses the emit_step/emit_summary JSON format. | ||
| """ | ||
|
|
||
| def __init__(self, sev_version): | ||
| self.sev_version = sev_version | ||
|
|
||
| def get_test_group_summary(self): | ||
| """Generate per-group test summaries from structured JSON results.""" | ||
| cmd = f"journalctl SEV_VERSION={self.sev_version} -o json" | ||
| result = subprocess.run(cmd, shell=True, text=True, capture_output=True, check=True) | ||
|
|
||
|
amd-aliem marked this conversation as resolved.
|
||
| groups = {} | ||
| for line in result.stdout.strip().splitlines(): | ||
| try: | ||
| record = json.loads(line) | ||
| message = record.get("MESSAGE", "") | ||
| if not message.startswith("{"): | ||
| continue | ||
| entry = json.loads(message) | ||
| except (json.JSONDecodeError, ValueError): | ||
| continue | ||
| group = record.get("SEV_TEST_GROUP", "unknown") | ||
| if group not in groups: | ||
| groups[group] = {"steps": [], "summary": None} | ||
| if entry.get("type") == "step": | ||
| groups[group]["steps"].append(entry) | ||
| elif entry.get("type") == "summary": | ||
| groups[group]["summary"] = entry | ||
|
|
||
| content = "" | ||
|
|
||
| for group, data in groups.items(): | ||
| summary = data["summary"] | ||
| steps = data["steps"] | ||
|
|
||
| if summary: | ||
| overall = summary.get("status", "?") | ||
| passed = summary.get("passed", 0) | ||
| failed = summary.get("failed", 0) | ||
| else: | ||
| passed = sum(1 for s in steps if s.get("status") == "pass") | ||
| failed = sum(1 for s in steps if s.get("status") == "fail") | ||
| overall = "fail" if failed > 0 else "pass" | ||
|
|
||
| overall_emoji = test_status_emojis.get(overall, "?") | ||
| content += f"\n[ {overall_emoji} ] {group} ({passed} passed, {failed} failed)\n" | ||
|
|
||
| for step in steps: | ||
| emoji = test_status_emojis.get(step.get("status", "?"), "?") | ||
| name = step.get("test", "?") | ||
| detail = step.get("detail", "") | ||
| line = f"\t{emoji} {name}" | ||
| if detail: | ||
| line += f" ({detail})" | ||
| content += line + "\n" | ||
|
|
||
| return content.expandtabs(2) | ||
|
|
||
| def get_sev_log(self): | ||
| """Get raw journal log for this certification level.""" | ||
| cmd = f"journalctl SEV_VERSION={self.sev_version} --no-hostname --utc" | ||
| result = subprocess.run(cmd, shell=True, text=True, capture_output=True, check=True) | ||
| return result.stdout | ||
|
amd-aliem marked this conversation as resolved.
|
||
|
|
||
| def generate_sev_certificate(self): | ||
| """Generate the SEV Certificate content for this level.""" | ||
| content = "\n ====== SEV CERTIFICATE ====== \n" | ||
| content += f"\n SEV VERSION: {self.sev_version} \n" | ||
|
|
||
| content += "\n=== SUMMARY ===\n" | ||
| content += self.get_test_group_summary() | ||
|
|
||
| content += f"\n=== SEV VERSION {self.sev_version} LOG ===\n" | ||
| content += self.get_sev_log() | ||
|
|
||
| return content.expandtabs(2) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 3 additions & 3 deletions
6
...les/system/guest/snpguest-ok/mkosi.extra/usr/local/lib/systemd/system/snpguest-ok.service
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| [Include] | ||
| Include=./snphost-config-commit | ||
| Include=./test-done |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.