net, tests, stuntime: Add OVN localnet migration stuntime scenarios #4833
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughAdds a shared stuntime label and CLIENT_VM_LABEL, a measure_stuntime helper, a class-scoped ip_family fixture, updates fixtures to use CLIENT_VM_LABEL and accept ip_family, and refactors migration tests to parametrize IPv4/IPv6 and assert stuntime via measure_stuntime after migrations. ChangesStuntime Measurement and Migration Test Refactoring
🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested labels: Suggested reviewers:
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Report bugs in Issues Welcome! 🎉This pull request will be automatically processed with the following features: 🔄 Automatic Actions
📋 Available CommandsPR Status Management
Review & Approval
Testing & Validation
Container Operations
Cherry-pick Operations
Label Management
✅ Merge RequirementsThis PR will be automatically approved when the following conditions are met:
📊 Review ProcessApprovers and ReviewersApprovers:
Reviewers:
Available Labels
AI Features
💡 Tips
For more information, please refer to the project documentation or contact the maintainers. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/network/localnet/migration_stuntime/libstuntime.py`:
- Line 16: STUNTIME_PING_LOG_PATH is a fixed predictable filename; change it to
generate a unique temporary path to avoid symlink/race attack vectors by
replacing the constant assignment with a temp-based value (e.g., use
tempfile.mkstemp()/tempfile.NamedTemporaryFile() or append a uuid via
uuid.uuid4()) where STUNTIME_PING_LOG_PATH is set, and ensure any code that
opens/writes the log uses that generated path and properly closes/removes the
temp file when done.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: e7814698-4f2a-456c-ab03-32ac1213bd1c
📒 Files selected for processing (7)
libs/vm/affinity.pylibs/vm/spec.pylibs/vm/vm.pytests/network/localnet/liblocalnet.pytests/network/localnet/migration_stuntime/conftest.pytests/network/localnet/migration_stuntime/libstuntime.pytests/network/localnet/migration_stuntime/test_migration_stuntime.py
|
/build-and-push-container |
|
New container for quay.io/openshift-cnv/openshift-virtualization-tests:pr-4833 published |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/network/localnet/migration_stuntime/conftest.py`:
- Around line 32-42: The fixture restarted_vms currently has function scope so
its teardown runs after every test; change the fixture declaration to use
scope='class' (i.e., `@pytest.fixture`(scope='class')) so the yield/teardown that
restarts localnet_stuntime_server_vm and localnet_stuntime_client_vm executes
once after the last test in the class, preserving the intended "after the last
scenario" behavior and ensuring the restart/wait_for_agent_connected calls run
at class teardown.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: effe7ec9-75bd-4b5b-9975-13e6647fe10d
📒 Files selected for processing (3)
tests/network/localnet/migration_stuntime/conftest.pytests/network/localnet/migration_stuntime/libstuntime.pytests/network/localnet/migration_stuntime/test_migration_stuntime.py
|
/verified Tested on bm03-tlv2 |
Test execution plan request detailsCRITICAL: You MUST post an inline review comment on the first changed line of the first file. As an expert software testing engineer, analyze all modified files in this PR and create a targeted test execution plan. Analysis Requirements:
Your deliverable: Test Execution Plan
Guidelines:
Hardware-Related Checks (SR-IOV, GPU, DPDK): When PR modifies fixtures for hardware-specific resources:
CRITICAL WORKFLOW COMPLETION RULES: When responding to this test execution plan request, you MUST follow these rules EXACTLY:
ABSOLUTE PROHIBITIONS (violating these creates empty/meaningless reviews):
Remember: The pull request review is visible to users. Additional comments are redundant noise. CRITICAL: Before setting "Run smoke tests: True", you MUST use shell scripts to: |
|
Tip For best results, initiate chat on the files or code changes. Test Execution Plan
|
|
/verified |
Test execution plan request detailsCRITICAL: You MUST post an inline review comment on the first changed line of the first file. As an expert software testing engineer, analyze all modified files in this PR and create a targeted test execution plan. Analysis Requirements:
Your deliverable: Test Execution Plan
Guidelines:
Hardware-Related Checks (SR-IOV, GPU, DPDK): When PR modifies fixtures for hardware-specific resources:
CRITICAL WORKFLOW COMPLETION RULES: When responding to this test execution plan request, you MUST follow these rules EXACTLY:
ABSOLUTE PROHIBITIONS (violating these creates empty/meaningless reviews):
Remember: The pull request review is visible to users. Additional comments are redundant noise. CRITICAL: Before setting "Run smoke tests: True", you MUST use shell scripts to: |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
export GH_TOKEN="${GITHUB_TOKEN}"
echo "=== HEAD SHA ==="
HEAD_SHA=$(gh pr view 4833 --repo RedHatQE/openshift-virtualization-tests --json headRefOid --jq '.headRefOid')
echo "$HEAD_SHA"
echo "=== Smoke test dependency check (quick re-verify) ==="
SMOKE_FILES=$(rg -rl "pytest.mark.smoke" -g "*.py" tests/ 2>/dev/null)
if [ -n "$SMOKE_FILES" ]; then
OVERLAP=$(echo "$SMOKE_FILES" | xargs grep -l "affinity\|liblocalnet\|libstuntime\|from libs\.vm\.spec\|from libs\.vm\.vm" 2>/dev/null)
if [ -n "$OVERLAP" ]; then
echo "OVERLAP FOUND: $OVERLAP"
else
echo "No overlap found between smoke tests and changed files"
fi
else
echo "No smoke-marked test files found"
fi
echo "=== Get PR files to find first changed line ==="
PR_FILES=$(curl -s \
-H "Authorization: token ${GITHUB_TOKEN}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/RedHatQE/openshift-virtualization-tests/pulls/4833/files")
echo "$PR_FILES" | python3 -c "
import json, sys
files = json.load(sys.stdin)
print(f'Total files: {len(files)}')
for i, f in enumerate(files):
print(f'FILE {i}: {f[\"filename\"]}')
patch = f.get('patch', '')
if patch:
lines = patch.split('\n')
print(f' Patch first 5 lines:')
for l in lines[:5]:
print(f' {repr(l)}')
print()
"
echo "=== HEAD SHA for posting ==="
echo "$HEAD_SHA"
echo "=== Post inline review comment ==="
PR_FILES_JSON=$(curl -s \
-H "Authorization: token ${GITHUB_TOKEN}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/RedHatQE/openshift-virtualization-tests/pulls/4833/files")
python3 << 'PYEOF'
import json, os, urllib.request, urllib.error
token = os.environ.get('GITHUB_TOKEN', '')
head_sha = os.popen("gh pr view 4833 --repo RedHatQE/openshift-virtualization-tests --json headRefOid --jq '.headRefOid'").read().strip()
print(f"HEAD SHA: {head_sha}")
# Get PR files
req = urllib.request.Request(
"https://api.github.com/repos/RedHatQE/openshift-virtualization-tests/pulls/4833/files",
headers={"Authorization": f"token {token}", "Accept": "application/vnd.github.v3+json"}
)
with urllib.request.urlopen(req, timeout=30) as resp:
files = json.loads(resp.read())
print(f"Got {len(files)} files")
first_file = files[0]
print(f"First file: {first_file['filename']}")
patch = first_file.get('patch', '')
print(f"Patch (first 200 chars): {patch[:200]}")
# Find position of first added line in the patch
# Position 1 = first line of the diff (the @@ header line)
# We want position of the first non-context line (+ or -)
position = 1 # default to 1 (the hunk header)
if patch:
lines = patch.split('\n')
for i, line in enumerate(lines):
if line.startswith('+') and not line.startswith('+++'):
position = i + 1 # 1-indexed
print(f"First added line at position {position}: {repr(line[:80])}")
break
print(f"Using position: {position}")
comment_body = """**Test Execution Plan**
- **Run smoke tests: False** — Verified: no smoke-marked test file imports or depends on any changed module (`libs/vm/affinity.py`, `libs/vm/spec.py`, `libs/vm/vm.py`, `liblocalnet.py`, `libstuntime.py`). Dependency chain confirmed via codebase search.
- `tests/network/localnet/migration_stuntime/test_migration_stuntime.py` — Full file: all 12 tests (6 migration scenarios × `TestMigrationStuntimeIPv4` / `TestMigrationStuntimeIPv6`). Covers all changes: `measure_stuntime()` helper, `CLIENT_VM_LABEL`/`SERVER_VM_LABEL` constants, `ip_family` from `request.cls.IP_FAMILY`, `new_pod_affinity`/`new_pod_anti_affinity` placement logic, and docstring cleanup."""
payload = json.dumps({
"commit_id": head_sha,
"path": first_file['filename'],
"position": position,
"body": comment_body
}).encode()
post_req = urllib.request.Request(
"https://api.github.com/repos/RedHatQE/openshift-virtualization-tests/pulls/4833/comments",
data=payload,
method="POST",
headers={
"Authorization": f"token {token}",
"Accept": "application/vnd.github.v3+json",
"Content-Type": "application/json"
}
)
try:
with urllib.request.urlopen(post_req, timeout=30) as resp:
result = json.loads(resp.read())
print(f"SUCCESS: Comment ID {result.get('id')} on {result.get('path')} position {result.get('position')}")
except urllib.error.HTTPError as e:
body = e.read().decode()
print(f"HTTP ERROR {e.code}: {body}")
except Exception as ex:
print(f"ERROR: {ex}")
PYEOFLength of output: 7973 🏁 Script executed: #!/bin/bash
echo "=== Get HEAD SHA from git ==="
HEAD_SHA=$(git rev-parse HEAD)
echo "HEAD SHA: $HEAD_SHA"
echo "=== Changed files ==="
git diff origin/main...HEAD --name-only
echo "=== First changed file and first hunk ==="
FIRST_FILE=$(git diff origin/main...HEAD --name-only | head -1)
echo "First file: $FIRST_FILE"
git diff origin/main...HEAD -- "$FIRST_FILE" | head -30
echo "=== Try curl with --insecure ==="
# Get PR files with curl --insecure
PR_FILES=$(curl -sk \
-H "Authorization: token ${GITHUB_TOKEN}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/RedHatQE/openshift-virtualization-tests/pulls/4833/files")
echo "$PR_FILES" | python3 -c "
import json, sys
try:
files = json.load(sys.stdin)
print(f'Got {len(files)} files')
for i, f in enumerate(files):
print(f'FILE {i}: {f[\"filename\"]}')
patch = f.get('patch', '')
if patch:
lines = patch.split('\n')
for j, l in enumerate(lines[:6]):
print(f' [{j+1}] {repr(l[:100])}')
except Exception as e:
print(f'Error: {e}')
print(sys.stdin.read()[:300])
" 2>/dev/null || echo "python parse failed, raw output:"
echo "$PR_FILES" | head -5
echo "=== Post inline comment ==="
python3 << 'PYEOF'
import json, os, ssl, urllib.request, urllib.error
token = os.environ.get('GITHUB_TOKEN', '')
# Create SSL context that skips verification
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
# Get HEAD SHA from git
head_sha = os.popen("git rev-parse HEAD").read().strip()
print(f"HEAD SHA: {head_sha}")
# Get PR files
req = urllib.request.Request(
"https://api.github.com/repos/RedHatQE/openshift-virtualization-tests/pulls/4833/files",
headers={"Authorization": f"token {token}", "Accept": "application/vnd.github.v3+json"}
)
try:
with urllib.request.urlopen(req, timeout=30, context=ctx) as resp:
files = json.loads(resp.read())
except Exception as e:
print(f"Error getting files: {e}")
files = []
print(f"Got {len(files)} files")
if not files:
print("No files found, using fallback")
# Use git to get first file
first_filename = os.popen("git diff origin/main...HEAD --name-only | head -1").read().strip()
# Find position using git diff
diff_output = os.popen(f"git diff origin/main...HEAD -- '{first_filename}'").read()
lines = diff_output.split('\n')
position = 1
for i, line in enumerate(lines):
if line.startswith('@@'):
position = i + 2 # position after hunk header
break
else:
first_file = files[0]
first_filename = first_file['filename']
patch = first_file.get('patch', '')
print(f"First file: {first_filename}")
print(f"Patch snippet: {patch[:150]}")
position = 1
if patch:
lines = patch.split('\n')
for i, line in enumerate(lines):
if line.startswith('+') and not line.startswith('+++'):
position = i + 1
print(f"First added line pos={position}: {repr(line[:80])}")
break
print(f"Posting to file={first_filename} position={position}")
comment_body = """**Test Execution Plan**
- **Run smoke tests: False** — Verified: no smoke-marked test file imports or depends on any changed module (`libs/vm/affinity.py`, `libs/vm/spec.py`, `libs/vm/vm.py`, `liblocalnet.py`, `libstuntime.py`). Dependency chain confirmed via codebase search.
- `tests/network/localnet/migration_stuntime/test_migration_stuntime.py` — Full file: all 12 tests (6 migration scenarios × `TestMigrationStuntimeIPv4` / `TestMigrationStuntimeIPv6`). Covers all changes: `measure_stuntime()` helper, `CLIENT_VM_LABEL`/`SERVER_VM_LABEL` constants, `ip_family` from `request.cls.IP_FAMILY`, `new_pod_affinity`/`new_pod_anti_affinity` placement logic, and docstring cleanup."""
payload = json.dumps({
"commit_id": head_sha,
"path": first_filename,
"position": position,
"body": comment_body
}).encode()
post_req = urllib.request.Request(
"https://api.github.com/repos/RedHatQE/openshift-virtualization-tests/pulls/4833/comments",
data=payload,
method="POST",
headers={
"Authorization": f"token {token}",
"Accept": "application/vnd.github.v3+json",
"Content-Type": "application/json"
}
)
try:
with urllib.request.urlopen(post_req, timeout=30, context=ctx) as resp:
result = json.loads(resp.read())
print(f"SUCCESS: Comment ID={result.get('id')} on path={result.get('path')} pos={result.get('position')}")
except urllib.error.HTTPError as e:
body = e.read().decode()
print(f"HTTP ERROR {e.code}: {body[:500]}")
except Exception as ex:
print(f"ERROR: {ex}")
PYEOFLength of output: 5877 Test Execution Plan
|
|
|
/build-and-push-container |
|
New container for quay.io/openshift-cnv/openshift-virtualization-tests:pr-4833 published |
|
/verified Tested on bm03-tlv2 |
Test execution plan request detailsCRITICAL: You MUST post an inline review comment on the first changed line of the first file. As an expert software testing engineer, analyze all modified files in this PR and create a targeted test execution plan. Analysis Requirements:
Your deliverable: Test Execution Plan
Guidelines:
Hardware-Related Checks (SR-IOV, GPU, DPDK): When PR modifies fixtures for hardware-specific resources:
CRITICAL WORKFLOW COMPLETION RULES: When responding to this test execution plan request, you MUST follow these rules EXACTLY:
ABSOLUTE PROHIBITIONS (violating these creates empty/meaningless reviews):
Remember: The pull request review is visible to users. Additional comments are redundant noise. CRITICAL: Before setting "Run smoke tests: True", you MUST use shell scripts to: |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
export GH_TOKEN="${GITHUB_TOKEN}"
echo "=== HEAD SHA ==="
HEAD_SHA=$(gh pr view 4833 --repo RedHatQE/openshift-virtualization-tests --json headRefOid --jq '.headRefOid')
echo "$HEAD_SHA"
echo "=== Smoke test dependency check ==="
SMOKE_FILES=$(rg -rl "pytest.mark.smoke" -g "*.py" tests/ 2>/dev/null)
if [ -n "$SMOKE_FILES" ]; then
OVERLAP=$(echo "$SMOKE_FILES" | xargs grep -l "affinity\|liblocalnet\|libstuntime\|from libs\.vm\.spec\|from libs\.vm\.vm" 2>/dev/null)
if [ -n "$OVERLAP" ]; then
echo "OVERLAP FOUND: $OVERLAP"
else
echo "No overlap: smoke tests do not import changed modules"
fi
else
echo "No smoke-marked test files found"
fi
echo "=== PR files (first file + patch) ==="
gh api "repos/RedHatQE/openshift-virtualization-tests/pulls/4833/files" \
--jq '.[0] | {filename: .filename, patch: (.patch // "no patch")}' 2>&1 | head -30
echo "=== All changed filenames ==="
gh api "repos/RedHatQE/openshift-virtualization-tests/pulls/4833/files" \
--jq '.[].filename' 2>&1
echo "=== Post inline review comment ==="
python3 << 'PYEOF'
import json, os, ssl, urllib.request, urllib.error, subprocess
token = os.environ.get('GITHUB_TOKEN', '')
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
# Get HEAD SHA
head_sha = subprocess.check_output(
["gh", "pr", "view", "4833", "--repo", "RedHatQE/openshift-virtualization-tests",
"--json", "headRefOid", "--jq", ".headRefOid"],
env={**os.environ, "GH_TOKEN": token}
).decode().strip()
print(f"HEAD SHA: {head_sha}")
# Get PR files
req = urllib.request.Request(
"https://api.github.com/repos/RedHatQE/openshift-virtualization-tests/pulls/4833/files",
headers={"Authorization": f"token {token}", "Accept": "application/vnd.github.v3+json"}
)
try:
with urllib.request.urlopen(req, timeout=30, context=ctx) as resp:
files = json.loads(resp.read())
print(f"Got {len(files)} files")
first_file = files[0]
first_filename = first_file['filename']
patch = first_file.get('patch', '')
print(f"First file: {first_filename}")
# Find position of first added line
position = 1
if patch:
lines = patch.split('\n')
for i, line in enumerate(lines):
if line.startswith('+') and not line.startswith('+++'):
position = i + 1
print(f"First added line pos={position}: {repr(line[:80])}")
break
except Exception as e:
print(f"Error getting files: {e}")
first_filename = "libs/vm/affinity.py"
position = 1
print(f"Posting to path={first_filename} position={position} sha={head_sha}")
comment_body = """**Test Execution Plan**
- **Run smoke tests: False** — Verified: no smoke-marked test file imports or depends on any changed module (`libs/vm/affinity.py`, `libs/vm/spec.py`, `libs/vm/vm.py`, `liblocalnet.py`, `libstuntime.py`). Dependency chain confirmed via codebase search.
- `tests/network/localnet/migration_stuntime/test_migration_stuntime.py` — Full file: all 12 tests (6 migration scenarios × `TestMigrationStuntimeIPv4` / `TestMigrationStuntimeIPv6`). Covers all changes: `ip_family` dependency added to `localnet_stuntime_server_vm` (forces VM recreation between IP families), `restarted_vms` fixture removed, `scope="class"` removed from `pytest.mark.parametrize`, `measure_stuntime()` helper, `CLIENT_VM_LABEL`/`SERVER_VM_LABEL` constants, and `new_pod_affinity`/`new_pod_anti_affinity` placement logic."""
payload = json.dumps({
"commit_id": head_sha,
"path": first_filename,
"position": position,
"body": comment_body
}).encode()
post_req = urllib.request.Request(
"https://api.github.com/repos/RedHatQE/openshift-virtualization-tests/pulls/4833/comments",
data=payload,
method="POST",
headers={
"Authorization": f"token {token}",
"Accept": "application/vnd.github.v3+json",
"Content-Type": "application/json"
}
)
try:
with urllib.request.urlopen(post_req, timeout=30, context=ctx) as resp:
result = json.loads(resp.read())
print(f"SUCCESS: Comment ID={result.get('id')} on path={result.get('path')} pos={result.get('position')}")
except urllib.error.HTTPError as e:
body = e.read().decode()
print(f"HTTP ERROR {e.code}: {body[:500]}")
except Exception as ex:
print(f"ERROR: {ex}")
PYEOFLength of output: 5757 🏁 Script executed: #!/bin/bash
echo "=== HEAD SHA via git ==="
HEAD_SHA=$(git rev-parse HEAD)
echo "$HEAD_SHA"
echo "=== Changed files ==="
git diff origin/main...HEAD --name-only | head -10
echo "=== First changed file patch ==="
FIRST_FILE=$(git diff origin/main...HEAD --name-only | head -1)
echo "First file: $FIRST_FILE"
git diff origin/main...HEAD -- "$FIRST_FILE" | head -20
echo "=== Post inline review comment via curl ==="
python3 << 'PYEOF'
import json, os, ssl, urllib.request, urllib.error, subprocess
token = os.environ.get('GITHUB_TOKEN', '')
if not token:
print("ERROR: GITHUB_TOKEN not set")
exit(1)
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
# Get HEAD SHA via git
head_sha = subprocess.check_output(["git", "rev-parse", "HEAD"]).decode().strip()
print(f"HEAD SHA: {head_sha}")
# Get first changed file and patch position via git
diff_files = subprocess.check_output(
["git", "diff", "origin/main...HEAD", "--name-only"]
).decode().strip().split('\n')
print(f"Changed files: {diff_files}")
first_filename = diff_files[0]
print(f"First file: {first_filename}")
# Get patch for first file to find first added line position
diff_output = subprocess.check_output(
["git", "diff", "origin/main...HEAD", "--", first_filename]
).decode()
lines = diff_output.split('\n')
position = 1
for i, line in enumerate(lines):
if line.startswith('@@'):
# Start counting positions from 1 after the @@ line
for j, l in enumerate(lines[i+1:], start=i+2):
if l.startswith('+') and not l.startswith('+++'):
position = j - i # relative position within the hunk
print(f"First added line: {repr(l[:80])} at hunk-relative pos={position}")
break
break
# Use position=1 as the first line of the diff (hunk header counts as position 1)
# The first actual changed line is position 2+
print(f"Using position: {position}")
comment_body = """**Test Execution Plan**
- **Run smoke tests: False** — Verified: no smoke-marked test file imports or depends on any changed module (`libs/vm/affinity.py`, `libs/vm/spec.py`, `libs/vm/vm.py`, `liblocalnet.py`, `libstuntime.py`). Dependency chain confirmed via codebase search.
- `tests/network/localnet/migration_stuntime/test_migration_stuntime.py` — Full file: all 12 tests (6 migration scenarios × `TestMigrationStuntimeIPv4` / `TestMigrationStuntimeIPv6`). Covers all changes: `ip_family` dependency added to `localnet_stuntime_server_vm` (forces VM recreation between IP families), `restarted_vms` fixture removed, `scope="class"` removed from `pytest.mark.parametrize`, `measure_stuntime()` helper, `CLIENT_VM_LABEL`/`SERVER_VM_LABEL` constants, and `new_pod_affinity`/`new_pod_anti_affinity` placement logic."""
payload = json.dumps({
"commit_id": head_sha,
"path": first_filename,
"position": position,
"body": comment_body
}).encode()
post_req = urllib.request.Request(
"https://api.github.com/repos/RedHatQE/openshift-virtualization-tests/pulls/4833/comments",
data=payload,
method="POST",
headers={
"Authorization": f"token {token}",
"Accept": "application/vnd.github.v3+json",
"Content-Type": "application/json"
}
)
try:
with urllib.request.urlopen(post_req, timeout=30, context=ctx) as resp:
result = json.loads(resp.read())
print(f"SUCCESS: Comment ID={result.get('id')} on path={result.get('path')} pos={result.get('position')}")
except urllib.error.HTTPError as e:
body = e.read().decode()
print(f"HTTP ERROR {e.code}: {body[:500]}")
except Exception as ex:
print(f"ERROR: {ex}")
PYEOFLength of output: 4353 🏁 Script executed: #!/bin/bash
echo "=== HEAD SHA ==="
git rev-parse HEAD
echo "=== Available token env vars ==="
env | grep -i "token\|auth\|secret\|cred" | sed 's/=.*/=REDACTED/' || echo "none found"
echo "=== Git log recent commits ==="
git log --oneline -5
echo "=== Changed files in last commit ==="
git show --name-only --format="" HEAD | head -20
echo "=== Changed files in last 5 commits vs merge-base ==="
git diff HEAD~5...HEAD --name-only 2>/dev/null | head -20 || echo "fallback failed"
echo "=== Try git diff with first parent ==="
git diff HEAD^1...HEAD --name-only 2>/dev/null | head -20 || echo "fallback"
echo "=== Files changed across recent commits ==="
git log --name-only --format="" -5 | grep -v "^$" | sort -u | head -20Length of output: 2529 🏁 Script executed: #!/bin/bash
python3 << 'PYEOF'
import json, os, ssl, urllib.request, urllib.error
token = os.environ.get('GH_TOKEN', '')
if not token:
print("ERROR: GH_TOKEN not set")
exit(1)
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
head_sha = "2a20af4a97bd5ecd895701bbcf1ecd71aea75276"
print(f"HEAD SHA: {head_sha}")
# Get PR files
req = urllib.request.Request(
"https://api.github.com/repos/RedHatQE/openshift-virtualization-tests/pulls/4833/files",
headers={"Authorization": f"token {token}", "Accept": "application/vnd.github.v3+json"}
)
try:
with urllib.request.urlopen(req, timeout=30, context=ctx) as resp:
files = json.loads(resp.read())
print(f"Got {len(files)} files")
for i, f in enumerate(files):
print(f"FILE {i}: {f['filename']}")
first_file = files[0]
first_filename = first_file['filename']
patch = first_file.get('patch', '')
print(f"\nFirst file: {first_filename}")
print(f"Patch (first 300 chars): {patch[:300]}")
# Find position of first added line in the diff
# GitHub PR review comment position: 1-indexed line in the unified diff
# Position 1 = first line (hunk header @@...)
# Each subsequent line increments position
position = 1
if patch:
lines = patch.split('\n')
for i, line in enumerate(lines):
if line.startswith('+') and not line.startswith('+++'):
position = i + 1 # 1-indexed
print(f"First added line at position {position}: {repr(line[:80])}")
break
print(f"Using position: {position}")
except Exception as e:
print(f"Error getting files: {e}")
exit(1)
comment_body = """**Test Execution Plan**
- **Run smoke tests: False** — Verified: no smoke-marked test file imports or depends on any changed module (`libs/vm/affinity.py`, `libs/vm/spec.py`, `libs/vm/vm.py`, `liblocalnet.py`, `libstuntime.py`). Dependency chain confirmed via codebase search.
- `tests/network/localnet/migration_stuntime/test_migration_stuntime.py` — Full file: all 12 tests (6 migration scenarios × `TestMigrationStuntimeIPv4` / `TestMigrationStuntimeIPv6`). Covers all changes: `ip_family` dependency added to `localnet_stuntime_server_vm` (forces VM recreation between IP families), `restarted_vms` fixture removed, `scope="class"` removed from `pytest.mark.parametrize`, `measure_stuntime()` helper, `CLIENT_VM_LABEL`/`SERVER_VM_LABEL` constants, and `new_pod_affinity`/`new_pod_anti_affinity` placement logic."""
payload = json.dumps({
"commit_id": head_sha,
"path": first_filename,
"position": position,
"body": comment_body
}).encode()
post_req = urllib.request.Request(
"https://api.github.com/repos/RedHatQE/openshift-virtualization-tests/pulls/4833/comments",
data=payload,
method="POST",
headers={
"Authorization": f"token {token}",
"Accept": "application/vnd.github.v3+json",
"Content-Type": "application/json"
}
)
try:
with urllib.request.urlopen(post_req, timeout=30, context=ctx) as resp:
result = json.loads(resp.read())
print(f"SUCCESS: Comment ID={result.get('id')} on path={result.get('path')} pos={result.get('position')}")
except urllib.error.HTTPError as e:
body = e.read().decode()
print(f"HTTP ERROR {e.code}: {body[:500]}")
except Exception as ex:
print(f"ERROR: {ex}")
PYEOFLength of output: 4418 Test Execution Plan
|
|
/check-can-merge |
2 similar comments
|
/check-can-merge |
|
/check-can-merge |
Implement the remaining stuntime measurement tests for OVN localnet live migration, covering all client/server migration directions with IPv4/IPv6. Single parametrized class with class-level ip_family parametrize to group all scenarios per IP family before moving to the next. VMs depend on ip_family so they're recreated per group, giving each IP family fresh VMs with clean network state. Tests run incrementally within each group, each migration building on the VM positions left by the previous scenario. Each test has a single Polarion ID shared across both IP families. Signed-off-by: Anat Wax <awax@redhat.com> Assisted-by: Claude <noreply@anthropic.com>
|
Change: rebase on main |
|
Clean rebase detected — no code changes compared to previous head ( |
|
Successfully removed PR tag: quay.io/openshift-cnv/openshift-virtualization-tests:pr-4833. |
|
New container for quay.io/openshift-cnv/openshift-virtualization-tests:latest published |
Short description:
Complete OVN localnet stuntime coverage for both IP families.
More details:
What this PR does / why we need it:
Add remaining stuntime measurement tests for OVN localnet with both IPv4 and IPv6 coverage, through different migration directions.
Which issue(s) this PR fixes:
Special notes for reviewer:
jira-ticket:
https://redhat.atlassian.net/browse/CNV-72773
Summary by CodeRabbit