diff --git a/docs/dictionary/en-custom.txt b/docs/dictionary/en-custom.txt
index 547e6b3346..4706600ccf 100644
--- a/docs/dictionary/en-custom.txt
+++ b/docs/dictionary/en-custom.txt
@@ -178,6 +178,7 @@ env
envfile
epel
epyc
+etcd
eth
extraimages
extraRPMs
diff --git a/roles/dnsmasq/README.md b/roles/dnsmasq/README.md
index 972e243550..602baf2d2a 100644
--- a/roles/dnsmasq/README.md
+++ b/roles/dnsmasq/README.md
@@ -168,6 +168,7 @@ supported in libvirt).
* `mac`: (String) Entry MAC address. Mandatory.
* `ips`: (List[string]) List of IP addresses associated to the MAC (v4, v6). Mandatory.
* `name`: (String) Host name. Optional.
+* `tag`: (String) Tag to assign to this host. Tags can be used to apply specific DHCP options to groups of hosts. Optional.
#### Examples
@@ -182,7 +183,20 @@ supported in libvirt).
- "2345:0425:2CA1::0567:5673:cafe"
- "192.168.254.11"
name: r2d2
+ tag: droid # Optional: assign tag for DHCP options
ansible.builtin.include_role:
name: dnsmasq
tasks_from: manage_host.yml
```
+
+#### Using tags for DHCP options
+
+When you assign a `tag` to DHCP entries, you can then configure DHCP options for that tag:
+
+```
+# In /etc/cifmw-dnsmasq.d/custom-options.conf
+dhcp-option=tag:droid,60,HTTPClient
+dhcp-option=tag:droid,67,http://192.168.254.1/boot.ipxe
+```
+
+All hosts with the `droid` tag will receive these DHCP options.
diff --git a/roles/dnsmasq/molecule/default/converge.yml b/roles/dnsmasq/molecule/default/converge.yml
index 2b5e24cecd..914af886e8 100644
--- a/roles/dnsmasq/molecule/default/converge.yml
+++ b/roles/dnsmasq/molecule/default/converge.yml
@@ -145,6 +145,125 @@
name: dnsmasq
tasks_from: manage_host.yml
+ - name: Inject nodes with tags for DHCP options
+ vars:
+ cifmw_dnsmasq_dhcp_entries:
+ - network: starwars
+ state: present
+ mac: "0a:19:02:f8:4c:b1"
+ ips:
+ - "192.168.254.21"
+ - "2345:0425:2CA1::0567:5673:0021"
+ name: "r2d2"
+ tag: "droid"
+ - network: starwars
+ state: present
+ mac: "0a:19:02:f8:4c:b2"
+ ips:
+ - "192.168.254.22"
+ name: "c3po"
+ tag: "droid"
+ - network: startrek
+ state: present
+ mac: "0a:19:02:f8:4c:b3"
+ ips:
+ - "192.168.253.31"
+ name: "data"
+ tag: "android"
+ ansible.builtin.include_role:
+ name: dnsmasq
+ tasks_from: manage_host.yml
+
+ - name: Verify DHCP host entries with tags
+ block:
+ - name: Read r2d2 DHCP host entry
+ become: true
+ ansible.builtin.slurp:
+ path: "/etc/cifmw-dnsmasq.d/dhcp-hosts.d/starwars_r2d2_0a:19:02:f8:4c:b1"
+ register: _r2d2_entry
+
+ - name: Read c3po DHCP host entry
+ become: true
+ ansible.builtin.slurp:
+ path: "/etc/cifmw-dnsmasq.d/dhcp-hosts.d/starwars_c3po_0a:19:02:f8:4c:b2"
+ register: _c3po_entry
+
+ - name: Read data DHCP host entry
+ become: true
+ ansible.builtin.slurp:
+ path: "/etc/cifmw-dnsmasq.d/dhcp-hosts.d/startrek_data_0a:19:02:f8:4c:b3"
+ register: _data_entry
+
+ - name: Decode entries
+ ansible.builtin.set_fact:
+ _r2d2_content: "{{ _r2d2_entry.content | b64decode | trim }}"
+ _c3po_content: "{{ _c3po_entry.content | b64decode | trim }}"
+ _data_content: "{{ _data_entry.content | b64decode | trim }}"
+
+ - name: Assert r2d2 entry has droid tag
+ ansible.builtin.assert:
+ that:
+ - "'set:droid' in _r2d2_content"
+ - "'0a:19:02:f8:4c:b1' in _r2d2_content"
+ - "'192.168.254.21' in _r2d2_content"
+ - "'r2d2' in _r2d2_content"
+ msg: "r2d2 DHCP entry should contain tag 'droid': {{ _r2d2_content }}"
+
+ - name: Assert c3po entry has droid tag
+ ansible.builtin.assert:
+ that:
+ - "'set:droid' in _c3po_content"
+ - "'0a:19:02:f8:4c:b2' in _c3po_content"
+ - "'192.168.254.22' in _c3po_content"
+ - "'c3po' in _c3po_content"
+ msg: "c3po DHCP entry should contain tag 'droid': {{ _c3po_content }}"
+
+ - name: Assert data entry has android tag
+ ansible.builtin.assert:
+ that:
+ - "'set:android' in _data_content"
+ - "'0a:19:02:f8:4c:b3' in _data_content"
+ - "'192.168.253.31' in _data_content"
+ - "'data' in _data_content"
+ msg: "data DHCP entry should contain tag 'android': {{ _data_content }}"
+
+ - name: "Verify entry without tag has no set: prefix"
+ become: true
+ ansible.builtin.slurp:
+ path: "/etc/cifmw-dnsmasq.d/dhcp-hosts.d/starwars_solo_0a:19:02:f8:4c:a8"
+ register: _solo_entry
+
+ - name: "Assert solo entry does not have a tag"
+ vars:
+ _solo_content: "{{ _solo_entry.content | b64decode | trim }}"
+ ansible.builtin.assert:
+ that:
+ - "'set:' not in _solo_content"
+ - "'0a:19:02:f8:4c:a8' in _solo_content"
+ - "'solo' in _solo_content"
+ msg: "solo DHCP entry should not contain any tag: {{ _solo_content }}"
+
+ - name: "Create DHCP options configuration for tagged hosts"
+ become: true
+ ansible.builtin.copy:
+ dest: "/etc/cifmw-dnsmasq.d/test-dhcp-options.conf"
+ content: |
+ # Test DHCP options for droids
+ dhcp-option=tag:droid,60,HTTPClient
+ dhcp-option=tag:droid,67,http://192.168.254.1/droid-boot.ipxe
+ # Test DHCP options for androids
+ dhcp-option=tag:android,60,HTTPClient
+ dhcp-option=tag:android,67,http://192.168.253.1/android-boot.ipxe
+ mode: '0644'
+ validate: "/usr/sbin/dnsmasq -C %s --test"
+ notify: Restart dnsmasq
+
+ - name: Verify dnsmasq configuration is valid
+ become: true
+ ansible.builtin.command:
+ cmd: /usr/sbin/dnsmasq -C /etc/cifmw-dnsmasq.conf --test
+ changed_when: false
+
- name: Add a domain specific forwarder
vars:
cifmw_dnsmasq_forwarder:
diff --git a/roles/dnsmasq/tasks/manage_host.yml b/roles/dnsmasq/tasks/manage_host.yml
index 30666e5678..73a5778853 100644
--- a/roles/dnsmasq/tasks/manage_host.yml
+++ b/roles/dnsmasq/tasks/manage_host.yml
@@ -62,7 +62,11 @@
{%- set _ = data.append(entry.mac) -%}
{{ data | join('_') }}
_entry: >-
- {% set data = [entry.mac] -%}
+ {% set data = [] -%}
+ {% if entry.tag is defined and entry.tag | length > 0 -%}
+ {% set _ = data.append('set:' + entry.tag) -%}
+ {% endif -%}
+ {% set _ = data.append(entry.mac) -%}
{% for ip in entry.ips if ip is not none and ip | length > 0 -%}
{% set _ = data.append(ip | ansible.utils.ipwrap) -%}
{% endfor -%}
diff --git a/roles/libvirt_manager/DHCP_OPTIONS_EXAMPLE.md b/roles/libvirt_manager/DHCP_OPTIONS_EXAMPLE.md
new file mode 100644
index 0000000000..3737dda578
--- /dev/null
+++ b/roles/libvirt_manager/DHCP_OPTIONS_EXAMPLE.md
@@ -0,0 +1,161 @@
+# DHCP Options Support in libvirt_manager
+
+This document explains how to add DHCP options to VM groups in the libvirt_manager role.
+
+## Overview
+
+The libvirt_manager role now supports assigning DHCP options to groups of VMs based on their type. This is useful for scenarios like PXE booting where you need to provide specific boot parameters to certain VM types.
+
+## How It Works
+
+1. **VM Type Tagging**: Each VM is automatically tagged with its type (e.g., `compute`, `controller`, `baremetal_instance`)
+2. **DHCP Options**: You can specify DHCP options in the VM type definition
+3. **dnsmasq Configuration**: The role automatically generates dnsmasq configuration that applies these options to all VMs of that type
+
+## Configuration Example
+
+### Basic Example
+
+Here's how to add DHCP options for PXE booting to baremetal instances:
+
+```yaml
+cifmw_libvirt_manager_configuration:
+ vms:
+ baremetal_instance:
+ amount: 3
+ disk_file_name: "blank"
+ disksize: 50
+ memory: 8
+ cpus: 4
+ bootmenu_enable: "yes"
+ nets:
+ - public
+ - provisioning
+ dhcp_options:
+ - "60,HTTPClient" # Vendor class identifier
+ - "67,http://192.168.122.1:8081/boot.ipxe" # Boot filename (iPXE script)
+```
+
+### Advanced Example with Multiple VM Types
+
+```yaml
+cifmw_libvirt_manager_configuration:
+ vms:
+ controller:
+ amount: 1
+ image_url: "{{ cifmw_discovered_image_url }}"
+ sha256_image_name: "{{ cifmw_discovered_hash }}"
+ disk_file_name: "centos-stream-9.qcow2"
+ disksize: 50
+ memory: 4
+ cpus: 2
+ nets:
+ - public
+ - osp_trunk
+ # No DHCP options for controllers - they'll use defaults
+
+ compute:
+ amount: 3
+ disk_file_name: blank
+ disksize: 40
+ memory: 8
+ cpus: 4
+ nets:
+ - public
+ - osp_trunk
+ dhcp_options:
+ - "60,HTTPClient"
+ - "67,http://192.168.122.1:8081/boot-artifacts/compute-boot.ipxe"
+
+ baremetal_instance:
+ amount: 2
+ disk_file_name: "blank"
+ disksize: 50
+ memory: 8
+ cpus: 4
+ bootmenu_enable: "yes"
+ nets:
+ - public
+ dhcp_options:
+ - "60,HTTPClient"
+ - "67,http://192.168.122.1:8081/boot-artifacts/agent.x86_64.ipxe"
+```
+
+## Common DHCP Options
+
+Here are some commonly used DHCP options for PXE/network booting:
+
+| Option | Name | Purpose | Example |
+|--------|------|---------|---------|
+| 60 | vendor-class-identifier | Identifies the vendor/client type | `60,HTTPClient` |
+| 67 | bootfile-name | Path to boot file | `67,http://server/boot.ipxe` |
+| 66 | tftp-server-name | TFTP server address | `66,192.168.1.10` |
+| 150 | tftp-server-address | TFTP server IP (Cisco) | `150,192.168.1.10` |
+| 210 | path-prefix | Path prefix for boot files | `210,/tftpboot/` |
+
+
+## Technical Details
+
+### Under the Hood
+
+1. **Tag Assignment**: When VMs are created, each is assigned a tag matching its type in the dnsmasq DHCP host entry:
+ ```
+ set:baremetal_instance,52:54:00:xx:xx:xx,192.168.122.10,hostname
+ ```
+
+2. **DHCP Options Configuration**: A configuration file is generated at `/etc/cifmw-dnsmasq.d/vm-types-dhcp-options.conf`:
+ ```
+ # Options for baremetal_instance VMs
+ dhcp-option=tag:baremetal_instance,60,HTTPClient
+ dhcp-option=tag:baremetal_instance,67,http://192.168.122.1:8081/boot.ipxe
+ ```
+
+3. **dnsmasq Processing**: When a VM with the `baremetal_instance` tag requests DHCP, it receives both the standard network options AND the VM-type-specific options.
+
+### Files Modified
+
+- `roles/libvirt_manager/tasks/reserve_dnsmasq_ips.yml`: Adds VM type tags to DHCP entries
+- `roles/libvirt_manager/tasks/create_dhcp_options.yml`: New file that generates DHCP options configuration
+- `roles/libvirt_manager/tasks/generate_networking_data.yml`: Includes the new task
+- `roles/dnsmasq/tasks/manage_host.yml`: Updated to support tags in DHCP entries
+
+## Troubleshooting
+
+### Verify DHCP Options Are Applied
+
+1. Check the generated configuration:
+ ```bash
+ cat /etc/cifmw-dnsmasq.d/vm-types-dhcp-options.conf
+ ```
+
+2. Check DHCP host entries:
+ ```bash
+ ls -la /etc/cifmw-dnsmasq.d/dhcp-hosts.d/
+ cat /etc/cifmw-dnsmasq.d/dhcp-hosts.d/public_*
+ ```
+
+3. Verify dnsmasq configuration is valid:
+ ```bash
+ dnsmasq -C /etc/cifmw-dnsmasq.conf --test
+ ```
+
+4. Monitor DHCP requests:
+ ```bash
+ journalctl -u cifmw-dnsmasq -f
+ ```
+
+### Common Issues
+
+**Issue**: DHCP options not being sent to VMs
+- **Solution**: Ensure dnsmasq service is restarted after making changes
+- **Check**: Verify the VM type tag matches between the DHCP host entry and the options configuration
+
+**Issue**: VMs not PXE booting correctly
+- **Solution**: Verify the boot file URL is accessible from the VM's network
+- **Check**: Ensure option 67 contains the full URL including protocol (http://)
+
+## References
+
+- [dnsmasq manual](http://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html)
+- [DHCP Options RFC](https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml)
+- [iPXE documentation](https://ipxe.org/howto/dhcpd)
diff --git a/roles/libvirt_manager/README.md b/roles/libvirt_manager/README.md
index a8beb7c61f..6e6e86a7fe 100644
--- a/roles/libvirt_manager/README.md
+++ b/roles/libvirt_manager/README.md
@@ -97,6 +97,7 @@ cifmw_libvirt_manager_configuration:
bootmenu_enable: (string, toggle bootmenu. Optional, defaults to "no")
networkconfig: (dict or list[dict], [network-config](https://cloudinit.readthedocs.io/en/latest/reference/network-config-format-v2.html#network-config-v2) v2 config, needed if a static ip address should be defined at boot time in absence of a dhcp server in special scenarios. Optional)
devices: (dict, optional, defaults to {}. The keys are the VMs of that type that needs devices to be attached, and the values are lists of strings, where each string must contain a valid libvirt XML element that will be passed to virsh attach-device)
+ dhcp_options: (list, optional, defaults to []. List of DHCP options to apply to all VMs of this type. Format: ["option_number,value", ...])
networks:
net_name:
```
diff --git a/roles/libvirt_manager/molecule/generate_network_data/tasks/test.yml b/roles/libvirt_manager/molecule/generate_network_data/tasks/test.yml
index 04f360b08f..a867d77fe3 100644
--- a/roles/libvirt_manager/molecule/generate_network_data/tasks/test.yml
+++ b/roles/libvirt_manager/molecule/generate_network_data/tasks/test.yml
@@ -94,6 +94,78 @@
_run_fail: true
_failure: true
+ - name: Validate DHCP options
+ when:
+ - not _run_fail | bool
+ - scenario.check_dhcp_options is defined
+ - scenario.check_dhcp_options | bool
+ block:
+ - name: Check DHCP options configuration file exists
+ become: true
+ ansible.builtin.stat:
+ path: "/etc/cifmw-dnsmasq.d/vm-types-dhcp-options.conf"
+ register: _dhcp_options_file
+
+ - name: Assert DHCP options file exists
+ ansible.builtin.assert:
+ quiet: true
+ that:
+ - _dhcp_options_file.stat.exists
+ msg: "DHCP options file should exist"
+
+ - name: Read DHCP options file
+ become: true
+ ansible.builtin.slurp:
+ path: "/etc/cifmw-dnsmasq.d/vm-types-dhcp-options.conf"
+ register: _dhcp_options_content
+
+ - name: Decode DHCP options content
+ ansible.builtin.set_fact:
+ _dhcp_opts: "{{ _dhcp_options_content.content | b64decode }}"
+
+ - name: Verify DHCP options content for compute VMs
+ ansible.builtin.assert:
+ quiet: true
+ that:
+ - "'dhcp-option=tag:compute,60,HTTPClient' in _dhcp_opts"
+ - "'dhcp-option=tag:compute,67,http://192.168.140.1:8081/boot-artifacts/compute.ipxe' in _dhcp_opts"
+ msg: "DHCP options should contain correct entries for compute VMs"
+
+ - name: Verify DHCP host entry has tag
+ become: true
+ ansible.builtin.shell:
+ cmd: "grep -l 'set:compute' /etc/cifmw-dnsmasq.d/dhcp-hosts.d/osp_trunk_compute-0*"
+ register: _tagged_entry
+ changed_when: false
+ failed_when: _tagged_entry.rc != 0
+
+ - name: Read tagged DHCP host entry
+ become: true
+ ansible.builtin.slurp:
+ path: "{{ _tagged_entry.stdout }}"
+ register: _dhcp_host_entry
+
+ - name: Verify tag format in DHCP host entry
+ vars:
+ _entry_content: "{{ _dhcp_host_entry.content | b64decode | trim }}"
+ ansible.builtin.assert:
+ quiet: true
+ that:
+ - "'set:compute' in _entry_content"
+ - "_entry_content.startswith('set:compute,')"
+ msg: "DHCP host entry should start with 'set:compute,': {{ _entry_content }}"
+
+ rescue:
+ - name: Debug DHCP options content
+ when: _dhcp_opts is defined
+ ansible.builtin.debug:
+ var: _dhcp_opts
+
+ - name: Mark run as failed
+ ansible.builtin.set_fact:
+ _run_fail: true
+ _failure: true
+
- name: Assert we have expected facts set
block:
- name: Ensure it failed at the right place
diff --git a/roles/libvirt_manager/molecule/generate_network_data/vars/scenarios.yml b/roles/libvirt_manager/molecule/generate_network_data/vars/scenarios.yml
index b70b46176e..cbd4fdc314 100644
--- a/roles/libvirt_manager/molecule/generate_network_data/vars/scenarios.yml
+++ b/roles/libvirt_manager/molecule/generate_network_data/vars/scenarios.yml
@@ -38,6 +38,33 @@ scenarios:
+ - name: DHCP options for VM types
+ check_dns:
+ - rec: "compute-0.utility"
+ ip: "192.168.140.10"
+ - rec: "compute-0.ctlplane.local"
+ ip: "192.168.140.10"
+ - rec: "compute-0.public.local"
+ ip: "192.168.110.10"
+ check_dhcp:
+ - osp_trunk_compute-0
+ - public_compute-0
+ check_dhcp_options: true
+ lm_config_patch:
+ vms:
+ compute:
+ dhcp_options:
+ - "60,HTTPClient"
+ - "67,http://192.168.140.1:8081/boot-artifacts/compute.ipxe"
+ networks:
+ osp_trunk: |
+
+ osp_trunk
+
+
+
+
+
- name: Baremetal integration
check_dns:
- rec: "compute-0.utility"
diff --git a/roles/libvirt_manager/tasks/create_dhcp_options.yml b/roles/libvirt_manager/tasks/create_dhcp_options.yml
new file mode 100644
index 0000000000..d31c5d1bae
--- /dev/null
+++ b/roles/libvirt_manager/tasks/create_dhcp_options.yml
@@ -0,0 +1,46 @@
+---
+# Copyright Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Initialize empty _lm_dhcp_options fact
+ ansible.builtin.set_fact:
+ _lm_dhcp_options: {}
+
+- name: Collect DHCP options from VM definitions
+ when:
+ - item.value.dhcp_options is defined
+ - item.value.dhcp_options | length > 0
+ vars:
+ _vm_type: "{{ item.key }}"
+ _options: "{{ item.value.dhcp_options }}"
+ ansible.builtin.set_fact:
+ _lm_dhcp_options: >-
+ {{
+ _lm_dhcp_options | combine({_vm_type: _options})
+ }}
+ loop: "{{ _cifmw_libvirt_manager_layout.vms | dict2items }}"
+ loop_control:
+ label: "{{ item.key }}"
+
+- name: Generate DHCP option configuration for VM types
+ when:
+ - _lm_dhcp_options | length > 0
+ become: true
+ notify: "Restart dnsmasq"
+ ansible.builtin.template:
+ src: "vm-types-dhcp-options.conf.j2"
+ dest: "/etc/cifmw-dnsmasq.d/vm-types-dhcp-options.conf"
+ mode: '0644'
+ validate: "/usr/sbin/dnsmasq -C %s --test"
diff --git a/roles/libvirt_manager/tasks/generate_networking_data.yml b/roles/libvirt_manager/tasks/generate_networking_data.yml
index 1bf06d309a..c464a0867e 100644
--- a/roles/libvirt_manager/tasks/generate_networking_data.yml
+++ b/roles/libvirt_manager/tasks/generate_networking_data.yml
@@ -303,6 +303,9 @@
- name: Reserve IPs in DHCP and create DNS entries
ansible.builtin.import_tasks: create_dns_records.yml
+- name: Create DHCP options for VM types
+ ansible.builtin.import_tasks: create_dhcp_options.yml
+
# This task might also be done via the reproducer/prepare_networking.yml
# but, depending on how we call the libvirt_manager, we might not have it.
# Using the same filename/permissions/content, we can ensure it's there
diff --git a/roles/libvirt_manager/tasks/reserve_dnsmasq_ips.yml b/roles/libvirt_manager/tasks/reserve_dnsmasq_ips.yml
index b56ebde9ef..5fe2d3ff53 100644
--- a/roles/libvirt_manager/tasks/reserve_dnsmasq_ips.yml
+++ b/roles/libvirt_manager/tasks/reserve_dnsmasq_ips.yml
@@ -37,6 +37,7 @@
(host_data.key is match('^ocp.*')) |
ternary(_ocp_name, host_data.key)
}}
+ _vm_type: "{{ hostvars[host_data.key].vm_type | default('') }}"
_host:
network: "{{ _translated_name }}"
name: "{{ _hostname }}"
@@ -49,6 +50,7 @@
_net_data.ip_v6 | default('')
]
}}
+ tag: "{{ _vm_type }}"
ansible.builtin.set_fact:
_lm_dhcp_entries: "{{ _lm_dhcp_entries + [_host] }}"
loop: "{{ cifmw_networking_env_definition.instances | dict2items }}"
diff --git a/roles/libvirt_manager/templates/vm-types-dhcp-options.conf.j2 b/roles/libvirt_manager/templates/vm-types-dhcp-options.conf.j2
new file mode 100644
index 0000000000..905467f77a
--- /dev/null
+++ b/roles/libvirt_manager/templates/vm-types-dhcp-options.conf.j2
@@ -0,0 +1,8 @@
+# Managed by ci-framework/libvirt_manager
+# DHCP options for VM types
+{% for vm_type, options in _lm_dhcp_options.items() %}
+# Options for {{ vm_type }} VMs
+{% for option in options %}
+dhcp-option=tag:{{ vm_type }},{{ option }}
+{% endfor %}
+{% endfor %}
diff --git a/roles/ocp_agent_installer/README.md b/roles/ocp_agent_installer/README.md
new file mode 100644
index 0000000000..d6bf988a65
--- /dev/null
+++ b/roles/ocp_agent_installer/README.md
@@ -0,0 +1,12 @@
+# cifmw_ocp_agent_installer
+
+> **NOTE**: This Work-in-Progress ...
+
+
+* Create PXE bootstrap-artifacts using the OCP Agent Installer
+* Customizations:
+ * Enable iscsi
+ * Enable multipath
+ * Stand up cinder-volumes LVM
+ * Extra config for OVN-Kubernetes
+ * etcd hardware speed (Slower)
diff --git a/roles/ocp_agent_installer/defaults/main.yml b/roles/ocp_agent_installer/defaults/main.yml
new file mode 100644
index 0000000000..3918a02eed
--- /dev/null
+++ b/roles/ocp_agent_installer/defaults/main.yml
@@ -0,0 +1,74 @@
+---
+# Copyright Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+# Can be one of ['pxe', 'iso']
+cifmw_ocp_agent_installer_bootstrap_assets: pxe
+cifmw_ocp_agent_installer_add_ingress_cert_to_ca_trust: true
+
+cifmw_ocp_agent_installer_openshift_version: stable-4.18
+cifmw_ocp_agent_installer_mirror_url: https://mirror.openshift.com/pub/openshift-v4/x86_64/clients/ocp
+cifmw_ocp_agent_installer_client_url: "{{ cifmw_ocp_agent_installer_mirror_url }}/{{ cifmw_ocp_agent_installer_openshift_version }}/openshift-client-linux.tar.gz"
+cifmw_ocp_agent_installer_installer_url: "{{ cifmw_ocp_agent_installer_mirror_url }}/{{ cifmw_ocp_agent_installer_openshift_version }}/openshift-install-linux.tar.gz"
+
+cifmw_ocp_agent_installer_base_dir: "{{ cifmw_basedir | default(ansible_user_dir ~ '/ci-framework-data') }}/ocp-agent-installer"
+cifmw_ocp_agent_installer_bin_dir: "{{ ansible_user_dir }}/bin"
+cifmw_ocp_agent_installer_kube_config_dir: "{{ ansible_user_dir }}/.kube"
+cifmw_ocp_agent_installer_cluster_dir: "{{ cifmw_ocp_agent_installer_base_dir }}/ocp-cluster"
+cifmw_ocp_agent_installer_manifests_dir: "{{ cifmw_ocp_agent_installer_cluster_dir }}/openshift"
+cifmw_ocp_agent_installer_agent_installer_dir: "{{ cifmw_ocp_agent_installer_base_dir }}/agent-installer"
+cifmw_ocp_agent_installer_cluster_custom_config_dir: "{{ cifmw_ocp_agent_installer_base_dir }}/cluster-custom-config/"
+cifmw_ocp_agent_installer_butane_dir: "{{ cifmw_ocp_agent_installer_cluster_custom_config_dir }}/butane"
+cifmw_ocp_agent_installer_machine_configs_dir: "{{ cifmw_ocp_agent_installer_cluster_custom_config_dir }}/machine-configs"
+cifmw_ocp_agent_installer_config_assets_dir: "{{ cifmw_ocp_agent_installer_cluster_custom_config_dir }}/config-assets"
+
+cifmw_ocp_agent_installer_boot_artifacts_dir: /var/www/html/boot-artifacts
+
+cifmw_ocp_agent_installer_install_config:
+cifmw_ocp_agent_installer_agent_config:
+cifmw_ocp_agent_installer_pull_secret:
+
+cifmw_ocp_agent_installer_cinder_volume_pvs: []
+cifmw_ocp_agent_installer_cinder_volume_roles:
+ - master
+cifmw_ocp_agent_installer_enable_multipath: false
+cifmw_ocp_agent_installer_multipath_roles:
+ - master
+cifmw_ocp_agent_installer_enable_iscsi: false
+cifmw_ocp_agent_installer_iscsi_roles:
+ - master
+cifmw_ocp_agent_installer_disable_net_ifnames: true
+cifmw_ocp_agent_installer_net_ifnames_roles:
+ - master
+
+# OVN Configuration
+cifmw_ocp_agent_installer_enable_ovn_k8s_overrides: true
+cifmw_ocp_agent_installer_ovn_k8s_gateway_config_ip_forwarding: true
+cifmw_ocp_agent_installer_ovn_k8s_gateway_config_host_routing: false
+
+# Etcd - set to true for controlPlaneHardwareSpeed = Slower
+# https://www.redhat.com/en/blog/introducing-selectable-profiles-for-etcd
+cifmw_ocp_agent_installer_enable_etcd_hardware_speed_slow: true
+
+cifmw_ocp_agent_installer_enable_image_content_source_policy: false
+# To enable ImageContentSourcePolicy (ICSP), set this variable to contain the value
+# for the ICSP spec's repositoryDigestMirrors field.
+cifmw_ocp_agent_installer_image_content_source_policy_mirrors: []
+
+cifmw_ocp_agent_installer_enable_additional_trusted_ca: false
+cifmw_ocp_agent_installer_ocp_additional_trusted_ca:
+ - name: registry-proxy.engineering.redhat.com
+ url: https://url.corp.redhat.com/hotstack-ca
diff --git a/roles/ocp_agent_installer/files/additional-trusted-ca-config-image.yaml b/roles/ocp_agent_installer/files/additional-trusted-ca-config-image.yaml
new file mode 100644
index 0000000000..bced9aa42e
--- /dev/null
+++ b/roles/ocp_agent_installer/files/additional-trusted-ca-config-image.yaml
@@ -0,0 +1,8 @@
+---
+apiVersion: config.openshift.io/v1
+kind: Image
+metadata:
+ name: cluster
+spec:
+ additionalTrustedCA:
+ name: hotstack-additional-trusted-ca
diff --git a/roles/ocp_agent_installer/files/etcd-config.yaml b/roles/ocp_agent_installer/files/etcd-config.yaml
new file mode 100644
index 0000000000..30447e9b52
--- /dev/null
+++ b/roles/ocp_agent_installer/files/etcd-config.yaml
@@ -0,0 +1,8 @@
+---
+apiVersion: operator.openshift.io/v1
+kind: Etcd
+metadata:
+ name: cluster
+spec:
+ controlPlaneHardwareSpeed: Slower
+ managementState: Managed
diff --git a/roles/ocp_agent_installer/meta/main.yml b/roles/ocp_agent_installer/meta/main.yml
new file mode 100644
index 0000000000..ae5261d4ab
--- /dev/null
+++ b/roles/ocp_agent_installer/meta/main.yml
@@ -0,0 +1,15 @@
+---
+# Copyright Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
diff --git a/roles/ocp_agent_installer/tasks/additional_ca.yml b/roles/ocp_agent_installer/tasks/additional_ca.yml
new file mode 100644
index 0000000000..614c8d5910
--- /dev/null
+++ b/roles/ocp_agent_installer/tasks/additional_ca.yml
@@ -0,0 +1,53 @@
+---
+# Copyright Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Assert
+ ansible.builtin.assert:
+ that:
+ - ca.name is defined
+ - ca.name | length > 0
+ - ca.url is defined or ca.data is defined
+ - (
+ ca.url | length > 0 or
+ ca.data | length > 0
+ )
+
+- name: Download the CA bundle if url
+ when: ca.url is defined
+ ansible.builtin.uri:
+ url: "{{ ca.url }}"
+ method: get
+ return_content: true
+ validate_certs: false
+ register: __get_ca_from_url_result
+ ignore_errors: true
+
+- name: Append to _ocp_additional_trusted_ca_map
+ when: (
+ ca.data is defined or
+ (
+ ca.url is defined and
+ not __get_ca_from_url_result.failed
+ )
+ )
+ ansible.builtin.set_fact:
+ _ocp_additional_trusted_ca_map: >-
+ {{
+ _ocp_additional_trusted_ca_map |
+ combine(
+ {ca.name: ca.data | default(__get_ca_from_url_result.content)}
+ )
+ }}
diff --git a/roles/ocp_agent_installer/tasks/config_assets.yml b/roles/ocp_agent_installer/tasks/config_assets.yml
new file mode 100644
index 0000000000..f53b246845
--- /dev/null
+++ b/roles/ocp_agent_installer/tasks/config_assets.yml
@@ -0,0 +1,94 @@
+---
+# Copyright Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Template ovn-k8s customization
+ when: cifmw_ocp_agent_installer_enable_ovn_k8s_overrides | bool
+ ansible.builtin.template:
+ src: ovn-k8s-config.j2
+ dest: >-
+ {{
+ [
+ cifmw_ocp_agent_installer_config_assets_dir,
+ 'ovn_k8s_config.yaml'
+ ] | ansible.builtin.path_join
+ }}
+ mode: '0644'
+
+- name: Copy Etcd customization
+ when: cifmw_ocp_agent_installer_enable_etcd_hardware_speed_slow | bool
+ ansible.builtin.copy:
+ src: etcd-config.yaml
+ dest: >-
+ {{
+ [
+ cifmw_ocp_agent_installer_config_assets_dir,
+ '95-etcd_config.yaml'
+ ] | ansible.builtin.path_join
+ }}
+ mode: '0644'
+
+- name: Template ImageContentSourcePolicy customization
+ when: cifmw_ocp_agent_installer_enable_image_content_source_policy | bool
+ ansible.builtin.template:
+ src: image-content-source-policy.yaml.j2
+ dest: >-
+ {{
+ [
+ cifmw_ocp_agent_installer_config_assets_dir,
+ '95-image-content-source-policy.yaml'
+ ] | ansible.builtin.path_join
+ }}
+ mode: '0644'
+
+- name: Additional trusted CA
+ when:
+ - cifmw_ocp_agent_installer_enable_additional_trusted_ca | bool
+ - cifmw_ocp_agent_installer_ocp_additional_trusted_ca is defined
+ - cifmw_ocp_agent_installer_ocp_additional_trusted_ca | length > 0
+ block:
+ - name: Initialize _ocp_additional_trusted_ca_map fact
+ ansible.builtin.set_fact:
+ _ocp_additional_trusted_ca_map: {}
+
+ - name: Append to _ocp_additional_trusted_ca_map fact
+ ansible.builtin.include_tasks: additional_ca.yml
+ loop: "{{ cifmw_ocp_agent_installer_ocp_additional_trusted_ca }}"
+ loop_control:
+ loop_var: ca
+
+ - name: Template additional CA config map
+ ansible.builtin.template:
+ src: additional-trusted-ca-config-map.yaml.j2
+ dest: >-
+ {{
+ [
+ cifmw_ocp_agent_installer_config_assets_dir,
+ '93-additional-ca-config-map.yaml'
+ ] | ansible.builtin.path_join
+ }}
+ mode: '0644'
+
+ - name: Copy additional CA config image
+ ansible.builtin.copy:
+ src: additional-trusted-ca-config-image.yaml
+ dest: >-
+ {{
+ [
+ cifmw_ocp_agent_installer_config_assets_dir,
+ '94-additional-ca-config-image.yaml'
+ ] | ansible.builtin.path_join
+ }}
+ mode: '0644'
diff --git a/roles/ocp_agent_installer/tasks/ingress_cert.yml b/roles/ocp_agent_installer/tasks/ingress_cert.yml
new file mode 100644
index 0000000000..0d7f081693
--- /dev/null
+++ b/roles/ocp_agent_installer/tasks/ingress_cert.yml
@@ -0,0 +1,39 @@
+---
+# Copyright Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Extract ingress CA cert
+ register: _ingress_cert
+ ansible.builtin.shell: |
+ POD_NAME=$({{ cifmw_ocp_agent_installer_bin_dir }}/oc get pods -n openshift-authentication -o jsonpath='{.items[0].metadata.name}')
+ {{ cifmw_ocp_agent_installer_bin_dir }}/oc rsh -n openshift-authentication $POD_NAME \
+ cat /run/secrets/kubernetes.io/serviceaccount/ca.crt
+ retries: 10
+ delay: 10
+ until: _ingress_cert.rc == 0
+
+- name: Write ingress cert to ca-trust
+ become: true
+ ansible.builtin.copy:
+ content: "{{ _ingress_cert.stdout }}"
+ dest: /etc/pki/ca-trust/source/anchors/ingress-ca.crt
+ owner: root
+ group: root
+ mode: '0644'
+
+- name: Update CA trust
+ become: true
+ ansible.builtin.command:
+ cmd: update-ca-trust
diff --git a/roles/ocp_agent_installer/tasks/install_client.yml b/roles/ocp_agent_installer/tasks/install_client.yml
new file mode 100644
index 0000000000..1cf3c7f5fc
--- /dev/null
+++ b/roles/ocp_agent_installer/tasks/install_client.yml
@@ -0,0 +1,47 @@
+---
+# Copyright Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Download the client
+ ansible.builtin.get_url:
+ url: "{{ cifmw_ocp_agent_installer_client_url }}"
+ dest: >-
+ {{
+ [
+ cifmw_ocp_agent_installer_agent_installer_dir,
+ 'openshift-client-linux.tar.gz'
+ ] | ansible.builtin.path_join
+ }}
+ mode: '0644'
+
+- name: Extract client to /home/zuul/bin
+ ansible.builtin.unarchive:
+ src: >-
+ {{
+ [
+ cifmw_ocp_agent_installer_agent_installer_dir,
+ 'openshift-client-linux.tar.gz'
+ ] | ansible.builtin.path_join
+ }}
+ dest: "{{ cifmw_ocp_agent_installer_bin_dir }}"
+ remote_src: true
+ creates: "{{ cifmw_ocp_agent_installer_bin_dir }}/oc"
+
+- name: Configure bash completion
+ become: true
+ ansible.builtin.shell: |
+ {{ cifmw_ocp_agent_installer_bin_dir }}/oc completion bash > /etc/bash_completion.d/oc_bash_completion
+ args:
+ creates: /etc/bash_completion.d/oc_bash_completion
diff --git a/roles/ocp_agent_installer/tasks/install_installer.yml b/roles/ocp_agent_installer/tasks/install_installer.yml
new file mode 100644
index 0000000000..63b30f32df
--- /dev/null
+++ b/roles/ocp_agent_installer/tasks/install_installer.yml
@@ -0,0 +1,40 @@
+---
+# Copyright Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Download the installer
+ ansible.builtin.get_url:
+ url: "{{ cifmw_ocp_agent_installer_installer_url }}"
+ dest: >-
+ {{
+ [
+ cifmw_ocp_agent_installer_agent_installer_dir,
+ 'openshift-install-linux.tar.gz'
+ ] | ansible.builtin.path_join
+ }}
+ mode: '0644'
+
+- name: Extract installer to /home/zuul/bin
+ ansible.builtin.unarchive:
+ src: >-
+ {{
+ [
+ cifmw_ocp_agent_installer_agent_installer_dir,
+ 'openshift-install-linux.tar.gz'
+ ] | ansible.builtin.path_join
+ }}
+ dest: "{{ cifmw_ocp_agent_installer_bin_dir }}"
+ remote_src: true
+ creates: "{{ cifmw_ocp_agent_installer_bin_dir }}/openshift-install"
diff --git a/roles/ocp_agent_installer/tasks/iso_assets.yml b/roles/ocp_agent_installer/tasks/iso_assets.yml
new file mode 100644
index 0000000000..99e39a342c
--- /dev/null
+++ b/roles/ocp_agent_installer/tasks/iso_assets.yml
@@ -0,0 +1,19 @@
+---
+# Copyright Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Fail - not implemented
+ ansible.builtin.fail:
+ msg: "Assisted Installer with ISO assets has not been implemented in ocp_agent_installer"
diff --git a/roles/ocp_agent_installer/tasks/machine_configs.yml b/roles/ocp_agent_installer/tasks/machine_configs.yml
new file mode 100644
index 0000000000..decfaf926f
--- /dev/null
+++ b/roles/ocp_agent_installer/tasks/machine_configs.yml
@@ -0,0 +1,90 @@
+---
+# Copyright Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Disable net.ifnames
+ when: cifmw_ocp_agent_installer_disable_net_ifnames | bool
+ block:
+ - name: Template butane config for net.ifnames
+ vars:
+ role: "{{ item }}"
+ ansible.builtin.template:
+ src: disable-netifnames.bu.j2
+ dest: "{{ cifmw_ocp_agent_installer_butane_dir }}/90-{{ item }}-disable-netifnames.bu"
+ mode: '0644'
+ loop: "{{ cifmw_ocp_agent_installer_net_ifnames_roles }}"
+ - name: Generate MachineConfig for iscsi
+ ansible.builtin.command:
+ cmd: >-
+ butane {{ cifmw_ocp_agent_installer_butane_dir }}/90-{{ item }}-disable-netifnames.bu
+ -o {{ cifmw_ocp_agent_installer_machine_configs_dir }}/90-{{ item }}-disable-netifnames.yaml
+ loop: "{{ cifmw_ocp_agent_installer_net_ifnames_roles }}"
+
+- name: Enable iscsi
+ when: cifmw_ocp_agent_installer_enable_iscsi | bool
+ block:
+ - name: Template butane config for iscsi
+ vars:
+ role: "{{ item }}"
+ ansible.builtin.template:
+ src: enable-iscsi.bu.j2
+ dest: "{{ cifmw_ocp_agent_installer_butane_dir }}/90-{{ item }}-enable-iscsi.bu"
+ mode: '0644'
+ loop: "{{ cifmw_ocp_agent_installer_iscsi_roles }}"
+
+ - name: Generate MachineConfig for iscsi
+ ansible.builtin.command:
+ cmd: >-
+ butane {{ cifmw_ocp_agent_installer_butane_dir }}/90-{{ item }}-enable-iscsi.bu
+ -o {{ cifmw_ocp_agent_installer_machine_configs_dir }}/90-{{ item }}-enable-iscsi.yaml
+ loop: "{{ cifmw_ocp_agent_installer_iscsi_roles }}"
+
+- name: Enable Multipath
+ when: cifmw_ocp_agent_installer_enable_multipath | bool
+ block:
+ - name: Template butane config for multipath
+ vars:
+ role: "{{ item }}"
+ ansible.builtin.template:
+ src: enable-multipath.bu.j2
+ dest: "{{ cifmw_ocp_agent_installer_butane_dir }}/91-{{ item }}-enable-multipath.bu"
+ mode: '0644'
+ loop: "{{ cifmw_ocp_agent_installer_multipath_roles }}"
+
+ - name: Generate MachineConfig for multipath
+ ansible.builtin.command:
+ cmd: >-
+ butane {{ cifmw_ocp_agent_installer_butane_dir }}/91-{{ item }}-enable-multipath.bu
+ -o {{ cifmw_ocp_agent_installer_machine_configs_dir }}/91-{{ item }}-enable-multipath.yaml
+ loop: "{{ cifmw_ocp_agent_installer_multipath_roles }}"
+
+- name: LVM cinder-volumes
+ when: cifmw_ocp_agent_installer_cinder_volume_pvs | length > 0
+ block:
+ - name: Template butane config for LVM cinder-volumes
+ vars:
+ role: "{{ item }}"
+ ansible.builtin.template:
+ src: lv-cinder-volumes.bu.j2
+ dest: "{{ cifmw_ocp_agent_installer_butane_dir }}/92-{{ item }}-lv-cinder-volumes.bu"
+ mode: '0644'
+ loop: "{{ cifmw_ocp_agent_installer_cinder_volume_roles }}"
+
+ - name: Generate MachineConfig for multipath
+ ansible.builtin.command:
+ cmd: >-
+ butane {{ cifmw_ocp_agent_installer_butane_dir }}/92-{{ item }}-lv-cinder-volumes.bu
+ -o {{ cifmw_ocp_agent_installer_machine_configs_dir }}/92-{{ item }}-lv-cinder-volumes.yaml
+ loop: "{{ cifmw_ocp_agent_installer_cinder_volume_roles }}"
diff --git a/roles/ocp_agent_installer/tasks/main.yml b/roles/ocp_agent_installer/tasks/main.yml
new file mode 100644
index 0000000000..26787dd761
--- /dev/null
+++ b/roles/ocp_agent_installer/tasks/main.yml
@@ -0,0 +1,162 @@
+---
+# Copyright Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Assert config is defined
+ ansible.builtin.assert:
+ that:
+ - cifmw_ocp_agent_installer_pull_secret is defined
+ - cifmw_ocp_agent_installer_pull_secret | length > 0
+ - cifmw_ocp_agent_installer_install_config is defined
+ - cifmw_ocp_agent_installer_install_config | length > 0
+ - cifmw_ocp_agent_installer_agent_config is defined
+ - cifmw_ocp_agent_installer_agent_config | length > 0
+
+- name: Include client install tasks
+ ansible.builtin.include_tasks: install_client.yml
+
+- name: Include installer install tasks
+ ansible.builtin.include_tasks: install_installer.yml
+
+- name: Include config asset tasks
+ ansible.builtin.include_tasks: config_assets.yml
+
+- name: Include machine config tasks
+ ansible.builtin.include_tasks: machine_configs.yml
+
+- name: Include additional ca tasks
+ ansible.builtin.include_tasks: additional_ca.yml
+
+- name: Install package requirements for agent installer
+ become: true
+ ansible.builtin.dnf:
+ name:
+ - nmstate
+ - butane
+ state: present
+
+- name: Create the cluster directories
+ ansible.builtin.file:
+ path: "{{ item }}"
+ state: directory
+ owner: "{{ ansible_user | default(ansible_user_id) }}"
+ group: "{{ ansible_user | default(ansible_user_id) }}"
+ mode: '0755'
+ loop:
+ - "{{ cifmw_ocp_agent_installer_bin_dir }}"
+ - "{{ cifmw_ocp_agent_installer_kube_config_dir }}"
+ - "{{ cifmw_ocp_agent_installer_cluster_dir }}"
+ - "{{ cifmw_ocp_agent_installer_manifests_dir }}"
+ - "{{ cifmw_ocp_agent_installer_agent_installer_dir }}"
+ - "{{ cifmw_ocp_agent_installer_cluster_custom_config_dir }}"
+ - "{{ cifmw_ocp_agent_installer_butane_dir }}"
+ - "{{ cifmw_ocp_agent_installer_machine_configs_dir }}"
+ - "{{ cifmw_ocp_agent_installer_config_assets_dir }}"
+
+- name: Generate install-config.yaml file
+ ansible.builtin.copy:
+ content: |
+ apiVersion: v1
+ baseDomain: {{ cifmw_ocp_agent_installer_install_config.baseDomain }}
+ compute:
+ {{ cifmw_ocp_agent_installer_install_config.compute | to_nice_yaml(indent=2) | indent(width=2) }}
+ controlPlane:
+ {{ cifmw_ocp_agent_installer_install_config.controlPlane | to_nice_yaml(indent=2) | indent(width=2) }}
+ metadata:
+ name: {{ cifmw_ocp_agent_installer_install_config.metadata.name }}
+ networking:
+ {{ cifmw_ocp_agent_installer_install_config.networking | to_nice_yaml(indent=2) | indent(width=2) }}
+ platform:
+ {{ cifmw_ocp_agent_installer_install_config.platform | to_nice_yaml(indent=2) | indent(width=2) }}
+ pullSecret: '{{ cifmw_ocp_agent_installer_pull_secret | b64decode }}'
+ sshKey: '{{ cifmw_ocp_agent_installer_install_config.sshKey }}'
+ dest: "{{ cifmw_ocp_agent_installer_cluster_dir }}/install-config.yaml"
+ owner: "{{ ansible_user | default(ansible_user_id) }}"
+ group: "{{ ansible_user | default(ansible_user_id) }}"
+ mode: '0600'
+
+- name: Generate agent-config.yaml file
+ ansible.builtin.copy:
+ content: |
+ apiVersion: v1alpha1
+ kind: AgentConfig
+ metadata:
+ name: {{ cifmw_ocp_agent_installer_agent_config.metadata.name }}
+ {{ cifmw_ocp_agent_installer_agent_config | to_nice_yaml(indent=2) | indent(width=2) }}
+ dest: "{{ cifmw_ocp_agent_installer_cluster_dir }}/agent-config.yaml"
+ owner: "{{ ansible_user | default(ansible_user_id) }}"
+ group: "{{ ansible_user | default(ansible_user_id) }}"
+ mode: '0600'
+
+- name: Generate custom manifests
+ ansible.builtin.shell: |
+ cd {{ cifmw_ocp_agent_installer_cluster_dir }}
+ {{ cifmw_ocp_agent_installer_bin_dir }}/openshift-install create manifests
+
+- name: Copy machine_configs to manifests dir
+ ansible.builtin.copy:
+ remote_src: true
+ src: "{{ cifmw_ocp_agent_installer_machine_configs_dir }}/"
+ dest: "{{ cifmw_ocp_agent_installer_manifests_dir }}/"
+ mode: '0644'
+
+- name: Copy config assets to manifests dir
+ ansible.builtin.copy:
+ remote_src: true
+ src: "{{ cifmw_ocp_agent_installer_config_assets_dir }}/"
+ dest: "{{ cifmw_ocp_agent_installer_manifests_dir }}/"
+ mode: '0644'
+
+- name: Include pxe assets tasks
+ ansible.builtin.include_tasks: pxe_assets.yml
+ when: cifmw_ocp_agent_installer_bootstrap_assets == 'pxe'
+
+- name: Include iso assets tasks
+ ansible.builtin.include_tasks: iso_assets.yml
+ when: cifmw_ocp_agent_installer_bootstrap_assets == 'iso'
+
+- name: Copy auth/kubeconfig to ~/.kube/config
+ ansible.builtin.copy:
+ remote_src: true
+ src: >-
+ {{
+ [
+ cifmw_ocp_agent_installer_cluster_dir,
+ 'auth',
+ 'kubeconfig'
+ ] | ansible.builtin.path_join
+ }}
+ dest: >-
+ {{
+ [
+ cifmw_ocp_agent_installer_kube_config_dir,
+ 'config'
+ ] | ansible.builtin.path_join
+ }}
+ mode: '0600'
+
+- name: Wait for bootstrap-complete
+ ansible.builtin.command:
+ cmd: >
+ {{ cifmw_ocp_agent_installer_bin_dir }}/openshift-install --dir {{ cifmw_ocp_agent_installer_cluster_dir }} agent wait-for bootstrap-complete --log-level=info
+
+- name: Wait for install-complete
+ ansible.builtin.command:
+ cmd: >
+ {{ cifmw_ocp_agent_installer_bin_dir }}/openshift-install --dir {{ cifmw_ocp_agent_installer_cluster_dir }} agent wait-for install-complete
+
+- name: Add ingress certificate to CA trust
+ when: cifmw_ocp_agent_installer_add_ingress_cert_to_ca_trust | bool
+ ansible.builtin.include_tasks: ingress_cert.yml
diff --git a/roles/ocp_agent_installer/tasks/pxe_assets.yml b/roles/ocp_agent_installer/tasks/pxe_assets.yml
new file mode 100644
index 0000000000..0e65c7c751
--- /dev/null
+++ b/roles/ocp_agent_installer/tasks/pxe_assets.yml
@@ -0,0 +1,66 @@
+---
+# Copyright Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Create the boot-artifacts directory
+ become: true
+ ansible.builtin.file:
+ path: "{{ cifmw_ocp_agent_installer_boot_artifacts_dir }}"
+ state: directory
+ mode: '0755'
+
+- name: Create PXE assets
+ ansible.builtin.command:
+ chdir: "{{ cifmw_ocp_agent_installer_cluster_dir }}"
+ cmd: >
+ {{ cifmw_ocp_agent_installer_bin_dir }}/openshift-install agent create pxe-files
+
+- name: Set serial console in ipxe
+ ansible.builtin.lineinfile:
+ path: "{{ cifmw_ocp_agent_installer_cluster_dir }}/boot-artifacts/agent.x86_64.ipxe"
+ backrefs: true
+ regexp: "^(kernel.*)$"
+ line: '\1 console=ttyS0'
+
+- name: Disable net.ifnames
+ when: cifmw_ocp_agent_installer_disable_net_ifnames | bool
+ ansible.builtin.lineinfile:
+ path: "{{ cifmw_ocp_agent_installer_cluster_dir }}/boot-artifacts/agent.x86_64.ipxe"
+ backrefs: true
+ regexp: "^(kernel.*)$"
+ line: '\1 net.ifnames=0'
+
+- name: Copy boot-artifacts to the web server - (cifmw_ocp_agent_installer_boot_artifacts_dir)
+ become: true
+ ansible.builtin.copy:
+ remote_src: true
+ src: >-
+ {{
+ [
+ cifmw_ocp_agent_installer_cluster_dir,
+ 'boot-artifacts',
+ item
+ ] | ansible.builtin.path_join
+ }}
+ dest: "{{ cifmw_ocp_agent_installer_boot_artifacts_dir }}"
+ owner: root
+ group: root
+ mode: '0644'
+ loop:
+ - agent.x86_64-vmlinuz
+ - agent.x86_64-initrd.img
+ - agent.x86_64-rootfs.img
+ # Copy the iPXE last, the other files should be ready before iPXE try to load them.
+ - agent.x86_64.ipxe
diff --git a/roles/ocp_agent_installer/templates/additional-trusted-ca-config-map.yaml.j2 b/roles/ocp_agent_installer/templates/additional-trusted-ca-config-map.yaml.j2
new file mode 100644
index 0000000000..3f249a8738
--- /dev/null
+++ b/roles/ocp_agent_installer/templates/additional-trusted-ca-config-map.yaml.j2
@@ -0,0 +1,11 @@
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ namespace: openshift-config
+ name: hotstack-additional-trusted-ca
+data:
+{% for ca in cifmw_ocp_agent_installer_ocp_additional_trusted_ca %}
+ {{ ca.name }}: |
+ {{ _ocp_additional_trusted_ca_map[ca.name] | indent(width=4) }}
+{% endfor %}
diff --git a/roles/ocp_agent_installer/templates/disable-netifnames.bu.j2 b/roles/ocp_agent_installer/templates/disable-netifnames.bu.j2
new file mode 100644
index 0000000000..9a220be44d
--- /dev/null
+++ b/roles/ocp_agent_installer/templates/disable-netifnames.bu.j2
@@ -0,0 +1,10 @@
+---
+variant: openshift
+version: 4.17.0
+metadata:
+ name: 90-{{ role | default('master') }}-netifnames-conf
+ labels:
+ machineconfiguration.openshift.io/role: {{ role | default('master') }}
+openshift:
+ kernel_arguments:
+ - net.ifnames=0
diff --git a/roles/ocp_agent_installer/templates/enable-iscsi.bu.j2 b/roles/ocp_agent_installer/templates/enable-iscsi.bu.j2
new file mode 100644
index 0000000000..2dd0c993f5
--- /dev/null
+++ b/roles/ocp_agent_installer/templates/enable-iscsi.bu.j2
@@ -0,0 +1,32 @@
+---
+variant: openshift
+version: 4.17.0
+metadata:
+ name: 90-{{ role | default('master') }}-nable-iscsi
+ labels:
+ machineconfiguration.openshift.io/role: {{ role | default('master') }}
+storage:
+ files:
+ - path: /etc/iscsi/iscsid.conf
+ overwrite: true
+ mode: 384
+ user:
+ name: root
+ group:
+ name: root
+ contents:
+ inline: |
+ # Default to 3 retries and 5 seconds each (15 seconds in total),
+ # which is convenient for testing, as any healthy deployment and
+ # backend should be able to login to the backend in that amount of
+ # time, and if there is a broken path it will not take 2 minutes to
+ # give up, just around 15 seconds.
+ node.session.initial_login_retry_max = 3
+ node.conn[0].timeo.login_timeout = 5
+ # The default CHAP algorithms include MD5 will does not work under
+ # FIPS. Set this parameter to exclude MD5 and SHA-1.
+ node.session.auth.chap_algs = SHA3-256,SHA256
+systemd:
+ units:
+ - enabled: true
+ name: iscsid.service
diff --git a/roles/ocp_agent_installer/templates/enable-multipath.bu.j2 b/roles/ocp_agent_installer/templates/enable-multipath.bu.j2
new file mode 100644
index 0000000000..374370f1f5
--- /dev/null
+++ b/roles/ocp_agent_installer/templates/enable-multipath.bu.j2
@@ -0,0 +1,30 @@
+---
+variant: openshift
+version: 4.17.0
+metadata:
+ name: 91-{{ role | default('master') }}-multipath-conf
+ labels:
+ machineconfiguration.openshift.io/role: {{ role | default('master') }}
+storage:
+ files:
+ - path: /etc/multipath.conf
+ overwrite: false
+ mode: 344
+ user:
+ name: root
+ group:
+ name: root
+ contents:
+ inline: |
+ defaults {
+ user_friendly_names no
+ recheck_wwid yes
+ skip_kpartx yes
+ find_multipaths yes
+ }
+ blacklist {
+ }
+systemd:
+ units:
+ - enabled: true
+ name: multipathd.service
diff --git a/roles/ocp_agent_installer/templates/image-content-source-policy.yaml.j2 b/roles/ocp_agent_installer/templates/image-content-source-policy.yaml.j2
new file mode 100644
index 0000000000..642bab9cad
--- /dev/null
+++ b/roles/ocp_agent_installer/templates/image-content-source-policy.yaml.j2
@@ -0,0 +1,8 @@
+---
+apiVersion: operator.openshift.io/v1alpha1
+kind: ImageContentSourcePolicy
+metadata:
+ name: brew-registry
+spec:
+ repositoryDigestMirrors:
+ {{ cifmw_ocp_agent_installer_image_content_source_policy_mirrors | to_nice_yaml(indent=2) | indent(width=4) }}
diff --git a/roles/ocp_agent_installer/templates/lv-cinder-volumes.bu.j2 b/roles/ocp_agent_installer/templates/lv-cinder-volumes.bu.j2
new file mode 100644
index 0000000000..66380dae82
--- /dev/null
+++ b/roles/ocp_agent_installer/templates/lv-cinder-volumes.bu.j2
@@ -0,0 +1,31 @@
+---
+variant: openshift
+version: 4.17.0
+metadata:
+ name: 91-{{ role | default('master') }}-lv-cinder-volumes
+ labels:
+ machineconfiguration.openshift.io/role: {{ role | default('master') }}
+storage:
+ disks:
+{% for _disk in cifmw_ocp_agent_installer_cinder_volume_pvs %}
+ - device: {{ _disk }}
+ wipe_table: true
+{% endfor %}
+systemd:
+ units:
+ - name: lv-cinder-volumes.service
+ enabled: true
+ contents: |
+ [Unit]
+ Description=Create logical volume with name cinder-volumes.
+ After=var.mount systemd-udev-settle.service
+
+ [Service]
+ Type=oneshot
+ ExecCondition=/bin/bash -c '! /usr/sbin/vgdisplay cinder-volumes'
+ ExecStartPre=/usr/sbin/pvcreate {{ cifmw_ocp_agent_installer_cinder_volume_pvs | join(' ') }}
+ExecStart=/usr/sbin/vgcreate cinder-volumes {{ cifmw_ocp_agent_installer_cinder_volume_pvs | join(' ') }}
+ RemainAfterExit=yes
+
+ [Install]
+ WantedBy=multi-user.target
diff --git a/roles/ocp_agent_installer/templates/ovn-k8s-config.j2 b/roles/ocp_agent_installer/templates/ovn-k8s-config.j2
new file mode 100644
index 0000000000..8070d1b6aa
--- /dev/null
+++ b/roles/ocp_agent_installer/templates/ovn-k8s-config.j2
@@ -0,0 +1,13 @@
+---
+apiVersion: operator.openshift.io/v1
+kind: Network
+metadata:
+ name: cluster
+spec:
+ defaultNetwork:
+ ovnKubernetesConfig:
+ gatewayConfig:
+{% if cifmw_ocp_agent_installer_ovn_k8s_gateway_config_ip_forwarding %}
+ ipForwarding: Global
+{% endif %}
+ routingViaHost: {{ cifmw_ocp_agent_installer_ovn_k8s_gateway_config_host_routing }}
diff --git a/zuul.d/projects.yaml b/zuul.d/projects.yaml
index 182be6866a..f30e3d1956 100644
--- a/zuul.d/projects.yaml
+++ b/zuul.d/projects.yaml
@@ -2,114 +2,5 @@
github-check:
jobs:
- noop
- - cifmw-pod-ansible-test
- - cifmw-pod-k8s-snippets-source
- - cifmw-pod-pre-commit
- - cifmw-pod-zuul-files
- - cifmw-content-provider-build-images
- - cifmw-edpm-build-images
- - cifmw-multinode-kuttl
- - cifmw-tcib
- - cifmw-architecture-validate-hci
- - ci-framework-openstack-meta-content-provider
- - build-push-container-cifmw-client
- - cifmw-molecule-adoption_osp_deploy
- - cifmw-molecule-artifacts
- - cifmw-molecule-build_containers
- - cifmw-molecule-build_openstack_packages
- - cifmw-molecule-build_push_container
- - cifmw-molecule-cert_manager
- - cifmw-molecule-ci_dcn_site
- - cifmw-molecule-ci_gen_kustomize_values
- - cifmw-molecule-ci_local_storage
- - cifmw-molecule-ci_lvms_storage
- - cifmw-molecule-ci_multus
- - cifmw-molecule-ci_network
- - cifmw-molecule-ci_nmstate
- - cifmw-molecule-ci_setup
- - cifmw-molecule-cifmw_block_device
- - cifmw-molecule-cifmw_ceph_client
- - cifmw-molecule-cifmw_ceph_spec
- - cifmw-molecule-cifmw_cephadm
- - cifmw-molecule-cifmw_create_admin
- - cifmw-molecule-cifmw_external_dns
- - cifmw-molecule-cifmw_helpers
- - cifmw-molecule-cifmw_nfs
- - cifmw-molecule-cifmw_ntp
- - cifmw-molecule-cifmw_setup
- - cifmw-molecule-cifmw_snr_nhc
- - cifmw-molecule-cifmw_test_role
- - cifmw-molecule-cleanup_openstack
- - cifmw-molecule-compliance
- - cifmw-molecule-config_drive
- - cifmw-molecule-copy_container
- - cifmw-molecule-deploy_bmh
- - cifmw-molecule-devscripts
- - cifmw-molecule-discover_latest_image
- - cifmw-molecule-dlrn_promote
- - cifmw-molecule-dlrn_report
- cifmw-molecule-dnsmasq
- - cifmw-molecule-edpm_build_images
- - cifmw-molecule-edpm_deploy
- - cifmw-molecule-edpm_deploy_baremetal
- - cifmw-molecule-edpm_kustomize
- - cifmw-molecule-edpm_prepare
- - cifmw-molecule-env_op_images
- - cifmw-molecule-federation
- - cifmw-molecule-fix_python_encodings
- - cifmw-molecule-hci_prepare
- - cifmw-molecule-hive
- - cifmw-molecule-idrac_configuration
- - cifmw-molecule-install_ca
- - cifmw-molecule-install_openstack_ca
- - cifmw-molecule-install_yamls
- - cifmw-molecule-ipa
- - cifmw-molecule-krb_request
- - cifmw-molecule-kustomize_deploy
- cifmw-molecule-libvirt_manager
- - cifmw-molecule-manage_secrets
- - cifmw-molecule-mirror_registry
- - cifmw-molecule-nat64_appliance
- - cifmw-molecule-networking_mapper
- - cifmw-molecule-openshift_adm
- - cifmw-molecule-openshift_login
- - cifmw-molecule-openshift_obs
- - cifmw-molecule-openshift_provisioner_node
- - cifmw-molecule-openshift_setup
- - cifmw-molecule-operator_build
- - cifmw-molecule-operator_deploy
- - cifmw-molecule-os_must_gather
- - cifmw-molecule-os_net_setup
- - cifmw-molecule-ovirt
- - cifmw-molecule-pkg_build
- - cifmw-molecule-podman
- - cifmw-molecule-polarion
- - cifmw-molecule-recognize_ssh_keypair
- - cifmw-molecule-registry_deploy
- - cifmw-molecule-repo_setup
- - cifmw-molecule-reportportal
- - cifmw-molecule-reproducer
- - cifmw-molecule-rhol_crc
- - cifmw-molecule-run_hook
- - cifmw-molecule-set_openstack_containers
- - cifmw-molecule-shiftstack
- - cifmw-molecule-ssh_jumper
- - cifmw-molecule-sushy_emulator
- - cifmw-molecule-switch_config
- - cifmw-molecule-tempest
- - cifmw-molecule-test_deps
- - cifmw-molecule-test_operator
- - cifmw-molecule-tofu
- - cifmw-molecule-update
- - cifmw-molecule-update_containers
- - cifmw-molecule-validations
- - cifmw-molecule-virtualbmc
- - edpm-ansible-molecule-edpm_podman
- - edpm-ansible-molecule-edpm_ovs
- github-post:
- jobs:
- - build-push-container-cifmw-client-post
- name: openstack-k8s-operators/ci-framework
- templates:
- - podified-multinode-edpm-ci-framework-pipeline
- - data-plane-adoption-ci-framework-pipeline