Skip to content

Commit 42e9155

Browse files
committed
WIP: Add networking-lab with devstack-nxsw-vxlan
Introduces a new networking-lab directory for network-focused scenarios that don't require full OpenShift deployments. Includes first scenario: devstack-nxsw-vxlan with spine-and-leaf topology featuring: - 4 Cisco NX-OS switches (2 spine + 2 leaf) with OSPF underlay - Devstack node with trunk port for VLAN-tagged traffic - 2 Ironic baremetal nodes attached to leaf switches - Individual POAP scripts and configs per switch - VXLAN/EVPN ready configuration - SVG topology diagram - Automated POAP md5sum management script and pre-commit hook Point-to-point links consolidated in 10.1.1.0/24 to preserve 10.1.2.0/24+ address space for future use. Signed-off-by: Harald Jensås <hjensas@redhat.com>
1 parent 9641a79 commit 42e9155

25 files changed

+4123
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
**/__pycache__/
22
.ansible/*
33
.venv/*
4+
*.gz.b64
5+
*.tar.gz

.pre-commit-config.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ repos:
5757
language: system
5858
files: ^scenarios/sno-nxsw/poap\.py$
5959
pass_filenames: false
60+
- id: networking-lab-poap-md5sums
61+
name: Format networking-lab POAP scripts with md5sum management
62+
entry: scenarios/networking-lab/manage-poap-md5sums.sh
63+
language: system
64+
files: ^scenarios/networking-lab/.*-poap\.py$
65+
pass_filenames: false
6066

6167
- repo: https://github.com/ansible/ansible-lint
6268
rev: v6.22.2

03-install_devstack.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
# Copyright Red Hat, Inc.
3+
# All Rights Reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License. You may obtain
7+
# a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
# License for the specific language governing permissions and limitations
15+
# under the License.
16+
17+
- name: Setup Devstack Installation
18+
hosts: localhost
19+
gather_facts: true
20+
strategy: linear
21+
pre_tasks:
22+
- name: Load stack output vars from file
23+
ansible.builtin.include_vars:
24+
file: "{{ hotstack_work_dir | default(playbook_dir) }}/{{ stack_name }}-outputs.yaml"
25+
name: stack_outputs
26+
27+
- name: Add controller-0 to the Ansible inventory
28+
ansible.builtin.add_host: "{{ stack_outputs.controller_ansible_host }}"
29+
30+
- name: Add devstack node with ProxyJump through controller
31+
ansible.builtin.add_host: "{{ stack_outputs.devstack_ansible_host }}"
32+
33+
- name: Install Devstack
34+
hosts: devstack
35+
gather_facts: true
36+
vars:
37+
scenario_dir: "{{ hotstack_work_dir | default(playbook_dir) }}/scenarios/{{ scenario_name | default('networking-lab/devstack-nxsw-vxlan') }}"
38+
roles:
39+
- role: devstack_installer
40+
vars:
41+
devstack_local_conf_template: "{{ scenario_dir }}/local.conf.j2"

bootstrap_devstack.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
# Copyright Red Hat, Inc.
3+
# All Rights Reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License. You may obtain
7+
# a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
# License for the specific language governing permissions and limitations
15+
# under the License.
16+
17+
- name: Bootstrap virtual infrastructure on Openstack cloud
18+
ansible.builtin.import_playbook: 01-infra.yml
19+
20+
- name: Bootstrap controller node
21+
ansible.builtin.import_playbook: 02-bootstrap_controller.yml
22+
23+
- name: Install DevStack
24+
ansible.builtin.import_playbook: 03-install_devstack.yml

roles/devstack_installer/README.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Devstack Installer Role
2+
3+
This role installs and configures DevStack. The actual devstack configuration is provided by a `local.conf.j2` template from the scenario directory, making each scenario self-contained and customizable.
4+
5+
## Requirements
6+
7+
- Ubuntu 24.04 (Noble) target system
8+
- User `stack` with sudo privileges and home directory at `/opt/stack`
9+
- Accessible via SSH (potentially through a jump host)
10+
- Network interface configured (typically via heat template cloud-init)
11+
- A `local.conf.j2` template in the scenario directory
12+
13+
## Execution Flow
14+
15+
The role performs the following steps:
16+
17+
1. **System Update**: Updates all packages to latest versions
18+
2. **Reboot if needed**: Checks for `/var/run/reboot-required` and reboots if kernel/core packages were updated
19+
3. **Wait for system**: Waits for system to come back online (up to 5 minutes)
20+
4. **Install dependencies**: Installs git, python3, and python3-pip
21+
5. **Verify network**: Checks that the trunk interface is UP
22+
6. **Clone devstack**: Clones the devstack repository
23+
7. **Generate config**: Creates local.conf from the scenario template
24+
8. **Run stack.sh**: Executes devstack installation
25+
9. **Mark complete**: Creates completion marker for idempotency
26+
27+
## Role Variables
28+
29+
Available variables are listed below, along with default values (see `defaults/main.yml`):
30+
31+
### Required Variables
32+
```yaml
33+
# Path to the local.conf.j2 template (must be provided by the playbook)
34+
devstack_local_conf_template: "{{ scenario_dir }}/local.conf.j2"
35+
```
36+
37+
### Optional Variables
38+
```yaml
39+
# DevStack repository configuration
40+
devstack_repo_url: https://opendev.org/openstack/devstack
41+
devstack_repo_dest: /opt/stack/devstack
42+
devstack_branch: master
43+
44+
# Network interface for physical bridge (should match heat template netplan config)
45+
# The heat template uses MAC matching to create a predictable name
46+
devstack_public_interface: trunk0
47+
48+
# System updates (set to false to skip for faster iterations during development)
49+
devstack_update_packages: true
50+
```
51+
52+
## Dependencies
53+
54+
None.
55+
56+
## Example Playbook
57+
58+
```yaml
59+
- name: Install Devstack
60+
hosts: devstack
61+
gather_facts: true
62+
vars:
63+
scenario_dir: "{{ playbook_dir }}/scenarios/networking-lab/devstack-nxsw-vxlan"
64+
roles:
65+
- role: devstack_installer
66+
vars:
67+
devstack_local_conf_template: "{{ scenario_dir }}/local.conf.j2"
68+
```
69+
70+
## Scenario Structure
71+
72+
Each scenario should provide its own `local.conf.j2` template:
73+
74+
```
75+
scenarios/
76+
networking-lab/
77+
devstack-nxsw-vxlan/
78+
heat_template.yaml
79+
local.conf.j2 # Devstack configuration template
80+
bootstrap_vars.yml
81+
```
82+
83+
The `local.conf.j2` template can use Jinja2 variables and can be as simple or complex as needed. For a minimal configuration, it can be a static file without any template variables.
84+
85+
## Features
86+
87+
- Scenario-specific configuration via local.conf.j2 templates
88+
- Network configuration handled by heat template (cloud-init)
89+
- Updates all packages before installation (dist-upgrade)
90+
- Automatic reboot if kernel or core packages are updated
91+
- Waits for system to be fully available after reboot
92+
- Idempotent - can be re-run safely (checks for .stack.sh.complete marker)
93+
- SSH access via jump host through controller
94+
95+
## License
96+
97+
Apache 2.0
98+
99+
## Author Information
100+
101+
This role was created as part of the HotStack project.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
# Devstack installer defaults
3+
4+
# Path to local.conf.j2 template (must be provided by playbook or scenario)
5+
devstack_local_conf_template: ""
6+
7+
# Devstack repository
8+
devstack_repo_url: https://opendev.org/openstack/devstack
9+
devstack_repo_dest: /opt/stack/devstack
10+
devstack_branch: master
11+
12+
# Network interface for physical bridge (configured by heat template via MAC matching)
13+
devstack_public_interface: trunk0
14+
15+
# System updates and reboot
16+
devstack_update_packages: true # Set to false to skip package updates
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
galaxy_info:
3+
author: HotStack Project
4+
description: Install and configure DevStack using scenario-specific configuration templates
5+
license: Apache-2.0
6+
min_ansible_version: "2.15"
7+
platforms:
8+
- name: Ubuntu
9+
versions:
10+
- noble
11+
12+
dependencies: []
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
---
2+
- name: Verify devstack_local_conf_template is provided
3+
ansible.builtin.assert:
4+
that:
5+
- devstack_local_conf_template is defined
6+
- devstack_local_conf_template | length > 0
7+
fail_msg: "devstack_local_conf_template must be provided (path to local.conf.j2)"
8+
9+
- name: Update all packages to latest version
10+
become: true
11+
ansible.builtin.apt:
12+
upgrade: dist
13+
update_cache: true
14+
cache_valid_time: 3600
15+
register: apt_upgrade
16+
when: devstack_update_packages | bool
17+
18+
- name: Check if reboot is required
19+
become: true
20+
ansible.builtin.stat:
21+
path: /var/run/reboot-required
22+
register: reboot_required_file
23+
when: devstack_update_packages | bool
24+
25+
- name: Reboot the system if required
26+
become: true
27+
ansible.builtin.reboot:
28+
msg: "Reboot initiated by Ansible for kernel updates"
29+
connect_timeout: 5
30+
reboot_timeout: 300
31+
pre_reboot_delay: 0
32+
post_reboot_delay: 30
33+
test_command: uptime
34+
when:
35+
- devstack_update_packages | bool
36+
- reboot_required_file.stat.exists
37+
38+
- name: Install required packages
39+
become: true
40+
ansible.builtin.apt:
41+
name:
42+
- git
43+
- python3
44+
- python3-pip
45+
state: present
46+
update_cache: true
47+
48+
- name: Verify trunk interface is up
49+
ansible.builtin.command: ip link show {{ devstack_public_interface }}
50+
register: interface_status
51+
changed_when: false
52+
failed_when: "'UP' not in interface_status.stdout"
53+
54+
- name: Clone devstack repository
55+
ansible.builtin.git:
56+
repo: "{{ devstack_repo_url }}"
57+
dest: "{{ devstack_repo_dest }}"
58+
version: "{{ devstack_branch }}"
59+
force: false
60+
61+
- name: Generate local.conf from scenario template
62+
ansible.builtin.template:
63+
src: "{{ devstack_local_conf_template }}"
64+
dest: "{{ devstack_repo_dest }}/local.conf"
65+
owner: stack
66+
group: stack
67+
mode: '0644'
68+
69+
- name: Run stack.sh
70+
ansible.builtin.command:
71+
cmd: ./stack.sh
72+
chdir: "{{ devstack_repo_dest }}"
73+
creates: "{{ devstack_repo_dest }}/.stack.sh.complete"
74+
environment:
75+
HOME: /opt/stack
76+
register: devstack_install
77+
78+
- name: Create completion marker
79+
ansible.builtin.file:
80+
path: "{{ devstack_repo_dest }}/.stack.sh.complete"
81+
state: touch
82+
owner: stack
83+
group: stack
84+
mode: '0644'
85+
when: devstack_install.rc == 0
86+
87+
- name: Display stack.sh output summary
88+
ansible.builtin.debug:
89+
msg: "Devstack installation completed successfully!"
90+
when: devstack_install.rc == 0

roles/heat_stack/tasks/main.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,18 @@
3636
msg:
3737
"{{ _latest_snapset.output }}"
3838

39+
- name: Compress files for user data
40+
when: compress_heat_files | default([]) | length > 0
41+
block:
42+
- name: Create tar archives and compress
43+
ansible.builtin.shell: |
44+
tar -czf "{{ item.archive }}.tar.gz" {{ item.files | join(' ') }}
45+
base64 -w0 "{{ item.archive }}.tar.gz" > "{{ item.archive }}.tar.gz.b64"
46+
args:
47+
chdir: "{{ stack_template_path | dirname }}"
48+
loop: "{{ compress_heat_files }}"
49+
changed_when: true
50+
3951
- name: Create stack
4052
openstack.cloud.stack:
4153
cloud: "{{ os_cloud }}"

scenarios/networking-lab/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Networking Lab Scenarios
2+
3+
This directory contains networking-focused lab scenarios designed for testing, development, and learning various network topologies and configurations without requiring a full OpenShift deployment.
4+
5+
## Available Scenarios
6+
7+
### devstack-nxsw-vxlan
8+
A spine-and-leaf Cisco NX-OS topology with VXLAN overlay capabilities, featuring:
9+
- 4 Cisco NX-OS switches (2 spine, 2 leaf)
10+
- Devstack node for OpenStack development
11+
- Ironic nodes for bare metal provisioning
12+
- VXLAN/EVPN ready configuration
13+
14+
See [devstack-nxsw-vxlan/README.md](devstack-nxsw-vxlan/README.md) for detailed documentation.
15+
16+
## Managing POAP Scripts
17+
18+
All POAP scripts (`*-poap.py`) in networking lab scenarios include md5sum validation. Use the `manage-poap-md5sums.sh` script to automatically update md5sums after modifying any POAP scripts:
19+
20+
```bash
21+
./scenarios/networking-lab/manage-poap-md5sums.sh
22+
```
23+
24+
This script:
25+
- Finds all `*-poap.py` files in networking-lab scenarios
26+
- Removes old md5sum lines
27+
- Calculates and adds new md5sum lines
28+
- Runs automatically via pre-commit hooks
29+
30+
## Contributing
31+
32+
When adding new networking lab scenarios:
33+
1. Create a descriptive directory name
34+
2. Follow the existing file structure
35+
3. Include comprehensive README documentation
36+
4. Document network topology with diagrams (SVG preferred)
37+
5. Provide example configurations and validation steps
38+
6. Include troubleshooting guidance
39+
7. If using POAP scripts, name them `*-poap.py` for automatic md5sum management
40+
41+
## Related Documentation
42+
43+
- [Main Scenarios README](../README.md)
44+
- [Hotstack Documentation](../../README.md)
45+
- [Switch Configuration Guide](../../docs/virtual_switches.md)

0 commit comments

Comments
 (0)