Skip to content

Commit 8fe2bca

Browse files
committed
Add hotstack CI Job - sno-2-bm
Single Node OpenShift (SNO), Sushy Emulator, 22 Ironic Nodes Assisted-By: Claude (claude-4.5-sonnet) Signed-off-by: Harald Jensås <hjensas@redhat.com>
1 parent d98151f commit 8fe2bca

File tree

15 files changed

+2433
-0
lines changed

15 files changed

+2433
-0
lines changed

ci/scenarios/sno-2-bm/README.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# sno-2-bm Scenario
2+
3+
## Overview
4+
5+
A Single Node OpenShift (SNO) scenario designed to test OpenStack Ironic bare
6+
metal provisioning with 2 dedicated Ironic nodes using mixed boot interfaces.
7+
This scenario validates the complete OpenStack bare metal lifecycle including
8+
node enrollment, provisioning, and comprehensive Tempest testing with both
9+
virtual media and iPXE network boot methods.
10+
11+
## Architecture
12+
13+
<!-- markdownlint-disable MD013 -->
14+
```mermaid
15+
graph TD
16+
Internet[("Internet")]
17+
Router{{"Neutron<br/>Router"}}
18+
19+
MachineNet["Machine Network<br/>192.168.32.0/24"]
20+
CtlPlane["CtlPlane Network<br/>192.168.122.0/24"]
21+
VLANNets["VLAN Trunk Networks<br/>Internal API: 172.17.0.0/24<br/>Storage: 172.18.0.0/24<br/>Tenant: 172.19.0.0/24"]
22+
IronicNet["Ironic Network<br/>172.20.1.0/24"]
23+
24+
Controller["Controller<br/>192.168.32.254<br/>DNS/HAProxy"]
25+
Master["SNO Master<br/>192.168.32.10"]
26+
IronicNodes["Ironic Nodes x2<br/>Virtual Baremetal"]
27+
28+
LVM["TopoLVM<br/>20GB"]
29+
CinderVols["Cinder Volumes x3<br/>20GB each"]
30+
31+
Internet --- Router
32+
33+
Router --- MachineNet
34+
Router --- CtlPlane
35+
Router --- VLANNets
36+
Router --- IronicNet
37+
38+
MachineNet --- Controller
39+
MachineNet --- Master
40+
CtlPlane --- Master
41+
VLANNets --- Master
42+
IronicNet --- Master
43+
IronicNet --- IronicNodes
44+
45+
Master --- LVM
46+
Master --- CinderVols
47+
48+
style Controller fill:#4A90E2,stroke:#2E5C8A,stroke-width:3px,color:#fff
49+
style Master fill:#F5A623,stroke:#C87D0E,stroke-width:3px,color:#fff
50+
style IronicNodes fill:#9B59B6,stroke:#6C3A82,stroke-width:2px,color:#fff
51+
style Router fill:#27AE60,stroke:#1E8449,stroke-width:3px,color:#fff
52+
```
53+
<!-- markdownlint-enable MD013 -->
54+
55+
### Component Details
56+
57+
- **Controller**: Hotstack controller providing DNS, load balancing, and
58+
orchestration services
59+
- **SNO Master**: Single-node OpenShift cluster running the complete OpenStack
60+
control plane
61+
- **Ironic Nodes**: 2 virtual bare metal nodes for testing Ironic provisioning workflows
62+
63+
## Networks
64+
65+
- **machine-net**: 192.168.32.0/24 (OpenShift cluster network)
66+
- **ctlplane-net**: 192.168.122.0/24 (OpenStack control plane)
67+
- **internal-api-net**: 172.17.0.0/24 (OpenStack internal services)
68+
- **storage-net**: 172.18.0.0/24 (Storage backend communication)
69+
- **tenant-net**: 172.19.0.0/24 (Tenant network traffic)
70+
- **ironic-net**: 172.20.1.0/24 (Bare metal provisioning network)
71+
72+
## OpenStack Services
73+
74+
This scenario deploys a comprehensive OpenStack environment:
75+
76+
### Core Services
77+
78+
- **Keystone**: Identity service with LoadBalancer on Internal API
79+
- **Nova**: Compute service with Ironic driver for bare metal
80+
- **Neutron**: Networking service with OVN backend
81+
- **Glance**: Image service with Swift backend
82+
- **Swift**: Object storage service
83+
- **Placement**: Resource placement service
84+
85+
### Bare Metal Services
86+
87+
- **Ironic**: Bare metal provisioning service
88+
- **Ironic Inspector**: Hardware inspection service
89+
- **Ironic Neutron Agent**: Network management for bare metal
90+
91+
## Ironic Boot Interface
92+
93+
Two boot interface modes are tested with the virtual Ironic nodes:
94+
95+
- **`redfish-virtual-media`**: Virtual media boot via sushy-tools rescue mode (ironic0)
96+
- **`ipxe`**: iPXE network boot via sushy-tools rescue mode (ironic1)
97+
98+
The mixed boot interface configuration validates both boot methods in a single deployment,
99+
ensuring compatibility and proper operation of different provisioning workflows.
100+
101+
## Usage
102+
103+
```bash
104+
# Deploy the scenario
105+
ansible-playbook -i inventory.yml bootstrap.yml \
106+
-e @scenarios/sno-2-bm/bootstrap_vars.yml \
107+
-e @~/cloud-secrets.yaml
108+
109+
# Run comprehensive tests
110+
ansible-playbook -i inventory.yml 06-test-operator.yml \
111+
-e @scenarios/sno-2-bm/bootstrap_vars.yml \
112+
-e @~/cloud-secrets.yaml
113+
```
114+
115+
## Configuration Files
116+
117+
- `bootstrap_vars.yml`: Infrastructure and OpenShift configuration.
118+
- `automation-vars.yml`: Hotloop deployment stages
119+
- `heat_template.yaml`: OpenStack infrastructure template (mixed boot interfaces)
120+
- `manifests/control-plane/control-plane.yaml`: OpenStack service configuration
121+
- `test-operator/automation-vars.yml`: Comprehensive test automation
122+
- `test-operator/tempest-tests.yml`: Tempest test specifications
123+
124+
This scenario provides a complete environment for validating OpenStack bare
125+
metal provisioning capabilities with mixed boot interfaces in a single-node
126+
OpenShift deployment with comprehensive testing automation.
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
---
2+
stages:
3+
- name: TopoLVM Dependencies
4+
stages: >-
5+
{{
6+
lookup("ansible.builtin.template",
7+
"common/stages/topolvm-deps-stages.yaml.j2")
8+
}}
9+
10+
- name: Dependencies
11+
stages: >-
12+
{{
13+
lookup("ansible.builtin.template",
14+
"common/stages/deps-stages.yaml.j2")
15+
}}
16+
17+
- name: Cinder LVM
18+
stages: >-
19+
{{
20+
lookup("ansible.builtin.file",
21+
"common/stages/cinder-lvm-label-stages.yaml")
22+
}}
23+
24+
- name: TopoLVM
25+
stages: >-
26+
{{
27+
lookup("ansible.builtin.template",
28+
"common/stages/topolvm-stages.yaml.j2")
29+
}}
30+
31+
- name: OLM Openstack
32+
stages: >-
33+
{{
34+
lookup("ansible.builtin.template",
35+
"common/stages/olm-openstack-stages.yaml.j2")
36+
}}
37+
38+
- name: NodeNetworkConfigurationPolicy (nncp)
39+
documentation: |
40+
Apply node network configuration policies to configure host networking.
41+
Waits for all policies to be successfully configured.
42+
j2_manifest: manifests/control-plane/networking/nncp.yaml.j2
43+
wait_conditions:
44+
- >-
45+
oc wait -n openstack nncp -l osp/nncm-config-type=standard
46+
--for jsonpath='{.status.conditions[0].reason}'=SuccessfullyConfigured
47+
--timeout=180s
48+
49+
- name: NetworkAttchmentDefinition (NAD)
50+
documentation: |
51+
Create network attachment definitions for OpenStack services.
52+
Defines additional network interfaces for pods.
53+
manifest: manifests/control-plane/networking/nad.yaml
54+
55+
- name: MetalLB - L2Advertisement and IPAddressPool
56+
documentation: |
57+
Configure MetalLB load balancer with IP address pools and L2 advertisements.
58+
Enables external access to OpenStack services.
59+
manifest: manifests/control-plane/networking/metallb.yaml
60+
61+
- name: OpenstackControlPlane
62+
documentation: |
63+
Deploy the OpenStack control plane with all core services.
64+
Waits for the control plane to be fully ready before proceeding.
65+
j2_manifest: manifests/control-plane/control-plane.yaml.j2
66+
wait_conditions:
67+
- >-
68+
oc -n openstack wait openstackcontrolplanes.core.openstack.org controlplane
69+
--for condition=OpenStackControlPlaneDNSReadyCondition --timeout=600s
70+
71+
- name: Extra DNS LoadBalancer on Ironic network
72+
documentation: |
73+
Deploy additional DNS service on the Ironic network for bare metal provisioning.
74+
Provides DNS resolution for ironic nodes during deployment and inspection.
75+
manifest: manifests/control-plane/dnsmasq-dns-ironic.yaml
76+
wait_conditions:
77+
- >-
78+
oc wait -n openstack service dnsmasq-dns-ironic
79+
--for jsonpath='.status.loadBalancer' --timeout=60s
80+
81+
- name: Wait for OpenstackControlPlane
82+
documentation: |
83+
Wait for the OpenStack control plane to be fully ready and operational.
84+
Ensures all services are running before proceeding with additional configurations.
85+
wait_conditions:
86+
- >-
87+
oc wait -n openstack openstackcontrolplane controlplane
88+
--for condition=Ready --timeout=30m
89+
90+
- name: Update openstack-operators OLM
91+
stages: >-
92+
{{
93+
lookup('ansible.builtin.template',
94+
'common/stages/openstack-olm-update.yaml.j2')
95+
}}
96+
run_conditions:
97+
- >-
98+
{{
99+
openstack_operators_update is defined and
100+
openstack_operators_update | bool
101+
}}
102+
103+
- name: Wait for condition MinorUpdateAvailable True
104+
documentation: |
105+
Wait for OpenStack version to indicate a minor update is available.
106+
Required before proceeding with version updates.
107+
wait_conditions:
108+
- >-
109+
oc -n openstack wait openstackversions.core.openstack.org controlplane
110+
--for=condition=MinorUpdateAvailable=True --timeout=10m
111+
run_conditions:
112+
- "{{ openstack_update is defined and openstack_update | bool }}"
113+
114+
- name: "Minor update :: Create OpenStackVersion patch"
115+
documentation: |
116+
This creates a patch file `{{ manifests_dir }}/patches/openstack_version_patch.yaml`
117+
If `openstack_update_custom_images` is defined it will populate the customContainerImages
118+
in the OpenstackVersion YAML patch.
119+
shell: >-
120+
{{
121+
lookup('ansible.builtin.template',
122+
'common/scripts/create_openstack_version_patch.sh.j2')
123+
}}
124+
run_conditions:
125+
- "{{ openstack_update is defined and openstack_update | bool }}"
126+
127+
- name: "Minor update :: Update the target version in the OpenStackVersion custom resource (CR)"
128+
documentation: |
129+
The `hotstack-openstack-version-patch` script will get the `availableVersion`
130+
and us it to replace the string `__TARGET_VERSION__` in the patch file and
131+
apply the patch using `oc patch` command.
132+
command: >-
133+
hotstack-openstack-version-patch --namespace openstack --name controlplane
134+
--file {{ manifests_dir }}/patches/openstack_version_patch.yaml
135+
wait_conditions:
136+
- oc -n openstack wait openstackversions.core.openstack.org controlplane
137+
--for=condition=Ready --timeout=10m
138+
run_conditions:
139+
- "{{ openstack_update is defined and openstack_update | bool }}"
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
---
2+
os_cloud: default
3+
os_floating_network: public
4+
os_router_external_network: public
5+
6+
scenario: sno-2-bm
7+
scenario_dir: scenarios
8+
stack_template_path: "{{ scenario_dir }}/{{ scenario }}/heat_template.yaml"
9+
automation_vars_file: "{{ scenario_dir }}/{{ scenario }}/automation-vars.yml"
10+
test_operator_automation_vars_file: "{{ scenario_dir }}/{{ scenario }}/test-operator/automation-vars.yml"
11+
12+
openstack_operators_image: quay.io/openstack-k8s-operators/openstack-operator-index:latest
13+
openstack_operator_channel: alpha
14+
openstack_operator_starting_csv: null
15+
16+
openshift_version: stable-4.18
17+
18+
ntp_servers: []
19+
dns_servers:
20+
- 172.31.0.129
21+
22+
pull_secret_file: ~/pull-secret.txt
23+
24+
ovn_k8s_gateway_config_host_routing: true
25+
enable_iscsi: true
26+
enable_multipath: true
27+
28+
cinder_volume_pvs:
29+
- /dev/vdc
30+
- /dev/vdd
31+
- /dev/vde
32+
33+
# Nova console recorder NFS settings
34+
nova_console_recorder_nfs_server: controller-0.openstack.lab
35+
nova_console_recorder_nfs_path: /export/nova-console-recordings
36+
37+
stack_name: "hs-{{ scenario }}-{{ zuul.build[:8] | default('no-zuul') }}"
38+
stack_parameters:
39+
# On misconfigured clouds, uncomment these to avoid issues.
40+
# Ref: https://access.redhat.com/solutions/7059376
41+
# net_value_specs:
42+
# mtu: 1442
43+
dns_servers: "{{ dns_servers }}"
44+
ntp_servers: "{{ ntp_servers }}"
45+
controller_ssh_pub_key: "{{ controller_ssh_pub_key | default('') }}"
46+
router_external_network: "{{ os_router_external_network | default('public') }}"
47+
floating_ip_network: "{{ os_floating_network | default('public') }}"
48+
controller_params:
49+
image: hotstack-controller
50+
flavor: hotstack.small
51+
ocp_master_params:
52+
image: ipxe-boot-usb
53+
flavor: hotstack.xxlarge
54+
ironic_params:
55+
image: CentOS-Stream-GenericCloud-9
56+
cd_image: sushy-tools-blank-image
57+
flavor: hotstack.medium

0 commit comments

Comments
 (0)