From 574992971513909089a31920ab180368f82d43e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harald=20Jens=C3=A5s?= Date: Sun, 13 Jul 2025 15:47:58 +0200 Subject: [PATCH] VeOS Switch --- ci/nmstate_validate.sh | 18 + scenarios/sno-nxsw/heat_template.yaml | 5 +- scenarios/sno-veos/README.md | 133 +++ scenarios/sno-veos/automation-vars.yml | 122 +++ scenarios/sno-veos/bootstrap_vars.yml | 62 ++ scenarios/sno-veos/heat_template.yaml | 977 ++++++++++++++++++ .../sno-veos/manifests/control-plane.yaml | 493 +++++++++ .../manifests/networking/metallb.yaml | 88 ++ .../sno-veos/manifests/networking/nad.yaml | 134 +++ .../manifests/networking/netconfig.yaml | 50 + .../sno-veos/manifests/networking/nncp.yaml | 136 +++ scenarios/sno-veos/manifests/ngs/config.yaml | 32 + .../sno-veos/manifests/openstack-version.yaml | 8 + scenarios/sno-veos/startup-config | 34 + scenarios/sno-veos/test-operator/README.md | 42 + .../test-operator/automation-vars.yml | 318 ++++++ .../sno-veos/test-operator/manifests/nad.yaml | 21 + .../sno-veos/test-operator/tempest-tests.yml | 89 ++ scenarios/sno-veos/ztp.config | 2 + 19 files changed, 2762 insertions(+), 2 deletions(-) create mode 100755 ci/nmstate_validate.sh create mode 100644 scenarios/sno-veos/README.md create mode 100644 scenarios/sno-veos/automation-vars.yml create mode 100644 scenarios/sno-veos/bootstrap_vars.yml create mode 100644 scenarios/sno-veos/heat_template.yaml create mode 100644 scenarios/sno-veos/manifests/control-plane.yaml create mode 100644 scenarios/sno-veos/manifests/networking/metallb.yaml create mode 100644 scenarios/sno-veos/manifests/networking/nad.yaml create mode 100644 scenarios/sno-veos/manifests/networking/netconfig.yaml create mode 100644 scenarios/sno-veos/manifests/networking/nncp.yaml create mode 100644 scenarios/sno-veos/manifests/ngs/config.yaml create mode 100644 scenarios/sno-veos/manifests/openstack-version.yaml create mode 100644 scenarios/sno-veos/startup-config create mode 100644 scenarios/sno-veos/test-operator/README.md create mode 100644 scenarios/sno-veos/test-operator/automation-vars.yml create mode 100644 scenarios/sno-veos/test-operator/manifests/nad.yaml create mode 100644 scenarios/sno-veos/test-operator/tempest-tests.yml create mode 100644 scenarios/sno-veos/ztp.config diff --git a/ci/nmstate_validate.sh b/ci/nmstate_validate.sh new file mode 100755 index 00000000..c380ea79 --- /dev/null +++ b/ci/nmstate_validate.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +set -x + +if ! command -v nmstatectl; then + echo "nmstatectl is not installed" + exit 0 +fi + +if ! command -v yq; then + echo "yq is not installed" + exit 0 +fi + +for document_idx in $(yq '.spec.desiredState | document_index' "$1" | grep -v "\---") +do + yq ".spec.desiredState | select(document_index == $document_idx)" "$1" | nmstatectl -q validate -- +done diff --git a/scenarios/sno-nxsw/heat_template.yaml b/scenarios/sno-nxsw/heat_template.yaml index 0ac7e488..079e8a02 100644 --- a/scenarios/sno-nxsw/heat_template.yaml +++ b/scenarios/sno-nxsw/heat_template.yaml @@ -1,8 +1,9 @@ --- heat_template_version: rocky -description: > - Heat template to set up SNO (Single Node OpenShift) infrastructure, 1x Controller, 1x OCP Master (no ironic nodes) +description: | + Heat template to set up SNO (Single Node OpenShift) infrastructure, + 1x Controller, 1x OCP Master, 1x Switch, 2x Ironic nodes parameters: dns_servers: diff --git a/scenarios/sno-veos/README.md b/scenarios/sno-veos/README.md new file mode 100644 index 00000000..fb48e8eb --- /dev/null +++ b/scenarios/sno-veos/README.md @@ -0,0 +1,133 @@ +# SNO-NXSW Scenario + +## Overview + +The `sno-veos` scenario is a Single Node OpenShift (SNO) deployment scenario +for HotStack that deploys OpenStack on OpenShift with ironic bare metal +provisioning capabilities and network switch integration. + +## Architecture + +This scenario provisions: + +- **1x Controller Node**: Management and DNS/DHCP services +- **1x OpenShift Master Node**: Single node OpenShift cluster running OpenStack services +- **1x Switch Node**: vEOS Lab switch with trunk ports for tenant VLAN networks +- **2x Ironic Nodes**: Virtual bare metal nodes for testing Ironic provisioning workflows + +## Features + +- **Complete OpenStack Stack**: Full OpenStack deployment with ironic bare + metal service +- **Network Switch Integration**: Automated switch configuration with + Zero Prov (??? Arista vEOS) and NGS (Networking Generic Switch) +- **Complete Networking**: All OpenStack service networks with dedicated + ironic networks +- **SNO Deployment**: Single node OpenShift optimized for OpenStack services +- **Development Ready**: Ideal for testing and development environments +- **Bare Metal Provisioning**: Ironic service with 2 nodes for testing bare + metal workflows + +## Networks + +- **machine-net**: 192.168.32.0/24 - External access network +- **ctlplane-net**: 192.168.122.0/24 - Control plane network +- **internal-api-net**: 172.17.0.0/24 - OpenStack internal API network +- **storage-net**: 172.18.0.0/24 - Storage network +- **tenant-net**: 172.19.0.0/24 - Tenant network for OpenStack workloads +- **ironic-net**: 172.20.1.0/24 - Ironic network for bare metal provisioning +- **tenant-vlan103**: 172.20.3.0/24 - Tenant VLAN network (VLAN 103) +- **tenant-vlan104**: 172.20.4.0/24 - Tenant VLAN network (VLAN 104) +- **ironic0-br-net**: 172.20.5.0/29 - Ironic0 bridge network +- **ironic1-br-net**: 172.20.5.8/29 - Ironic1 bridge network + +## Switch Instance Configuration + +The switch instance provides network switching capabilities with the following +interface configuration: + +### Network Interface Summary + +```text +Switch Instance: +├── eth0: machine-net (management interface) +├── eth1: trunk (ironic:101, tenant-vlan103:103, tenant-vlan104:104) +├── eth2: ironic0-br-net (ironic bridge network) +└── eth3: ironic1-br-net (ironic bridge network) +``` + +### VLAN Mapping + +- **VLAN 101**: ironic (172.20.1.0/24) +- **VLAN 102**: Default native VLAN +- **VLAN 103**: tenant-vlan103 (172.20.3.0/24) +- **VLAN 104**: tenant-vlan104 (172.20.4.0/24) + +The switch uses the `nxsw` image and provides dual trunk ports for redundancy +and high availability. + +### POAP (Power-On Auto Provisioning) + +POAP is a Cisco NX-OS feature that automates the initial configuration of +network switches. When the switch boots up, it automatically: + +1. **Downloads Configuration**: Fetches the switch configuration from a + TFTP/HTTP server +2. **Applies Settings**: Automatically configures interfaces, VLANs, and + network settings +3. **Enables Services**: Activates required network services (NETCONF, LACP, LLDP) +4. **Validates Setup**: Performs integrity checks using MD5 checksums + +In this scenario, POAP enables zero-touch deployment of the NX-OS switch with pre-configured: + +- **Interface Configuration**: Trunk and access ports for tenant VLANs +- **VLAN Setup**: VLANs for network segmentation +- **Management Settings**: IP addressing, DNS, and routing configuration +- **Security**: User accounts and access control + +## Ironic Nodes + +The scenario includes 2 virtual bare metal nodes for testing Ironic provisioning: + +### Ironic Node 0 + +- **Network**: ironic0-br-net (172.20.5.0/29) +- **Purpose**: Bare metal provisioning testing +- **Configuration**: Virtual media boot capable with sushy-tools + +### Ironic Node 1 + +- **Network**: ironic1-br-net (172.20.5.8/29) +- **Purpose**: Bare metal provisioning testing +- **Configuration**: Virtual media boot capable with sushy-tools + +## Usage + +This scenario is ideal for: + +- Testing OpenStack deployments with neutron ML2 plugins +- Validating bare metal provisioning workflows with Ironic +- Network switch integration testing with OpenStack +- Development and testing of networking-generic-switch functionality + +## Files + +- `bootstrap_vars.yml`: Main configuration variables +- `heat_template.yaml`: OpenStack Heat template for infrastructure +- `automation-vars.yml`: Automation pipeline definition +- `manifests/`: OpenShift/Kubernetes manifests +- `test-operator/`: Test automation configuration + +## Upload switch image to cloud + +```bash + openstack image create vEOS-lab-4.34.1F \ + --disk-format qcow2 \ + --file vEOS-lab-4.34.1F.qcow2 \ + --property hw_video_model=none +``` + +## Deployment + +Follow the standard HotStack deployment process with this scenario by setting +the scenario name to `sno-veos` in your deployment configuration. diff --git a/scenarios/sno-veos/automation-vars.yml b/scenarios/sno-veos/automation-vars.yml new file mode 100644 index 00000000..4a9c19c6 --- /dev/null +++ b/scenarios/sno-veos/automation-vars.yml @@ -0,0 +1,122 @@ +--- +stages: + - name: Dependencies + stages: >- + {{ + lookup("ansible.builtin.template", + "common/stages/deps-stages.yaml.j2") + }} + + - name: Cinder LVM + stages: >- + {{ + lookup("ansible.builtin.file", + "common/stages/cinder-lvm-label-stages.yaml") + }} + + - name: TopoLVM + stages: >- + {{ + lookup("ansible.builtin.template", + "common/stages/topolvm-stages.yaml.j2") + }} + + - name: OLM Openstack + stages: >- + {{ + lookup("ansible.builtin.template", + "common/stages/olm-openstack-stages.yaml.j2") + }} + + - name: NodeNetworkConfigurationPolicy (nncp) + manifest: manifests/networking/nncp.yaml + wait_conditions: + - >- + oc wait -n openstack nncp -l osp/nncm-config-type=standard + --for jsonpath='{.status.conditions[0].reason}'=SuccessfullyConfigured + --timeout=180s + + - name: NetworkAttchmentDefinition (NAD) + manifest: manifests/networking/nad.yaml + + - name: MetalLB - L2Advertisement and IPAddressPool + manifest: manifests/networking/metallb.yaml + + - name: Netconfig + manifest: manifests/networking/netconfig.yaml + + - name: NGS config (Networking Generic Switch) + manifest: manifests/ngs/config.yaml + wait_conditions: + - >- + oc wait -n openstack secret neutron-switch-config + --for jsonpath='{.metadata.name}'=neutron-switch-config + --timeout=30s + + - name: Openstack Version + manifest: manifests/openstack-version.yaml + patches: + - path: spec.customContainerImages + value: "{{ customContainerImages }}" + wait_conditions: + - >- + oc wait -n openstack openstackversions.core.openstack.org controlplane + --for condition=Initialized --timeout=30m + run_conditions: + - >- + {{ customContainerImages is defined and customContainerImages | length > 0 }} + + - name: OpenstackControlPlane + manifest: manifests/control-plane.yaml + wait_conditions: + - >- + oc wait -n openstack openstackcontrolplane controlplane + --for condition=Ready --timeout=30m + + - name: Update openstack-operators OLM + stages: >- + {{ + lookup('ansible.builtin.template', + 'common/stages/openstack-olm-update.yaml.j2') + }} + run_conditions: + - >- + {{ + openstack_operators_update is defined and + openstack_operators_update | bool + }} + + - name: Wait for condition MinorUpdateAvailable True + wait_conditions: + - >- + oc -n openstack wait openstackversions.core.openstack.org controlplane + --for=condition=MinorUpdateAvailable=True --timeout=10m + run_conditions: + - "{{ openstack_update is defined and openstack_update | bool }}" + + - name: "Minor update :: Create OpenStackVersion patch" + documentation: | + This creates a patch file `{{ manifests_dir }}/patches/openstack_version_patch.yaml` + If `openstack_update_custom_images` is defined it will populate the customContainerImages + in the OpenstackVersion YAML patch. + shell: >- + {{ + lookup('ansible.builtin.template', + 'common/scripts/create_openstack_version_patch.sh.j2') + }} + run_conditions: + - "{{ openstack_update is defined and openstack_update | bool }}" + + - name: "Minor update :: Update the target version in the OpenStackVersion custom resource (CR)" + documentation: | + The `hotstack-openstack-version-patch` script will get the `availableVersion` + and us it to replace the string `__TARGET_VERSION__` in the patch file and + apply the patch using `oc patch` command. + command: >- + hotstack-openstack-version-patch --namespace openstack --name controlplane + --file {{ manifests_dir }}/patches/openstack_version_patch.yaml + wait_conditions: + - oc -n openstack wait openstackversions.core.openstack.org controlplane + --for=condition=Ready --timeout=10m + run_conditions: + - "{{ openstack_update is defined and openstack_update | bool }}" diff --git a/scenarios/sno-veos/bootstrap_vars.yml b/scenarios/sno-veos/bootstrap_vars.yml new file mode 100644 index 00000000..78410a1b --- /dev/null +++ b/scenarios/sno-veos/bootstrap_vars.yml @@ -0,0 +1,62 @@ +--- +os_cloud: default +os_floating_network: public +os_router_external_network: public + +controller_ssh_pub_key: "{{ lookup('ansible.builtin.file', '~/.ssh/id_rsa.pub') }}" + +scenario: sno-veos +scenario_dir: scenarios +stack_template_path: "{{ scenario_dir }}/{{ scenario }}/heat_template.yaml" +automation_vars_file: "{{ scenario_dir }}/{{ scenario }}/automation-vars.yml" +test_operator_automation_vars_file: "{{ scenario_dir }}/{{ scenario }}/test-operator/automation-vars.yml" + +openstack_operators_image: quay.io/openstack-k8s-operators/openstack-operator-index:latest +openstack_operator_channel: alpha +openstack_operator_starting_csv: null + +openshift_version: stable-4.18 + +ntp_servers: [] +dns_servers: + - 8.8.8.8 + - 8.8.4.4 + +pull_secret_file: ~/pull-secret.txt + +ovn_k8s_gateway_config_host_routing: true +enable_iscsi: true +enable_multipath: true + +cinder_volume_pvs: + - /dev/vdc + - /dev/vdd + - /dev/vde + +stack_name: "hs-{{ scenario }}-{{ zuul.build[:8] | default('no-zuul') }}" +stack_parameters: + # On misconfigured clouds, uncomment these to avoid issues. + # Ref: https://access.redhat.com/solutions/7059376 + # net_value_specs: + # mtu: 1442 + dns_servers: "{{ dns_servers }}" + ntp_servers: "{{ ntp_servers }}" + controller_ssh_pub_key: "{{ controller_ssh_pub_key }}" + router_external_network: "{{ os_router_external_network | default('public') }}" + floating_ip_network: "{{ os_floating_network | default('public') }}" + controller_params: + image: hotstack-controller + flavor: hotstack.small + ocp_master_params: + image: ipxe-boot-usb + flavor: hotstack.xxlarge + switch_params: + image: vEOS64-lab-4.34.1F + flavor: hotstack.large + ironic_params: + image: CentOS-Stream-GenericCloud-9 + cd_image: sushy-tools-blank-image + flavor: hotstack.medium + +customContainerImages: + neutronAPIImage: quay.io/steveb/openstack-neutron-server:18.0.9-2.1751380459-ngs diff --git a/scenarios/sno-veos/heat_template.yaml b/scenarios/sno-veos/heat_template.yaml new file mode 100644 index 00000000..06651eb3 --- /dev/null +++ b/scenarios/sno-veos/heat_template.yaml @@ -0,0 +1,977 @@ +--- +heat_template_version: rocky + +description: | + Heat template to set up SNO (Single Node OpenShift) infrastructure, + 1x Controller, 1x OCP Master, 1x Switch, 2x Ironic nodes + +parameters: + dns_servers: + type: comma_delimited_list + default: + - 8.8.8.8 + - 8.8.4.4 + ntp_servers: + type: comma_delimited_list + default: [] + controller_ssh_pub_key: + type: string + dataplane_ssh_pub_key: + type: string + router_external_network: + type: string + default: public + floating_ip_network: + type: string + default: public + net_value_specs: + type: json + default: {} + + controller_params: + type: json + default: + image: hotstack-controller + flavor: hotstack.small + ocp_master_params: + type: json + default: + image: ipxe-boot-usb + flavor: hotstack.xxlarge + ocp_worker_params: + type: json + default: + image: ipxe-boot-usb + flavor: hotstack.xxlarge + compute_params: + type: json + default: + image: CentOS-Stream-GenericCloud-9 + flavor: hotstack.large + networker_params: + type: json + default: + image: CentOS-Stream-GenericCloud-9 + flavor: hotstack.small + bmh_params: + type: json + default: + image: CentOS-Stream-GenericCloud-9 + cd_image: sushy-tools-blank-image + flavor: hotstack.medium + ironic_params: + type: json + default: + image: CentOS-Stream-GenericCloud-9 + cd_image: sushy-tools-blank-image + flavor: hotstack.medium + switch_params: + type: json + default: + image: vEOS-lab-4.34.1F + flavor: hotstack.medium + +resources: + # + # Networks + # + machine-net: + type: OS::Neutron::Net + properties: + port_security_enabled: false + value_specs: {get_param: net_value_specs} + + ctlplane-net: + type: OS::Neutron::Net + properties: + port_security_enabled: false + value_specs: {get_param: net_value_specs} + + internal-api-net: + type: OS::Neutron::Net + properties: + port_security_enabled: false + value_specs: {get_param: net_value_specs} + + storage-net: + type: OS::Neutron::Net + properties: + port_security_enabled: false + value_specs: {get_param: net_value_specs} + + tenant-net: + type: OS::Neutron::Net + properties: + port_security_enabled: false + value_specs: {get_param: net_value_specs} + + ironic-net: + type: OS::Neutron::Net + properties: + port_security_enabled: false + value_specs: {get_param: net_value_specs} + + trunk-net: + type: OS::Neutron::Net + properties: + port_security_enabled: false + value_specs: {get_param: net_value_specs} + + tenant-vlan103: + type: OS::Neutron::Net + properties: + port_security_enabled: false + value_specs: {get_param: net_value_specs} + + tenant-vlan104: + type: OS::Neutron::Net + properties: + port_security_enabled: false + value_specs: {get_param: net_value_specs} + + ironic0-br-net: + type: OS::Neutron::Net + properties: + port_security_enabled: false + value_specs: {get_param: net_value_specs} + + ironic1-br-net: + type: OS::Neutron::Net + properties: + port_security_enabled: false + value_specs: {get_param: net_value_specs} + + + # + # Subnets + # + machine-subnet: + type: OS::Neutron::Subnet + properties: + network: {get_resource: machine-net} + ip_version: 4 + cidr: 192.168.32.0/24 + enable_dhcp: true + dns_nameservers: + - 192.168.32.254 + + ctlplane-subnet: + type: OS::Neutron::Subnet + properties: + network: {get_resource: ctlplane-net} + ip_version: 4 + cidr: 192.168.122.0/24 + enable_dhcp: false + allocation_pools: + - start: 192.168.122.100 + end: 192.168.122.150 + dns_nameservers: + - 192.168.122.80 + + internal-api-subnet: + type: OS::Neutron::Subnet + properties: + network: {get_resource: internal-api-net} + ip_version: 4 + cidr: 172.17.0.0/24 + enable_dhcp: false + allocation_pools: + - start: 172.17.0.100 + end: 172.17.0.150 + + storage-subnet: + type: OS::Neutron::Subnet + properties: + network: {get_resource: storage-net} + ip_version: 4 + cidr: 172.18.0.0/24 + enable_dhcp: false + allocation_pools: + - start: 172.18.0.100 + end: 172.18.0.150 + + tenant-subnet: + type: OS::Neutron::Subnet + properties: + network: {get_resource: tenant-net} + ip_version: 4 + cidr: 172.19.0.0/24 + enable_dhcp: false + allocation_pools: + - start: 172.19.0.100 + end: 172.19.0.150 + + ironic-subnet: + type: OS::Neutron::Subnet + properties: + network: {get_resource: ironic-net} + ip_version: 4 + cidr: 172.20.1.0/24 + enable_dhcp: false + allocation_pools: + - start: 172.20.1.100 + end: 172.20.1.150 + + trunk-subnet: + type: OS::Neutron::Subnet + properties: + network: {get_resource: trunk-net} + ip_version: 4 + cidr: 172.20.2.0/24 + enable_dhcp: false + allocation_pools: + - start: 172.20.2.100 + end: 172.20.2.150 + + tenant-vlan103-subnet: + type: OS::Neutron::Subnet + properties: + network: {get_resource: tenant-vlan103} + ip_version: 4 + cidr: 172.20.3.0/24 + enable_dhcp: false + allocation_pools: + - start: 172.20.3.100 + end: 172.20.3.150 + + tenant-vlan104-subnet: + type: OS::Neutron::Subnet + properties: + network: {get_resource: tenant-vlan104} + ip_version: 4 + cidr: 172.20.4.0/24 + enable_dhcp: false + allocation_pools: + - start: 172.20.4.100 + end: 172.20.4.150 + + ironic0-br-subnet: + type: OS::Neutron::Subnet + properties: + network: {get_resource: ironic0-br-net} + ip_version: 4 + cidr: 172.20.5.0/29 + enable_dhcp: false + gateway_ip: null + + ironic1-br-subnet: + type: OS::Neutron::Subnet + properties: + network: {get_resource: ironic1-br-net} + ip_version: 4 + cidr: 172.20.5.8/29 + enable_dhcp: false + gateway_ip: null + + # + # Routers + # + router: + type: OS::Neutron::Router + properties: + admin_state_up: true + external_gateway_info: + network: {get_param: router_external_network} + # enable_snat: true + + machine-net-router-interface: + type: OS::Neutron::RouterInterface + properties: + router: {get_resource: router} + subnet: {get_resource: machine-subnet} + + ctlplane-net-router-interface: + type: OS::Neutron::RouterInterface + properties: + router: {get_resource: router} + subnet: {get_resource: ctlplane-subnet} + + ironic-net-router-interface: + type: OS::Neutron::RouterInterface + properties: + router: {get_resource: router} + subnet: {get_resource: ironic-subnet} + + tenant-vlan103-router-interface: + type: OS::Neutron::RouterInterface + properties: + router: {get_resource: router} + subnet: {get_resource: tenant-vlan103-subnet} + + tenant-vlan104-router-interface: + type: OS::Neutron::RouterInterface + properties: + router: {get_resource: router} + subnet: {get_resource: tenant-vlan104-subnet} + + # + # Instances + # + controller_users: + type: OS::Heat::CloudConfig + properties: + cloud_config: + users: + - default + - name: zuul + gecos: "Zuul user" + sudo: ALL=(ALL) NOPASSWD:ALL + ssh_authorized_keys: + - {get_param: controller_ssh_pub_key} + + controller-write-files: + type: OS::Heat::CloudConfig + properties: + cloud_config: + write_files: + - path: /etc/dnsmasq.conf + content: | + # dnsmasq service config + # Include all files in /etc/dnsmasq.d except RPM backup files + conf-dir=/etc/dnsmasq.d,.rpmnew,.rpmsave,.rpmorig + no-resolv + owner: root:dnsmasq + - path: /etc/dnsmasq.d/forwarders.conf + content: + str_replace: + template: | + # DNS forwarders records + server=$dns1 + server=$dns2 + params: + $dns1: {get_param: [dns_servers, 0]} + $dns2: {get_param: [dns_servers, 1]} + owner: root:dnsmasq + - path: /etc/dnsmasq.d/host_records.conf + content: + str_replace: + template: | + # Host records + host-record=controller-0.openstack.lab,$controller0 + host-record=nxos.openstack.lab,$nxos0 + host-record=api.sno.openstack.lab,$master0 + host-record=api-int.sno.openstack.lab,$master0 + host-record=master-0.sno.openstack.lab,$master0 + params: + $controller0: {get_attr: [controller-machine-port, fixed_ips, 0, ip_address]} + $nxos0: {get_attr: [switch-machine-port, fixed_ips, 0, ip_address]} + $master0: {get_attr: [master0-machine-port, fixed_ips, 0, ip_address]} + owner: root:dnsmasq + - path: /etc/dnsmasq.d/wildcard_records.conf + content: + str_replace: + template: | + # Wildcard records + address=/apps.sno.openstack.lab/$addr + params: + $addr: {get_attr: [controller-machine-port, fixed_ips, 0, ip_address]} + owner: root:dnsmasq + - path: /etc/resolv.conf + content: | + nameserver: 127.0.0.1 + owner: root:root + - path: /etc/NetworkManager/conf.d/98-rc-manager.conf + content: | + [main] + rc-manager=unmanaged + owner: root:root + - path: /etc/haproxy/haproxy.cfg + content: | + global + log 127.0.0.1 local2 + pidfile /var/run/haproxy.pid + maxconn 4000 + daemon + defaults + mode http + log global + option dontlognull + option http-server-close + option redispatch + retries 3 + timeout http-request 10s + timeout queue 1m + timeout connect 10s + timeout client 1m + timeout server 1m + timeout http-keep-alive 10s + timeout check 10s + maxconn 3000 + listen api-server-6443 + bind *:6443 + mode tcp + server master-0 master-0.sno.openstack.lab:6443 check inter 1s + listen machine-config-server-22623 + bind *:22623 + mode tcp + server master-0 master-0.sno.openstack.lab:22623 check inter 1s + listen ingress-router-443 + bind *:443 + mode tcp + balance source + server master-0 master-0.sno.openstack.lab:443 check inter 1s + listen ingress-router-80 + bind *:80 + mode tcp + balance source + server master-0 master-0.sno.openstack.lab:80 check inter 1s + owner: root:root + - path: /etc/dnsmasq.d/tftpboot.conf + content: | + enable-tftp + tftp-root=/var/lib/tftpboot + tftp-mtu=1442 + owner: root:root + - path: /var/lib/tftpboot/ztp.config + content: {get_file: ztp.config} + owner: root:root + - path: /var/lib/tftpboot/startup-config + content: {get_file: startup-config} + owner: root:root + + controller-runcmd: + type: OS::Heat::CloudConfig + properties: + cloud_config: + runcmd: + - ['setenforce', 'permissive'] + - ['systemctl', 'enable', 'haproxy.service'] + - ['systemctl', 'start', 'haproxy.service'] + - ['sed', '-i', 's/Listen 80/Listen 8081/g', '/etc/httpd/conf/httpd.conf'] + - ['systemctl', 'enable', 'httpd.service'] + - ['systemctl', 'start', 'httpd.service'] + - ['systemctl', 'enable', 'dnsmasq.service'] + - ['systemctl', 'start', 'dnsmasq.service'] + + controller-init: + type: OS::Heat::MultipartMime + properties: + parts: + - config: {get_resource: controller_users} + - config: {get_resource: controller-write-files} + - config: {get_resource: controller-runcmd} + + controller-machine-port: + type: OS::Neutron::Port + properties: + network: {get_resource: machine-net} + mac_address: "fa:16:9e:81:f6:05" + fixed_ips: + - ip_address: 192.168.32.254 + + controller-floating-ip: + depends_on: machine-net-router-interface + type: OS::Neutron::FloatingIP + properties: + floating_network: {get_param: floating_ip_network} + port_id: {get_resource: controller-machine-port} + + controller: + type: OS::Nova::Server + properties: + image: {get_param: [controller_params, image]} + flavor: {get_param: [controller_params, flavor]} + networks: + - port: {get_resource: controller-machine-port} + user_data_format: RAW + user_data: {get_resource: controller-init} + + # OCP Masters + + # DHCP Opts value + extra-dhcp-opts-value: + type: OS::Heat::Value + properties: + type: json + value: + extra_dhcp_opts: + - opt_name: "60" + opt_value: "HTTPClient" + ip_version: 4 + - opt_name: "67" + opt_value: + str_replace: + template: http://$server_address:8081/boot-artifacts/agent.x86_64.ipxe + params: + $server_address: {get_attr: [controller-machine-port, fixed_ips, 0, ip_address]} + + master0-machine-port: + type: OS::Neutron::Port + properties: + network: {get_resource: machine-net} + port_security_enabled: false + mac_address: "fa:16:9e:81:f6:10" + fixed_ips: + - ip_address: 192.168.32.10 + value_specs: {get_attr: [extra-dhcp-opts-value, value]} + + master0-ctlplane-trunk-parent-port: + type: OS::Neutron::Port + properties: + network: {get_resource: ctlplane-net} + port_security_enabled: false + fixed_ips: + - ip_address: 192.168.122.10 + + master0-internal-api-port: + type: OS::Neutron::Port + properties: + network: {get_resource: internal-api-net} + port_security_enabled: false + fixed_ips: + - ip_address: 172.17.0.10 + + master0-storage-port: + type: OS::Neutron::Port + properties: + network: {get_resource: storage-net} + port_security_enabled: false + fixed_ips: + - ip_address: 172.18.0.10 + + master0-tenant-port: + type: OS::Neutron::Port + properties: + network: {get_resource: tenant-net} + port_security_enabled: false + fixed_ips: + - ip_address: 172.19.0.10 + + master0-trunk0: + type: OS::Neutron::Trunk + properties: + port: {get_resource: master0-ctlplane-trunk-parent-port} + sub_ports: + - port: {get_resource: master0-internal-api-port} + segmentation_id: 20 + segmentation_type: vlan + - port: {get_resource: master0-storage-port} + segmentation_id: 21 + segmentation_type: vlan + - port: {get_resource: master0-tenant-port} + segmentation_id: 22 + segmentation_type: vlan + + master0-ironic-trunk-parent-port: + type: OS::Neutron::Port + properties: + network: {get_resource: trunk-net} + port_security_enabled: false + fixed_ips: + - ip_address: 172.20.2.10 + + master0-ironic-subport: + type: OS::Neutron::Port + properties: + network: {get_resource: ironic-net} + port_security_enabled: false + fixed_ips: + - ip_address: 172.20.1.10 + + master0-tenant-vlan103-subport: + type: OS::Neutron::Port + properties: + network: {get_resource: tenant-vlan103} + port_security_enabled: false + fixed_ips: + - ip_address: 172.20.3.10 + + master0-tenant-vlan104-subport: + type: OS::Neutron::Port + properties: + network: {get_resource: tenant-vlan104} + port_security_enabled: false + fixed_ips: + - ip_address: 172.20.4.10 + + master0-ironic-trunk: + type: OS::Neutron::Trunk + properties: + port: {get_resource: master0-ironic-trunk-parent-port} + sub_ports: + - port: {get_resource: master0-ironic-subport} + segmentation_id: 101 + segmentation_type: vlan + - port: {get_resource: master0-tenant-vlan103-subport} + segmentation_id: 103 + segmentation_type: vlan + - port: {get_resource: master0-tenant-vlan104-subport} + segmentation_id: 104 + segmentation_type: vlan + + master0-lvms-vol0: + type: OS::Cinder::Volume + properties: + size: 20 + + master0-cinder-vol0: + type: OS::Cinder::Volume + properties: + size: 20 + + master0-cinder-vol1: + type: OS::Cinder::Volume + properties: + size: 20 + + master0-cinder-vol2: + type: OS::Cinder::Volume + properties: + size: 20 + + master0: + type: OS::Nova::Server + properties: + image: {get_param: [ocp_master_params, image]} + flavor: {get_param: [ocp_master_params, flavor]} + block_device_mapping_v2: + - boot_index: -1 + device_type: disk + volume_id: {get_resource: master0-lvms-vol0} + - boot_index: -1 + device_type: disk + volume_id: {get_resource: master0-cinder-vol0} + - boot_index: -1 + device_type: disk + volume_id: {get_resource: master0-cinder-vol1} + - boot_index: -1 + device_type: disk + volume_id: {get_resource: master0-cinder-vol2} + networks: + - port: {get_resource: master0-machine-port} + - port: {get_attr: [master0-trunk0, port_id]} + - port: {get_attr: [master0-ironic-trunk, port_id]} + + # + # Switch + # + + switch-extra-dhcp-opts-value: + type: OS::Heat::Value + properties: + type: json + value: + extra_dhcp_opts: + - opt_name: "66" + opt_value: + str_replace: + template: "$server_address" + params: + $server_address: {get_attr: [controller-machine-port, fixed_ips, 0, ip_address]} + ip_version: 4 + - opt_name: "67" + opt_value: "ztp.config" + ip_version: 4 + + switch-machine-port: + type: OS::Neutron::Port + properties: + network: {get_resource: machine-net} + port_security_enabled: false + mac_address: "22:57:f8:dd:fe:ab" + fixed_ips: + - ip_address: 192.168.32.6 + value_specs: {get_attr: [switch-extra-dhcp-opts-value, value]} + + switch-trunk-parent-port: + type: OS::Neutron::Port + properties: + network: {get_resource: trunk-net} + port_security_enabled: false + mac_address: "22:57:f8:dd:fe:08" + + switch-trunk-ironic-port: + type: OS::Neutron::Port + properties: + network: {get_resource: ironic-net} + port_security_enabled: false + mac_address: "22:57:f8:dd:fe:09" + + switch-trunk-tenant-vlan103-port: + type: OS::Neutron::Port + properties: + network: {get_resource: tenant-vlan103} + port_security_enabled: false + mac_address: "22:57:f8:dd:fe:0a" + + switch-trunk-tenant-vlan104-port: + type: OS::Neutron::Port + properties: + network: {get_resource: tenant-vlan104} + port_security_enabled: false + mac_address: "22:57:f8:dd:fe:0b" + + switch-trunk: + type: OS::Neutron::Trunk + properties: + port: {get_resource: switch-trunk-parent-port} + sub_ports: + # Ironic VLAN + - port: {get_resource: switch-trunk-ironic-port} + segmentation_id: 101 + segmentation_type: vlan + # Tenant VLANs + - port: {get_resource: switch-trunk-tenant-vlan103-port} + segmentation_id: 103 + segmentation_type: vlan + - port: {get_resource: switch-trunk-tenant-vlan104-port} + segmentation_id: 104 + segmentation_type: vlan + + switch-ironic0-br-port: + type: OS::Neutron::Port + properties: + network: {get_resource: ironic0-br-net} + port_security_enabled: false + mac_address: "22:57:f8:dd:fe:0c" + + switch-ironic1-br-port: + type: OS::Neutron::Port + properties: + network: {get_resource: ironic1-br-net} + port_security_enabled: false + mac_address: "22:57:f8:dd:fe:0d" + + switch: + type: OS::Nova::Server + properties: + image: {get_param: [switch_params, image]} + flavor: {get_param: [switch_params, flavor]} + config_drive: false + diskConfig: MANUAL + networks: + - port: {get_resource: switch-machine-port} + - port: {get_attr: [switch-trunk, port_id]} + - port: {get_resource: switch-ironic0-br-port} + - port: {get_resource: switch-ironic1-br-port} + + # + # Ironics + # + ironic0-port: + type: OS::Neutron::Port + properties: + network: {get_resource: ironic0-br-net} + port_security_enabled: false + + ironic0: + type: OS::Nova::Server + properties: + flavor: {get_param: [ironic_params, flavor]} + block_device_mapping_v2: + - device_type: disk + boot_index: 1 + image_id: {get_param: [ironic_params, image]} + volume_size: 40 + delete_on_termination: true + - device_type: cdrom + disk_bus: scsi + boot_index: 0 + image_id: {get_param: [ironic_params, cd_image]} + volume_size: 5 + delete_on_termination: true + networks: + - port: {get_resource: ironic0-port} + + ironic1-port: + type: OS::Neutron::Port + properties: + network: {get_resource: ironic1-br-net} + port_security_enabled: false + + ironic1: + type: OS::Nova::Server + properties: + flavor: {get_param: [ironic_params, flavor]} + block_device_mapping_v2: + - device_type: disk + boot_index: 1 + image_id: {get_param: [ironic_params, image]} + volume_size: 40 + delete_on_termination: true + - device_type: cdrom + disk_bus: scsi + boot_index: 0 + image_id: {get_param: [ironic_params, cd_image]} + volume_size: 5 + delete_on_termination: true + networks: + - port: {get_resource: ironic1-port} + + +outputs: + controller_floating_ip: + description: Controller Floating IP + value: {get_attr: [controller-floating-ip, floating_ip_address]} + controller_ansible_host: + description: > + Controller ansible host, this struct can be passed to the ansible.builtin.add_host module + value: + name: controller-0 + ansible_ssh_user: zuul + ansible_host: {get_attr: [controller-floating-ip, floating_ip_address]} + ansible_ssh_common_args: '-o StrictHostKeyChecking=no' + groups: controllers + + sushy_emulator_uuids: + description: UUIDs of instances to manage with sushy-tools - RedFish virtual BMC + value: + ironic0: {get_resource: ironic0} + ironic1: {get_resource: ironic1} + + ironic_nodes: + description: Ironic nodes YAML, used with openstack baremetal create to enroll nodes in Openstack Ironic + value: + nodes: + - name: ironic0 + driver: redfish + bios_interface: no-bios + boot_interface: redfish-virtual-media + driver_info: + redfish_address: http://sushy-emulator.apps.sno.openstack.lab + redfish_system_id: + str_replace: + template: "/redfish/v1/Systems/$SYS_ID" + params: + $SYS_ID: {get_resource: ironic0} + redfish_username: admin + redfish_password: password + ports: + - address: {get_attr: [ironic0-port, mac_address]} + physical_network: ironic + local_link_connection: + switch_info: veos.openstack.lab + switch_id: "22:dd:fe:ab:1b:08" + port_id: "ethernet2" + - name: ironic1 + driver: redfish + bios_interface: no-bios + boot_interface: redfish-virtual-media + driver_info: + redfish_address: http://sushy-emulator.apps.sno.openstack.lab + redfish_system_id: + str_replace: + template: "/redfish/v1/Systems/$SYS_ID" + params: + $SYS_ID: {get_resource: ironic1} + redfish_username: admin + redfish_password: password + ports: + - address: {get_attr: [ironic1-port, mac_address]} + physical_network: ironic + local_link_connection: + switch_info: veos.openstack.lab + switch_id: "22:dd:fe:ab:1b:08" + port_id: "ethernet3" + + ocp_install_config: + description: OCP install-config.yaml + value: + apiVersion: v1 + baseDomain: openstack.lab + controlPlane: + architecture: amd64 + hyperthreading: Disabled + name: master + replicas: 1 + compute: + - architecture: amd64 + hyperthreading: Disabled + name: worker + replicas: 0 + metadata: + name: sno + networking: + clusterNetwork: + - cidr: 10.128.0.0/16 + hostPrefix: 23 + machineNetwork: + - cidr: {get_attr: [machine-subnet, cidr]} + serviceNetwork: + - 172.30.0.0/16 + networkType: OVNKubernetes + platform: + none: {} + pullSecret: _replaced_ + sshKey: {get_param: dataplane_ssh_pub_key} + + ocp_agent_config: + description: OCP agent-config.yaml + value: + apiVersion: v1beta1 + kind: AgentConfig + metadata: + name: sno + rendezvousIP: {get_attr: [master0-machine-port, fixed_ips, 0, ip_address]} + additionalNTPSources: {get_param: ntp_servers} + bootArtifactsBaseURL: + str_replace: + template: http://$server_address:8081/boot-artifacts + params: + $server_address: {get_attr: [controller-machine-port, fixed_ips, 0, ip_address]} + hosts: + - hostname: master-0 + role: master + interfaces: + - name: eth0 + macAddress: {get_attr: [master0-machine-port, mac_address]} + - name: eth1 + macAddress: {get_attr: [master0-ctlplane-trunk-parent-port, mac_address]} + - name: eth2 + macAddress: {get_attr: [master0-ironic-trunk-parent-port, mac_address]} + networkConfig: + interfaces: + - name: eth0 + type: ethernet + state: up + mac-address: {get_attr: [master0-machine-port, mac_address]} + ipv4: + enabled: true + dhcp: true + ipv6: + enabled: false + - name: eth1 + type: ethernet + state: down + mac-address: {get_attr: [master0-ctlplane-trunk-parent-port, mac_address]} + - name: eth2 + type: ethernet + state: down + mac-address: {get_attr: [master0-ironic-trunk-parent-port, mac_address]} + + ansible_inventory: + description: Ansible inventory + value: + all: + children: + controllers: + vars: + ocps: + vars: + switches: + vars: + localhosts: + hosts: + localhost: + ansible_connection: local + controllers: + hosts: + controller0: + ansible_host: {get_attr: [controller-machine-port, fixed_ips, 0, ip_address]} + ansible_user: zuul + ansible_ssh_common_args: '-o StrictHostKeyChecking=no' + ansible_ssh_private_key_file: '~/.ssh/id_rsa' + ocps: + hosts: + master0: + ansible_host: {get_attr: [master0-machine-port, fixed_ips, 0, ip_address]} + ansible_user: core + ansible_ssh_common_args: '-o StrictHostKeyChecking=no' + ansible_ssh_private_key_file: '~/.ssh/id_rsa' + switches: + hosts: + switch0: + ansible_host: {get_attr: [switch-machine-port, fixed_ips, 0, ip_address]} + ansible_user: admin + ansible_ssh_common_args: '-o StrictHostKeyChecking=no' + ansible_ssh_private_key_file: '~/.ssh/id_rsa' diff --git a/scenarios/sno-veos/manifests/control-plane.yaml b/scenarios/sno-veos/manifests/control-plane.yaml new file mode 100644 index 00000000..173bcf1a --- /dev/null +++ b/scenarios/sno-veos/manifests/control-plane.yaml @@ -0,0 +1,493 @@ +--- +apiVersion: v1 +data: + server-ca-passphrase: MTIzNDU2Nzg= +kind: Secret +metadata: + name: octavia-ca-passphrase + namespace: openstack +type: Opaque +--- +apiVersion: v1 +data: + AdminPassword: MTIzNDU2Nzg= + AodhDatabasePassword: MTIzNDU2Nzg= + AodhPassword: MTIzNDU2Nzg= + BarbicanDatabasePassword: MTIzNDU2Nzg= + BarbicanPassword: MTIzNDU2Nzg= + BarbicanSimpleCryptoKEK: r0wDZ1zrD5upafX9RDfYqvDkW2LENBWH7Gz9+Tr3NdM= + CeilometerPassword: MTIzNDU2Nzg= + CinderDatabasePassword: MTIzNDU2Nzg= + CinderPassword: MTIzNDU2Nzg= + DatabasePassword: MTIzNDU2Nzg= + DbRootPassword: MTIzNDU2Nzg= + DesignateDatabasePassword: MTIzNDU2Nzg= + DesignatePassword: MTIzNDU2Nzg= + GlanceDatabasePassword: MTIzNDU2Nzg= + GlancePassword: MTIzNDU2Nzg= + HeatAuthEncryptionKey: NzY3YzNlZDA1NmNiYWEzYjlkZmVkYjhjNmY4MjViZjA= + HeatDatabasePassword: MTIzNDU2Nzg= + HeatPassword: MTIzNDU2Nzg= + IronicDatabasePassword: MTIzNDU2Nzg= + IronicInspectorDatabasePassword: MTIzNDU2Nzg= + IronicInspectorPassword: MTIzNDU2Nzg= + IronicPassword: MTIzNDU2Nzg= + KeystoneDatabasePassword: MTIzNDU2Nzg= + ManilaDatabasePassword: MTIzNDU2Nzg= + ManilaPassword: MTIzNDU2Nzg= + MetadataSecret: MTIzNDU2Nzg0Mg== + NeutronDatabasePassword: MTIzNDU2Nzg= + NeutronPassword: MTIzNDU2Nzg= + NovaAPIDatabasePassword: MTIzNDU2Nzg= + NovaCell0DatabasePassword: MTIzNDU2Nzg= + NovaCell1DatabasePassword: MTIzNDU2Nzg= + NovaPassword: MTIzNDU2Nzg= + OctaviaDatabasePassword: MTIzNDU2Nzg= + OctaviaHeartbeatKey: MTIzNDU2Nzg= + OctaviaPassword: MTIzNDU2Nzg= + PlacementDatabasePassword: MTIzNDU2Nzg= + PlacementPassword: MTIzNDU2Nzg= + SwiftPassword: MTIzNDU2Nzg= +kind: Secret +metadata: + name: osp-secret + namespace: openstack +type: Opaque +--- +apiVersion: core.openstack.org/v1beta1 +kind: OpenStackControlPlane +metadata: + name: controlplane + namespace: openstack +spec: + barbican: + enabled: false + ceilometer: + enabled: false + cinder: + apiOverride: + route: + haproxy.router.openshift.io/timeout: 60s + template: + cinderAPI: + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer + replicas: 1 + cinderBackup: + customServiceConfig: | + [DEFAULT] + backup_driver = cinder.backup.drivers.swift.SwiftBackupDriver + networkAttachments: + - storage + replicas: 1 + cinderScheduler: + replicas: 1 + cinderVolumes: + lvm-iscsi: + customServiceConfig: | + [lvm] + image_volume_cache_enabled = false + volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver + volume_group = cinder-volumes + target_protocol = iscsi + target_helper = lioadm + volume_backend_name = lvm_iscsi + target_ip_address=172.18.0.10 + target_secondary_ip_addresses = 172.19.0.10 + nodeSelector: + openstack.org/cinder-lvm: "" + replicas: 1 + customServiceConfig: | + # Debug logs by default, jobs can override as needed. + [DEFAULT] + debug = true + databaseInstance: openstack + preserveJobs: false + secret: osp-secret + uniquePodNames: true + designate: + enabled: false + dns: + template: + options: + - key: server + values: + - 192.168.32.254 + override: + service: + metadata: + annotations: + metallb.universe.tf/address-pool: ctlplane + metallb.universe.tf/allow-shared-ip: ctlplane + metallb.universe.tf/loadBalancerIPs: 192.168.122.80 + spec: + type: LoadBalancer + replicas: 1 + galera: + enabled: true + templates: + openstack: + replicas: 1 + secret: osp-secret + storageRequest: 5G + openstack-cell1: + replicas: 1 + secret: osp-secret + storageRequest: 5G + glance: + apiOverrides: + default: + route: + haproxy.router.openshift.io/timeout: 60s + template: + customServiceConfig: | + [DEFAULT] + debug = True + enabled_backends = default_backend:swift + + [glance_store] + default_backend = default_backend + + [default_backend] + swift_store_create_container_on_put = True + swift_store_auth_version = 3 + swift_store_auth_address = {{ .KeystoneInternalURL }} + swift_store_endpoint_type = internalURL + swift_store_user = service:glance + swift_store_key = {{ .ServicePassword }} + databaseInstance: openstack + glanceAPIs: + default: + networkAttachments: + - storage + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer + replicas: 3 + preserveJobs: false + storage: + storageClass: lvms-local-storage + storageRequest: 10G + uniquePodNames: true + heat: + enabled: false + horizon: + enabled: false + ironic: + enabled: true + template: + databaseInstance: openstack + ironicAPI: + customServiceConfig: | + [DEFAULT] + default_network_interface=neutron + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: ctlplane + metallb.universe.tf/allow-shared-ip: ctlplane + metallb.universe.tf/loadBalancerIPs: 192.168.122.80 + spec: + type: LoadBalancer + replicas: 1 + ironicConductors: + - customServiceConfig: | + [DEFAULT] + default_network_interface=neutron + + [conductor] + power_state_change_timeout = 120 + + [pxe] + kernel_append_params = console=ttyS0 + + [neutron] + cleaning_network = provisioning + provisioning_network = provisioning + rescuing_network = provisioning + inspection_network = provisioning + networkAttachments: + - ironic + provisionNetwork: ironic + replicas: 1 + storageRequest: 10G + ironicInspector: + customServiceConfig: | + [capabilities] + boot_mode = true + + [processing] + update_pxe_enabled = false + inspectionNetwork: ironic + networkAttachments: + - ironic + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: ctlplane + metallb.universe.tf/allow-shared-ip: ctlplane + metallb.universe.tf/loadBalancerIPs: 192.168.122.80 + spec: + type: LoadBalancer + preserveJobs: false + replicas: 1 + ironicNeutronAgent: + replicas: 1 + preserveJobs: false + rpcTransport: oslo + secret: osp-secret + keystone: + apiOverride: + route: {} + template: + databaseInstance: openstack + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer + preserveJobs: false + replicas: 3 + secret: osp-secret + manila: + enabled: false + memcached: + templates: + memcached: + replicas: 1 + neutron: + apiOverride: + route: {} + template: + customServiceConfig: | + [DEFAULT] + vlan_transparent = true + agent_down_time = 600 + router_distributed = true + router_scheduler_driver = neutron.scheduler.l3_agent_scheduler.ChanceScheduler + allow_automatic_l3agent_failover = true + debug = true + + [agent] + report_interval = 300 + + [database] + max_retries = -1 + db_max_retries = -1 + + [keystone_authtoken] + region_name = regionOne + memcache_use_advanced_pool = True + + [oslo_messaging_notifications] + driver = noop + + [oslo_middleware] + enable_proxy_headers_parsing = true + + [oslo_policy] + policy_file = /etc/neutron/policy.yaml + + [ovs] + igmp_snooping_enable = true + + [ovn] + ovsdb_probe_interval = 60000 + ovn_emit_need_to_frag = true + + [ml2] + global_physnet_mtu = 1442 + type_drivers = geneve,vxlan,vlan,flat,local + tenant_network_types = geneve,flat + databaseInstance: openstack + extraMounts: + - name: switchConf + extraVol: + - volumes: + - name: neutron-switch-config + secret: + secretName: neutron-switch-config + mounts: + - name: neutron-switch-config + mountPath: /etc/neutron/neutron.conf.d/03-ml2-genericswitch.conf + subPath: 03-ml2-genericswitch.conf + readOnly: true + ml2MechanismDrivers: + - genericswitch + - baremetal + - ovn + networkAttachments: + - internalapi + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer + preserveJobs: false + replicas: 1 + secret: osp-secret + nova: + apiOverride: + route: {} + template: + apiServiceTemplate: + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer + replicas: 1 + cellTemplates: + cell0: + cellDatabaseAccount: nova-cell0 + cellDatabaseInstance: openstack + cellMessageBusInstance: rabbitmq + hasAPIAccess: true + cell1: + cellDatabaseAccount: nova-cell1 + cellDatabaseInstance: openstack-cell1 + cellMessageBusInstance: rabbitmq-cell1 + hasAPIAccess: true + novaComputeTemplates: + compute-ironic: + computeDriver: ironic.IronicDriver + metadataServiceTemplate: + override: + service: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer + replicas: 1 + preserveJobs: false + schedulerServiceTemplate: + replicas: 1 + secret: osp-secret + octavia: + enabled: false + ovn: + template: + ovnController: + networkAttachment: tenant + nicMappings: + datacentre: ocpbr + ironic: ironicbr + ovnDBCluster: + ovndbcluster-nb: + dbType: NB + networkAttachment: internalapi + replicas: 1 + storageRequest: 10G + ovndbcluster-sb: + dbType: SB + networkAttachment: internalapi + replicas: 1 + storageRequest: 10G + ovnNorthd: + logLevel: info + nThreads: 1 + replicas: 1 + resources: {} + tls: {} + placement: + apiOverride: + route: {} + template: + databaseInstance: openstack + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer + preserveJobs: false + replicas: 1 + secret: osp-secret + rabbitmq: + templates: + rabbitmq: + override: + service: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.85 + spec: + type: LoadBalancer + replicas: 1 + rabbitmq-cell1: + override: + service: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.86 + spec: + type: LoadBalancer + replicas: 1 + secret: osp-secret + storageClass: lvms-local-storage + swift: + enabled: true + proxyOverride: + route: {} + template: + swiftProxy: + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer + replicas: 1 + swiftRing: + ringReplicas: 1 + swiftStorage: + replicas: 1 + telemetry: + enabled: false diff --git a/scenarios/sno-veos/manifests/networking/metallb.yaml b/scenarios/sno-veos/manifests/networking/metallb.yaml new file mode 100644 index 00000000..a71f9d48 --- /dev/null +++ b/scenarios/sno-veos/manifests/networking/metallb.yaml @@ -0,0 +1,88 @@ +--- +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + labels: + osp/lb-addresses-type: standard + name: ctlplane + namespace: metallb-system +spec: + addresses: + - 192.168.122.80-192.168.122.90 +--- +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + labels: + osp/lb-addresses-type: standard + name: internalapi + namespace: metallb-system +spec: + addresses: + - 172.17.0.80-172.17.0.90 +--- +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + labels: + osp/lb-addresses-type: standard + name: storage + namespace: metallb-system +spec: + addresses: + - 172.18.0.80-172.18.0.90 +--- +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + labels: + osp/lb-addresses-type: standard + name: tenant + namespace: metallb-system +spec: + addresses: + - 172.19.0.80-172.19.0.90 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: ctlplane + namespace: metallb-system +spec: + interfaces: + - ospbr + ipAddressPools: + - ctlplane +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: internalapi + namespace: metallb-system +spec: + interfaces: + - internalapi + ipAddressPools: + - internalapi +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: storage + namespace: metallb-system +spec: + interfaces: + - storage + ipAddressPools: + - storage +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: tenant + namespace: metallb-system +spec: + interfaces: + - tenant + ipAddressPools: + - tenant diff --git a/scenarios/sno-veos/manifests/networking/nad.yaml b/scenarios/sno-veos/manifests/networking/nad.yaml new file mode 100644 index 00000000..fa5e8f71 --- /dev/null +++ b/scenarios/sno-veos/manifests/networking/nad.yaml @@ -0,0 +1,134 @@ +--- +apiVersion: k8s.cni.cncf.io/v1 +kind: NetworkAttachmentDefinition +metadata: + labels: + osp/net: ctlplane + osp/net-attach-def-type: standard + name: ctlplane + namespace: openstack +spec: + config: | + { + "cniVersion": "0.3.1", + "name": "ctlplane", + "type": "macvlan", + "master": "ospbr", + "ipam": { + "type": "whereabouts", + "range": "192.168.122.0/24", + "range_start": "192.168.122.30", + "range_end": "192.168.122.70" + } + } +--- +apiVersion: k8s.cni.cncf.io/v1 +kind: NetworkAttachmentDefinition +metadata: + labels: + osp/net: ironic + osp/net-attach-def-type: standard + name: ironic + namespace: openstack +spec: + config: | + { + "cniVersion": "0.3.1", + "name": "ironic", + "type": "bridge", + "bridge": "ironic", + "mtu": 1442, + "ipam": { + "type": "whereabouts", + "range": "172.20.1.0/24", + "range_start": "172.20.1.30", + "range_end": "172.20.1.70" + } + } +--- +apiVersion: k8s.cni.cncf.io/v1 +kind: NetworkAttachmentDefinition +metadata: + labels: + osp/net: datacentre + osp/net-attach-def-type: standard + name: datacentre + namespace: openstack +spec: + config: | + { + "cniVersion": "0.3.1", + "name": "datacentre", + "type": "bridge", + "bridge": "ospbr", + "ipam": {} + } +--- +apiVersion: k8s.cni.cncf.io/v1 +kind: NetworkAttachmentDefinition +metadata: + labels: + osp/net: internalapi + osp/net-attach-def-type: standard + name: internalapi + namespace: openstack +spec: + config: | + { + "cniVersion": "0.3.1", + "name": "internalapi", + "type": "macvlan", + "master": "internalapi", + "ipam": { + "type": "whereabouts", + "range": "172.17.0.0/24", + "range_start": "172.17.0.30", + "range_end": "172.17.0.70" + } + } +--- +apiVersion: k8s.cni.cncf.io/v1 +kind: NetworkAttachmentDefinition +metadata: + labels: + osp/net: storage + osp/net-attach-def-type: standard + name: storage + namespace: openstack +spec: + config: | + { + "cniVersion": "0.3.1", + "name": "storage", + "type": "macvlan", + "master": "storage", + "ipam": { + "type": "whereabouts", + "range": "172.18.0.0/24", + "range_start": "172.18.0.30", + "range_end": "172.18.0.70" + } + } +--- +apiVersion: k8s.cni.cncf.io/v1 +kind: NetworkAttachmentDefinition +metadata: + labels: + osp/net: tenant + osp/net-attach-def-type: standard + name: tenant + namespace: openstack +spec: + config: | + { + "cniVersion": "0.3.1", + "name": "tenant", + "type": "macvlan", + "master": "tenant", + "ipam": { + "type": "whereabouts", + "range": "172.19.0.0/24", + "range_start": "172.19.0.30", + "range_end": "172.19.0.70" + } + } diff --git a/scenarios/sno-veos/manifests/networking/netconfig.yaml b/scenarios/sno-veos/manifests/networking/netconfig.yaml new file mode 100644 index 00000000..637d66d3 --- /dev/null +++ b/scenarios/sno-veos/manifests/networking/netconfig.yaml @@ -0,0 +1,50 @@ +--- +apiVersion: network.openstack.org/v1beta1 +kind: NetConfig +metadata: + name: netconfig + namespace: openstack +spec: + networks: + - dnsDomain: ctlplane.openstack.lab + mtu: 1442 + name: ctlplane + subnets: + - allocationRanges: + - end: 192.168.122.120 + start: 192.168.122.100 + - end: 192.168.122.200 + start: 192.168.122.150 + cidr: 192.168.122.0/24 + gateway: 192.168.122.1 + name: subnet1 + - dnsDomain: internalapi.openstack.lab + mtu: 1442 + name: internalapi + subnets: + - allocationRanges: + - end: 172.17.0.250 + start: 172.17.0.100 + cidr: 172.17.0.0/24 + name: subnet1 + vlan: 20 + - dnsDomain: storage.openstack.lab + mtu: 1442 + name: storage + subnets: + - allocationRanges: + - end: 172.18.0.250 + start: 172.18.0.100 + cidr: 172.18.0.0/24 + name: subnet1 + vlan: 21 + - dnsDomain: tenant.openstack.lab + mtu: 1442 + name: tenant + subnets: + - allocationRanges: + - end: 172.19.0.250 + start: 172.19.0.100 + cidr: 172.19.0.0/24 + name: subnet1 + vlan: 22 diff --git a/scenarios/sno-veos/manifests/networking/nncp.yaml b/scenarios/sno-veos/manifests/networking/nncp.yaml new file mode 100644 index 00000000..8ca2c42c --- /dev/null +++ b/scenarios/sno-veos/manifests/networking/nncp.yaml @@ -0,0 +1,136 @@ +--- +apiVersion: nmstate.io/v1 +kind: NodeNetworkConfigurationPolicy +metadata: + labels: + osp/nncm-config-type: standard + name: master-0 + namespace: openstack +spec: + desiredState: + dns-resolver: + config: + search: [] + server: + - 192.168.32.254 + interfaces: + - name: internalapi + type: vlan + description: internalapi vlan interface + ipv4: + address: + - ip: 172.17.0.10 + prefix-length: "24" + dhcp: false + enabled: true + ipv6: + enabled: false + mtu: 1442 + state: up + vlan: + base-iface: eth1 + id: "20" + - name: storage + type: vlan + description: storage vlan interface + ipv4: + address: + - ip: 172.18.0.10 + prefix-length: "24" + dhcp: false + enabled: true + ipv6: + enabled: false + mtu: 1442 + state: up + vlan: + base-iface: eth1 + id: "21" + - name: tenant + type: vlan + description: tenant vlan interface + ipv4: + address: + - ip: 172.19.0.10 + prefix-length: "24" + dhcp: false + enabled: true + ipv6: + enabled: false + mtu: 1442 + state: up + vlan: + base-iface: eth1 + id: "22" + - description: ctlplane interface + mtu: 1442 + name: eth1 + state: up + type: ethernet + - name: ospbr + type: linux-bridge + description: linux-bridge over ctlplane interface + bridge: + options: + stp: + enabled: false + port: + - name: eth1 + vlan: {} + ipv4: + address: + - ip: 192.168.122.10 + prefix-length: "24" + dhcp: false + enabled: true + ipv6: + enabled: false + mtu: 1442 + state: up + - description: ironic interface + mtu: 1442 + name: eth2 + state: up + type: ethernet + - name: ironic + type: linux-bridge + description: ironic-bridge + bridge: + options: + stp: + enabled: false + port: + - name: eth2 + vlan: + mode: trunk + trunk-tags: + - id: 102 + - id: 103 + - id: 104 + tag: 101 + enable-native: true + ipv4: + address: + - ip: 172.20.1.10 + prefix-length: "24" + dhcp: false + enabled: true + ipv6: + enabled: false + mtu: 1442 + route-rules: + config: [] + routes: + config: + - destination: 172.20.3.0/24 + next-hop-address: 172.20.1.1 + next-hop-interface: ironic + table-id: 254 + - destination: 172.20.4.0/24 + next-hop-address: 172.20.1.1 + next-hop-interface: ironic + table-id: 254 + + nodeSelector: + kubernetes.io/hostname: master-0 + node-role.kubernetes.io/worker: "" diff --git a/scenarios/sno-veos/manifests/ngs/config.yaml b/scenarios/sno-veos/manifests/ngs/config.yaml new file mode 100644 index 00000000..661f1be2 --- /dev/null +++ b/scenarios/sno-veos/manifests/ngs/config.yaml @@ -0,0 +1,32 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: neutron-switch-config + namespace: openstack +stringData: + 03-ml2-genericswitch.conf: | + [ngs] + session_log_file = /var/log/neutron/ngs.log + + [ml2] + tenant_network_types = geneve,vlan,flat + + [ml2_type_vlan] + network_vlan_ranges = datacentre,ironic:100:120 + + [genericswitch:nxos] + device_type = netmiko_arista_eos + ngs_mac_address = 22:dd:fe:aa:1b:08 + # 101 = ironic + # 102 = tenant-vlan102 (native vlan) + # 103 = tenant-vlan103 + # 104 = tenant-vlan104 + ngs_allowed_vlans = 101,102,103,104 + ngs_port_default_vlan = 102 + ngs_trunk_ports = ethernet1/1 + ngs_physical_networks = ironic + ip = veos.openstack.lab + username = admin + password = password +type: Opaque diff --git a/scenarios/sno-veos/manifests/openstack-version.yaml b/scenarios/sno-veos/manifests/openstack-version.yaml new file mode 100644 index 00000000..f4e8c47e --- /dev/null +++ b/scenarios/sno-veos/manifests/openstack-version.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: core.openstack.org/v1beta1 +kind: OpenStackVersion +metadata: + name: controlplane + namespace: openstack +spec: + customContainerImages: {} diff --git a/scenarios/sno-veos/startup-config b/scenarios/sno-veos/startup-config new file mode 100644 index 00000000..82e944d8 --- /dev/null +++ b/scenarios/sno-veos/startup-config @@ -0,0 +1,34 @@ +hostname veos.openstack.lab + +username admin password password privilege 15 + +interface Management1 + description ZTP_Management_Interface + ip address 192.168.32.6/24 + no shutdown + +ip route 0.0.0.0/0 192.168.32.1 + +feature ssh +ssh key rsa 2048 + +vlan 102 + name Native VLAN + +interface Ethernet1 + description Trunk port + switchport mode trunk + switchport trunk allowed vlan 101,102,103,104 + no shutdown + +interface Ethernet2 + description Access port ironic0 + switchport mode access + switchport access vlan 102 + no shutdown + +interface Ethernet2 + description Access port ironic1 + switchport mode access + switchport access vlan 102 + no shutdown diff --git a/scenarios/sno-veos/test-operator/README.md b/scenarios/sno-veos/test-operator/README.md new file mode 100644 index 00000000..dc44ea00 --- /dev/null +++ b/scenarios/sno-veos/test-operator/README.md @@ -0,0 +1,42 @@ + +# AI generated README + +## Tempest Tests Configuration for Test Operator + +The YAML file, `tempest-tests.yml`, is a configuration for running Tempest +tests, which is a validation framework for OpenStack. Here's a breakdown of the +configuration: + +1. **apiVersion, kind, and metadata**: These fields define the API version, + kind (type) of resource, and metadata (name and namespace) for the Tempest + test job. + +2. **spec**: This section contains the configuration for the Tempest test job. + + - **networkAttachments**: This field specifies the network attachment for + the test job. In this case, it's set to `ctlplane`. + - **storageClass**: This field sets the storage class for the test job to + `lvms-local-storage`. + - **privileged**: This field is set to `true`, which means the test + containers will have elevated privileges. + - **workflow**: This section defines the steps to be executed in the test + job. There are two steps in this configuration: + - **ironic-scenario-testing**: This step runs scenario tests for Ironic, + the OpenStack bare-metal provisioning service. The `tempestconfRun` + section configures Tempest settings for this step, such as disabling + isolated networks, setting the number of available nodes, and specifying + the compute flavor and hypervisor type. The `tempestRun` section + specifies the concurrency level and the list of tests to include and + exclude. + - **ironic-api-testing**: This step runs API tests for Ironic. Similar to + the previous step, the `tempestconfRun` section configures Tempest + settings, and the `tempestRun` section specifies the concurrency level + and the list of tests to include and exclude. + +In summary, this YAML file configures a Tempest test job to run two types of +tests for Ironic: scenario tests and API tests. The tests are executed with +specific configurations and concurrency levels. diff --git a/scenarios/sno-veos/test-operator/automation-vars.yml b/scenarios/sno-veos/test-operator/automation-vars.yml new file mode 100644 index 00000000..a7a1a6c0 --- /dev/null +++ b/scenarios/sno-veos/test-operator/automation-vars.yml @@ -0,0 +1,318 @@ +--- +stages: + # - name: Apply ironic network-attachement-definition + # manifest: manifests/nad.yaml + # wait_conditions: + # - >- + # oc wait -n sushy-emulator network-attachment-definitions.k8s.cni.cncf.io ironic + # --for jsonpath='{.metadata.annotations}' --timeout=30s + + # - name: Patch RedFish Sushy Emulator Deployment - add network attachment + # shell: | + # set -xe -o pipefail + + # TMP_DIR="$(mktemp -d)" + # trap 'rm -rf -- "$TMP_DIR"' EXIT + + # oc project sushy-emulator + + # cat << EOF > ${TMP_DIR}/sushy-emulator-network-annotations-patch.yaml + # spec: + # template: + # metadata: + # annotations: + # k8s.v1.cni.cncf.io/networks: '[{"name":"ironic","namespace":"sushy-emulator","interface":"ironic"}]' + # EOF + + # oc patch deployments.apps sushy-emulator --patch-file ${TMP_DIR}/sushy-emulator-network-annotations-patch.yaml + # wait_conditions: + # - "oc -n sushy-emulator wait deployments.apps sushy-emulator --for condition=Available --timeout=300s" + + - name: Set a multiattach volume type and create it if needed + shell: | + set -xe -o pipefail + oc project openstack + + oc rsh openstackclient openstack volume type show multiattach &>/dev/null || \ + oc rsh openstackclient openstack volume type create multiattach + + oc rsh openstackclient openstack volume type set --property multiattach=" True" multiattach + + - name: Create public network if needed + shell: | + set -xe -o pipefail + oc project openstack + + oc rsh openstackclient openstack network show public &>/dev/null || \ + oc rsh openstackclient openstack network create public \ + --external \ + --no-share \ + --default \ + --provider-network-type flat \ + --provider-physical-network datacentre + + - name: Create subnet on public network if needed + shell: | + set -xe -o pipefail + oc project openstack + + oc rsh openstackclient openstack subnet show public_subnet &>/dev/null || \ + oc rsh openstackclient openstack subnet create public_subnet \ + --network public \ + --subnet-range 192.168.122.0/24 \ + --allocation-pool start=192.168.122.171,end=192.168.122.250 \ + --gateway 192.168.122.1 \ + --dhcp + + - name: Create private network if needed + shell: | + set -xe -o pipefail + oc project openstack + + oc rsh openstackclient openstack network show private &>/dev/null || \ + oc rsh openstackclient openstack network create private --share + + - name: Create subnet on private network if needed + shell: | + set -xe -o pipefail + oc project openstack + + oc rsh openstackclient openstack subnet show private_subnet &>/dev/null || \ + oc rsh openstackclient openstack subnet create private_subnet \ + --network private \ + --subnet-range 10.2.0.0/24 \ + --allocation-pool start=10.2.0.10,end=10.2.0.250 \ + --gateway 10.2.0.1 \ + --dhcp + + - name: Create network for ironic provisioning if needed + shell: | + set -xe -o pipefail + oc project openstack + + oc rsh openstackclient openstack network show provisioning &>/dev/null || \ + oc rsh openstackclient \ + openstack network create provisioning \ + --share \ + --provider-physical-network ironic \ + --provider-network-type vlan \ + --provider-segment 100 + + - name: Create subnet for ironic provisioning if needed + shell: | + set -xe -o pipefail + oc project openstack + + oc rsh openstackclient openstack subnet show provisioning-subnet &>/dev/null || \ + oc rsh openstackclient \ + openstack subnet create provisioning-subnet \ + --network provisioning \ + --subnet-range 172.20.1.0/24 \ + --gateway 172.20.1.1 \ + --dns-nameserver 192.168.122.80 \ + --allocation-pool start=172.20.1.100,end=172.20.1.200 + + - name: Create tenant network vlan 103 if needed + shell: | + set -xe -o pipefail + oc project openstack + + oc rsh openstackclient openstack network show vlan103 &>/dev/null || \ + oc rsh openstackclient \ + openstack network create vlan103 \ + --share \ + --provider-physical-network ironic \ + --provider-network-type vlan \ + --provider-segment 103 + + - name: Create subnet for tenant network vlan 103 if needed + shell: | + set -xe -o pipefail + oc project openstack + + oc rsh openstackclient openstack subnet show vlan103-subnet &>/dev/null || \ + oc rsh openstackclient \ + openstack subnet create vlan103-subnet \ + --network vlan103 \ + --subnet-range 172.20.3.0/24 \ + --gateway 172.20.3.1 \ + --dns-nameserver 192.168.122.80 \ + --allocation-pool start=172.20.3.100,end=172.20.3.200 + + - name: Create tenant network vlan 104 if needed + shell: | + set -xe -o pipefail + oc project openstack + + oc rsh openstackclient openstack network show vlan104 &>/dev/null || \ + oc rsh openstackclient \ + openstack network create vlan104 \ + --share \ + --provider-physical-network ironic \ + --provider-network-type vlan \ + --provider-segment 104 + + - name: Create subnet for tenant network vlan 104 if needed + shell: | + set -xe -o pipefail + oc project openstack + + oc rsh openstackclient openstack subnet show vlan104-subnet &>/dev/null || \ + oc rsh openstackclient \ + openstack subnet create vlan104-subnet \ + --network vlan104 \ + --subnet-range 172.20.4.0/24 \ + --gateway 172.20.4.1 \ + --dns-nameserver 192.168.122.80 \ + --allocation-pool start=172.20.4.100,end=172.20.4.200 + + - name: Create baremetal flavor if needed + shell: | + set -xe -o pipefail + oc project openstack + + oc rsh openstackclient openstack flavor show baremetal &>/dev/null || \ + oc rsh openstackclient \ + openstack flavor create baremetal \ + --id 123456789-1234-1234-1234-000000000001 \ + --ram 1024 \ + --vcpus 1 \ + --disk 15 \ + --property resources:VCPU=0 \ + --property resources:MEMORY_MB=0 \ + --property resources:DISK_GB=0 \ + --property resources:CUSTOM_BAREMETAL=1 \ + --property capabilities:boot_mode=uefi + + - name: Copy ironic_nodes.yaml to the openstackclient pod + shell: | + set -xe -o pipefail + oc project openstack + oc cp ~/data/ironic_nodes.yaml openstackclient:ironic_nodes.yaml + + - name: Enroll nodes in ironic + shell: | + set -xe -o pipefail + oc project openstack + oc rsh openstackclient openstack baremetal create ironic_nodes.yaml + + - name: Wait for ironic nodes to get to state - enroll + shell: | + set -xe -o pipefail + oc project openstack + + counter=0 + retries=100 + node_state=enroll + set +e + until ! oc rsh openstackclient openstack baremetal node list -f value -c "Provisioning State" | grep -P "^(?!${node_state}).*$"; do + if [[ "$counter" -eq "$retries" ]]; then + echo "ERROR: Timeout. Nodes did not reach state: enroll" + exit 1 + fi + echo "Waiting for nodes to reach state enroll" + sleep 10 + ((counter++)) + done + + - name: Manage ironic nodes + shell: | + set -xe -o pipefail + oc project openstack + + oc rsh openstackclient openstack baremetal node manage ironic0 + oc rsh openstackclient openstack baremetal node manage ironic1 + + - name: Wait for ironic nodes to get to state - manageable + shell: | + set -xe -o pipefail + oc project openstack + + counter=0 + retries=100 + node_state=manageable + set +e + until ! oc rsh openstackclient openstack baremetal node list -f value -c "Provisioning State" | grep -P "^(?!${node_state}).*$"; do + if [[ "$counter" -eq "$retries" ]]; then + echo "ERROR: Timeout. Nodes did not reach state: manageable" + set -e + exit 1 + fi + echo "Waiting for nodes to reach state manageable" + sleep 10 + ((counter++)) + done + + - name: Power off the ironic nodes + shell: | + set -xe -o pipefail + oc project openstack + + oc rsh openstackclient openstack baremetal node power off ironic0 + oc rsh openstackclient openstack baremetal node power off ironic1 + + - name: Set capabilities boot_mode:uefi for ironic nodes + shell: | + set -xe -o pipefail + oc project openstack + + oc rsh openstackclient openstack baremetal node set --property capabilities='boot_mode:uefi' ironic0 + oc rsh openstackclient openstack baremetal node set --property capabilities='boot_mode:uefi' ironic1 + + - name: Ensure ironic nodes are powered off + shell: | + set -xe -o pipefail + oc project openstack + + counter=0 + retries=100 + power_state="off" + set +e + until ! oc rsh openstackclient openstack baremetal node list -f value -c "Power State" | grep -P "^power.(?!${power_state}).*$"; do + if [[ "$counter" -eq "$retries" ]]; then + echo "ERROR: Timeout. Nodes did not reach power state: power off" + set -e + exit 1 + fi + echo "Waiting for nodes to reach power state off" + sleep 10 + ((counter++)) + done + + - name: Provide ironic nodes + shell: | + set -xe -o pipefail + oc project openstack + + oc rsh openstackclient openstack baremetal node provide ironic0 + oc rsh openstackclient openstack baremetal node provide ironic1 + + - name: Wait for ironic nodes to get to state - available + shell: | + set -xe -o pipefail + oc project openstack + + counter=0 + retries=100 + node_state=available + set +e + until ! oc rsh openstackclient openstack baremetal node list -f value -c "Provisioning State" | grep -P "^(?!${node_state}).*$"; do + if [[ "$counter" -eq "$retries" ]]; then + echo "ERROR: Timeout. Nodes did not reach state: available" + set -e + exit 1 + fi + echo "Waiting for nodes to reach state: active" + sleep 10 + ((counter++)) + done + set -e + + - name: Wait for expected compute services (OSPRH-10942) + wait_conditions: + - >- + timeout --foreground 5m hotstack-nova-discover-hosts + --namespace openstack --num-computes 1 + + - name: Run tempest + manifest: tempest-tests.yml diff --git a/scenarios/sno-veos/test-operator/manifests/nad.yaml b/scenarios/sno-veos/test-operator/manifests/nad.yaml new file mode 100644 index 00000000..f10e0061 --- /dev/null +++ b/scenarios/sno-veos/test-operator/manifests/nad.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: k8s.cni.cncf.io/v1 +kind: NetworkAttachmentDefinition +metadata: + name: ironic + namespace: sushy-emulator +spec: + config: | + { + "cniVersion": "0.3.1", + "name": "ironic", + "type": "bridge", + "bridge": "ironic", + "mtu": 1442, + "ipam": { + "type": "whereabouts", + "range": "172.20.1.0/24", + "range_start": "172.20.1.71", + "range_end": "172.20.1.75" + } + } diff --git a/scenarios/sno-veos/test-operator/tempest-tests.yml b/scenarios/sno-veos/test-operator/tempest-tests.yml new file mode 100644 index 00000000..045d42a4 --- /dev/null +++ b/scenarios/sno-veos/test-operator/tempest-tests.yml @@ -0,0 +1,89 @@ +--- +apiVersion: test.openstack.org/v1beta1 +kind: Tempest +metadata: + name: tempest-tests + namespace: openstack +spec: + networkAttachments: + - ctlplane + privileged: true + workflow: + - stepName: ironic-scenario-testing + storageClass: lvms-local-storage + tempestconfRun: + create: true + overrides: | + auth.create_isolated_networks false + baremetal.available_nodes 2 + baremetal.max_microversion 1.82 + compute-feature-enabled.disk_config false + compute-feature-enabled.interface_attach false + compute.fixed_network_name provisioning + compute.flavor_ref 123456789-1234-1234-1234-000000000001 + compute.hypervisor_type ironic + network.shared_physical_network true + service_available.ironic_inspector false + service_available.ironic true + validation.connect_method fixed + validation.network_for_ssh provisioning + tempestRun: + concurrency: 4 + includeList: | + ^ironic_tempest_plugin.tests.scenario.test_baremetal_basic_ops.* + excludeList: | + ^ironic_tempest_plugin.tests.scenario.test_baremetal_basic_ops.BaremetalBasicOps.test_baremetal_server_ops_partition_image + + - stepName: ironic-api-testing + storageClass: lvms-local-storage + tempestconfRun: + create: true + overrides: | + baremetal.driver fake-hardware + baremetal.max_microversion 1.82 + service_available.ironic_inspector true + service_available.ironic true + tempestRun: + concurrency: 8 + includeList: | + ^ironic_tempest_plugin.tests.api.* + excludeList: | + ^ironic_tempest_plugin.tests.api.admin.test_allocations.TestAllocations.test_create_allocation_candidate_node + ^ironic_tempest_plugin.tests.api.admin.test_allocations.TestAllocations.test_create_allocation_node_mismatch + ^ironic_tempest_plugin.tests.api.admin.test_allocations.TestAllocations.test_create_allocation_resource_class_mismatch + ^ironic_tempest_plugin.tests.api.admin.test_allocations.TestAllocations.test_create_allocation_traits_mismatch + ^ironic_tempest_plugin.tests.api.admin.test_allocations.TestAllocations.test_create_allocation_with_traits + ^ironic_tempest_plugin.tests.api.admin.test_allocations.TestAllocations.test_create_show_allocation + ^ironic_tempest_plugin.tests.api.admin.test_allocations.TestAllocations.test_delete_allocation + ^ironic_tempest_plugin.tests.api.admin.test_allocations.TestAllocations.test_delete_allocation_by_name + ^ironic_tempest_plugin.tests.api.admin.test_allocations.TestAllocations.test_list_allocations + ^ironic_tempest_plugin.tests.api.admin.test_allocations.TestAllocations.test_list_allocations_by_state + ^ironic_tempest_plugin.tests.api.admin.test_allocations.TestAllocations.test_show_by_name + ^ironic_tempest_plugin.tests.api.admin.test_allocations.TestBackfill.test_backfill_allocation + ^ironic_tempest_plugin.tests.api.admin.test_allocations.TestBackfill.test_backfill_without_resource_class + ^ironic_tempest_plugin.tests.api.admin.test_nodestates.TestNodeStatesV1_11.test_set_node_provision_state + ^ironic_tempest_plugin.tests.api.admin.test_nodestates.TestNodeStatesV1_1.test_set_node_provision_state + ^ironic_tempest_plugin.tests.api.admin.test_nodestates.TestNodeStatesV1_2.test_set_node_provision_state + ^ironic_tempest_plugin.tests.api.admin.test_nodestates.TestNodeStatesV1_4.test_set_node_provision_state + ^ironic_tempest_plugin.tests.api.admin.test_nodestates.TestNodeStatesV1_6.test_set_node_provision_state + ^ironic_tempest_plugin.tests.api.admin.test_nodes.TestHardwareInterfaces.test_reset_interfaces + ^ironic_tempest_plugin.tests.api.admin.test_nodes.TestNodeProtected.test_node_protected + ^ironic_tempest_plugin.tests.api.admin.test_nodes.TestNodeProtected.test_node_protected_from_deletion + ^ironic_tempest_plugin.tests.api.admin.test_nodes.TestNodeProtected.test_node_protected_negative + ^ironic_tempest_plugin.tests.api.admin.test_nodes.TestNodeProtected.test_node_protected_set_unset + ^ironic_tempest_plugin.tests.api.admin.test_nodes.TestNodesProtectedOldApi.test_node_protected_old_api + ^ironic_tempest_plugin.tests.api.admin.test_nodes.TestNodesVif.test_vif_already_attached_on_internal_info + ^ironic_tempest_plugin.tests.api.admin.test_nodes.TestNodesVif.test_vif_already_attached_with_portgroups + ^ironic_tempest_plugin.tests.api.admin.test_nodes.TestNodesVif.test_vif_already_set + ^ironic_tempest_plugin.tests.api.admin.test_nodes.TestNodesVif.test_vif_attach_no_args + ^ironic_tempest_plugin.tests.api.admin.test_nodes.TestNodesVif.test_vif_attach_no_free_port + ^ironic_tempest_plugin.tests.api.admin.test_nodes.TestNodesVif.test_vif_attach_no_port + ^ironic_tempest_plugin.tests.api.admin.test_nodes.TestNodesVif.test_vif_attach_port_not_in_portgroup + ^ironic_tempest_plugin.tests.api.admin.test_nodes.TestNodesVif.test_vif_attach_with_empty_portgroup + ^ironic_tempest_plugin.tests.api.admin.test_nodes.TestNodesVif.test_vif_detach_not_existing + ^ironic_tempest_plugin.tests.api.admin.test_nodes.TestNodesVif.test_vif_on_port + ^ironic_tempest_plugin.tests.api.admin.test_nodes.TestNodesVif.test_vif_on_portgroup + ^ironic_tempest_plugin.tests.api.admin.test_nodes.TestResetInterfaces.test_reset_interfaces + ^ironic_tempest_plugin.tests.api.rbac_defaults.test_nodes.TestNodeProjectReader.test_reader_cannot_update_owner_provisioned + ^ironic_tempest_plugin.tests.api.rbac_defaults.test_nodes.TestNodeSystemReader.test_reader_cannot_update_owner_provisioned + ^ironic_tempest_plugin.tests.api.rbac_defaults.test_nodes.TestNodeSystemReader.* diff --git a/scenarios/sno-veos/ztp.config b/scenarios/sno-veos/ztp.config new file mode 100644 index 00000000..dbff1d99 --- /dev/null +++ b/scenarios/sno-veos/ztp.config @@ -0,0 +1,2 @@ +#!/usr/bin/Cli -p2 +copy tfpt://192.168.32.254/startup-config flash:startup-config