This guide describes the steps and processes required to leverage the Ansible for OpenShift Virtualization Migration within a disconnected or restricted environment from a networking and content management perspective.
A disconnected (air-gapped) environment has no direct access to the internet. All software artifacts — container images, Operator catalogs, Ansible collections, Python packages, and VMware utilities — must be mirrored to internal registries and repositories before they can be consumed.
- An internal container registry (e.g., a self-hosted Quay, Artifactory, or Nexus instance) accessible from all OpenShift clusters.
- An internal HTTP/HTTPS server or Automation Hub instance for hosting Ansible collections and Python packages.
oc-mirrorCLI plugin installed on a bastion host that has internet access (or a sneaker-net transfer mechanism).ocCLI with cluster-admin access to the target OpenShift clusters.- A Red Hat account with entitlements for downloading Operator catalog indexes and container images.
Note: This guide assumes that an Execution Environment (EE) is used for playbook execution, which satisfies Python package and Ansible collection dependencies at runtime. The mirroring steps below are provided for environments that build custom EEs or run playbooks outside of an EE.
The Ansible for OpenShift Virtualization Migration depends on the following OLM-managed Operators. Each must be available in a mirrored CatalogSource on every target cluster.
| Operator | Package Name | Default Namespace (for reference) |
|---|---|---|
| Migration Toolkit for Virtualization (MTV) | mtv-operator |
openshift-mtv |
| OpenShift Virtualization (CNV) | kubevirt-hyperconverged |
openshift-cnv |
| Advanced Cluster Management (ACM) | advanced-cluster-management |
open-cluster-management |
| OpenShift API for Data Protection (OADP) | redhat-oadp-operator |
openshift-adp |
| Fence Agents Remediation (FAR) | fence-agents-remediation |
openshift-workload-availability |
| NMState | kubernetes-nmstate-operator |
openshift-nmstate |
| Node Healthcheck (NHO) | node-healthcheck-operator |
openshift-workload-availability |
| OpenShift GitOps | openshift-gitops-operator |
openshift-gitops |
Create an ImageSetConfiguration that includes the required Operator
packages from the redhat-operators catalog:
apiVersion: mirror.openshift.io/v1alpha2
kind: ImageSetConfiguration
mirror:
operators:
- catalog: registry.redhat.io/redhat/redhat-operator-index:v4.x
packages:
- name: mtv-operator
- name: kubevirt-hyperconverged
- name: advanced-cluster-management
- name: redhat-oadp-operator
- name: fence-agents-remediation
- name: kubernetes-nmstate-operator
- name: node-healthcheck-operator
- name: openshift-gitops-operatorReplace v4.x with the OpenShift version running on your clusters.
Run the mirror:
oc-mirror --config imageset-config.yaml \
docker://<internal-registry>/<namespace>After mirroring, oc-mirror generates ImageContentSourcePolicy (or
ImageDigestMirrorSet) and CatalogSource resources. Apply them to
each cluster:
oc apply -f oc-mirror-workspace/results-*/The operator_management role supports custom CatalogSources via the
operator_management_catalogsources variable. Configure it to point to
the mirrored catalog:
operator_management_catalogsources:
mirrored_redhat_operators:
metadata:
name: mirrored-redhat-operators
namespace: openshift-marketplace
spec:
displayName: Mirrored Red Hat Operators
publisher: Internal
image: <internal-registry>/<namespace>/redhat-operator-index:v4.xTo prevent Operator installations from utilizing the default catalog which are externally hosted, disable the default OperatorHub sources:
oc patch operatorhub cluster --type merge \
-p '{"spec":{"disableAllDefaultSources": true}}'Beyond the Operator images (handled by oc-mirror), the following
workload images must be mirrored to the internal registry.
The Ansible Automation Platform Execution Environment (EE) used by the Ansible for OpenShift Virtualization Migration must be available internally. The inventory references this image via:
aap_execution_environment_image: registry.example.com/openshift-virtualization-migration-ee:latestMirror the EE image from its source to the internal registry:
skopeo copy \
docker://source-registry/openshift-virtualization-migration-ee:latest \
docker://<internal-registry>/openshift-virtualization-migration-ee:latestUpdate aap_execution_environment_image in the inventory to reference
the internal registry path.
Tip:
oc-mirrorcan also mirror container images using theadditionalImagesproperty in theImageSetConfiguration. See the oc-mirror v2 documentation for details.
VMware migrations require the Virtual Disk Development Kit (VDDK) image. This image is typically built by the user from the VMware VDDK SDK and pushed to a container registry. In disconnected environments, ensure the VDDK image is available in the internal registry:
# In migration target configuration
vddk:
image: <internal-registry>/openshift-virtualization-migration-vddk:latest
username: "{{ container_username }}"
password: "{{ container_password }}"If using Red Hat Dev Spaces for development workflows, mirror the Dev
Spaces Operator images along with the other Operators in the
ImageSetConfiguration.
The Ansible for OpenShift Virtualization Migration depends on the following Ansible collections. These must be available from an internal Automation Hub or a local filesystem path.
From Red Hat Certified Content (Automation Hub — Published):
| Collection | Minimum Version |
|---|---|
redhat.openshift_virtualization |
>=2.1.0 |
redhat.openshift |
>=4.0.0 |
vmware.vmware_rest |
>=4.6.0 |
ansible.controller |
>=4.5.12 |
ansible.posix |
>=1.6.2 |
kubernetes.core |
>=5.2.0 |
community.crypto |
>=2.26.0 |
community.general |
>=10.5.0 |
community.vmware |
>=5.5.0 |
ansible.utils |
>=6.0.0 |
From Red Hat Validated Content (Automation Hub — Validated):
| Collection | Minimum Version |
|---|---|
infra.aap_utilities |
>=2.6.0 |
infra.aap_configuration |
>=3.3.0 |
infra.controller_configuration |
>=3.0.2 |
If you are running a Private Automation Hub, configure it to sync content from the Red Hat Certified and Validated repositories. On a connected bastion host, download the collection tarballs:
ansible-galaxy collection download <collection_name> \
-p /path/to/download/directoryThen publish them to the Private Automation Hub:
ansible-galaxy collection publish \
/path/to/download/directory/<collection_tarball>.tar.gz \
--server https://<private-hub>/api/galaxy/content/published/ \
--token <hub-token>Update the Automation Hub credential URLs in the inventory to point to the internal Private Automation Hub:
automation_hub_certified_url: https://<private-hub>/api/galaxy/content/published/
automation_hub_certified_auth_url: https://<private-hub>/auth/token/
automation_hub_certified_token: <hub-token>
automation_hub_validated_url: https://<private-hub>/api/galaxy/content/validated/
automation_hub_validated_auth_url: https://<private-hub>/auth/token/
automation_hub_validated_token: <hub-token>The Execution Environment requires the following Python packages at build time or runtime. These must be available from an internal PyPI mirror (e.g., Nexus, Artifactory, or devpi).
| Package | Version Constraint |
|---|---|
ansible-core |
>=2.20 |
kubernetes |
>=12.0.0 |
PyYAML |
>=3.11 |
omsdk |
>=1.2.490 |
aiohttp |
latest |
pyVim |
latest |
PyVmomi |
latest |
jmespath |
latest |
packaging |
<25.0, >=23.2 |
Use a tool such as bandersnatch or pip2pi on a connected host to
download and mirror the required packages:
pip download -r requirements-dev.txt -d /path/to/packages/Transfer the packages to the disconnected environment and host them on an internal PyPI-compatible server. Configure pip to use the internal index:
# pip.conf or PIP_INDEX_URL environment variable
[global]
index-url = https://<internal-pypi>/simple/
trusted-host = <internal-pypi>When building a custom Execution Environment with ansible-builder,
supply the internal PyPI URL in the EE definition:
additional_build_steps:
prepend_base:
- RUN pip config set global.index-url https://<internal-pypi>/simple/The Ansible for OpenShift Virtualization Migration project source and any GitOps export targets must be reachable from the Ansible Automation Platform controller. In a disconnected environment:
- Mirror the collection repository to an internal Git server (e.g., GitLab, Gitea, or Bitbucket).
- Update the
aap_project_repoinventory variable to point to the internal Git URL:
aap_project_repo: https://<internal-git>/org/openshift_virtualization_migration.git
aap_project_branch: main- If using the
vm_gitops_exportrole (this role is planned to move to theopenshift_virtualization_opscollection), ensure the target Git repository is also hosted internally and accessible from the EE.
When deploying AAP in a disconnected environment:
- The AAP Operator must be included in the mirrored Operator catalog (assumes AAP is deployed on OpenShift) (it
is not in the default list above — add the
ansible-automation-platform-operatorpackage to theImageSetConfiguration). - The AAP controller and hub pods must be able to pull images from the internal registry.
- Configure the AAP instance to use the Private Automation Hub as its primary content source.
- Ensure the EE image referenced in the inventory is available in the internal registry (see Section 2).
In a restricted (not fully air-gapped) environment, the following endpoints may need firewall allowlisting:
| Endpoint | Purpose |
|---|---|
registry.redhat.io |
Red Hat container images |
cloud.redhat.com |
Automation Hub collections |
sso.redhat.com |
Automation Hub authentication |
quay.io |
Operator index images |
cdn.redhat.com |
Red Hat subscriptions |
| vCenter / RHV Manager host | Source hypervisor API access |
| OpenShift API endpoints | Cluster management (port 6443) |
| Internal registry | Mirrored images |
| Internal Git server | Project source code |
| Internal Automation Hub | Ansible collections |
For fully air-gapped environments, none of the external endpoints need to be reachable — all content must be pre-mirrored.
Before running the Ansible for OpenShift Virtualization Migration in a disconnected environment, verify the following:
- All required Operators are installable from the mirrored CatalogSource.
- The EE image is pullable from the internal registry.
- The VDDK image is pullable from the internal registry.
- All required Ansible collections are available in the Private Automation Hub.
- All required Python packages are available in the internal PyPI mirror (or baked into the EE).
- The collection Git repository is cloned on the internal Git server.
- AAP can reach the OpenShift API of all hub and spoke clusters.
- AAP can reach the source hypervisor (vCenter / RHV Manager).
-
oc-mirrorImageContentSourcePolicyorImageDigestMirrorSetresources are applied to all clusters. - Default OperatorHub sources are disabled on all clusters.