diff --git a/.zuul.yaml b/.zuul.yaml index 6dae1e0..bf16258 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -19,7 +19,9 @@ - airship-maas-chart-build-latest-htk - airship-maas-docker-build-gate-ubuntu-focal - airship-maas-docker-build-gate-ubuntu-jammy + - airship-maas-docker-build-gate-ubuntu-noble - airship-maas-lint-yaml + - maas-airskiff-deployment-noble-kubeadm - maas-airskiff-deployment-jammy-kubeadm - maas-airskiff-deployment-focal-kubeadm gate: @@ -28,11 +30,14 @@ - airship-maas-chart-build-gate - airship-maas-docker-build-gate-ubuntu-focal - airship-maas-docker-build-gate-ubuntu-jammy + - airship-maas-docker-build-gate-ubuntu-noble - airship-maas-lint-yaml post: jobs: - - airship-maas-docker-publish + - airship-maas-docker-publish-focal + - airship-maas-docker-publish-jammy + - airship-maas-docker-publish-noble - maas-upload-git-mirror - nodeset: @@ -80,6 +85,22 @@ vars: HTK_COMMIT: master +- job: + name: airship-maas-docker-build-gate-ubuntu-noble + # Pinned for now due to Ansible 11 stopped verbosive output. + ansible-version: 9 + timeout: 3600 + run: tools/gate/playbooks/docker-image-build.yaml + nodeset: airship-maas-single-node-jammy + files: + - "^images/.*" + vars: + publish: false + distro: ubuntu_noble + tags: + dynamic: + patch_set: true + - job: name: airship-maas-docker-build-gate-ubuntu-jammy # Pinned for now due to Ansible 11 stopped verbosive output. @@ -125,7 +146,28 @@ - "^charts/maas/templates/.*" - job: - name: airship-maas-docker-publish + name: airship-maas-docker-publish-focal + # Pinned for now due to Ansible 11 stopped verbosive output. + ansible-version: 9 + timeout: 3600 + run: tools/gate/playbooks/docker-image-build.yaml + nodeset: airship-maas-single-node-jammy + secrets: + - airship_maas_quay_creds + irrelevant-files: + - "^images/.*" + vars: + publish: true + distro: ubuntu_focal + tags: + dynamic: + branch: true + commit: true + static: + - latest + +- job: + name: airship-maas-docker-publish-jammy # Pinned for now due to Ansible 11 stopped verbosive output. ansible-version: 9 timeout: 3600 @@ -145,6 +187,49 @@ static: - latest +- job: + name: airship-maas-docker-publish-noble + # Pinned for now due to Ansible 11 stopped verbosive output. + ansible-version: 9 + timeout: 3600 + run: tools/gate/playbooks/docker-image-build.yaml + nodeset: airship-maas-single-node-jammy + secrets: + - airship_maas_quay_creds + irrelevant-files: + - "^images/.*" + vars: + publish: true + distro: ubuntu_jammy + tags: + dynamic: + branch: true + commit: true + static: + - latest + +- job: + name: maas-airskiff-deployment-noble-kubeadm + # Pinned for now due to Ansible 11 stopped verbosive output. + ansible-version: 9 + description: | + Deploy maas using Airskiff and submitted Shipyard changes. + parent: treasuremap-airskiff-deploy-maas-drydock-base + nodeset: treasuremap-airskiff-1node-32GB-ubuntu_jammy + required-projects: + - name: airship/treasuremap + override-checkout: v1.9 + roles: + - zuul: airship/treasuremap + vars: + treasuremap_ref: v1.9 + CLONE_MAAS: false + MAKE_MAAS_IMAGES: true + DISTRO: ubuntu_noble + DOCKER_REGISTRY: localhost:5000 + gate_scripts_relative_path: ../../airship/treasuremap + zuul_treasuremap_relative_path: ../../airship/treasuremap + - job: name: maas-airskiff-deployment-jammy-kubeadm # Pinned for now due to Ansible 11 stopped verbosive output. diff --git a/images/maas-rack-controller-focal/Dockerfile b/images/maas-rack-controller-focal/Dockerfile index 9523944..7dacba4 100644 --- a/images/maas-rack-controller-focal/Dockerfile +++ b/images/maas-rack-controller-focal/Dockerfile @@ -19,6 +19,7 @@ ENV DEBIAN_FRONTEND=noninteractive ENV container=docker ENV MAAS_VERSION=1:3.0.2-10056-g.089ec66c2-0ubuntu1~20.04.1 +ENV MAAS_PPA=ppa:maas/3.0 RUN apt-get -qq update \ && apt-get install -y \ @@ -43,7 +44,7 @@ RUN apt-get -qq update \ -exec rm \{} \; \ && systemctl set-default multi-user.target \ # Install maas from the ppa - && add-apt-repository -yu ppa:maas/3.0 \ + && add-apt-repository -yu $MAAS_PPA \ && apt-get install -y \ maas-rack-controller=$MAAS_VERSION \ && rm -rf /var/lib/apt/lists/*\ diff --git a/images/maas-rack-controller-jammy/Dockerfile b/images/maas-rack-controller-jammy/Dockerfile index fc37f43..e03c17e 100644 --- a/images/maas-rack-controller-jammy/Dockerfile +++ b/images/maas-rack-controller-jammy/Dockerfile @@ -19,6 +19,7 @@ ENV DEBIAN_FRONTEND=noninteractive ENV container=docker ENV MAAS_VERSION=1:3.5.8-16381-g.d7e999261-0ubuntu1~22.04.1 +ENV MAAS_PPA=ppa:maas/3.5 RUN apt-get -qq update \ && apt upgrade -y \ @@ -44,7 +45,7 @@ RUN apt-get -qq update \ -exec rm \{} \; \ && systemctl set-default multi-user.target \ # Install maas from the ppa - && add-apt-repository -yu ppa:maas/3.5 \ + && add-apt-repository -yu $MAAS_PPA \ && apt-get install -y \ maas-rack-controller=$MAAS_VERSION \ && rm -rf /var/lib/apt/lists/*\ diff --git a/images/maas-rack-controller-noble/3.6_ipmi_error.patch b/images/maas-rack-controller-noble/3.6_ipmi_error.patch new file mode 100644 index 0000000..bcfafe3 --- /dev/null +++ b/images/maas-rack-controller-noble/3.6_ipmi_error.patch @@ -0,0 +1,27 @@ +diff --git a/src/provisioningserver/drivers/power/ipmi.py b/src/provisioningserver/drivers/power/ipmi.py +index 752ae66..e8f1632 100644 +--- a/src/provisioningserver/drivers/power/ipmi.py ++++ b/src/provisioningserver/drivers/power/ipmi.py +@@ -155,6 +155,13 @@ IPMI_ERRORS = { + ), + "exception": PowerConnError, + }, ++ "BMC error": { ++ "message": ( ++ "Device not responding correctly while performing power action." ++ " MAAS performed several retries. Please wait and try again." ++ ), ++ "exception": PowerConnError, ++ }, + "could not find inband device": { + "message": ( + "An inband device could not be found." +@@ -321,7 +328,7 @@ class IPMIPowerDriver(PowerDriver): + ), + ] + ip_extractor = make_ip_extractor("power_address") +- wait_time = (4, 8, 16, 32) ++ wait_time = (4, 4, 8, 8, 16, 16, 32, 32) + + def detect_missing_packages(self): + if not shell.has_command_available("ipmipower"): diff --git a/images/maas-rack-controller-noble/3.6_nic_filter.patch b/images/maas-rack-controller-noble/3.6_nic_filter.patch new file mode 100644 index 0000000..ba4da85 --- /dev/null +++ b/images/maas-rack-controller-noble/3.6_nic_filter.patch @@ -0,0 +1,13 @@ +diff --git a/src/provisioningserver/utils/network.py b/src/provisioningserver/utils/network.py +index 6124f68..fb1fa0b 100644 +--- a/src/provisioningserver/utils/network.py ++++ b/src/provisioningserver/utils/network.py +@@ -1187,6 +1187,8 @@ def get_all_interfaces_definition( + # interfaces for guests. By themselves, they're not useful for MAAS to + # manage. + "tunnel", ++ # Always exclude non-specific ethernet interfaces. ++ "ethernet", + ] + if not running_in_container(): + # When not running in a container, we should be able to identify diff --git a/images/maas-rack-controller-noble/3.6_redfish_retries.patch b/images/maas-rack-controller-noble/3.6_redfish_retries.patch new file mode 100644 index 0000000..040a0e8 --- /dev/null +++ b/images/maas-rack-controller-noble/3.6_redfish_retries.patch @@ -0,0 +1,12 @@ +diff --git a/src/provisioningserver/drivers/power/redfish.py b/src/provisioningserver/drivers/power/redfish.py +index e46d930..dbe17a3 100644 +--- a/src/provisioningserver/drivers/power/redfish.py ++++ b/src/provisioningserver/drivers/power/redfish.py +@@ -175,6 +175,7 @@ class RedfishPowerDriver(RedfishPowerDriverBase): + make_setting_field("node_id", "Node ID", scope=SETTING_SCOPE.NODE), + ] + ip_extractor = make_ip_extractor("power_address") ++ wait_time = (4, 8, 16, 32) + + def detect_missing_packages(self): + # no required packages diff --git a/images/maas-rack-controller-noble/3.6_secure_headers.patch b/images/maas-rack-controller-noble/3.6_secure_headers.patch new file mode 100644 index 0000000..ca66adf --- /dev/null +++ b/images/maas-rack-controller-noble/3.6_secure_headers.patch @@ -0,0 +1,12 @@ +diff --git a/src/twisted/web/server.py b/src/twisted/web/server.py +index d30156b..3a04ecb 100644 +--- a/src/twisted/web/server.py ++++ b/src/twisted/web/server.py +@@ -206,7 +206,6 @@ class Request(Copyable, http.Request, components.Componentized): + self.site = self.channel.site + + # set various default headers +- self.setHeader(b"server", version) + self.setHeader(b"date", http.datetimeToString()) + + # Resource Identification diff --git a/images/maas-rack-controller-noble/3.6_transfer_trusted_only.patch b/images/maas-rack-controller-noble/3.6_transfer_trusted_only.patch new file mode 100644 index 0000000..faa6dcf --- /dev/null +++ b/images/maas-rack-controller-noble/3.6_transfer_trusted_only.patch @@ -0,0 +1,9 @@ +diff --git a/src/provisioningserver/templates/dns/named.conf.options.inside.maas.template b/src/provisioningserver/templates/dns/named.conf.options.inside.maas.template +index d76fcfa9a..0cca0fe8d 100644 +--- a/src/provisioningserver/templates/dns/named.conf.options.inside.maas.template ++++ b/src/provisioningserver/templates/dns/named.conf.options.inside.maas.template +@@ -18,3 +18,4 @@ allow-recursion { trusted; }; + {{if not upstream_allow_query_cache}} + allow-query-cache { trusted; }; + {{endif}} ++allow-transfer { trusted; }; diff --git a/images/maas-rack-controller-noble/Dockerfile b/images/maas-rack-controller-noble/Dockerfile new file mode 100644 index 0000000..86ae3fe --- /dev/null +++ b/images/maas-rack-controller-noble/Dockerfile @@ -0,0 +1,96 @@ +ARG FROM=quay.io/airshipit/ubuntu:noble +FROM ${FROM} + +LABEL org.opencontainers.image.authors='airship-discuss@lists.airshipit.org, irc://#airshipit@freenode' +LABEL org.opencontainers.image.url='https://airshipit.org' +LABEL org.opencontainers.image.documentation='https://github.com/openstack/airship-maas' +LABEL org.opencontainers.image.source='https://git.openstack.org/openstack/airship-maas' +LABEL org.opencontainers.image.vendor='The Airship Authors' +LABEL org.opencontainers.image.licenses='Apache-2.0' + +ARG HTTP_PROXY +ARG HTTPS_PROXY +ARG NO_PROXY +ARG http_proxy +ARG https_proxy +ARG no_proxy + +ENV DEBIAN_FRONTEND=noninteractive +ENV container=docker + +ENV MAAS_VERSION=1:3.6.2-17588-g.7b59ae9e8-0ubuntu1~24.04.1 +ENV MAAS_PPA=ppa:maas/3.6 + +RUN apt-get -qq update \ + && apt upgrade -y \ + && apt-get install -y \ + avahi-daemon \ + isc-dhcp-server \ + jq \ + libvirt-clients \ + libvirt-daemon-system\ + patch \ + software-properties-common \ + sudo \ + systemd \ + ca-certificates \ +# Don't start any optional services except for the few we need. +# (specifically, don't start avahi-daemon, isc-dhcp-server, or libvirtd) + && find /etc/systemd/system \ + /lib/systemd/system \ + -path '*.wants/*' \ + -not -name '*journald*' \ + -not -name '*systemd-tmpfiles*' \ + -not -name '*systemd-user-sessions*' \ + -exec rm \{} \; \ + && systemctl set-default multi-user.target \ +# Install maas from the ppa + && add-apt-repository -yu $MAAS_PPA \ + && apt-get install -y \ + maas-rack-controller=$MAAS_VERSION \ + && rm -rf /var/lib/apt/lists/*\ + && rm -f /etc/ssl/private/.*snakeoil.* + +# Preserve the directory structure, permissions, and contents of /var/lib/maas +RUN mkdir -p /opt/maas/ && tar -cvzf /opt/maas/var-lib-maas.tgz /var/lib/maas + +# register ourselves with the region controller +COPY scripts/register-rack-controller.service /lib/systemd/system/register-rack-controller.service +RUN systemctl enable register-rack-controller.service + +# Patch so that Calico interfaces are ignored +COPY 3.6_nic_filter.patch /tmp/3.6_nic_filter.patch +COPY 3.6_secure_headers.patch /tmp/3.6_secure_headers.patch +# Patch so maas knows that "BMC error" is retriable +COPY 3.6_ipmi_error.patch /tmp/3.6_ipmi_error.patch +# Patch to space redfish request retries apart a bit, to avoid overwhelming the BMC +COPY 3.6_redfish_retries.patch /tmp/3.6_redfish_retries.patch +# Patch to restrict access to zone transfers +COPY 3.6_transfer_trusted_only.patch /tmp/3.6_transfer_trusted_only.patch + +RUN cd /usr/lib/python3/dist-packages/provisioningserver/utils && patch network.py < /tmp/3.6_nic_filter.patch +RUN cd /usr/lib/python3/dist-packages/twisted/web && patch server.py < /tmp/3.6_secure_headers.patch +RUN cd /usr/lib/python3/dist-packages/provisioningserver/drivers/power && patch ipmi.py < /tmp/3.6_ipmi_error.patch +RUN cd /usr/lib/python3/dist-packages/provisioningserver/drivers/power && patch redfish.py < /tmp/3.6_redfish_retries.patch +RUN cd /usr/lib/python3/dist-packages/provisioningserver/templates/dns && patch named.conf.options.inside.maas.template < /tmp/3.6_transfer_trusted_only.patch + +# echo journalctl logs to the container's stdout +COPY scripts/journalctl-to-tty.service /etc/systemd/system/journalctl-to-tty.service +RUN systemctl enable journalctl-to-tty.service + +# quiet sudo for the maas user +RUN umask 0337; echo 'Defaults:maas !pam_session, !syslog' > /etc/sudoers.d/99-maas-no-log + +# avoid triggering bind9 high cpu utilization bug +RUN sed -i -e '$a\include "/etc/bind/bind.keys";' /etc/bind/named.conf && /usr/lib/maas/maas-common setup-dns + +# fix chronyd.pid permission +COPY scripts/override.chrony.conf /etc/systemd/system/chrony.service.d/override.conf + +# fix httpproxy.sock permission +COPY scripts/maas-http-watcher.service /etc/systemd/system/maas-http-watcher.service +COPY scripts/maas-http-watcher.path /etc/systemd/system/maas-http-watcher.path +RUN systemctl enable maas-http-watcher.service + +# initalize systemd +CMD ["/bin/bash", "-c", "exec /sbin/init --log-target=console 3>&1"] diff --git a/images/maas-rack-controller-noble/README.md b/images/maas-rack-controller-noble/README.md new file mode 100644 index 0000000..0a11659 --- /dev/null +++ b/images/maas-rack-controller-noble/README.md @@ -0,0 +1 @@ +[![Docker Repository on Quay](https://quay.io/repository/airshipit/maas-rack/status "Docker Repository on Quay")](https://quay.io/repository/airshipit/maas-rack) Ubuntu MaaS Rack Controller diff --git a/images/maas-rack-controller-noble/scripts/journalctl-to-tty.service b/images/maas-rack-controller-noble/scripts/journalctl-to-tty.service new file mode 100644 index 0000000..2725055 --- /dev/null +++ b/images/maas-rack-controller-noble/scripts/journalctl-to-tty.service @@ -0,0 +1,13 @@ +[Unit] +Description=Journald console log streamer +Requires=systemd-journald.service +After=systemd-journald.service + +[Service] +Restart=always +RestartSec=0 +ExecStart=/bin/journalctl -f +StandardOutput=tty + +[Install] +WantedBy=basic.target diff --git a/images/maas-rack-controller-noble/scripts/maas-http-watcher.path b/images/maas-rack-controller-noble/scripts/maas-http-watcher.path new file mode 100644 index 0000000..7a6b60f --- /dev/null +++ b/images/maas-rack-controller-noble/scripts/maas-http-watcher.path @@ -0,0 +1,5 @@ +[Path] +PathModified=/var/run/maas/httpproxy.sock + +[Install] +WantedBy=multi-user.target diff --git a/images/maas-rack-controller-noble/scripts/maas-http-watcher.service b/images/maas-rack-controller-noble/scripts/maas-http-watcher.service new file mode 100644 index 0000000..89ccd4b --- /dev/null +++ b/images/maas-rack-controller-noble/scripts/maas-http-watcher.service @@ -0,0 +1,9 @@ +[Unit] +Description=MAAS HTTP server and reverse proxy server +After=network.target + +[Service] +ExecStart=bash -c 'until (stat -f /var/run/maas/httpproxy.sock); do sleep 60; done; chmod o+rw /var/run/maas/httpproxy.sock' + +[Install] +WantedBy=multi-user.target diff --git a/images/maas-rack-controller-noble/scripts/override.chrony.conf b/images/maas-rack-controller-noble/scripts/override.chrony.conf new file mode 100644 index 0000000..6f3cd41 --- /dev/null +++ b/images/maas-rack-controller-noble/scripts/override.chrony.conf @@ -0,0 +1,3 @@ +[Service] +ExecStartPre=-mkdir -p /var/log/chrony +ExecStartPre=-chown root /var/run/chrony diff --git a/images/maas-rack-controller-noble/scripts/register-rack-controller.service b/images/maas-rack-controller-noble/scripts/register-rack-controller.service new file mode 100644 index 0000000..fb439d3 --- /dev/null +++ b/images/maas-rack-controller-noble/scripts/register-rack-controller.service @@ -0,0 +1,12 @@ +[Unit] +Description=Register with MaaS Region Controller +Wants=network-online.target +After=network-online.target + +[Service] +Type=oneshot +PassEnvironment=MAAS_ENDPOINT MAAS_REGION_SECRET MAAS_API_KEY HOST_MOUNT_PATH +ExecStart=/usr/local/bin/register-rack-controller.sh + +[Install] +WantedBy=multi-user.target diff --git a/images/maas-rack-controller/Dockerfile b/images/maas-rack-controller/Dockerfile index a1a022c..4ac7c15 100644 --- a/images/maas-rack-controller/Dockerfile +++ b/images/maas-rack-controller/Dockerfile @@ -19,6 +19,7 @@ ENV DEBIAN_FRONTEND noninteractive ENV container docker ENV MAAS_VERSION=2.8.7-8611-g.f2514168f-0ubuntu1~18.04.1 +ENV MAAS_PPA=ppa:maas/2.8 RUN apt-get -qq update \ && apt-get install -y \ @@ -42,7 +43,7 @@ RUN apt-get -qq update \ -exec rm \{} \; \ && systemctl set-default multi-user.target \ # Install maas from the ppa - && add-apt-repository -yu ppa:maas/2.8 \ + && add-apt-repository -yu $MAAS_PPA \ && apt-get install -y \ maas-rack-controller=$MAAS_VERSION \ && rm -rf /var/lib/apt/lists/* diff --git a/images/maas-region-controller-focal/Dockerfile b/images/maas-region-controller-focal/Dockerfile index 3a4bbf1..2ccb4db 100644 --- a/images/maas-region-controller-focal/Dockerfile +++ b/images/maas-region-controller-focal/Dockerfile @@ -19,6 +19,7 @@ ENV DEBIAN_FRONTEND=noninteractive ENV container=docker ENV MAAS_VERSION=1:3.0.2-10056-g.089ec66c2-0ubuntu1~20.04.1 +ENV MAAS_PPA=ppa:maas/3.0 RUN apt-get -qq update \ && apt-get install -y \ @@ -41,7 +42,7 @@ RUN apt-get -qq update \ -exec rm \{} \; \ && systemctl set-default multi-user.target \ # Install maas from the ppa - && add-apt-repository -yu ppa:maas/3.0 \ + && add-apt-repository -yu $MAAS_PPA \ && apt-get install -y \ maas-region-api=$MAAS_VERSION \ # tcpdump is required by /usr/lib/maas/beacon-monitor diff --git a/images/maas-region-controller-jammy/Dockerfile b/images/maas-region-controller-jammy/Dockerfile index 0074d76..c6f9cd7 100644 --- a/images/maas-region-controller-jammy/Dockerfile +++ b/images/maas-region-controller-jammy/Dockerfile @@ -19,6 +19,7 @@ ENV DEBIAN_FRONTEND=noninteractive ENV container=docker ENV MAAS_VERSION=1:3.5.8-16381-g.d7e999261-0ubuntu1~22.04.1 +ENV MAAS_PPA=ppa:maas/3.5 RUN apt-get -qq update \ && apt upgrade -y \ @@ -43,7 +44,7 @@ RUN apt-get -qq update \ -exec rm \{} \; \ && systemctl set-default multi-user.target \ # Install maas from the ppa - && add-apt-repository -yu ppa:maas/3.5 \ + && add-apt-repository -yu $MAAS_PPA \ && apt-get install -y \ maas-region-api=$MAAS_VERSION \ # tcpdump is required by /usr/lib/maas/beacon-monitor diff --git a/images/maas-region-controller-noble/3.6_configure_ipmi_user.patch b/images/maas-region-controller-noble/3.6_configure_ipmi_user.patch new file mode 100644 index 0000000..136b928 --- /dev/null +++ b/images/maas-region-controller-noble/3.6_configure_ipmi_user.patch @@ -0,0 +1,70 @@ +diff --git a/src/metadataserver/builtin_scripts/commissioning_scripts/bmc_config.py b/src/metadataserver/builtin_scripts/commissioning_scripts/bmc_config.py +index 9d032ee..b01a12a 100755 +--- a/src/metadataserver/builtin_scripts/commissioning_scripts/bmc_config.py ++++ b/src/metadataserver/builtin_scripts/commissioning_scripts/bmc_config.py +@@ -129,17 +129,27 @@ class BMCConfig(metaclass=ABCMeta): + """Returns boolean value of whether the BMC was detected.""" + + def add_bmc_user(self): +- """Add the specified BMC user and (re)set its password. +- +- Should set the username and password, even if it hasn't been +- changed. +- """ +- # MAAS is the default user and will always be passed to the script. +- if self.username not in (None, "maas"): +- print( +- "WARNING: Unable to set a specific username or password on %s!" +- % self +- ) ++ """Create/configure an IPMI user, but with several tries""" ++ attempt = 1 ++ max_attempts = 5 ++ backoff_amount = 30 ++ exceptions_caught = [] ++ while attempt <= max_attempts: ++ print("INFO: Attempt to add IPMI BMC user - %s" % attempt) ++ try: ++ self._add_bmc_user() ++ except Exception as e: ++ exceptions_caught.append(e) ++ if (attempt + 1) > max_attempts: ++ # This is our last attempt, exiting ++ print("ERROR: Unable to add BMC user!\n{}".format(exceptions_caught), file=sys.stderr) ++ sys.exit(1) ++ ++ if self.password is None: ++ time.sleep(attempt * backoff_amount) ++ else: ++ return ++ attempt += 1 + + def configure(self): + """Configure the BMC for use.""" +@@ -188,7 +198,7 @@ class IPMIBase(BMCConfig): + first_unused = section_name + return first_unused + +- def add_bmc_user(self): ++ def _add_bmc_user(self): + if not self.username: + self.username = "maas" + user_number = self._pick_user_number(self.username) +@@ -212,7 +222,7 @@ class IPMIBase(BMCConfig): + if self._bmc_config[user_number].get(key) != value: + self._bmc_set(user_number, key, value) + except Exception: +- pass ++ raise + else: + self.password = password + # Not all user settings are available on all BMC keys, its +@@ -227,8 +237,6 @@ class IPMIBase(BMCConfig): + "Yes", + ) + return +- print("ERROR: Unable to add BMC user!", file=sys.stderr) +- sys.exit(1) + + def _bmc_get_config(self, section=None): + """Fetch and cache all BMC settings.""" diff --git a/images/maas-region-controller-noble/3.6_kernel_package.patch b/images/maas-region-controller-noble/3.6_kernel_package.patch new file mode 100644 index 0000000..a3b095b --- /dev/null +++ b/images/maas-region-controller-noble/3.6_kernel_package.patch @@ -0,0 +1,31 @@ +diff --git a/src/maasserver/preseed.py b/src/maasserver/preseed.py +index 72a7c86..4559326 100644 +--- a/src/maasserver/preseed.py ++++ b/src/maasserver/preseed.py +@@ -254,7 +254,26 @@ def compose_curtin_kernel_preseed(node): + if node.get_osystem() == "custom": + return [] + ++ # previous logic to retrieve kpackage parameter + kpackage = BootResource.objects.get_kpackage_for_node(node) ++ ++ # determine if this node has kernel parameters applied by drydock ++ # and override kpackage if we discover the right properties ++ kernel_opt_tag = "%s_kp" % (node.hostname) ++ if kernel_opt_tag in node.tag_names(): ++ ++ # the tag exists, retrieve it ++ kernel_opts = node.tags.get(name=kernel_opt_tag).kernel_opts ++ ++ # parse the string and find our package param value ++ # e.g. kernel_package=linux-image-4.15.0-34-generic ++ kparams = kernel_opts.split() ++ kdict = dict( ++ kparam.split("=", 1) for kparam in kparams if "=" in kparam ++ ) ++ if "kernel_package" in kdict: ++ kpackage = kdict["kernel_package"] ++ + if kpackage: + kernel_config = {"kernel": {"package": kpackage, "mapping": {}}} + return [yaml.safe_dump(kernel_config)] diff --git a/images/maas-region-controller-noble/3.6_partitiontable_does_not_exist.patch b/images/maas-region-controller-noble/3.6_partitiontable_does_not_exist.patch new file mode 100644 index 0000000..8346799 --- /dev/null +++ b/images/maas-region-controller-noble/3.6_partitiontable_does_not_exist.patch @@ -0,0 +1,13 @@ +diff --git a/src/maasserver/api/partitions.py b/src/maasserver/api/partitions.py +index 4302d8d..f0e51c8 100644 +--- a/src/maasserver/api/partitions.py ++++ b/src/maasserver/api/partitions.py +@@ -99,7 +99,7 @@ class PartitionsHandler(OperationsHandler): + device = BlockDevice.objects.get_block_device_or_404( + system_id, device_id, request.user, NodePermission.view + ) +- partition_table = device.partitiontable_set.get() ++ partition_table = device.get_partitiontable() + if partition_table is None: + return [] + else: diff --git a/images/maas-region-controller-noble/3.6_proxy_acl.patch b/images/maas-region-controller-noble/3.6_proxy_acl.patch new file mode 100644 index 0000000..0de535e --- /dev/null +++ b/images/maas-region-controller-noble/3.6_proxy_acl.patch @@ -0,0 +1,10 @@ +18,24c18 +< http_access allow maas_proxy_manager localhost +< http_access deny maas_proxy_manager +< http_access deny !Safe_ports +< http_access deny CONNECT !SSL_ports +< http_access allow localnet +< http_access allow localhost +< http_access deny all +--- +> http_access allow all diff --git a/images/maas-region-controller-noble/3.6_regex_tags.patch b/images/maas-region-controller-noble/3.6_regex_tags.patch new file mode 100644 index 0000000..fd96f95 --- /dev/null +++ b/images/maas-region-controller-noble/3.6_regex_tags.patch @@ -0,0 +1,24 @@ +diff --git a/src/maasserver/models/ownerdata.py b/src/maasserver/models/ownerdata.py +index 2cbaa9d..bb83b4b 100644 +--- a/src/maasserver/models/ownerdata.py ++++ b/src/maasserver/models/ownerdata.py +@@ -17,7 +17,7 @@ from django.db.models import ( + + from maasserver.models.cleansave import CleanSave + +-DATA_KEY_RE = re.compile(r"[\w.-]+$") ++#DATA_KEY_RE = re.compile(r"[\w.-]+$") + + + class OwnerDataManager(Manager): +@@ -32,8 +32,8 @@ class OwnerDataManager(Manager): + if value is None: + to_remove.add(key) + else: +- if not DATA_KEY_RE.match(key): +- raise ValueError("Invalid character in key name") ++ # if not DATA_KEY_RE.match(key): ++ # raise ValueError("Invalid character in key name") + + self.update_or_create( + node=node, key=key, defaults={"value": value} diff --git a/images/maas-region-controller-noble/3.6_route.patch b/images/maas-region-controller-noble/3.6_route.patch new file mode 100644 index 0000000..676204c --- /dev/null +++ b/images/maas-region-controller-noble/3.6_route.patch @@ -0,0 +1,17 @@ +diff --git a/src/maasserver/preseed_network.py b/src/maasserver/preseed_network.py +index 1203e6b..5475b18 100644 +--- a/src/maasserver/preseed_network.py ++++ b/src/maasserver/preseed_network.py +@@ -307,7 +307,11 @@ class InterfaceConfiguration: + + def _get_matching_routes(self, source): + """Return all route objects matching `source`.""" +- return {route for route in self.routes if route.source == source} ++ return { ++ route ++ for route in self.routes ++ if str(route.source.cidr) == str(source.cidr) ++ } + + def _generate_addresses(self): + """Generate the various addresses needed for this interface.""" diff --git a/images/maas-region-controller-noble/3.6_secure_headers.patch b/images/maas-region-controller-noble/3.6_secure_headers.patch new file mode 100644 index 0000000..ca66adf --- /dev/null +++ b/images/maas-region-controller-noble/3.6_secure_headers.patch @@ -0,0 +1,12 @@ +diff --git a/src/twisted/web/server.py b/src/twisted/web/server.py +index d30156b..3a04ecb 100644 +--- a/src/twisted/web/server.py ++++ b/src/twisted/web/server.py +@@ -206,7 +206,6 @@ class Request(Copyable, http.Request, components.Componentized): + self.site = self.channel.site + + # set various default headers +- self.setHeader(b"server", version) + self.setHeader(b"date", http.datetimeToString()) + + # Resource Identification diff --git a/images/maas-region-controller-noble/3.6_transfer_trusted_only.patch b/images/maas-region-controller-noble/3.6_transfer_trusted_only.patch new file mode 100644 index 0000000..faa6dcf --- /dev/null +++ b/images/maas-region-controller-noble/3.6_transfer_trusted_only.patch @@ -0,0 +1,9 @@ +diff --git a/src/provisioningserver/templates/dns/named.conf.options.inside.maas.template b/src/provisioningserver/templates/dns/named.conf.options.inside.maas.template +index d76fcfa9a..0cca0fe8d 100644 +--- a/src/provisioningserver/templates/dns/named.conf.options.inside.maas.template ++++ b/src/provisioningserver/templates/dns/named.conf.options.inside.maas.template +@@ -18,3 +18,4 @@ allow-recursion { trusted; }; + {{if not upstream_allow_query_cache}} + allow-query-cache { trusted; }; + {{endif}} ++allow-transfer { trusted; }; diff --git a/images/maas-region-controller-noble/Dockerfile b/images/maas-region-controller-noble/Dockerfile new file mode 100644 index 0000000..9a98617 --- /dev/null +++ b/images/maas-region-controller-noble/Dockerfile @@ -0,0 +1,96 @@ +ARG FROM=quay.io/airshipit/ubuntu:noble +FROM ${FROM} + +LABEL org.opencontainers.image.authors='airship-discuss@lists.airshipit.org, irc://#airshipit@freenode' +LABEL org.opencontainers.image.url='https://airshipit.org' +LABEL org.opencontainers.image.documentation='https://github.com/openstack/airship-maas' +LABEL org.opencontainers.image.source='https://git.openstack.org/openstack/airship-maas' +LABEL org.opencontainers.image.vendor='The Airship Authors' +LABEL org.opencontainers.image.licenses='Apache-2.0' + +ARG HTTP_PROXY +ARG HTTPS_PROXY +ARG NO_PROXY +ARG http_proxy +ARG https_proxy +ARG no_proxy + +ENV DEBIAN_FRONTEND=noninteractive +ENV container=docker + +ENV MAAS_VERSION=1:3.6.2-17588-g.7b59ae9e8-0ubuntu1~24.04.1 +ENV MAAS_PPA=ppa:maas/3.6 + +RUN apt-get -qq update \ + && apt upgrade -y \ + && apt-get install -y \ + avahi-daemon \ + jq \ + patch \ + software-properties-common \ + sudo \ + systemd \ + cron \ + ca-certificates \ + bind9-dnsutils \ +# Don't start any optional services except for the few we need. +# (specifically, don't start avahi-daemon) + && find /etc/systemd/system \ + /lib/systemd/system \ + -path '*.wants/*' \ + -not -name '*journald*' \ + -not -name '*systemd-tmpfiles*' \ + -not -name '*systemd-user-sessions*' \ + -exec rm \{} \; \ + && systemctl set-default multi-user.target \ +# Install maas from the ppa + && add-apt-repository -yu $MAAS_PPA \ + && apt-get install -y \ + maas-region-api=$MAAS_VERSION \ + # tcpdump is required by /usr/lib/maas/beacon-monitor + tcpdump \ + && rm -rf /var/lib/apt/lists/*\ + && rm -f /etc/ssl/private/.*snakeoil.* + +# Preserve the directory structure, permissions, and contents of /var/lib/maas +RUN mkdir -p /opt/maas/ && tar -cvzf /opt/maas/var-lib-maas.tgz /var/lib/maas + +# MAAS workarounds +COPY 3.6_route.patch /tmp/3.6_route.patch +COPY 3.6_kernel_package.patch /tmp/3.6_kernel_package.patch +# sh8121att: allow all requests via the proxy to allow it to work +# behind ingress +COPY 3.6_proxy_acl.patch /tmp/3.6_proxy_acl.patch +# Patch to add retrying to MaaS BMC user setup, and improve exception handling +COPY 3.6_configure_ipmi_user.patch /tmp/3.6_configure_ipmi_user.patch +COPY 3.6_secure_headers.patch /tmp/3.6_secure_headers.patch +COPY 3.6_partitiontable_does_not_exist.patch /tmp/3.6_partitiontable_does_not_exist.patch +# Allow tags with '/' symbols +COPY 3.6_regex_tags.patch /tmp/3.6_regex_tags.patch +# Patch to restrict access to zone transfers +COPY 3.6_transfer_trusted_only.patch /tmp/3.6_transfer_trusted_only.patch + +RUN cd /usr/lib/python3/dist-packages/maasserver && patch preseed_network.py < /tmp/3.6_route.patch +RUN cd /usr/lib/python3/dist-packages/maasserver && patch preseed.py < /tmp/3.6_kernel_package.patch +RUN cd /usr/lib/python3/dist-packages/metadataserver/builtin_scripts/commissioning_scripts && patch bmc_config.py < /tmp/3.6_configure_ipmi_user.patch +RUN cd /usr/lib/python3/dist-packages/provisioningserver/templates/proxy && patch maas-proxy.conf.template < /tmp/3.6_proxy_acl.patch +RUN cd /usr/lib/python3/dist-packages/twisted/web && patch server.py < /tmp/3.6_secure_headers.patch +RUN cd /usr/lib/python3/dist-packages/maasserver/api && patch partitions.py < /tmp/3.6_partitiontable_does_not_exist.patch +RUN cd /usr/lib/python3/dist-packages/maasserver/models && patch ownerdata.py < /tmp/3.6_regex_tags.patch +RUN cd /usr/lib/python3/dist-packages/provisioningserver/templates/dns && patch named.conf.options.inside.maas.template < /tmp/3.6_transfer_trusted_only.patch + +# echo journalctl logs to the container's stdout +COPY journalctl-to-tty.service /etc/systemd/system/journalctl-to-tty.service +RUN systemctl enable journalctl-to-tty.service + +# quiet sudo for the maas user +RUN umask 0337; echo 'Defaults:maas !pam_session, !syslog' > /etc/sudoers.d/99-maas-no-log + +# avoid triggering bind9 high cpu utilization bug +RUN sed -i -e '$a\include "/etc/bind/bind.keys";' /etc/bind/named.conf && /usr/lib/maas/maas-common setup-dns + +# fix chronyd.pid permission +COPY override.chrony.conf /etc/systemd/system/chrony.service.d/override.conf + +# initalize systemd +CMD ["/bin/bash", "-c", "exec /sbin/init --log-target=console 3>&1"] diff --git a/images/maas-region-controller-noble/README.md b/images/maas-region-controller-noble/README.md new file mode 100644 index 0000000..cd33b83 --- /dev/null +++ b/images/maas-region-controller-noble/README.md @@ -0,0 +1 @@ +[![Docker Repository on Quay](https://quay.io/repository/airshipit/maas-rack/status "Docker Repository on Quay")](https://quay.io/repository/airshipit/maas-region) Ubuntu MaaS Region Controller diff --git a/images/maas-region-controller-noble/journalctl-to-tty.service b/images/maas-region-controller-noble/journalctl-to-tty.service new file mode 100644 index 0000000..2725055 --- /dev/null +++ b/images/maas-region-controller-noble/journalctl-to-tty.service @@ -0,0 +1,13 @@ +[Unit] +Description=Journald console log streamer +Requires=systemd-journald.service +After=systemd-journald.service + +[Service] +Restart=always +RestartSec=0 +ExecStart=/bin/journalctl -f +StandardOutput=tty + +[Install] +WantedBy=basic.target diff --git a/images/maas-region-controller-noble/override.chrony.conf b/images/maas-region-controller-noble/override.chrony.conf new file mode 100644 index 0000000..6f3cd41 --- /dev/null +++ b/images/maas-region-controller-noble/override.chrony.conf @@ -0,0 +1,3 @@ +[Service] +ExecStartPre=-mkdir -p /var/log/chrony +ExecStartPre=-chown root /var/run/chrony diff --git a/images/maas-region-controller/Dockerfile b/images/maas-region-controller/Dockerfile index 46e51c8..c8fa664 100644 --- a/images/maas-region-controller/Dockerfile +++ b/images/maas-region-controller/Dockerfile @@ -19,6 +19,7 @@ ENV DEBIAN_FRONTEND noninteractive ENV container docker ENV MAAS_VERSION 2.8.7-8611-g.f2514168f-0ubuntu1~18.04.1 +ENV MAAS_PPA ppa:maas/2.8 RUN apt-get -qq update \ && apt-get install -y \ @@ -40,7 +41,7 @@ RUN apt-get -qq update \ -exec rm \{} \; \ && systemctl set-default multi-user.target \ # Install maas from the ppa - && add-apt-repository -yu ppa:maas/2.8 \ + && add-apt-repository -yu $MAAS_PPA \ && apt-get install -y \ maas-region-api=$MAAS_VERSION \ # tcpdump is required by /usr/lib/maas/beacon-monitor diff --git a/images/sstream-cache-noble/Dockerfile b/images/sstream-cache-noble/Dockerfile new file mode 100644 index 0000000..3e2516a --- /dev/null +++ b/images/sstream-cache-noble/Dockerfile @@ -0,0 +1,50 @@ +ARG FROM=quay.io/airshipit/ubuntu:noble +FROM ${FROM} + +LABEL org.opencontainers.image.authors='airship-discuss@lists.airshipit.org, irc://#airshipit@freenode' +LABEL org.opencontainers.image.url='https://airshipit.org' +LABEL org.opencontainers.image.documentation='https://github.com/openstack/airship-maas' +LABEL org.opencontainers.image.source='https://git.openstack.org/openstack/airship-maas' +LABEL org.opencontainers.image.vendor='The Airship Authors' +LABEL org.opencontainers.image.licenses='Apache-2.0' + +ARG HTTP_PROXY +ARG HTTPS_PROXY +ARG NO_PROXY +ARG http_proxy +ARG https_proxy +ARG no_proxy + +ARG SSTREAM_IMAGE=https://images.maas.io/ephemeral-v3/stable/ +ARG SSTREAM_RELEASE=jammy + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get -qq update && \ + apt upgrade -y && \ + apt-get install -y --no-install-recommends \ + apache2 \ + file \ + gpgv \ + python3-certifi \ + simplestreams \ + ubuntu-cloudimage-keyring + +RUN sstream-mirror --keyring=/usr/share/keyrings/ubuntu-cloudimage-keyring.gpg ${SSTREAM_IMAGE} \ + /var/www/html/maas/images/ephemeral-v3/daily 'arch=amd64' "release~${SSTREAM_RELEASE}" --max=1 --progress + +RUN sstream-mirror --keyring=/usr/share/keyrings/ubuntu-cloudimage-keyring.gpg ${SSTREAM_IMAGE} \ + /var/www/html/maas/images/ephemeral-v3/daily 'os~(grub*|pxelinux)' --max=1 --progress + +RUN sh -c 'echo "" > /etc/apache2/ports.conf' + +ENV APACHE_RUN_USER=www-data +ENV APACHE_RUN_GROUP=www-data +ENV APACHE_PID_FILE=/var/run/apache2.pid +ENV APACHE_RUN_DIR=/var/run/ +ENV APACHE_LOCK_DIR=/var/lock +ENV APACHE_LOG_DIR=/var/log/ +ENV LANG=C + +ENTRYPOINT ["/usr/sbin/apache2"] +CMD ["-E", "/dev/stderr","-c","ErrorLog /dev/stderr","-c","Listen 8888","-c","ServerRoot /etc/apache2","-c","DocumentRoot /var/www/html","-D","FOREGROUND"] diff --git a/tools/gate/playbooks/docker-image-build.yaml b/tools/gate/playbooks/docker-image-build.yaml index a9741a8..3a30980 100644 --- a/tools/gate/playbooks/docker-image-build.yaml +++ b/tools/gate/playbooks/docker-image-build.yaml @@ -66,6 +66,9 @@ when: not publish shell: | make images + environment: + DISTRO: "{{ distro }}" + DISTRO_ALIAS: "{{ distro }}" args: chdir: "{{ zuul.project.src_dir }}" executable: /bin/bash @@ -79,8 +82,10 @@ target: images params: IMAGE_TAG: "{{ item }}" - DISTRO: "{{ distro }}" with_items: "{{ image_tags.stdout_lines }}" + environment: + DISTRO: "{{ distro }}" + DISTRO_ALIAS: "{{ distro }}" - shell: "docker images" register: docker_images