forked from avocado-framework/avocado
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
VM image dependencies in tests * Comprehensive functional tests in `runner_vmimage.py` * Documentation section in dependencies guide * Example test and recipe JSON * Integration with resolver and check systems * Setup.py entry points for plugin discovery Reference: avocado-framework#6043 Signed-off-by: Harvey Lynden <[email protected]>
- Loading branch information
1 parent
0e6226f
commit d1b8ec3
Showing
9 changed files
with
406 additions
and
3 deletions.
There are no files selected for viewing
This file contains 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,114 @@ | ||
import sys | ||
import traceback | ||
from multiprocessing import set_start_method | ||
|
||
from avocado.core.nrunner.app import BaseRunnerApp | ||
from avocado.core.nrunner.runner import BaseRunner | ||
from avocado.core.utils import messages | ||
from avocado.plugins.vmimage import download_image | ||
from avocado.utils import vmimage | ||
|
||
|
||
class VMImageRunner(BaseRunner): | ||
""" | ||
Runner for dependencies of type vmimage. | ||
This runner uses the vmimage plugin's download_image function which handles: | ||
1. Checking if the image exists in cache | ||
2. Downloading the image if not in cache | ||
3. Storing the image in the configured cache directory | ||
4. Returning the cached image path | ||
""" | ||
|
||
name = "vmimage" | ||
description = "Runner for dependencies of type vmimage" | ||
|
||
def run(self, runnable): | ||
try: | ||
yield messages.StartedMessage.get() | ||
|
||
provider = runnable.kwargs.get("provider") | ||
version = runnable.kwargs.get("version") | ||
arch = runnable.kwargs.get("arch") | ||
|
||
if not all([provider, version, arch]): | ||
stderr = "Missing required parameters: provider, version, and arch" | ||
yield messages.StderrMessage.get(stderr.encode()) | ||
yield messages.FinishedMessage.get("error") | ||
return | ||
|
||
try: | ||
yield messages.StdoutMessage.get( | ||
f"Getting VM image for {provider} {version} {arch}".encode() | ||
) | ||
|
||
try: | ||
provider_normalized = provider.lower() | ||
available_providers = [ | ||
p.name.lower() for p in vmimage.IMAGE_PROVIDERS | ||
] | ||
if provider_normalized not in available_providers: | ||
raise ValueError( | ||
f"Provider '{provider}' not found. Available providers: {', '.join(available_providers)}" | ||
) | ||
|
||
# download_image will use cache if available, otherwise download | ||
image = download_image(provider_normalized, version, arch) | ||
if not image: | ||
raise RuntimeError("Failed to get image") | ||
|
||
yield messages.StdoutMessage.get( | ||
f"Successfully retrieved VM image from cache or downloaded to: {image['file']}".encode() | ||
) | ||
yield messages.FinishedMessage.get("pass") | ||
return | ||
|
||
except Exception as e: | ||
yield messages.StderrMessage.get( | ||
f"Failed to download image: {str(e)}".encode() | ||
) | ||
yield messages.FinishedMessage.get( | ||
"error", | ||
fail_reason=str(e), | ||
fail_class=e.__class__.__name__, | ||
traceback=traceback.format_exc(), | ||
) | ||
return | ||
|
||
except Exception as e: | ||
yield messages.StderrMessage.get( | ||
f"Failed to get/download VM image: {str(e)}".encode() | ||
) | ||
yield messages.FinishedMessage.get( | ||
"error", | ||
fail_reason=str(e), | ||
fail_class=e.__class__.__name__, | ||
traceback=traceback.format_exc(), | ||
) | ||
return | ||
|
||
except Exception as e: | ||
yield messages.StderrMessage.get(traceback.format_exc().encode()) | ||
yield messages.FinishedMessage.get( | ||
"error", | ||
fail_reason=str(e), | ||
fail_class=e.__class__.__name__, | ||
traceback=traceback.format_exc(), | ||
) | ||
return | ||
|
||
|
||
class RunnerApp(BaseRunnerApp): | ||
PROG_NAME = "avocado-runner-vmimage" | ||
PROG_DESCRIPTION = "nrunner application for dependencies of type vmimage" | ||
RUNNABLE_KINDS_CAPABLE = ["vmimage"] | ||
|
||
|
||
def main(): | ||
if sys.platform == "darwin": | ||
set_start_method("fork") | ||
app = RunnerApp(print) | ||
app.run() | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains 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 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 @@ | ||
{"kind": "vmimage", "kwargs": {"provider": "fedora", "version": "41", "arch": "x86_64"}} |
This file contains 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,85 @@ | ||
import os | ||
from avocado import Test | ||
|
||
|
||
class VmimageTest(Test): | ||
""" | ||
Test demonstrating VM image dependency usage. | ||
The vmimage dependency runner will ensure the required VM image | ||
is downloaded and cached before the test execution begins. | ||
:avocado: dependency={"type": "vmimage", "provider": "fedora", "version": "41", "arch": "s390x"} | ||
""" | ||
|
||
def test_vmimage_exists(self): | ||
""" | ||
Verify that the VM image was downloaded by the vmimage runner. | ||
""" | ||
from avocado.core.settings import settings | ||
|
||
# Get cache directory from settings | ||
cache_dir = settings.as_dict().get("datadir.paths.cache_dirs")[0] | ||
cache_base = os.path.join(cache_dir, "by_location") | ||
|
||
# The image should be in the cache since the runner downloaded it | ||
self.assertTrue( | ||
os.path.exists(cache_base), | ||
f"Cache directory {cache_base} does not exist" | ||
) | ||
|
||
# Log cache contents for debugging | ||
self.log.info("Cache directory contents:") | ||
for root, _, files in os.walk(cache_base): | ||
for f in files: | ||
if f.endswith((".qcow2", ".raw")): | ||
self.log.info("Found image: %s", os.path.join(root, f)) | ||
|
||
|
||
class MultiArchVmimageTest(Test): | ||
""" | ||
Test demonstrating multiple VM image dependencies with different architectures. | ||
:avocado: dependency={"type": "vmimage", "provider": "fedora", "version": "41", "arch": "s390x"} | ||
:avocado: dependency={"type": "vmimage", "provider": "fedora", "version": "41", "arch": "x86_64"} | ||
""" | ||
|
||
def test_multiple_images(self): | ||
""" | ||
Verify that multiple VM images can be handled by the runner. | ||
""" | ||
self.log.info("Test with multiple VM image dependencies") | ||
|
||
|
||
class UbuntuVmimageTest(Test): | ||
""" | ||
Test demonstrating VM image dependency with a different provider. | ||
:avocado: dependency={"type": "vmimage", "provider": "ubuntu", "version": "22.04", "arch": "x86_64"} | ||
""" | ||
|
||
def test_ubuntu_image(self): | ||
""" | ||
Verify that Ubuntu images can be handled by the runner. | ||
""" | ||
self.log.info("Test with Ubuntu VM image dependency") | ||
|
||
|
||
# Testing instructions: | ||
# | ||
# 1. Clear the cache first: | ||
# $ avocado cache clear | ||
# | ||
# 2. Run the tests: | ||
# $ avocado run examples/tests/dependency_vmimage.py | ||
# | ||
# 3. Check the cache to see downloaded images: | ||
# $ avocado cache list | ||
# | ||
# 4. Run again to verify cache is used: | ||
# $ avocado run examples/tests/dependency_vmimage.py | ||
# | ||
# The vmimage runner should: | ||
# - Download the required images on first run | ||
# - Use cached images on subsequent runs | ||
# - Handle multiple dependencies per test | ||
# - Support different providers and architectures |
This file contains 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 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 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
Oops, something went wrong.