CI: Add magnum-capi initial CI job

Adding 2026.1 variant only for now, because
cluster-api-janitor-openstack is failing with master
devstack due to a bug [1].

[1]: https://github.com/azimuth-cloud/cluster-api-janitor-openstack/pull/285

Change-Id: Id1056773d08f6972cc225004256bf74d285d3335
Signed-off-by: Michal Nasiadka <mnasiadka@gmail.com>
Signed-off-by: Matt Crees <mattc@stackhpc.com>
This commit is contained in:
Michal Nasiadka
2025-08-18 15:32:19 +02:00
parent 9f25d2fe8b
commit 5f123f402d
10 changed files with 248 additions and 325 deletions
+1
View File
@@ -27,6 +27,7 @@ var
sdist
develop-eggs
.installed.cfg
!devstack/lib
lib
lib64
-325
View File
@@ -1,325 +0,0 @@
#!/bin/bash
#
# These instructions assume an Ubuntu-based host or VM for running devstack.
# Please note that if you are running this in a VM, it is vitally important
# that the underlying hardware have nested virtualization enabled or you will
# experience very poor amphora performance.
#
# Heavily based on:
# https://opendev.org/openstack/octavia/src/branch/master/devstack/contrib/new-octavia-devstack.sh
set -ex
OPENSTACK_VERSION="${OPENSTACK_VERSION:-master}"
# Set up the packages we need. Ubuntu package manager is assumed.
sudo apt-get update
sudo apt-get install git vim apparmor apparmor-utils jq -y
# Clone the devstack repo
sudo mkdir -p /opt/stack
if [ ! -f /opt/stack/stack.sh ]; then
sudo chown -R ${USER}. /opt/stack
git clone https://git.openstack.org/openstack-dev/devstack -b $OPENSTACK_VERSION /opt/stack
fi
default_interface=$(ip route show default | awk 'NR==1 {print $5}')
HOSTNAME=$(ip addr show "$default_interface" | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
cat <<EOF > /opt/stack/local.conf
[[local|localrc]]
HOST_IP=$(echo $HOSTNAME)
DATABASE_PASSWORD=secretdatabase
RABBIT_PASSWORD=secretrabbit
ADMIN_PASSWORD=secretadmin
SERVICE_PASSWORD=secretservice
SERVICE_TOKEN=111222333444
# Keystone config
KEYSTONE_ADMIN_ENDPOINT=true
# Glance config
GLANCE_LIMIT_IMAGE_SIZE_TOTAL=20000
# Logging
# -------
# By default ``stack.sh`` output only goes to the terminal where it runs. It can
# be configured to additionally log to a file by setting ``LOGFILE`` to the full
# path of the destination log file. A timestamp will be appended to the given name.
LOGFILE=$DEST/logs/stack.sh.log
# Old log files are automatically removed after 7 days to keep things neat. Change
# the number of days by setting ``LOGDAYS``.
LOGDAYS=2
# Nova logs will be colorized if ``SYSLOG`` is not set; turn this off by setting
# ``LOG_COLOR`` false.
#LOG_COLOR=False
# Enable OVN
Q_AGENT=ovn
Q_ML2_PLUGIN_MECHANISM_DRIVERS=ovn,logger
Q_ML2_PLUGIN_TYPE_DRIVERS=local,flat,vlan,geneve
Q_ML2_TENANT_NETWORK_TYPE="geneve"
# Enable OVN services
enable_service ovn-northd
enable_service ovn-controller
enable_service q-ovn-metadata-agent
# Use Neutron
enable_service q-svc
# Disable Neutron agents not used with OVN.
# disable_service q-agt
# disable_service q-l3
# disable_service q-dhcp
# disable_service q-meta
# Enable services, these services depend on neutron plugin.
enable_plugin neutron https://opendev.org/openstack/neutron $OPENSTACK_VERSION
enable_service q-trunk
enable_service q-dns
#enable_service q-qos
FIXED_RANGE=10.1.0.0/24
# Enable octavia tempest plugin tests
# NOTE: Doesn't follow standard OS branch naming conventions
enable_plugin octavia-tempest-plugin https://opendev.org/openstack/octavia-tempest-plugin
# Horizon config
disable_service horizon
# Cinder (OpenStack Block Storage) is disabled by default to speed up
# DevStack a bit. You may enable it here if you would like to use it.
enable_service cinder c-sch c-api c-vol
# A UUID to uniquely identify this system. If one is not specified, a random
# one will be generated and saved in the file 'ovn-uuid' for re-use in future
# DevStack runs.
#OVN_UUID=
# If using the OVN native layer-3 service, choose a router scheduler to
# manage the distribution of router gateways on hypervisors/chassis.
# Default value is leastloaded.
#OVN_L3_SCHEDULER=leastloaded
# The DevStack plugin defaults to using the ovn branch from the official ovs
# repo. You can optionally use a different one. For example, you may want to
# use the latest patches in blp's ovn branch (and see OVN_BUILD_FROM_SOURCE):
#OVN_REPO=https://github.com/blp/ovs-reviews.git
#OVN_BRANCH=ovn
# NOTE: When specifying the branch, as shown above, you must also enable this!
# By default, OVN will be installed from packages. In order to build OVN from
# source, set OVN_BUILD_FROM_SOURCE=True
#OVN_BUILD_FROM_SOURCE=False
# If the admin wants to enable this chassis to host gateway routers for
# external connectivity, then set ENABLE_CHASSIS_AS_GW to True.
# Then devstack will set ovn-cms-options with enable-chassis-as-gw
# in Open_vSwitch table's external_ids column.
# If this option is not set on any chassis, all the of them with bridge
# mappings configured will be eligible to host a gateway.
#ENABLE_CHASSIS_AS_GW=True
# If you wish to use the provider network for public access to the cloud,
# set the following
#Q_USE_PROVIDERNET_FOR_PUBLIC=True
# Create public bridge
#OVN_L3_CREATE_PUBLIC_NETWORK=True
# This needs to be equalized with Neutron devstack
PUBLIC_NETWORK_GATEWAY="172.24.4.1"
# Nova config
LIBVIRT_TYPE=kvm
# Octavia configuration
OCTAVIA_NODE="api"
DISABLE_AMP_IMAGE_BUILD=True
enable_plugin barbican https://opendev.org/openstack/barbican $OPENSTACK_VERSION
enable_plugin octavia https://opendev.org/openstack/octavia $OPENSTACK_VERSION
enable_plugin octavia-dashboard https://opendev.org/openstack/octavia-dashboard $OPENSTACK_VERSION
LIBS_FROM_GIT+=python-octaviaclient
enable_service octavia
enable_service o-api
enable_service o-hk
enable_service o-da
enable_service o-cw
enable_service o-hm
# OVN octavia provider plugin
enable_plugin ovn-octavia-provider https://opendev.org/openstack/ovn-octavia-provider $OPENSTACK_VERSION
# Magnum
enable_plugin magnum https://opendev.org/openstack/magnum $OPENSTACK_VERSION
[[post-config|$NOVA_CONF]]
[scheduler]
discover_hosts_in_cells_interval = 2
EOF
# Fix permissions on current tty so screens can attach
sudo chmod go+rw `tty`
# Stack that stack!
/opt/stack/stack.sh
#
# Install this checkout and restart the Magnum services
#
SELF_PATH="$(realpath "${BASH_SOURCE[0]:-${(%):-%x}}")"
REPO_PATH="$(dirname "$(dirname "$(dirname "$SELF_PATH")")")"
python3 -m pip install -e "$REPO_PATH"
sudo systemctl restart devstack@magnum-api devstack@magnum-cond
new_path="/home/ubuntu/.local/bin"
source ~/.bashrc
# Check if the path is already in the PATH variable
if [[ ":$PATH:" != *":$new_path:"* ]]; then
# If it's not in the PATH, add it
echo 'export PATH="$PATH:'"$new_path"'"' >> ~/.bashrc
fi
# Get latest capi-helm-charts tag
LATEST_TAG=$(curl -fsL https://api.github.com/repos/azimuth-cloud/capi-helm-charts/tags | jq -r '.[0].name')
# Curl the dependencies URL
DEPENDENCIES_JSON=$(curl -fsL https://github.com/azimuth-cloud/capi-helm-charts/releases/download/$LATEST_TAG/dependencies.json)
# Parse JSON into bash variables
ADDON_PROVIDER=$(echo $DEPENDENCIES_JSON | jq -r '.["addon-provider"]')
AZIMUTH_IMAGES_TAG=$(echo $DEPENDENCIES_JSON | jq -r '.["azimuth-images"]')
CLUSTER_API=$(echo $DEPENDENCIES_JSON | jq -r '.["cluster-api"]')
CLUSTER_API_JANITOR_OPENSTACK=$(echo $DEPENDENCIES_JSON | jq -r '.["cluster-api-janitor-openstack"]')
CLUSTER_API_PROVIDER_OPENSTACK=$(echo $DEPENDENCIES_JSON | jq -r '.["cluster-api-provider-openstack"]')
CERT_MANAGER=$(echo $DEPENDENCIES_JSON | jq -r '.["cert-manager"]')
HELM=$(echo $DEPENDENCIES_JSON | jq -r '.["helm"]')
SONOBUOY=$(echo $DEPENDENCIES_JSON | jq -r '.["sonobuoy"]')
# # Install `kubectl` CLI
curl -fsLo /tmp/kubectl "https://dl.k8s.io/release/$(curl -fsL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 /tmp/kubectl /usr/local/bin/kubectl
# Install k3s
curl -fsL https://get.k3s.io | sudo bash -s - --disable traefik
# copy kubeconfig file into standard location
mkdir -p $HOME/.kube
sudo cp /etc/rancher/k3s/k3s.yaml $HOME/.kube/config
sudo chown $USER $HOME/.kube/config
# Install helm
curl -fsL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# Install cert manager
{
helm upgrade cert-manager cert-manager \
--install \
--namespace cert-manager \
--create-namespace \
--repo https://charts.jetstack.io \
--version $CERT_MANAGER \
--set installCRDs=true \
--wait \
--timeout 10m
} || {
kubectl -n cert-manager get pods | awk '$1 && $1!="NAME" { print $1 }' | xargs -n1 kubectl -n cert-manager logs
exit
}
# Install clusterctl
curl -L https://github.com/kubernetes-sigs/cluster-api/releases/download/$CLUSTER_API/clusterctl-linux-amd64 -o clusterctl
sudo install -o root -g root -m 0755 clusterctl /usr/local/bin/clusterctl
# Install Cluster API resources
# using the matching tested values here:
# https://github.com/azimuth-cloud/capi-helm-charts/blob/main/dependencies.json
clusterctl init \
--core cluster-api:$CLUSTER_API \
--bootstrap kubeadm:$CLUSTER_API \
--control-plane kubeadm:$CLUSTER_API \
--infrastructure openstack:$CLUSTER_API_PROVIDER_OPENSTACK
# Install addon manager
helm upgrade cluster-api-addon-provider cluster-api-addon-provider \
--install \
--repo https://azimuth-cloud.github.io/cluster-api-addon-provider \
--version $ADDON_PROVIDER \
--namespace capi-addon-system \
--create-namespace \
--wait \
--timeout 10m
# Install janitor
helm upgrade cluster-api-janitor-openstack cluster-api-janitor-openstack \
--install \
--repo https://azimuth-cloud.github.io/cluster-api-janitor-openstack \
--version $CLUSTER_API_JANITOR_OPENSTACK \
--namespace capi-janitor-system \
--create-namespace \
--wait \
--timeout 10m
pip install python-magnumclient
# Configure OpenStack auth
source /opt/stack/openrc admin admin
# Create a flavor that is *just* big enough for Kubernetes
openstack flavor create ds2G20 --ram 2048 --disk 20 --id d5 --vcpus 2 --public
# Curl the manifest
AZIMUTH_IMAGES=$(curl -fsL "https://github.com/azimuth-cloud/azimuth-images/releases/download/$AZIMUTH_IMAGES_TAG/manifest.json")
# Get the keys of the Kubernetes images
K8S_IMAGE_KEYS="$(echo "$AZIMUTH_IMAGES" | jq -r '. | with_entries(select(.value | has("kubernetes_version"))) | keys | sort | .[]')"
# For each Kubernetes image, upload the image and create a corresponding COE template
for K8S_IMAGE_KEY in $K8S_IMAGE_KEYS; do
K8S_IMAGE_NAME="$(echo "$AZIMUTH_IMAGES" | jq -r ".[\"$K8S_IMAGE_KEY\"].name")"
K8S_IMAGE_URL="$(echo "$AZIMUTH_IMAGES" | jq -r ".[\"$K8S_IMAGE_KEY\"].url")"
K8S_IMAGE_VERSION="$(echo "$AZIMUTH_IMAGES" | jq -r ".[\"$K8S_IMAGE_KEY\"].kubernetes_version")"
# Download the image and upload it to Glance
curl -fsSLo "$K8S_IMAGE_NAME.qcow2" "$K8S_IMAGE_URL"
openstack image create "$K8S_IMAGE_NAME" \
--file "$K8S_IMAGE_NAME.qcow2" \
--disk-format qcow2 \
--container-format bare \
--public
rm "$K8S_IMAGE_NAME.qcow2"
openstack image set "$K8S_IMAGE_NAME" --os-distro ubuntu --os-version 22.04
openstack image set "$K8S_IMAGE_NAME" --property kube_version="$K8S_IMAGE_VERSION"
K8S_IMAGE_ID=$(openstack image show $K8S_IMAGE_NAME -c id -f value)
# Create a COE template for the image
openstack coe cluster template create "k8s-${K8S_IMAGE_VERSION//./-}" \
--coe kubernetes \
--image "$K8S_IMAGE_ID" \
--labels \
capi_helm_chart_version="$LATEST_TAG",\
octavia_provider=ovn,\
monitoring_enabled=true,\
kube_dashboard_enabled=true \
--external-network public \
--master-flavor ds2G20 \
--flavor ds2G20 \
--public \
--master-lb-enabled
done
# You can test it like this:
# openstack coe cluster create devstacktest \
# --cluster-template k8s-v1-28-5 \
# --master-count 1 \
# --node-count 2
# openstack coe cluster list
# openstack coe cluster config devstacktest
+63
View File
@@ -0,0 +1,63 @@
#!/bin/bash
#
# lib/magnum-capi-helm
# Functions to control the configuration and operation of the **magnum_capi_helm** driver
# Dependencies:
#
# - ``functions`` file
# - ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined
# - ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined
# ``stack.sh`` calls the entry points in this order:
#
# - install_magnum_capi_helm
# Save trace setting
XTRACE=$(set +o | grep xtrace)
set +o xtrace
# Defaults
# --------
# Set up default directories
MAGNUM_CAPI_HELM_REPO=${MAGNUM_CAPI_HELM_REPO:-${GIT_BASE}/openstack/magnum-capi-helm.git}
MAGNUM_CAPI_HELM_BRANCH=${MAGNUM_CAPI_HELM_BRANCH:-master}
MAGNUM_CAPI_HELM_DIR=$DEST/magnum-capi-helm
MAGNUM_CAPI_HELM_ADDON_PROVIDER_VERSION=${MAGNUM_CAPI_HELM_ADDON_PROVIDER_VERSION:-"0.12.0"}
MAGNUM_CAPI_HELM_CAPI_JANITOR_OPENSTACK_VERSION=${MAGNUM_CAPI_HELM_CAPI_JANITOR_OPENSTACK_VERSION:-"0.12.0"}
# install_magnum_capi_helm() - Collect source and prepare
function install_magnum_capi_helm {
setup_develop $MAGNUM_CAPI_HELM_DIR
}
# install_helm() - Collect helm CLI and install
function install_helm {
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
}
# install_azimuth_cluster_api_addon_provider()
function install_azimuth_cluster_api_addon_provider {
helm upgrade cluster-api-addon-provider cluster-api-addon-provider \
--install \
--repo https://azimuth-cloud.github.io/cluster-api-addon-provider \
--version $MAGNUM_CAPI_HELM_ADDON_PROVIDER_VERSION \
--namespace capi-addon-system \
--create-namespace \
--wait \
--timeout 10m
}
# install_azimuth_cluster_api_janitor_openstack()
function install_azimuth_capi_janitor_openstack {
helm upgrade cluster-api-janitor-openstack cluster-api-janitor-openstack \
--install \
--repo https://azimuth-cloud.github.io/cluster-api-janitor-openstack \
--version $MAGNUM_CAPI_HELM_CAPI_JANITOR_OPENSTACK_VERSION \
--namespace capi-janitor-system \
--create-namespace \
--wait \
--timeout 10m
}
+28
View File
@@ -0,0 +1,28 @@
# magnum-capi-helm plugin.sh - Devstack extras script to install magnum
# Save trace setting
XTRACE=$(set +o | grep xtrace)
set -o xtrace
echo_summary "magnum's plugin.sh was called..."
source $DEST/magnum-capi-helm/devstack/lib/magnum-capi-helm
(set -o posix; set)
if is_service_enabled magnum-api magnum-cond; then
if [[ "$1" == "stack" && "$2" == "install" ]]; then
echo_summary "Installing helm binary"
install_helm
echo_summary "Installing magnum-capi-helm"
install_magnum_capi_helm
elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
if is_service_enabled k8s-capi; then
echo_summary "Installing Azimuth CAPI addon provider"
install_azimuth_cluster_api_addon_provider
echo_summary "Installing Azimuth CAPI janitor OpenStack"
install_azimuth_capi_janitor_openstack
fi
fi
fi
# Restore xtrace
$XTRACE
+9
View File
@@ -0,0 +1,9 @@
---
- hosts: all
roles:
- fetch_docker_log
- fetch_kubelet_log
- hosts: controller
roles:
- fetch_pod_log
+16
View File
@@ -0,0 +1,16 @@
- hosts: all
tasks:
- name: Set up ipv4 iptables rules for Kubernetes
become: yes
iptables:
state: present
action: insert
chain: INPUT
ip_version: ipv4
source: "{{ item }}"
jump: ACCEPT
with_items:
# Default flannel pod cidr
- "10.244.0.0/16"
# Default kubernetes service cidr
- "10.96.0.0/12"
+39
View File
@@ -0,0 +1,39 @@
---
- job:
name: magnum-capi-helm-tests-cluster
parent: magnum-tempest-plugin-tests-cluster-base
nodeset: magnum-ubuntu-noble-32GB
pre-run: playbooks/pre.yaml
post-run: playbooks/post.yaml
roles:
- zuul: openstack/devstack-plugin-container
vars:
devstack_localrc:
CONTAINER_ENGINE: "crio"
CRIO_VERSION: "1.32.1"
K8S_TOKEN: "0cvq6p.k454yiandj1tjxxv"
K8S_COPY_KUBECONFIG_PATH: "/etc/magnum/kubeconfig"
FIXED_RANGE: 10.1.0.0/20
OCTAVIA_NODE: api
DISABLE_AMP_IMAGE_BUILD: true
devstack_plugins:
devstack-plugin-container: https://opendev.org/openstack/devstack-plugin-container
magnum: https://review.opendev.org/openstack/magnum
magnum-capi-helm: https://opendev.org/openstack/magnum-capi-helm
octavia: https://opendev.org/openstack/octavia
ovn-octavia-provider: https://github.com/openstack/ovn-octavia-provider
devstack_services:
etcd3: true
container: true
k8s-master: true
k8s-capi: true
octavia: true
o-api: true
o-cw: true
o-da: true
o-hk: true
o-hm: true
required-projects:
- openstack/devstack-plugin-container
- openstack/octavia
- openstack/ovn-octavia-provider
+82
View File
@@ -0,0 +1,82 @@
---
- project-template:
name: magnum-capi-helm-tests-cluster-v1_34
description: |
Runs Magnum CAPI Helm v1.34 jobs
check:
jobs:
- magnum-capi-helm-tests-cluster-v1_34-2026_1
gate:
jobs:
- magnum-capi-helm-tests-cluster-v1_34-2026_1
- job:
name: magnum-capi-helm-tests-cluster-v1_34-2026_1
parent: magnum-capi-helm-tests-cluster-v1_34
required-projects:
- name: openstack/magnum
override-checkout: stable/2026.1
- job:
name: magnum-capi-helm-tests-cluster-v1_34
parent: magnum-capi-helm-tests-cluster
vars:
devstack_localrc:
ETCD_VERSION: "v3.6.11"
ETCD_SHA256: "8756f7a4eaf921668a83de0bf13c0f65cae9186a165696e3ae8396afe6f557ed"
K8S_CAPI_VERSION: "v1.10.4"
K8S_CAPO_VERSION: "v0.11.3"
K8S_VERSION: "1.34.7"
MAGNUM_GUEST_IMAGE_URL: "https://github.com/vexxhost/capo-image-elements/releases/download/2026.04-5/ubuntu-22.04-v1.34.7.qcow2"
MAGNUM_GUEST_IMAGE_EXTRA_PROPERTIES: "--property kube_version=1.34.7"
devstack_local_conf:
post-config:
$MAGNUM_CONF:
capi_helm:
default_helm_chart_version: "0.23.0"
test-config:
$TEMPEST_CONFIG:
magnum:
image_id: ubuntu-22.04-v1.34.7
labels:
octavia_provider: "ovn"
master_lb_floating_ip_enabled: "true"
- job:
name: magnum-capi-helm-tests-cluster
parent: magnum-tempest-plugin-tests-cluster-base
nodeset: magnum-ubuntu-noble-32GB
pre-run: playbooks/pre.yaml
post-run: playbooks/post.yaml
roles:
- zuul: openstack/devstack-plugin-container
vars:
devstack_localrc:
CONTAINER_ENGINE: "crio"
CRIO_VERSION: "1.32.1"
K8S_TOKEN: "0cvq6p.k454yiandj1tjxxv"
K8S_COPY_KUBECONFIG_PATH: "/etc/magnum/kubeconfig"
FIXED_RANGE: 10.1.0.0/20
OCTAVIA_NODE: api
DISABLE_AMP_IMAGE_BUILD: true
devstack_plugins:
devstack-plugin-container: https://opendev.org/openstack/devstack-plugin-container
magnum: https://review.opendev.org/openstack/magnum
magnum-capi-helm: https://opendev.org/openstack/magnum-capi-helm
octavia: https://opendev.org/openstack/octavia
ovn-octavia-provider: https://github.com/openstack/ovn-octavia-provider
devstack_services:
etcd3: true
container: true
k8s-master: true
k8s-capi: true
octavia: true
o-api: true
o-cw: true
o-da: true
o-hk: true
o-hm: true
required-projects:
- openstack/devstack-plugin-container
- openstack/octavia
- openstack/ovn-octavia-provider
+9
View File
@@ -0,0 +1,9 @@
- nodeset:
name: magnum-ubuntu-noble-32GB
nodes:
- name: controller
label: ubuntu-noble-32GB
groups:
- name: tempest
nodes:
- controller
+1
View File
@@ -2,6 +2,7 @@
- project:
queue: magnum
templates:
- magnum-capi-helm-tests-cluster-v1_34
- openstack-cover-jobs-magnum
- openstack-python3-jobs-magnum
- release-notes-jobs-python3