Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ scratch-test/
assets/templates/99_master-chronyd-redhat.yaml
assets/templates/99_worker-chronyd-redhat.yaml

pull_secret.json
pull_secret.json

# Auto-generated ansible vars (may contain secrets)
ansible/.config_vars.yml
ansible/.runtime_vars.yml
71 changes: 64 additions & 7 deletions 05_create_install_config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,79 @@ early_deploy_validation
set_api_and_ingress_vip

if [ ! -f "${OCP_DIR}/install-config.yaml" ]; then
# Validate there are enough nodes to avoid confusing errors later..
NODES_LEN=$(jq '.nodes | length' "${NODES_FILE}")
if (( NODES_LEN < NUM_MASTERS + NUM_WORKERS )); then
echo "ERROR: ${NODES_FILE} contains ${NODES_LEN} nodes, but ${NUM_MASTERS} masters and ${NUM_WORKERS} workers requested"
exit 1
fi

# Create a nodes.json file
mkdir -p "${OCP_DIR}"
jq '{nodes: .}' "${NODES_FILE}" | tee "${BAREMETALHOSTS_FILE}"
# Generate base config vars from the resolved bash environment
SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
"${SCRIPTDIR}/ansible/vars_bridge.sh"

# Create install config for openshift-installer
generate_ocp_install_config "${OCP_DIR}"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we delete this function now?

EXTRA_VARS_FILE="${SCRIPTDIR}/ansible/.runtime_vars.yml"

# Append runtime-computed values that vars_bridge.sh does not cover
cat > "${EXTRA_VARS_FILE}" << RUNTIME_EOF
# Runtime vars generated by 05_create_install_config.sh
devscripts_machine_os_bootstrap_image_name: "${MACHINE_OS_BOOTSTRAP_IMAGE_NAME}"
devscripts_machine_os_bootstrap_image_sha256: "${MACHINE_OS_BOOTSTRAP_IMAGE_UNCOMPRESSED_SHA256}"
devscripts_nodes_file: "${NODES_FILE}"
devscripts_ocp_dir: "${OCP_DIR}"
devscripts_scriptdir: "${SCRIPTDIR}"
RUNTIME_EOF

# BMC verify CA certificate (OCP >= 4.22)
BMC_CA_FILE="${WORKING_DIR}/virtualbmc/sushy-tools/cert.pem"
if [[ -f "${BMC_CA_FILE}" ]] && ! is_lower_version "$(openshift_version "${OCP_DIR}")" "4.22"; then
{
echo 'devscripts_bmc_verify_ca: |'
sed 's/^/ /' "${BMC_CA_FILE}"
} >> "${EXTRA_VARS_FILE}"
fi

# Image mirror content sources and trust bundle
MIRROR_CONTENT=$(image_mirror_config || true)
if [[ -n "${MIRROR_CONTENT}" ]]; then
# Extract imageContentSources as JSON array for the template
ICS_YAML=$(echo "${MIRROR_CONTENT}" | sed -n '/^imageContentSources:/,/^[a-zA-Z]/p' | sed '$d')
if [[ -n "${ICS_YAML}" ]]; then
echo "${ICS_YAML}" >> "${EXTRA_VARS_FILE}"
fi

# Extract additionalTrustBundle content
TRUST_BUNDLE=$(echo "${MIRROR_CONTENT}" | sed -n '/^additionalTrustBundle:/,$ p')
if [[ -n "${TRUST_BUNDLE}" ]]; then
{
echo "devscripts_additional_trust_bundle_content: |"
echo "${TRUST_BUNDLE}" | tail -n +2
} >> "${EXTRA_VARS_FILE}"
fi
elif [[ -n "${ADDITIONAL_TRUST_BUNDLE:-}" ]]; then
{
echo "devscripts_additional_trust_bundle_content: |"
awk '{ print " ", $0 }' "${ADDITIONAL_TRUST_BUNDLE}"
} >> "${EXTRA_VARS_FILE}"
fi

# Proxy variables (when INSTALLER_PROXY is set)
if [[ -n "${INSTALLER_PROXY:-}" ]]; then
cat >> "${EXTRA_VARS_FILE}" << PROXY_EOF
devscripts_http_proxy: "${HTTP_PROXY}"
devscripts_https_proxy: "${HTTPS_PROXY}"
devscripts_no_proxy: "${NO_PROXY}"
PROXY_EOF
fi

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It, uh, feels a bit like like we replaced the install-config heredoc with an equally long ansible config heredoc + 500 lines of YAML 😬


ANSIBLE_FORCE_COLOR=true ansible-playbook \
-i "${SCRIPTDIR}/ansible/inventory/hosts" \
--extra-vars "@${SCRIPTDIR}/ansible/.config_vars.yml" \
--extra-vars "@${EXTRA_VARS_FILE}" \
-v \
"${SCRIPTDIR}/ansible/playbooks/install_config.yml"
fi

# Generate the assets for extra worker VMs
# Generate the assets for extra worker VMs (not yet migrated to Ansible)
if [ -f "${EXTRA_NODES_FILE}" ]; then
jq '.nodes' "${EXTRA_NODES_FILE}" | tee "${EXTRA_BAREMETALHOSTS_FILE}"
generate_ocp_host_manifest "${OCP_DIR}" "${EXTRA_BAREMETALHOSTS_FILE}" extra_host_manifests.yaml "${EXTRA_WORKERS_NAMESPACE}"
Expand Down
43 changes: 43 additions & 0 deletions ansible/group_vars/all/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Cluster identity
devscripts_cluster_name: ostest
devscripts_base_domain: test.metalkube.org
devscripts_working_dir: /opt/dev-scripts
devscripts_ssh_pub_key: "{{ lookup('file', ansible_env.HOME + '/.ssh/id_rsa.pub') }}"

# Release image
# These mirror the bash defaults from common.sh.
# Set devscripts_release_image to pin an explicit image and skip resolution.
devscripts_release_stream: "4.22"
devscripts_release_type: nightly
devscripts_release_image: ""
devscripts_openshift_version: ""

# CI mode — when true, skips pull-secret merge, uses mixed BMC driver, etc.
devscripts_openshift_ci: false

# Security and features
devscripts_fips_mode: false
devscripts_feature_set: ""
devscripts_feature_gates: ""
devscripts_os_image_stream: ""

# Capabilities
devscripts_baseline_capability_set: ""
devscripts_additional_capabilities: ""

# Workload partitioning (set to true to add cpuPartitioningMode: AllNodes)
devscripts_enable_workload_partitioning: false

# Node counts
devscripts_num_masters: 3
devscripts_num_workers: 2
devscripts_num_arbiters: 0
devscripts_num_extra_workers: 0

# BMC driver: redfish, redfish-virtualmedia, ipmi, mixed
devscripts_bmc_driver: redfish

# Misc
devscripts_disable_multicast: false
devscripts_enable_bootstrap_static_ip: false
devscripts_external_loadbalancer: false
82 changes: 82 additions & 0 deletions ansible/group_vars/all/network.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# IP stack configuration
# Choices: v4, v6, v4v6, v6v4
devscripts_ip_stack: v6
devscripts_host_ip_stack: "{{ devscripts_ip_stack }}"

# Provisioning network profile: Managed or Disabled
devscripts_provisioning_network_profile: Managed

# Network names (derived from cluster name by default)
devscripts_provisioning_network_name: "{{ devscripts_cluster_name }}pr"
devscripts_baremetal_network_name: "{{ devscripts_cluster_name }}bm"

# Provisioning network CIDR — defaults depend on host_ip_stack.
# Override explicitly or leave empty to use the ip-stack-based default.
devscripts_provisioning_network: >-
{%- if devscripts_host_ip_stack in ['v4', 'v4v6'] -%}
172.22.0.0/24
{%- else -%}
fd00:1101::0/64
{%- endif -%}

# External subnets — defaults depend on host_ip_stack.
# For single-stack, the unused family is left empty.
devscripts_external_subnet_v4: >-
{%- if devscripts_host_ip_stack in ['v4', 'v4v6', 'v6v4'] -%}
192.168.111.0/24
{%- else -%}
{%- endif -%}

devscripts_external_subnet_v6: >-
{%- if devscripts_host_ip_stack in ['v6', 'v4v6', 'v6v4'] -%}
fd2e:6f44:5dd8:c956::/120
{%- else -%}
{%- endif -%}

# Cluster networking — defaults depend on ip_stack.
devscripts_cluster_subnet_v4: >-
{%- if devscripts_ip_stack in ['v4', 'v4v6', 'v6v4'] -%}
10.128.0.0/14
{%- else -%}
{%- endif -%}

devscripts_cluster_subnet_v6: >-
{%- if devscripts_ip_stack in ['v6', 'v4v6', 'v6v4'] -%}
fd01::/48
{%- else -%}
{%- endif -%}

devscripts_cluster_host_prefix_v4: >-
{%- if devscripts_ip_stack in ['v4', 'v4v6', 'v6v4'] -%}
23
{%- else -%}
{%- endif -%}

devscripts_cluster_host_prefix_v6: >-
{%- if devscripts_ip_stack in ['v6', 'v4v6', 'v6v4'] -%}
64
{%- else -%}
{%- endif -%}

devscripts_service_subnet_v4: >-
{%- if devscripts_ip_stack in ['v4', 'v4v6', 'v6v4'] -%}
172.30.0.0/16
{%- else -%}
{%- endif -%}

devscripts_service_subnet_v6: >-
{%- if devscripts_ip_stack in ['v6', 'v4v6', 'v6v4'] -%}
fd02::/112
{%- else -%}
{%- endif -%}

# Network type — OVNKubernetes is required for IPv6 and dual-stack.
# For IPv4-only on OCP < 4.15, OpenShiftSDN was the default.
devscripts_network_type: OVNKubernetes

# Provisioning interface inside the cluster nodes
devscripts_cluster_provisioning_interface: enp1s0

# Proxy settings (set devscripts_installer_proxy to true to enable)
devscripts_installer_proxy: false
devscripts_installer_proxy_port: 8215
32 changes: 32 additions & 0 deletions ansible/group_vars/all/registry.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Local registry — set devscripts_enable_local_registry to true to start one
devscripts_enable_local_registry: false

# Registry backend: podman or quay
devscripts_registry_backend: podman
devscripts_registry_port: "5000"
devscripts_registry_user: ocp-user
devscripts_registry_pass: ocp-pass
devscripts_registry_dir: "{{ devscripts_working_dir }}/registry"
devscripts_registry_dns_name: "virthost.{{ devscripts_cluster_name }}.{{ devscripts_base_domain }}"
devscripts_registry_crt: registry.2.crt

# Image mirroring — required for IPv6, optional for IPv4
# When left empty, defaults to true for v6 ip_stack.
devscripts_mirror_images: >-
{%- if devscripts_ip_stack == 'v6' -%}
true
{%- else -%}
false
{%- endif -%}

# Mirror command: oc-adm or oc-mirror
devscripts_mirror_command: oc-adm

# OLM operators to mirror (comma-separated)
devscripts_mirror_olm: ""

# Custom images to mirror (comma-separated)
devscripts_mirror_custom_images: ""

# Additional trust bundle PEM file path (leave empty to skip)
devscripts_additional_trust_bundle: ""
2 changes: 2 additions & 0 deletions ansible/inventory/hosts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[all]
localhost ansible_connection=local
16 changes: 16 additions & 0 deletions ansible/playbooks/install_config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
- name: Generate install-config.yaml
hosts: localhost
gather_facts: true
pre_tasks:
- name: Load nodes file
ansible.builtin.set_fact:
devscripts_nodes: "{{ (lookup('file', devscripts_nodes_file) | from_json).nodes }}"

- name: Resolve registry credentials path
ansible.builtin.set_fact:
devscripts_registry_creds: >-
{{ ansible_env.HOME }}/private-mirror-{{ devscripts_cluster_name }}.json

roles:
- role: "{{ playbook_dir }}/../roles/install_config"
73 changes: 73 additions & 0 deletions ansible/roles/install_config/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Role defaults — lowest precedence; overridden by group_vars or extra-vars.
# Variables not yet migrated to group_vars fall back to lookup('env').

# Paths derived from group_vars
devscripts_ocp_dir: "{{ devscripts_scriptdir }}/ocp/{{ devscripts_cluster_name }}"
devscripts_scriptdir: "{{ playbook_dir }}/../.."
devscripts_nodes_file: "{{ devscripts_working_dir }}/{{ devscripts_cluster_name }}/ironic_nodes.json"
devscripts_baremetalhosts_file: "{{ devscripts_ocp_dir }}/baremetalhosts.json"
devscripts_pull_secret_file: "{{ devscripts_working_dir }}/pull_secret.json"
devscripts_cluster_domain: "{{ devscripts_cluster_name }}.{{ devscripts_base_domain }}"

# Computed network values
devscripts_provisioning_host_external_ip: >-
{% if devscripts_host_ip_stack in ['v6', 'v6v4'] -%}
{{ devscripts_external_subnet_v6 | ansible.utils.nthhost(1) }}
{%- else -%}
{{ devscripts_external_subnet_v4 | ansible.utils.nthhost(1) }}
{%- endif %}
devscripts_mirror_ip: "{{ devscripts_provisioning_host_external_ip }}"

# DNS VIP
devscripts_dns_vip: >-
{% if devscripts_ip_stack == 'v6' -%}
{{ devscripts_external_subnet_v6 | ansible.utils.nthhost(2) }}
{%- else -%}
{{ devscripts_external_subnet_v4 | ansible.utils.nthhost(2) }}
{%- endif %}

# VIPs — will be resolved in tasks from libvirt DNS or computed from subnets
devscripts_api_vips: []
devscripts_ingress_vips: []

# Bootstrap static IP (.9 on the primary external subnet)
devscripts_bootstrap_static_ip: >-
{% if devscripts_enable_bootstrap_static_ip -%}
{% if devscripts_ip_stack in ['v6', 'v6v4'] -%}
{{ devscripts_external_subnet_v6 | ansible.utils.nthhost(9) }}
{%- else -%}
{{ devscripts_external_subnet_v4 | ansible.utils.nthhost(9) }}
{%- endif %}
{%- endif %}

# Provisioning IPs
devscripts_bootstrap_provisioning_ip: >-
{% if devscripts_provisioning_network_profile == 'Disabled' -%}
{% if devscripts_host_ip_stack == 'v6' -%}
{{ devscripts_external_subnet_v6 | ansible.utils.nthhost(7) }}
{%- else -%}
{{ devscripts_external_subnet_v4 | ansible.utils.nthhost(7) }}
{%- endif %}
{%- else -%}
{{ devscripts_provisioning_network | ansible.utils.nthhost(2) }}
{%- endif %}

devscripts_cluster_provisioning_ip: >-
{% if devscripts_provisioning_network_profile == 'Disabled' -%}
{% if devscripts_host_ip_stack == 'v6' -%}
{{ devscripts_external_subnet_v6 | ansible.utils.nthhost(8) }}
{%- else -%}
{{ devscripts_external_subnet_v4 | ansible.utils.nthhost(8) }}
{%- endif %}
{%- else -%}
{{ devscripts_provisioning_network | ansible.utils.nthhost(3) }}
{%- endif %}

# Not yet migrated — fall back to environment variables
devscripts_root_disk_name: "{{ lookup('env', 'ROOT_DISK_NAME') | default('/dev/sda', true) }}"
devscripts_remote_libvirt: "{{ lookup('env', 'REMOTE_LIBVIRT') | default('0', true) }}"
devscripts_provisioning_host_user: "{{ lookup('env', 'PROVISIONING_HOST_USER') | default(ansible_user_id, true) }}"
devscripts_provisioning_host_ip: "{{ lookup('env', 'PROVISIONING_HOST_IP') | default(devscripts_provisioning_network | ansible.utils.nthhost(1), true) }}"
devscripts_network_config_folder: "{{ lookup('env', 'NETWORK_CONFIG_FOLDER') | default('', true) }}"
devscripts_enable_two_node_fencing: "{{ lookup('env', 'ENABLE_TWO_NODE_FENCING') | default('false', true) | bool }}"
devscripts_master_hostname_format: "{{ lookup('env', 'MASTER_HOSTNAME_FORMAT') | default('master-%d', true) }}"
Loading