Skip to content

Commit 8493767

Browse files
Merge remote-tracking branch 'origin/main' into kasenlaskar/hyperv_module_add_and_fix
2 parents c0f0e0e + fa955c8 commit 8493767

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+3857
-670
lines changed

.github/copilot-instructions.md

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# LISA Testing Guidelines for Pull Requests
2+
3+
This document provides comprehensive guidelines for generating test suggestions for pull requests (PRs) in the LISA project. These guidelines ensure thorough validation while maintaining cost efficiency and testing relevance.
4+
5+
## Overview
6+
7+
When reviewing or creating PRs, follow these three key areas of testing guidance:
8+
9+
1. **Test Case Selection** - Identify the essential test methods
10+
2. **Feature Impact Analysis** - Determine affected LISA features
11+
3. **Image Selection** - Choose appropriate Azure marketplace images
12+
13+
## Copilot Instructions for Code Reviews
14+
15+
**MANDATORY REQUIREMENT:** Every code review must include a test suggestion using the Quick Reference Template provided below. This is required for all pull request reviews to ensure consistent test coverage guidance.
16+
17+
When reviewing any pull request, you must:
18+
19+
1. **Always generate and present the test suggestion block** as part of your review
20+
2. **Use the exact Quick Reference Template format** (found at the bottom of this document) for copy-paste convenience
21+
3. **Include all three required components:**
22+
- Essential integration/end-to-end test method names (using exact method names separated by `|`)
23+
- Directly impacted LISA feature class names (using exact class names as they appear in codebase)
24+
- Minimal set of Azure Marketplace images required for validation (using exact image strings from the provided list)
25+
26+
This ensures every code review provides actionable, standardized test guidance that reviewers and contributors can immediately use for validation.
27+
28+
## Test Case Selection Guidelines
29+
30+
### Unit Tests
31+
- Unit tests are automatically included and should **not** be listed in test suggestions
32+
- Focus only on integration and end-to-end test recommendations
33+
34+
### Key Test Cases
35+
- **Identify Essential Tests Only**: Select the minimal set of test cases that validate your specific changes
36+
- **Use Method Names**: Always specify the exact test method names, never include class names or file paths
37+
- ✅ Correct: `verify_reboot_in_platform`
38+
- ❌ Incorrect: `core.provisioning` or `TestProvisioning.verify_reboot_in_platform`
39+
- **Multiple Test Format**: When suggesting multiple tests, separate method names with a pipe (`|`) for easy copy-paste usage
40+
- Example: `verify_reboot_in_platform|verify_stop_start_in_platform|verify_resize_operation`
41+
42+
### Test Selection Strategy
43+
- If your change targets specific functionality, choose tests that directly exercise that functionality
44+
- If your change is broad or foundational, select representative tests that cover the most likely impact areas
45+
46+
## LISA Features Impact Analysis
47+
48+
### What are LISA Features?
49+
LISA Features are platform-specific capability classes that represent testable functionality. They serve as requirements for test cases and help identify testing scope.
50+
51+
### Common LISA Features
52+
Examples include (but are not limited to):
53+
- `Gpu` - Graphics processing capabilities
54+
- `Nvme` - NVMe storage functionality
55+
- `StartStop` - VM start/stop operations
56+
- `Resize` - VM resizing capabilities
57+
- `NetworkInterface` - Network interface management
58+
- `SerialConsole` - Serial console access
59+
- `Hibernate` - VM hibernation features
60+
61+
### Feature Selection Guidelines
62+
- List only features **directly impacted** by your changes
63+
- Use the exact feature class names as they appear in the codebase
64+
- Consider both primary and secondary impacts of your changes
65+
66+
## Azure Marketplace Image Selection
67+
68+
### Selection Principles
69+
- **Minimize Cost**: Select only the essential images needed to validate your changes
70+
- **Maximize Coverage**: Ensure selected images cover the key scenarios affected by your PR
71+
- **Use Exact Strings**: Always provide the complete image string exactly as listed below for direct copy-paste usage
72+
73+
### When to Select Images
74+
- **OS-Specific Changes**: Choose images representing the affected operating systems
75+
- **Architecture Changes**: Include both x64 and ARM64 variants if relevant
76+
- **Generation Changes**: Consider both Gen1 and Gen2 images if applicable
77+
- **Distribution Changes**: Select specific Linux distributions if your change is distribution-sensitive
78+
79+
### Available Azure Marketplace Images
80+
81+
Copy the exact string for the images you need:
82+
83+
#### Ubuntu Images
84+
- `canonical 0001-com-ubuntu-server-jammy 22_04-lts latest`
85+
- `canonical 0001-com-ubuntu-server-jammy 22_04-lts-arm64 latest`
86+
- `canonical 0001-com-ubuntu-server-jammy 22_04-lts-gen2 latest`
87+
- `canonical ubuntu-24_04-lts server latest`
88+
- `canonical ubuntu-24_04-lts server-arm64 latest`
89+
- `canonical ubuntu-24_04-lts server-gen1 latest`
90+
91+
#### Debian Images
92+
- `debian debian-11 11 latest`
93+
- `debian debian-11 11-gen2 latest`
94+
- `debian debian-12 12 latest`
95+
- `debian debian-12 12-arm64 latest`
96+
- `debian debian-12 12-gen2 latest`
97+
98+
#### Azure Linux Images
99+
- `microsoftcblmariner azure-linux-3 azure-linux-3 latest`
100+
- `microsoftcblmariner azure-linux-3 azure-linux-3-arm64 latest`
101+
- `microsoftcblmariner azure-linux-3 azure-linux-3-gen2 latest`
102+
103+
#### Oracle Linux Images
104+
- `oracle oracle-linux ol810-arm64-lvm-gen2 latest`
105+
- `oracle oracle-linux ol810-lvm latest`
106+
- `oracle oracle-linux ol810-lvm-gen2 latest`
107+
- `oracle oracle-linux ol94-arm64-lvm-gen2 latest`
108+
- `oracle oracle-linux ol94-lvm latest`
109+
- `oracle oracle-linux ol94-lvm-gen2 latest`
110+
111+
#### Red Hat Enterprise Linux Images
112+
- `redhat rhel 8_10 latest`
113+
- `redhat rhel 810-gen2 latest`
114+
- `redhat rhel 9_5 latest`
115+
- `redhat rhel 95_gen2 latest`
116+
- `redhat rhel-arm64 9_5-arm64 latest`
117+
118+
#### SUSE Linux Enterprise Server Images
119+
- `suse sles-12-sp5 gen1 latest`
120+
- `suse sles-12-sp5 gen2 latest`
121+
- `suse sles-15-sp6 gen1 latest`
122+
- `suse sles-15-sp6 gen2 latest`
123+
- `suse sles-15-sp6-arm64 gen2 latest`
124+
125+
## Best Practices Summary
126+
127+
1. **Be Specific**: Use exact method names, feature classes, and image strings
128+
2. **Be Minimal**: Select only what's necessary to validate your changes
129+
3. **Be Practical**: Format suggestions for easy copy-paste usage
130+
4. **Be Comprehensive**: Consider all three areas (tests, features, images) for complete coverage
131+
5. **Be Cost-Conscious**: Remember that each image selection has cost implications
132+
133+
## Quick Reference Template
134+
135+
When providing test suggestions, use this format:
136+
137+
```
138+
**Key Test Cases:**
139+
verify_reboot_in_platform|verify_stop_start_in_platform|smoke_test
140+
141+
**Impacted LISA Features:**
142+
FeatureName1, FeatureName2, FeatureName3
143+
144+
**Tested Azure Marketplace Images:**
145+
- exact image string 1
146+
- exact image string 2
147+
- exact image string 3
148+
```

docs/run_test/platform.rst

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,13 +141,14 @@ deployment.
141141
...
142142
admin_private_key_file: "<path of private key file>"
143143
azure:
144-
virtual_network_resource_group: $(vnet_resource_group)
145-
virtual_network_name: $(vnet_name)
146-
subnet_prefix: $(subnet_name)
144+
virtual_network_resource_group: $(virtual_network_resource_group)
145+
virtual_network_name: $(virtual_network_name)
146+
subnet_prefix: $(subnet_prefix)
147147
use_public_address: "<true or false>"
148148
create_public_address: "<true or false>"
149149
use_ipv6: "<true or false>"
150150
enable_vm_nat: "<true or false>"
151+
source_address_prefixes: $(source_address_prefixes)
151152
requirement:
152153
...
153154
ignored_capability:
@@ -205,6 +206,22 @@ deployment.
205206
subnet to access the internet. The default value is `false`, it means that
206207
the DefaultOutboundAccess property of the subnet will be set to "False".
207208
This means that the VMs in the subnet cannot access the internet.
209+
* **source_address_prefixes**. Specify source IP address ranges that are
210+
allowed to access the VMs through network security group rules. If not
211+
provided, your current public IP address will be automatically detected and
212+
used. You can specify multiple IP ranges using either comma-separated string
213+
format or YAML list format. Examples:
214+
215+
.. code:: bash
216+
217+
# Single IP range (string format)
218+
lisa -r ./microsoft/runbook/azure.yml -v "source_address_prefixes:192.168.1.0/24"
219+
220+
# Multiple IP ranges (comma-separated string format)
221+
lisa -r ./microsoft/runbook/azure.yml -v "source_address_prefixes:192.168.1.0/24,10.0.0.0/8"
222+
223+
# List format
224+
lisa -r ./microsoft/runbook/azure.yml -v "source_address_prefixes:['192.168.1.0/24','10.0.0.0/8']"
208225
* **ignored_capability**. Specify feature names which will be ignored in
209226
test requirement. You can find the feature name from its name method in source code.
210227
For example, IsolatedResource feature's name defined in ``lisa/features/isolated_resource.py`` as below:

docs/run_test/runbook.rst

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ Runbook Reference
6464
- `path <#path-2>`__
6565
- `auto_open <#auto-open>`__
6666

67+
- `junit <#junit>`__
68+
69+
- `path <#path-3>`__
70+
- `include_subtest <#include-subtest>`__
71+
- `append_message_id <#append-message-id>`__
72+
6773
- `environment <#environment>`__
6874

6975
- `retry <#retry>`__
@@ -668,6 +674,50 @@ Example of html notifier:
668674
path: ./lisa.html
669675
auto_open: true
670676
677+
junit
678+
^^^^^
679+
680+
Output test results in JUnit XML format. The generated XML file can be used
681+
for integration with CI/CD systems, dashboards, and other tools that consume
682+
JUnit test results.
683+
684+
.. _path-3:
685+
686+
path
687+
''''
688+
689+
type: str, optional, default: lisa.junit.xml
690+
691+
Specify the output file name and path for the JUnit XML report.
692+
693+
include_subtest
694+
'''''''''''''''
695+
696+
type: bool, optional, default: True
697+
698+
When set to True, subtests will be included as separate test cases in the
699+
JUnit XML output. When set to False, only main test cases are included.
700+
701+
append_message_id
702+
'''''''''''''''''
703+
704+
type: bool, optional, default: True
705+
706+
When set to True, the message ID will be appended to test case names in the
707+
format "test_name (message_id)". This is useful when using combinators to
708+
distinguish multiple test runs of the same test case. When set to False,
709+
only the base test case name is used.
710+
711+
Example of junit notifier:
712+
713+
.. code:: yaml
714+
715+
notifier:
716+
- type: junit
717+
path: ./results.xml
718+
include_subtest: true
719+
append_message_id: false
720+
671721
environment
672722
~~~~~~~~~~~
673723

docs/run_test/transformers.rst

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,10 @@ Usage
244244
transformer:
245245
- type: azure_deploy
246246
resource_group_name: rg_name
247+
deploy: true
248+
source_address_prefixes:
249+
- "192.168.1.0/24"
250+
- "10.0.0.0/8"
247251
requirement:
248252
azure:
249253
marketplace: image_name
@@ -268,7 +272,7 @@ resource_group_name
268272

269273
type: string
270274

271-
Name of the resource group in which VM should be deployed. Creates a new RG if not specified.
275+
Name of the resource group in which VM should be deployed. Creates a new RG if not specified. When not provided, the platform configuration will be used for the transformer. When the VM of transformer has different resource group requirements, it can be overwritten here. This only works for new fresh deployment - if the resource group already exists, it does nothing.
272276

273277
requirement
274278
^^^^^^^^^^^
@@ -288,6 +292,12 @@ type: bool | Default: true
288292

289293
Whether to create a new deployment. If true, creates a new VM deployment. If false, uses existing VMs in the specified resource_group_name.
290294

295+
source_address_prefixes
296+
^^^^^^^^^^^^^^^^^^^^^^^
297+
type: Optional[Union[str, List[str]]] | Default: None
298+
299+
Source address prefixes for network security rules. Can be a single string, a comma-separated string, or a list of strings. When not specified, defaults to the current public IP address for security. When not provided, the platform configuration will be used for the transformer. When the VM of transformer has different network infrastructure requirements, it can be overwritten here.
300+
291301

292302
Use Delete Transformer
293303
~~~~~~~~~~~~~~~~~~~~~~

examples/__init__.py

Whitespace-only changes.

lisa/base_tools/cat.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,14 @@ def read_with_filter(
3838
force_run: bool = False,
3939
sudo: bool = False,
4040
invert_match: bool = False,
41+
ignore_error: bool = False,
4142
) -> str:
4243
# Combining cat with grep
4344
if invert_match:
4445
params = f'{file} | grep -v "{grep_string}"'
4546
else:
4647
params = f'{file} | grep "{grep_string}"'
4748
result = self.run(params, force_run=force_run, sudo=sudo, shell=True)
48-
result.assert_exit_code(message=f"Error : {result.stdout}")
49+
if not ignore_error:
50+
result.assert_exit_code(message=f"Error : {result.stdout}")
4951
return result.stdout

lisa/base_tools/service.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from typing import Optional, Type
77

88
from lisa.executable import ExecutableResult, Tool
9+
from lisa.tools.dmesg import Dmesg
10+
from lisa.tools.journalctl import Journalctl
911
from lisa.tools.powershell import PowerShell
1012
from lisa.util import (
1113
LisaException,
@@ -49,6 +51,9 @@ def _check_exists(self) -> bool:
4951
def restart_service(self, name: str, ignore_exit_code: int = 0) -> None:
5052
self._internal_tool.restart_service(name, ignore_exit_code) # type: ignore
5153

54+
def start_service(self, name: str, ignore_exit_code: int = 0) -> None:
55+
self._internal_tool.start_service(name, ignore_exit_code) # type: ignore
56+
5257
def stop_service(self, name: str) -> None:
5358
self._internal_tool.stop_service(name) # type: ignore
5459

@@ -135,6 +140,14 @@ def stop_service(self, name: str) -> None:
135140

136141
def restart_service(self, name: str, ignore_exit_code: int = 0) -> None:
137142
cmd_result = self.run(f"restart {name}", shell=True, sudo=True, force_run=True)
143+
if cmd_result.exit_code != 0 and cmd_result.exit_code != ignore_exit_code:
144+
self._collect_logs(name)
145+
_check_error_codes(cmd_result, ignore_exit_code)
146+
147+
def start_service(self, name: str, ignore_exit_code: int = 0) -> None:
148+
cmd_result = self.run(f"start {name}", shell=True, sudo=True, force_run=True)
149+
if cmd_result.exit_code != 0 and cmd_result.exit_code != ignore_exit_code:
150+
self._collect_logs(name)
138151
_check_error_codes(cmd_result, ignore_exit_code)
139152

140153
def enable_service(self, name: str) -> None:
@@ -209,6 +222,44 @@ def _check_service_running(self, name: str) -> bool:
209222
or "not-found" in cmd_result.stdout
210223
) and 0 == cmd_result.exit_code
211224

225+
def _collect_logs(self, service_name: str) -> None:
226+
self._log.info(f"Collecting logs for service '{service_name}'.")
227+
228+
# Get detailed status from systemctl status
229+
status_cmd = f"status {service_name} --no-pager -n 100"
230+
try:
231+
_ = self.run(status_cmd, shell=True, sudo=True, force_run=True)
232+
except Exception as e_status:
233+
self._log.info(f"Failed to get status for {service_name}: {e_status}")
234+
235+
try:
236+
journal_tail_lines = 50
237+
journalctl_tool = self.node.tools[Journalctl]
238+
journal_output = journalctl_tool.logs_for_unit(unit_name=service_name)
239+
journal_lines = journal_output.splitlines()
240+
tail_lines = "\n".join(journal_lines[-journal_tail_lines:])
241+
self._log.info(
242+
f"Last {journal_tail_lines} journal logs for unit '{service_name}':\n"
243+
f"{tail_lines}"
244+
)
245+
except Exception as e_journal:
246+
self._log.info(
247+
f"Could not retrieve or process journal logs for {service_name}: "
248+
f"{e_journal}"
249+
)
250+
251+
try:
252+
dmesg_tail_lines = 25
253+
dmesg = self.node.tools[Dmesg]
254+
dmesg_out = dmesg.get_output(
255+
force_run=True, no_debug_log=True, tail_lines=dmesg_tail_lines
256+
)
257+
self._log.info(
258+
f"Last {dmesg_tail_lines} lines of dmesg output:\n{dmesg_out}"
259+
)
260+
except Exception as e_dmesg:
261+
self._log.info(f"Could not retrieve dmesg output: {e_dmesg}")
262+
212263

213264
def _check_error_codes(cmd_result: ExecutableResult, error_code: int = 0) -> None:
214265
cmd_result.assert_exit_code(expected_exit_code=[0, error_code])

0 commit comments

Comments
 (0)