Skip to content

Commit bcb103d

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

File tree

15 files changed

+2399
-0
lines changed

15 files changed

+2399
-0
lines changed

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

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# sno-1-bm Scenario
2+
3+
## Overview
4+
5+
A Single Node OpenShift (SNO) scenario designed to test OpenStack Ironic bare
6+
metal provisioning with 1 dedicated Ironic node using iPXE network boot. This
7+
scenario validates the complete OpenStack bare metal lifecycle including node
8+
enrollment, provisioning, and Tempest testing.
9+
10+
## Architecture
11+
12+
<!-- markdownlint-disable MD013 -->
13+
```mermaid
14+
graph TD
15+
Internet[("Internet")]
16+
Router{{"Neutron<br/>Router"}}
17+
18+
MachineNet["Machine Network<br/>192.168.32.0/24"]
19+
CtlPlane["CtlPlane Network<br/>192.168.122.0/24"]
20+
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"]
21+
IronicNet["Ironic Network<br/>172.20.1.0/24"]
22+
23+
Controller["Controller<br/>192.168.32.254<br/>DNS/HAProxy"]
24+
Master["SNO Master<br/>192.168.32.10"]
25+
IronicNodes["Ironic Node x1<br/>Virtual Baremetal"]
26+
27+
LVM["TopoLVM<br/>20GB"]
28+
CinderVols["Cinder Volumes x3<br/>20GB each"]
29+
30+
Internet --- Router
31+
32+
Router --- MachineNet
33+
Router --- CtlPlane
34+
Router --- VLANNets
35+
Router --- IronicNet
36+
37+
MachineNet --- Controller
38+
MachineNet --- Master
39+
CtlPlane --- Master
40+
VLANNets --- Master
41+
IronicNet --- Master
42+
IronicNet --- IronicNodes
43+
44+
Master --- LVM
45+
Master --- CinderVols
46+
47+
style Controller fill:#4A90E2,stroke:#2E5C8A,stroke-width:3px,color:#fff
48+
style Master fill:#F5A623,stroke:#C87D0E,stroke-width:3px,color:#fff
49+
style IronicNodes fill:#9B59B6,stroke:#6C3A82,stroke-width:2px,color:#fff
50+
style Router fill:#27AE60,stroke:#1E8449,stroke-width:3px,color:#fff
51+
```
52+
<!-- markdownlint-enable MD013 -->
53+
54+
### Component Details
55+
56+
- **Controller**: Hotstack controller providing DNS, load balancing, and
57+
orchestration services
58+
- **SNO Master**: Single-node OpenShift cluster running the complete OpenStack
59+
control plane
60+
- **Ironic Node**: 1 virtual bare metal node for testing Ironic provisioning workflows
61+
62+
## Networks
63+
64+
- **machine-net**: 192.168.32.0/24 (OpenShift cluster network)
65+
- **ctlplane-net**: 192.168.122.0/24 (OpenStack control plane)
66+
- **internal-api-net**: 172.17.0.0/24 (OpenStack internal services)
67+
- **storage-net**: 172.18.0.0/24 (Storage backend communication)
68+
- **tenant-net**: 172.19.0.0/24 (Tenant network traffic)
69+
- **ironic-net**: 172.20.1.0/24 (Bare metal provisioning network)
70+
71+
## OpenStack Services
72+
73+
This scenario deploys a comprehensive OpenStack environment:
74+
75+
### Core Services
76+
77+
- **Keystone**: Identity service with LoadBalancer on Internal API
78+
- **Nova**: Compute service with Ironic driver for bare metal
79+
- **Neutron**: Networking service with OVN backend
80+
- **Glance**: Image service with Swift backend
81+
- **Swift**: Object storage service
82+
- **Placement**: Resource placement service
83+
84+
### Bare Metal Services
85+
86+
- **Ironic**: Bare metal provisioning service
87+
- **Ironic Inspector**: Hardware inspection service
88+
- **Ironic Neutron Agent**: Network management for bare metal
89+
90+
## Usage
91+
92+
```bash
93+
# Deploy the scenario
94+
ansible-playbook -i inventory.yml bootstrap.yml \
95+
-e @scenarios/sno-1-bm/bootstrap_vars.yml \
96+
-e @~/cloud-secrets.yaml
97+
98+
# Run comprehensive tests
99+
ansible-playbook -i inventory.yml 06-test-operator.yml \
100+
-e @scenarios/sno-1-bm/bootstrap_vars.yml \
101+
-e @~/cloud-secrets.yaml
102+
```
103+
104+
## Configuration Files
105+
106+
- `bootstrap_vars.yml`: Infrastructure and OpenShift configuration.
107+
- `automation-vars.yml`: Hotloop deployment stages
108+
- `heat_template_ipxe.yaml`: OpenStack infrastructure template (iPXE network boot)
109+
- `manifests/control-plane/control-plane.yaml`: OpenStack service configuration
110+
- `test-operator/automation-vars.yml`: Comprehensive test automation
111+
- `test-operator/tempest-tests.yml`: Tempest test specifications
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-1-bm
7+
scenario_dir: scenarios
8+
stack_template_path: "{{ scenario_dir }}/{{ scenario }}/heat_template_ipxe.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)