# How to Create Custom Test Providers for Adding New Guest Image Sources in Avocado-VT

> Learn to create custom test providers for new guest image sources in Avocado-VT. Add an INI file and declare images for automatic fetching.

- Repository: [avocado/avocado-vt](https://github.com/avocado-framework/avocado-vt)
- Tags: how-to-guide
- Published: 2026-02-25

---

**You create custom test providers by adding an INI definition file to `virttest/test-providers.d/` that points to a directory or git repository containing backend-specific subdirectories, then declare guest images in `virttest/shared/downloads/` for automatic fetching.**

Avocado-VT uses a flexible provider system to discover and manage test suites, configuration files, and guest images from various sources. Whether you need to integrate a proprietary image repository or organize tests for a new virtualization backend, creating a custom test provider allows you to extend the framework without modifying core code. This guide walks through the architecture and implementation details based on the `avocado-framework/avocado-vt` source code.

## Understanding the Test Provider Architecture

### How Avocado-VT Discovers Providers

Avocado-VT discovers available test providers by scanning the `virttest/test-providers.d` directory for INI definition files. Each file describes the provider's location—either a local directory, a file URL, or a remote git repository—and maps backend identifiers to subdirectories within the provider. The parsing logic resides in [`virttest/asset.py`](https://github.com/avocado-framework/avocado-vt/blob/main/virttest/asset.py) (lines 22-53), where the `ConfigLoader` class processes these definitions.

### The Bootstrap Process

When tests execute, the bootstrap routine in [`virttest/bootstrap.py`](https://github.com/avocado-framework/avocado-vt/blob/main/virttest/bootstrap.py) initializes the provider system. It calls helper functions from [`virttest/asset.py`](https://github.com/avocado-framework/avocado-vt/blob/main/virttest/asset.py)—specifically `get_test_provider_names()`, `get_test_provider_info()`, and `download_test_provider()`—to resolve provider names, fetch remote repositories if needed, and expose the file tree to the test runner. Directory paths are computed via `data_dir.get_test_provider_dir(provider)` from [`virttest/data_dir.py`](https://github.com/avocado-framework/avocado-vt/blob/main/virttest/data_dir.py).

## Creating a Custom Test Provider

### Step 1: Design the Provider Directory Structure

A custom provider follows a backend-based layout. Create a root directory containing subdirectories for each backend you support (e.g., `qemu`, `generic`, `libvirt`). Each backend folder contains `cfg/` for configuration files, `deps/` for binaries and ISO images, and `tests/cfg/` for test-specific configurations.

```bash
my-provider/
├── generic/
│   ├── cfg/          # Generic test configuration files

│   ├── deps/         # Optional binaries, ISO images, etc.

│   └── tests/
│       └── cfg/      # Per-test configuration files

└── qemu/
    ├── cfg/
    ├── deps/
    └── tests/
        └── cfg/

```

The top-level directories (`generic`, `qemu`) are backend identifiers defined in the provider's INI file.

### Step 2: Create the Provider Definition INI File

Register your provider by creating an INI file in `virttest/test-providers.d/`. The `uri` field specifies the provider location—use `file://` for local directories or `git://`/`https://` for remote repositories. Backend sections map logical names to subdirectories within your provider.

```ini

# File: virttest/test-providers.d/my-custom-provider.ini

[provider]
uri: file:///absolute/path/to/my-provider

[generic]
subdir: generic/

[qemu]
subdir: qemu/

```

The `uri` field tells Avocado-VT where to locate the provider; remote URIs trigger a clone via `download_test_provider()` in [`virttest/asset.py`](https://github.com/avocado-framework/avocado-vt/blob/main/virttest/asset.py).

### Step 3: Declare Guest Image Sources

Guest images are declared in the shared downloads directory. Create an INI file in `virttest/shared/downloads/` describing the image URL, destination path, and optional uncompressed destination.

```ini

# File: virttest/shared/downloads/my-image.ini

[my-image]
url = https://example.com/images/my-image.qcow2.xz
destination = images/my-image.qcow2.xz
destination_uncompressed = images/my-image.qcow2

```

The download machinery in [`virttest/asset.py`](https://github.com/avocado-framework/avocado-vt/blob/main/virttest/asset.py) (specifically `download_file()` at lines 475-525) handles fetching and uncompression automatically.

## Integrating Guest Images with Your Provider

### The Download Mechanism

When Avocado-VT initializes, it processes download definitions from `virttest/shared/downloads/`. The `download_file()` function in [`virttest/asset.py`](https://github.com/avocado-framework/avocado-vt/blob/main/virttest/asset.py) retrieves files from the specified `url`, stores them in the `destination` path within the shared data directory, and optionally uncompresses them to `destination_uncompressed`. This ensures guest images are available before tests execute without manual intervention.

### Referencing Images in Tests

To use your custom provider and its associated images in a test, set the `provider` parameter in your test configuration or Python code. The bootstrap code automatically expands the provider name into concrete backend paths by calling `get_test_provider_subdirs()` (lines 1515-1533 in [`virttest/asset.py`](https://github.com/avocado-framework/avocado-vt/blob/main/virttest/asset.py)).

```python
def test_my_image_boot(params, env):
    # Select the custom provider

    params['provider'] = 'my-custom-provider'
    vm = env.get_vm(params=params)
    
    # Reference the downloaded image

    image_path = os.path.join(
        virttest.data_dir.get_deps_dir('my-image'), 'my-image.qcow2'
    )
    vm.params['image_name'] = image_path
    vm.create()
    vm.wait_for_login()

```

## Summary

- Avocado-VT discovers test providers by scanning `virttest/test-providers.d` for INI definition files that specify the provider URI and backend subdirectories.
- **Create a custom provider** by establishing a directory structure with backend folders (e.g., `qemu/`, `generic/`) containing `cfg/`, `deps/`, and `tests/cfg/` subdirectories.
- **Register the provider** by adding an INI file to `virttest/test-providers.d/` with a `uri` field (local `file://` or remote git) and `[backend]` sections mapping to subdirectories.
- **Add guest images** by creating download definitions in `virttest/shared/downloads/`; the `download_file()` function in [`virttest/asset.py`](https://github.com/avocado-framework/avocado-vt/blob/main/virttest/asset.py) handles automatic fetching and uncompression.
- **Reference providers in tests** by setting the `provider` parameter, which the bootstrap routine resolves via `get_test_provider_subdirs()` in [`virttest/asset.py`](https://github.com/avocado-framework/avocado-vt/blob/main/virttest/asset.py).

## Frequently Asked Questions

### What file format does Avocado-VT use for test provider definitions?

Avocado-VT uses INI files placed in the `virttest/test-providers.d/` directory. Each file contains a `[provider]` section with a mandatory `uri` field specifying the location (local path or git repository), plus optional backend sections like `[qemu]` or `[generic]` that map logical names to subdirectories within the provider.

### Can I use a git repository instead of a local directory for my custom provider?

Yes. The `uri` field in the provider INI file supports git URIs (e.g., `git://github.com/user/repo` or `https://github.com/user/repo.git`). When Avocado-VT initializes, `download_test_provider()` in [`virttest/asset.py`](https://github.com/avocado-framework/avocado-vt/blob/main/virttest/asset.py) automatically clones or updates the repository into the test provider directory.

### How does Avocado-VT know where to download guest images?

Guest images are declared in INI files within `virttest/shared/downloads/`. Each file specifies the source `url`, `destination` path, and optional `destination_uncompressed` path. The `download_file()` function in [`virttest/asset.py`](https://github.com/avocado-framework/avocado-vt/blob/main/virttest/asset.py) (lines 475-525) processes these definitions during bootstrap, fetching and uncompressing files as needed.

### Do I need to modify core Avocado-VT code to use a custom provider?

No. The provider system is designed for extension without core modifications. Simply create your provider directory structure, add an INI definition to `virttest/test-providers.d/`, and optionally add download entries to `virttest/shared/downloads/`. The bootstrap routine in [`virttest/bootstrap.py`](https://github.com/avocado-framework/avocado-vt/blob/main/virttest/bootstrap.py) automatically discovers and loads your provider via the API in [`virttest/asset.py`](https://github.com/avocado-framework/avocado-vt/blob/main/virttest/asset.py).