From aa9aa54149a31fb8352b43b003ba6cfba01ed98a7beca03848c3cb405af5c819 Mon Sep 17 00:00:00 2001 From: Marco Chiappero Date: Tue, 24 Jun 2025 12:09:31 +0000 Subject: [PATCH 01/14] Restore the upstream directory structure It is now possible to bring back the original directory structure for config (/ironic-config) files and scripts (/scripts). This will make updates to re-align with upstream easier. Signed-off-by: Marco Chiappero --- ironic-image/Dockerfile | 21 ++++++++++--------- .../{ => ironic-config}/apache2-ipxe.conf.j2 | 0 .../apache2-vmedia.conf.j2 | 0 .../{ => ironic-config}/dnsmasq.conf.j2 | 0 .../httpd-ironic-api.conf.j2 | 0 .../{ => ironic-config}/httpd-modules.conf | 0 .../{ => ironic-config}/httpd.conf.j2 | 0 .../{ => ironic-config}/inspector.ipxe.j2 | 0 .../{ => ironic-config}/ipxe_config.template | 0 .../{ => ironic-config}/ironic.conf.j2 | 0 .../network-data-schema-empty.json | 0 ironic-image/{ => scripts}/auth-common.sh | 0 .../{ => scripts}/configure-ironic.sh | 0 ironic-image/{ => scripts}/ironic-common.sh | 0 ironic-image/{ => scripts}/ironic-probe.j2 | 0 ironic-image/{ => scripts}/rundnsmasq | 0 ironic-image/{ => scripts}/runhttpd | 0 ironic-image/{ => scripts}/runironic | 0 ironic-image/{ => scripts}/runironic-exporter | 0 ironic-image/{ => scripts}/runlogwatch.sh | 0 ironic-image/{ => scripts}/tls-common.sh | 0 21 files changed, 11 insertions(+), 10 deletions(-) rename ironic-image/{ => ironic-config}/apache2-ipxe.conf.j2 (100%) rename ironic-image/{ => ironic-config}/apache2-vmedia.conf.j2 (100%) rename ironic-image/{ => ironic-config}/dnsmasq.conf.j2 (100%) rename ironic-image/{ => ironic-config}/httpd-ironic-api.conf.j2 (100%) rename ironic-image/{ => ironic-config}/httpd-modules.conf (100%) rename ironic-image/{ => ironic-config}/httpd.conf.j2 (100%) rename ironic-image/{ => ironic-config}/inspector.ipxe.j2 (100%) rename ironic-image/{ => ironic-config}/ipxe_config.template (100%) rename ironic-image/{ => ironic-config}/ironic.conf.j2 (100%) rename ironic-image/{ => ironic-config}/network-data-schema-empty.json (100%) rename ironic-image/{ => scripts}/auth-common.sh (100%) rename ironic-image/{ => scripts}/configure-ironic.sh (100%) rename ironic-image/{ => scripts}/ironic-common.sh (100%) rename ironic-image/{ => scripts}/ironic-probe.j2 (100%) rename ironic-image/{ => scripts}/rundnsmasq (100%) rename ironic-image/{ => scripts}/runhttpd (100%) rename ironic-image/{ => scripts}/runironic (100%) rename ironic-image/{ => scripts}/runironic-exporter (100%) rename ironic-image/{ => scripts}/runlogwatch.sh (100%) rename ironic-image/{ => scripts}/tls-common.sh (100%) diff --git a/ironic-image/Dockerfile b/ironic-image/Dockerfile index 3f779c1..54e82ee 100644 --- a/ironic-image/Dockerfile +++ b/ironic-image/Dockerfile @@ -62,8 +62,9 @@ RUN echo 'alias mkisofs="xorriso -as mkisofs"' >> ~/.bashrc COPY mkisofs_wrapper /usr/bin/mkisofs RUN set -euo pipefail; chmod +x /usr/bin/mkisofs -COPY auth-common.sh configure-ironic.sh ironic-common.sh rundnsmasq runhttpd runironic runlogwatch.sh tls-common.sh configure-nonroot.sh ironic-probe.j2 /bin/ -RUN set -euo pipefail; chmod +x /bin/auth-common.sh; chmod +x /bin/configure-ironic.sh; chmod +x /bin/ironic-common.sh; chmod +x /bin/rundnsmasq; chmod +x /bin/runhttpd; chmod +x /bin/runironic; chmod +x /bin/runlogwatch.sh; chmod +x /bin/tls-common.sh; chmod +x /bin/configure-nonroot.sh; +COPY scripts/ /bin/ +COPY configure-nonroot.sh /bin/ +RUN set -euo pipefail; chmod +x /bin/configure-ironic.sh /bin/rundnsmasq /bin/runhttpd /bin/runironic /bin/runironic-exporter /bin/runlogwatch.sh /bin/configure-nonroot.sh RUN mkdir -p /tftpboot RUN mkdir -p $GRUB_DIR @@ -85,18 +86,18 @@ RUN if [ "$(uname -m)" = "aarch64" ]; then\ COPY --from=base /tmp/esp-x86_64.img /tmp/uefi_esp-x86_64.img COPY --from=base /tmp/esp-aarch64.img /tmp/uefi_esp-arm64.img -COPY ironic.conf.j2 /etc/ironic/ -COPY inspector.ipxe.j2 httpd-ironic-api.conf.j2 ipxe_config.template /tmp/ -COPY network-data-schema-empty.json /etc/ironic/ +COPY ironic-config/ironic.conf.j2 /etc/ironic/ +COPY ironic-config/inspector.ipxe.j2 ironic-config/httpd-ironic-api.conf.j2 ironic-config/ipxe_config.template /tmp/ +COPY ironic-config/network-data-schema-empty.json /etc/ironic/ # DNSMASQ -COPY dnsmasq.conf.j2 /etc/ +COPY ironic-config/dnsmasq.conf.j2 /etc/ # Custom httpd config, removes all but the bare minimum needed modules -COPY httpd.conf.j2 /etc/httpd/conf/ -COPY httpd-modules.conf /etc/httpd/conf.modules.d/ -COPY apache2-vmedia.conf.j2 /etc/httpd-vmedia.conf.j2 -COPY apache2-ipxe.conf.j2 /etc/httpd-ipxe.conf.j2 +COPY ironic-config/httpd.conf.j2 /etc/httpd/conf/ +COPY ironic-config/httpd-modules.conf /etc/httpd/conf.modules.d/ +COPY ironic-config/apache2-vmedia.conf.j2 /etc/httpd-vmedia.conf.j2 +COPY ironic-config/apache2-ipxe.conf.j2 /etc/httpd-ipxe.conf.j2 # Workaround # Removing the 010-ironic.conf file that comes with the package diff --git a/ironic-image/apache2-ipxe.conf.j2 b/ironic-image/ironic-config/apache2-ipxe.conf.j2 similarity index 100% rename from ironic-image/apache2-ipxe.conf.j2 rename to ironic-image/ironic-config/apache2-ipxe.conf.j2 diff --git a/ironic-image/apache2-vmedia.conf.j2 b/ironic-image/ironic-config/apache2-vmedia.conf.j2 similarity index 100% rename from ironic-image/apache2-vmedia.conf.j2 rename to ironic-image/ironic-config/apache2-vmedia.conf.j2 diff --git a/ironic-image/dnsmasq.conf.j2 b/ironic-image/ironic-config/dnsmasq.conf.j2 similarity index 100% rename from ironic-image/dnsmasq.conf.j2 rename to ironic-image/ironic-config/dnsmasq.conf.j2 diff --git a/ironic-image/httpd-ironic-api.conf.j2 b/ironic-image/ironic-config/httpd-ironic-api.conf.j2 similarity index 100% rename from ironic-image/httpd-ironic-api.conf.j2 rename to ironic-image/ironic-config/httpd-ironic-api.conf.j2 diff --git a/ironic-image/httpd-modules.conf b/ironic-image/ironic-config/httpd-modules.conf similarity index 100% rename from ironic-image/httpd-modules.conf rename to ironic-image/ironic-config/httpd-modules.conf diff --git a/ironic-image/httpd.conf.j2 b/ironic-image/ironic-config/httpd.conf.j2 similarity index 100% rename from ironic-image/httpd.conf.j2 rename to ironic-image/ironic-config/httpd.conf.j2 diff --git a/ironic-image/inspector.ipxe.j2 b/ironic-image/ironic-config/inspector.ipxe.j2 similarity index 100% rename from ironic-image/inspector.ipxe.j2 rename to ironic-image/ironic-config/inspector.ipxe.j2 diff --git a/ironic-image/ipxe_config.template b/ironic-image/ironic-config/ipxe_config.template similarity index 100% rename from ironic-image/ipxe_config.template rename to ironic-image/ironic-config/ipxe_config.template diff --git a/ironic-image/ironic.conf.j2 b/ironic-image/ironic-config/ironic.conf.j2 similarity index 100% rename from ironic-image/ironic.conf.j2 rename to ironic-image/ironic-config/ironic.conf.j2 diff --git a/ironic-image/network-data-schema-empty.json b/ironic-image/ironic-config/network-data-schema-empty.json similarity index 100% rename from ironic-image/network-data-schema-empty.json rename to ironic-image/ironic-config/network-data-schema-empty.json diff --git a/ironic-image/auth-common.sh b/ironic-image/scripts/auth-common.sh similarity index 100% rename from ironic-image/auth-common.sh rename to ironic-image/scripts/auth-common.sh diff --git a/ironic-image/configure-ironic.sh b/ironic-image/scripts/configure-ironic.sh similarity index 100% rename from ironic-image/configure-ironic.sh rename to ironic-image/scripts/configure-ironic.sh diff --git a/ironic-image/ironic-common.sh b/ironic-image/scripts/ironic-common.sh similarity index 100% rename from ironic-image/ironic-common.sh rename to ironic-image/scripts/ironic-common.sh diff --git a/ironic-image/ironic-probe.j2 b/ironic-image/scripts/ironic-probe.j2 similarity index 100% rename from ironic-image/ironic-probe.j2 rename to ironic-image/scripts/ironic-probe.j2 diff --git a/ironic-image/rundnsmasq b/ironic-image/scripts/rundnsmasq similarity index 100% rename from ironic-image/rundnsmasq rename to ironic-image/scripts/rundnsmasq diff --git a/ironic-image/runhttpd b/ironic-image/scripts/runhttpd similarity index 100% rename from ironic-image/runhttpd rename to ironic-image/scripts/runhttpd diff --git a/ironic-image/runironic b/ironic-image/scripts/runironic similarity index 100% rename from ironic-image/runironic rename to ironic-image/scripts/runironic diff --git a/ironic-image/runironic-exporter b/ironic-image/scripts/runironic-exporter similarity index 100% rename from ironic-image/runironic-exporter rename to ironic-image/scripts/runironic-exporter diff --git a/ironic-image/runlogwatch.sh b/ironic-image/scripts/runlogwatch.sh similarity index 100% rename from ironic-image/runlogwatch.sh rename to ironic-image/scripts/runlogwatch.sh diff --git a/ironic-image/tls-common.sh b/ironic-image/scripts/tls-common.sh similarity index 100% rename from ironic-image/tls-common.sh rename to ironic-image/scripts/tls-common.sh -- 2.49.0 From 7f24019049b388aa77d4b3a10fbf9da7571ec813f3c4588a3c4261389ca08920 Mon Sep 17 00:00:00 2001 From: Marco Chiappero Date: Wed, 25 Jun 2025 11:19:43 +0000 Subject: [PATCH 02/14] Apply misc changes to Dockerfile to align with upstream Having a completely different image and build system the Dockerfile will always differ quite significantly from the upstream one. Nonetheless, it's still useful to make the commont parts to look alike as much as possible to ease maintanance and update. Note, this is just a small set of changes that are possible, more effort into this direction may follow at later stage. --- ironic-image/Dockerfile | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/ironic-image/Dockerfile b/ironic-image/Dockerfile index 54e82ee..8ff9096 100644 --- a/ironic-image/Dockerfile +++ b/ironic-image/Dockerfile @@ -32,7 +32,9 @@ RUN mkdir -p /installroot/var/lib/ironic && \ /installroot/usr/bin/sqlite3 /installroot/var/lib/ironic/ironic.sqlite "pragma journal_mode=wal" && \ zypper --installroot /installroot --non-interactive remove sqlite3 +# build actual image FROM micro AS final + MAINTAINER SUSE LLC (https://www.suse.com/) # Define labels according to https://en.opensuse.org/Building_derived_containers LABEL org.opencontainers.image.title="SLE Openstack Ironic Container Image" @@ -62,11 +64,12 @@ RUN echo 'alias mkisofs="xorriso -as mkisofs"' >> ~/.bashrc COPY mkisofs_wrapper /usr/bin/mkisofs RUN set -euo pipefail; chmod +x /usr/bin/mkisofs +RUN mkdir -p /tftpboot +RUN mkdir -p $GRUB_DIR + COPY scripts/ /bin/ COPY configure-nonroot.sh /bin/ RUN set -euo pipefail; chmod +x /bin/configure-ironic.sh /bin/rundnsmasq /bin/runhttpd /bin/runironic /bin/runironic-exporter /bin/runlogwatch.sh /bin/configure-nonroot.sh -RUN mkdir -p /tftpboot -RUN mkdir -p $GRUB_DIR # No need to support the Legacy BIOS boot #RUN cp /usr/share/syslinux/pxelinux.0 /tftpboot @@ -93,16 +96,15 @@ COPY ironic-config/network-data-schema-empty.json /etc/ironic/ # DNSMASQ COPY ironic-config/dnsmasq.conf.j2 /etc/ +# Workaround +# Removing the 010-ironic.conf file that comes with the package +RUN rm /etc/ironic/ironic.conf.d/010-ironic.conf + # Custom httpd config, removes all but the bare minimum needed modules COPY ironic-config/httpd.conf.j2 /etc/httpd/conf/ COPY ironic-config/httpd-modules.conf /etc/httpd/conf.modules.d/ COPY ironic-config/apache2-vmedia.conf.j2 /etc/httpd-vmedia.conf.j2 COPY ironic-config/apache2-ipxe.conf.j2 /etc/httpd-ipxe.conf.j2 -# Workaround -# Removing the 010-ironic.conf file that comes with the package -RUN rm /etc/ironic/ironic.conf.d/010-ironic.conf - # configure non-root user and set relevant permissions -RUN configure-nonroot.sh && \ - rm -f /bin/configure-nonroot.sh +RUN configure-nonroot.sh && rm -f /bin/configure-nonroot.sh -- 2.49.0 From c7e6740ac2ffde976b056e914e7f024fa2e4178386af1dc1c8c1fd8dd5f19afc Mon Sep 17 00:00:00 2001 From: Marco Chiappero Date: Wed, 25 Jun 2025 11:21:04 +0000 Subject: [PATCH 03/14] Remove stale file entries for old BIOS based machines Two entries pointing to old and unesed files for non UEFI servers seem to be unused both here and upstream, so this commit removes them. --- ironic-image/Dockerfile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ironic-image/Dockerfile b/ironic-image/Dockerfile index 8ff9096..085b5ca 100644 --- a/ironic-image/Dockerfile +++ b/ironic-image/Dockerfile @@ -71,10 +71,6 @@ COPY scripts/ /bin/ COPY configure-nonroot.sh /bin/ RUN set -euo pipefail; chmod +x /bin/configure-ironic.sh /bin/rundnsmasq /bin/runhttpd /bin/runironic /bin/runironic-exporter /bin/runlogwatch.sh /bin/configure-nonroot.sh -# No need to support the Legacy BIOS boot -#RUN cp /usr/share/syslinux/pxelinux.0 /tftpboot -#RUN cp /usr/share/syslinux/chain.c32 /tftpboot/ - # IRONIC # RUN cp /usr/share/ipxe/undionly.kpxe /tftpboot/undionly.kpxe #!ArchExclusiveLine: x86_64 -- 2.49.0 From ecdb953890c78295d4e6b1e8fe1809ff519c00e2c872d13e63a9c73928de2206 Mon Sep 17 00:00:00 2001 From: Marco Chiappero Date: Mon, 30 Jun 2025 12:55:07 +0000 Subject: [PATCH 04/14] Move the copy of Jinja templates to resemble upstream Follow the same location for the COPY command moving the Jinja template files in the image. Signed-off-by: Marco Chiappero --- ironic-image/Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ironic-image/Dockerfile b/ironic-image/Dockerfile index 085b5ca..2f9f721 100644 --- a/ironic-image/Dockerfile +++ b/ironic-image/Dockerfile @@ -71,6 +71,9 @@ COPY scripts/ /bin/ COPY configure-nonroot.sh /bin/ RUN set -euo pipefail; chmod +x /bin/configure-ironic.sh /bin/rundnsmasq /bin/runhttpd /bin/runironic /bin/runironic-exporter /bin/runlogwatch.sh /bin/configure-nonroot.sh +COPY ironic-config/inspector.ipxe.j2 ironic-config/httpd-ironic-api.conf.j2 \ + ironic-config/ipxe_config.template /tmp/ + # IRONIC # RUN cp /usr/share/ipxe/undionly.kpxe /tftpboot/undionly.kpxe #!ArchExclusiveLine: x86_64 @@ -86,7 +89,6 @@ COPY --from=base /tmp/esp-x86_64.img /tmp/uefi_esp-x86_64.img COPY --from=base /tmp/esp-aarch64.img /tmp/uefi_esp-arm64.img COPY ironic-config/ironic.conf.j2 /etc/ironic/ -COPY ironic-config/inspector.ipxe.j2 ironic-config/httpd-ironic-api.conf.j2 ironic-config/ipxe_config.template /tmp/ COPY ironic-config/network-data-schema-empty.json /etc/ironic/ # DNSMASQ -- 2.49.0 From da9f8f9c2c4cd9cd3ab91ec786af39ae8b7680da3fea5823b420778d70917f18 Mon Sep 17 00:00:00 2001 From: Marco Chiappero Date: Thu, 26 Jun 2025 12:48:09 +0000 Subject: [PATCH 05/14] Copy files from upstream v30.0.0 Drop all the config and script files into their respective directory from the upstream release v30.0.0. Any required customization will follow in subsequent commits, which could potentially be reused for future realignments. Signed-off-by: Marco Chiappero --- .../ironic-config/apache2-vmedia.conf.j2 | 14 ++-- ironic-image/ironic-config/dnsmasq.conf.j2 | 11 +-- .../ironic-config/httpd-ironic-api.conf.j2 | 6 +- ironic-image/ironic-config/httpd-modules.conf | 38 +++++----- ironic-image/ironic-config/httpd.conf.j2 | 10 +-- ironic-image/ironic-config/inspector.ipxe.j2 | 4 +- ironic-image/ironic-config/ironic.conf.j2 | 36 +++++----- .../network-data-schema-empty.json | 1 - ironic-image/scripts/auth-common.sh | 70 ++++++++++++++----- ironic-image/scripts/configure-ironic.sh | 51 ++++---------- ironic-image/scripts/ironic-common.sh | 66 ++++++++++++----- ironic-image/scripts/ironic-probe.j2 | 9 --- ironic-image/scripts/ironic-probe.sh | 23 ++++++ ironic-image/scripts/rundatabase-upgrade | 10 +++ ironic-image/scripts/rundnsmasq | 16 +++-- ironic-image/scripts/runhttpd | 40 +++++------ ironic-image/scripts/runironic | 17 ++--- ironic-image/scripts/runironic-exporter | 4 +- ironic-image/scripts/runlogwatch.sh | 26 +++---- .../scripts/runonline-data-migrations | 10 +++ ironic-image/scripts/tls-common.sh | 24 +++++-- 21 files changed, 291 insertions(+), 195 deletions(-) delete mode 100644 ironic-image/ironic-config/network-data-schema-empty.json delete mode 100644 ironic-image/scripts/ironic-probe.j2 create mode 100755 ironic-image/scripts/ironic-probe.sh create mode 100755 ironic-image/scripts/rundatabase-upgrade create mode 100755 ironic-image/scripts/runonline-data-migrations diff --git a/ironic-image/ironic-config/apache2-vmedia.conf.j2 b/ironic-image/ironic-config/apache2-vmedia.conf.j2 index fd87d39..20dc4a7 100644 --- a/ironic-image/ironic-config/apache2-vmedia.conf.j2 +++ b/ironic-image/ironic-config/apache2-vmedia.conf.j2 @@ -10,15 +10,13 @@ Listen {{ env.VMEDIA_TLS_PORT }} SSLCertificateFile {{ env.IRONIC_VMEDIA_CERT_FILE }} SSLCertificateKeyFile {{ env.IRONIC_VMEDIA_KEY_FILE }} - - AllowOverride None - Require all granted + + Order deny,allow + deny from all - - - Options Indexes FollowSymLinks - AllowOverride None - Require all granted + + Order allow,deny + allow from all diff --git a/ironic-image/ironic-config/dnsmasq.conf.j2 b/ironic-image/ironic-config/dnsmasq.conf.j2 index ad58078..f216fed 100644 --- a/ironic-image/ironic-config/dnsmasq.conf.j2 +++ b/ironic-image/ironic-config/dnsmasq.conf.j2 @@ -3,6 +3,7 @@ bind-dynamic enable-tftp tftp-root=/shared/tftpboot log-queries +dhcp-leasefile=/data/dnsmasq/dnsmasq.leases # Configure listening for DNS (0 disables DNS) port={{ env.DNS_PORT }} @@ -31,11 +32,11 @@ dhcp-match=ipxe,175 # Client is already running iPXE; move to next stage of chainloading {%- if env.IPXE_TLS_SETUP == "true" %} # iPXE with (U)EFI -dhcp-boot=tag:efi,tag:ipxe,http://{{ env.IRONIC_URL_HOST }}:{{ env.HTTP_PORT }}/custom-ipxe/snponly.efi +dhcp-boot=tag:efi,tag:ipxe,{{ env.IRONIC_HTTP_URL }}/custom-ipxe/snponly.efi # iPXE with BIOS -dhcp-boot=tag:ipxe,http://{{ env.IRONIC_URL_HOST }}:{{ env.HTTP_PORT }}/custom-ipxe/undionly.kpxe +dhcp-boot=tag:ipxe,{{ env.IRONIC_HTTP_URL }}/custom-ipxe/undionly.kpxe {% else %} -dhcp-boot=tag:ipxe,http://{{ env.IRONIC_URL_HOST }}:{{ env.HTTP_PORT }}/boot.ipxe +dhcp-boot=tag:ipxe,{{ env.IRONIC_HTTP_URL }}/boot.ipxe {% endif %} # Note: Need to test EFI booting @@ -59,8 +60,8 @@ ra-param={{ env.PROVISIONING_INTERFACE }},0,0 dhcp-vendorclass=set:pxe6,enterprise:343,PXEClient dhcp-userclass=set:ipxe6,iPXE -dhcp-option=tag:pxe6,option6:bootfile-url,tftp://{{ env.IRONIC_URL_HOST }}/snponly.efi -dhcp-option=tag:ipxe6,option6:bootfile-url,http://{{ env.IRONIC_URL_HOST }}:{{ env.HTTP_PORT }}/boot.ipxe +dhcp-option=tag:pxe6,option6:bootfile-url,{{ env.IRONIC_TFTP_URL }}/snponly.efi +dhcp-option=tag:ipxe6,option6:bootfile-url,{{ env.IRONIC_HTTP_URL }}/boot.ipxe # It can be used when setting DNS or GW variables. {%- if env["GATEWAY_IP"] is undefined %} diff --git a/ironic-image/ironic-config/httpd-ironic-api.conf.j2 b/ironic-image/ironic-config/httpd-ironic-api.conf.j2 index 15c73b6..a374894 100644 --- a/ironic-image/ironic-config/httpd-ironic-api.conf.j2 +++ b/ironic-image/ironic-config/httpd-ironic-api.conf.j2 @@ -27,8 +27,8 @@ Listen {{ env.IRONIC_URL_HOST }}:{{ env.IRONIC_LISTEN_PORT }} ProxyPassReverse "/" "http://127.0.0.1:{{ env.IRONIC_PRIVATE_PORT }}/" {% endif %} - SetEnv APACHE_RUN_USER ironic-suse - SetEnv APACHE_RUN_GROUP ironic-suse + SetEnv APACHE_RUN_USER ironic + SetEnv APACHE_RUN_GROUP ironic ErrorLog /dev/stderr LogLevel debug @@ -45,7 +45,7 @@ Listen {{ env.IRONIC_URL_HOST }}:{{ env.IRONIC_LISTEN_PORT }} {% if "IRONIC_HTPASSWD" in env and env.IRONIC_HTPASSWD | length %} AuthType Basic AuthName "Restricted area" - AuthUserFile "/etc/ironic/htpasswd" + AuthUserFile {{ env.HTPASSWD_FILE }} Require valid-user {% endif %} diff --git a/ironic-image/ironic-config/httpd-modules.conf b/ironic-image/ironic-config/httpd-modules.conf index fd2bc99..5984994 100644 --- a/ironic-image/ironic-config/httpd-modules.conf +++ b/ironic-image/ironic-config/httpd-modules.conf @@ -1,20 +1,20 @@ # Bare minimum set of modules -LoadModule log_config_module /usr/lib64/apache2/mod_log_config.so -LoadModule mime_module /usr/lib64/apache2/mod_mime.so -LoadModule dir_module /usr/lib64/apache2/mod_dir.so -LoadModule authz_core_module /usr/lib64/apache2/mod_authz_core.so -#LoadModule unixd_module modules/mod_unixd.so -#LoadModule mpm_event_module modules/mod_mpm_event.so -LoadModule ssl_module /usr/lib64/apache2/mod_ssl.so -LoadModule env_module /usr/lib64/apache2/mod_env.so -LoadModule proxy_module /usr/lib64/apache2/mod_proxy.so -LoadModule proxy_ajp_module /usr/lib64/apache2/mod_proxy_ajp.so -LoadModule proxy_balancer_module /usr/lib64/apache2/mod_proxy_balancer.so -LoadModule proxy_http_module /usr/lib64/apache2/mod_proxy_http.so -LoadModule slotmem_shm_module /usr/lib64/apache2/mod_slotmem_shm.so -LoadModule headers_module /usr/lib64/apache2/mod_headers.so -LoadModule authn_core_module /usr/lib64/apache2/mod_authn_core.so -LoadModule auth_basic_module /usr/lib64/apache2/mod_auth_basic.so -LoadModule authn_file_module /usr/lib64/apache2/mod_authn_file.so -LoadModule authz_user_module /usr/lib64/apache2/mod_authz_user.so -LoadModule access_compat_module /usr/lib64/apache2/mod_access_compat.so +LoadModule log_config_module /etc/httpd/modules/mod_log_config.so +LoadModule mime_module /etc/httpd/modules/mod_mime.so +LoadModule dir_module /etc/httpd/modules/mod_dir.so +LoadModule authz_core_module /etc/httpd/modules/mod_authz_core.so +LoadModule unixd_module /etc/httpd/modules/mod_unixd.so +LoadModule mpm_event_module /etc/httpd/modules/mod_mpm_event.so +LoadModule ssl_module /etc/httpd/modules/mod_ssl.so +LoadModule env_module /etc/httpd/modules/mod_env.so +LoadModule proxy_module /etc/httpd/modules/mod_proxy.so +LoadModule proxy_ajp_module /etc/httpd/modules/mod_proxy_ajp.so +LoadModule proxy_balancer_module /etc/httpd/modules/mod_proxy_balancer.so +LoadModule proxy_http_module /etc/httpd/modules/mod_proxy_http.so +LoadModule slotmem_shm_module /etc/httpd/modules/mod_slotmem_shm.so +LoadModule headers_module /etc/httpd/modules/mod_headers.so +LoadModule authn_core_module /etc/httpd/modules/mod_authn_core.so +LoadModule auth_basic_module /etc/httpd/modules/mod_auth_basic.so +LoadModule authn_file_module /etc/httpd/modules/mod_authn_file.so +LoadModule authz_user_module /etc/httpd/modules/mod_authz_user.so +LoadModule access_compat_module /etc/httpd/modules/mod_access_compat.so diff --git a/ironic-image/ironic-config/httpd.conf.j2 b/ironic-image/ironic-config/httpd.conf.j2 index 28e5308..aa78d73 100644 --- a/ironic-image/ironic-config/httpd.conf.j2 +++ b/ironic-image/ironic-config/httpd.conf.j2 @@ -1,12 +1,12 @@ -ServerRoot "/etc/httpd" +ServerRoot {{ env.HTTPD_DIR }} {%- if env.LISTEN_ALL_INTERFACES | lower == "true" %} Listen {{ env.HTTP_PORT }} {% else %} Listen {{ env.IRONIC_URL_HOST }}:{{ env.HTTP_PORT }} {% endif %} -Include conf.modules.d/*.conf -User ironic-suse -Group ironic-suse +Include /etc/httpd/conf.modules.d/*.conf +User apache +Group apache AllowOverride none @@ -64,7 +64,7 @@ AddDefaultCharset UTF-8 MIMEMagicFile conf/magic -PidFile /var/tmp/httpd.pid +PidFile {{ env.IRONIC_TMP_DATA_DIR }}/httpd.pid # EnableSendfile directive could speed up deployments but it could also cause # issues depending on the underlying file system, to learn more: diff --git a/ironic-image/ironic-config/inspector.ipxe.j2 b/ironic-image/ironic-config/inspector.ipxe.j2 index c105178..23b5e5e 100644 --- a/ironic-image/ironic-config/inspector.ipxe.j2 +++ b/ironic-image/ironic-config/inspector.ipxe.j2 @@ -5,6 +5,6 @@ echo In inspector.ipxe imgfree # NOTE(dtantsur): keep inspection kernel params in [mdns]params in # ironic-inspector-image and configuration in configure-ironic.sh -kernel --timeout 60000 http://{{ env.IRONIC_URL_HOST }}:{{ env.HTTP_PORT }}/images/ironic-python-agent-${buildarch}.kernel ipa-insecure=1 ipa-inspection-collectors={{ env.IRONIC_IPA_COLLECTORS }} systemd.journald.forward_to_console=yes BOOTIF=${mac} ipa-debug=1 ipa-enable-vlan-interfaces={{ env.IRONIC_ENABLE_VLAN_INTERFACES }} ipa-inspection-dhcp-all-interfaces=1 ipa-collect-lldp=1 {{ env.INSPECTOR_EXTRA_ARGS }} initrd=ironic-python-agent.initramfs {% if env.IRONIC_RAMDISK_SSH_KEY %}sshkey="{{ env.IRONIC_RAMDISK_SSH_KEY|trim }}"{% endif %} {{ env.IRONIC_KERNEL_PARAMS|trim }} || goto retry_boot -initrd --timeout 60000 http://{{ env.IRONIC_URL_HOST }}:{{ env.HTTP_PORT }}/images/ironic-python-agent-${buildarch}.initramfs || goto retry_boot +kernel --timeout 60000 {{ env.IRONIC_HTTP_URL }}/images/ironic-python-agent.kernel ipa-insecure=1 ipa-inspection-collectors={{ env.IRONIC_IPA_COLLECTORS }} systemd.journald.forward_to_console=yes BOOTIF=${mac} ipa-debug=1 ipa-enable-vlan-interfaces={{ env.IRONIC_ENABLE_VLAN_INTERFACES }} ipa-inspection-dhcp-all-interfaces=1 ipa-collect-lldp=1 {{ env.INSPECTOR_EXTRA_ARGS }} initrd=ironic-python-agent.initramfs {% if env.IRONIC_RAMDISK_SSH_KEY %}sshkey="{{ env.IRONIC_RAMDISK_SSH_KEY|trim }}"{% endif %} {{ env.IRONIC_KERNEL_PARAMS|trim }} || goto retry_boot +initrd --timeout 60000 {{ env.IRONIC_HTTP_URL }}/images/ironic-python-agent.initramfs || goto retry_boot boot diff --git a/ironic-image/ironic-config/ironic.conf.j2 b/ironic-image/ironic-config/ironic.conf.j2 index 58bc69d..ed7c87d 100644 --- a/ironic-image/ironic-config/ironic.conf.j2 +++ b/ironic-image/ironic-config/ironic.conf.j2 @@ -39,7 +39,7 @@ isolinux_bin = /usr/share/syslinux/isolinux.bin # NOTE(dtantsur): this path is specific to the GRUB image that is built into # the ESP provided in [conductor]bootloader. -grub_config_path = EFI/BOOT/grub.cfg +grub_config_path = EFI/centos/grub.cfg [agent] deploy_logs_collect = always @@ -49,6 +49,7 @@ deploy_logs_local_path = /shared/log/ironic/deploy # retries here works around such problems without affecting the normal path. # See https://bugzilla.redhat.com/show_bug.cgi?id=1822763 max_command_attempts = 30 +certificates_path = {{ env.IRONIC_GEN_CERT_DIR }} [api] {% if env.IRONIC_REVERSE_PROXY_SETUP == "true" %} @@ -71,9 +72,6 @@ enable_ssl_api = true {% endif %} api_workers = {{ env.NUMWORKERS }} -# Disable schema validation so we can pass nmstate format -network_data_schema = /etc/ironic/network-data-schema-empty.json - [conductor] automated_clean = {{ env.IRONIC_AUTOMATED_CLEAN }} # NOTE(dtantsur): keep aligned with [pxe]boot_retry_timeout below. @@ -83,7 +81,7 @@ send_sensor_data = {{ env.SEND_SENSOR_DATA }} # Power state is checked every 60 seconds and BMC activity should # be avoided more often than once every sixty seconds. send_sensor_data_interval = 160 -bootloader = {{ env.IRONIC_BOOT_BASE_URL }}/uefi_esp-{{ env.DEPLOY_ARCHITECTURE }}.img +bootloader = file:///templates/uefi_esp.img verify_step_priority_override = management.clear_job_queue:90 # We don't use this feature, and it creates an additional load on the database node_history = False @@ -95,16 +93,22 @@ deploy_kernel = file://{{ env.IRONIC_DEFAULT_KERNEL }} {% if env.IRONIC_DEFAULT_RAMDISK is defined %} deploy_ramdisk = file://{{ env.IRONIC_DEFAULT_RAMDISK }} {% endif %} +{% if env.DISABLE_DEEP_IMAGE_INSPECTION | lower == "true" %} +disable_deep_image_inspection = True +{% endif %} +# Allowed path for file:// links: ipa-downloader uses /shared/html/images, +# while the bootloader configuration above refers to /templates. +file_url_allowed_paths = /shared/html/images,/templates [database] -{% if env.IRONIC_USE_MARIADB | lower == "false" %} -connection = sqlite:////var/lib/ironic/ironic.sqlite +{% if env.IRONIC_USE_MARIADB | lower == "true" %} +connection = {{ env.MARIADB_CONNECTION }} +{% else %} +connection = {{ env.LOCAL_DB_URI }} # Synchronous mode is required for data integrity in case of operating system # crash. In our case we restart the container from scratch, so we can save some # IO by not doing syncs all the time. sqlite_synchronous = False -{% else %} -connection = {{ env.MARIADB_CONNECTION }} {% endif %} [deploy] @@ -112,7 +116,7 @@ default_boot_option = local erase_devices_metadata_priority = 10 erase_devices_priority = 0 http_root = /shared/html/ -http_url = {{ env.IRONIC_BOOT_BASE_URL }} +http_url = {{ env.IRONIC_HTTP_URL }} fast_track = {{ env.IRONIC_FAST_TRACK }} {% if env.IRONIC_BOOT_ISO_SOURCE %} ramdisk_image_download_source = {{ env.IRONIC_BOOT_ISO_SOURCE }} @@ -175,7 +179,7 @@ cipher_suite_versions = 3,17 # unauthenticated connections from other processes in the same host since the # containers are in host networking. auth_strategy = http_basic -http_basic_auth_user_file = /etc/ironic/htpasswd-rpc +http_basic_auth_user_file = {{ env.IRONIC_RPC_HTPASSWD_FILE }} host_ip = {% if env.LISTEN_ALL_INTERFACES | lower == "true" %}::{% else %}{{ env.IRONIC_IP }}{% endif %} {% if env.IRONIC_TLS_SETUP == "true" %} use_ssl = true @@ -201,7 +205,7 @@ images_path = /shared/html/tmp instance_master_path = /shared/html/master_images tftp_master_path = /shared/tftpboot/master_images tftp_root = /shared/tftpboot -kernel_append_params = nofb nomodeset vga=normal ipa-insecure={{ env.IPA_INSECURE }} {% if env.ENABLE_FIPS_IPA %}fips={{ env.ENABLE_FIPS_IPA|trim }}{% endif %} {% if env.IRONIC_RAMDISK_SSH_KEY %}sshkey="{{ env.IRONIC_RAMDISK_SSH_KEY|trim }}"{% endif %} {{ env.IRONIC_KERNEL_PARAMS|trim }} systemd.journald.forward_to_console=yes net.ifnames={{ '0' if env.PREDICTABLE_NIC_NAMES == 'false' else '1' }} +kernel_append_params = nofb nomodeset vga=normal ipa-insecure=1 {% if env.ENABLE_FIPS_IPA %}fips={{ env.ENABLE_FIPS_IPA|trim }}{% endif %} {% if env.IRONIC_RAMDISK_SSH_KEY %}sshkey="{{ env.IRONIC_RAMDISK_SSH_KEY|trim }}"{% endif %} {{ env.IRONIC_KERNEL_PARAMS|trim }} systemd.journald.forward_to_console=yes # This makes networking boot templates generated even for nodes using local # boot (the default), ensuring that they boot correctly even if they start # netbooting for some reason (e.g. with the noop management interface). @@ -209,19 +213,19 @@ enable_netboot_fallback = true # Enable the fallback path to in-band inspection ipxe_fallback_script = inspector.ipxe {% if env.IPXE_TLS_SETUP | lower == "true" %} -ipxe_config_template = /tmp/ipxe_config.template +ipxe_config_template = /templates/ipxe_config.template {% endif %} [redfish] use_swift = false -kernel_append_params = nofb nomodeset vga=normal ipa-insecure={{ env.IPA_INSECURE }} {% if env.ENABLE_FIPS_IPA %}fips={{ env.ENABLE_FIPS_IPA|trim }}{% endif %} {% if env.IRONIC_RAMDISK_SSH_KEY %}sshkey="{{ env.IRONIC_RAMDISK_SSH_KEY|trim }}"{% endif %} {{ env.IRONIC_KERNEL_PARAMS|trim }} systemd.journald.forward_to_console=yes net.ifnames={{ '0' if env.PREDICTABLE_NIC_NAMES == 'false' else '1' }} +kernel_append_params = nofb nomodeset vga=normal ipa-insecure=1 {% if env.ENABLE_FIPS_IPA %}fips={{ env.ENABLE_FIPS_IPA|trim }}{% endif %} {% if env.IRONIC_RAMDISK_SSH_KEY %}sshkey="{{ env.IRONIC_RAMDISK_SSH_KEY|trim }}"{% endif %} {{ env.IRONIC_KERNEL_PARAMS|trim }} systemd.journald.forward_to_console=yes [ilo] -kernel_append_params = nofb nomodeset vga=normal ipa-insecure={{ env.IPA_INSECURE }} {% if env.ENABLE_FIPS_IPA %}fips={{ env.ENABLE_FIPS_IPA|trim }}{% endif %} {% if env.IRONIC_RAMDISK_SSH_KEY %}sshkey="{{ env.IRONIC_RAMDISK_SSH_KEY|trim }}"{% endif %} {{ env.IRONIC_KERNEL_PARAMS|trim }} systemd.journald.forward_to_console=yes net.ifnames={{ '0' if env.PREDICTABLE_NIC_NAMES == 'false' else '1' }} +kernel_append_params = nofb nomodeset vga=normal ipa-insecure=1 {% if env.ENABLE_FIPS_IPA %}fips={{ env.ENABLE_FIPS_IPA|trim }}{% endif %} {% if env.IRONIC_RAMDISK_SSH_KEY %}sshkey="{{ env.IRONIC_RAMDISK_SSH_KEY|trim }}"{% endif %} {{ env.IRONIC_KERNEL_PARAMS|trim }} systemd.journald.forward_to_console=yes use_web_server_for_images = true [irmc] -kernel_append_params = nofb nomodeset vga=normal ipa-insecure={{ env.IPA_INSECURE }} {% if env.ENABLE_FIPS_IPA %}fips={{ env.ENABLE_FIPS_IPA|trim }}{% endif %} {% if env.IRONIC_RAMDISK_SSH_KEY %}sshkey="{{ env.IRONIC_RAMDISK_SSH_KEY|trim }}"{% endif %} {{ env.IRONIC_KERNEL_PARAMS|trim }} systemd.journald.forward_to_console=yes net.ifnames={{ '0' if env.PREDICTABLE_NIC_NAMES == 'false' else '1' }} +kernel_append_params = nofb nomodeset vga=normal ipa-insecure=1 {% if env.ENABLE_FIPS_IPA %}fips={{ env.ENABLE_FIPS_IPA|trim }}{% endif %} {% if env.IRONIC_RAMDISK_SSH_KEY %}sshkey="{{ env.IRONIC_RAMDISK_SSH_KEY|trim }}"{% endif %} {{ env.IRONIC_KERNEL_PARAMS|trim }} systemd.journald.forward_to_console=yes [service_catalog] endpoint_override = {{ env.IRONIC_BASE_URL }} diff --git a/ironic-image/ironic-config/network-data-schema-empty.json b/ironic-image/ironic-config/network-data-schema-empty.json deleted file mode 100644 index d31a3bc..0000000 --- a/ironic-image/ironic-config/network-data-schema-empty.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/ironic-image/scripts/auth-common.sh b/ironic-image/scripts/auth-common.sh index cb6a548..b9526d4 100644 --- a/ironic-image/scripts/auth-common.sh +++ b/ironic-image/scripts/auth-common.sh @@ -4,6 +4,12 @@ set -euxo pipefail export IRONIC_REVERSE_PROXY_SETUP=${IRONIC_REVERSE_PROXY_SETUP:-false} +# CUSTOM_CONFIG_DIR is also managed in the ironic-common.sh, in order to +# keep auth-common and ironic-common separate (to stay consistent with the +# architecture) part of the ironic-common logic had to be duplicated +CUSTOM_CONFIG_DIR="${CUSTOM_CONFIG_DIR:-/conf}" +IRONIC_CONF_DIR="${CUSTOM_CONFIG_DIR}/ironic" + # Backward compatibility if [[ "${IRONIC_DEPLOYMENT:-}" == "Conductor" ]]; then export IRONIC_EXPOSE_JSON_RPC=true @@ -11,42 +17,74 @@ else export IRONIC_EXPOSE_JSON_RPC="${IRONIC_EXPOSE_JSON_RPC:-false}" fi -IRONIC_HTPASSWD_FILE=/etc/ironic/htpasswd +IRONIC_HTPASSWD_FILE="${IRONIC_CONF_DIR}/htpasswd" +export IRONIC_RPC_HTPASSWD_FILE="${IRONIC_HTPASSWD_FILE}-rpc" if [[ -f "/auth/ironic/htpasswd" ]]; then IRONIC_HTPASSWD=$( "${IRONIC_HTPASSWD_FILE}-rpc" + else + printf "%s\n" "${IRONIC_RPC_HTPASSWD}" > "${IRONIC_RPC_HTPASSWD_FILE}" fi } configure_ironic_auth() { - local config=/etc/ironic/ironic.conf # Configure HTTP basic auth for API server if [[ -n "${IRONIC_HTPASSWD}" ]]; then printf "%s\n" "${IRONIC_HTPASSWD}" > "${IRONIC_HTPASSWD_FILE}" if [[ "${IRONIC_REVERSE_PROXY_SETUP}" == "false" ]]; then - crudini --set "${config}" DEFAULT auth_strategy http_basic - crudini --set "${config}" DEFAULT http_basic_auth_user_file "${IRONIC_HTPASSWD_FILE}" + crudini --set "${IRONIC_CONFIG}" DEFAULT auth_strategy http_basic + crudini --set "${IRONIC_CONFIG}" DEFAULT http_basic_auth_user_file "${IRONIC_HTPASSWD_FILE}" fi fi } diff --git a/ironic-image/scripts/configure-ironic.sh b/ironic-image/scripts/configure-ironic.sh index 8ab2404..d2154d0 100644 --- a/ironic-image/scripts/configure-ironic.sh +++ b/ironic-image/scripts/configure-ironic.sh @@ -19,10 +19,11 @@ export IRONIC_ENABLE_VLAN_INTERFACES=${IRONIC_ENABLE_VLAN_INTERFACES:-${IRONIC_I export HTTP_PORT=${HTTP_PORT:-80} -export IRONIC_USE_MARIADB=${IRONIC_USE_MARIADB:-true} - -if [[ "$IRONIC_USE_MARIADB" == "true" ]]; then - MARIADB_PASSWORD=${MARIADB_PASSWORD} +if [[ "${IRONIC_USE_MARIADB}" == true ]]; then + if [[ -z "${MARIADB_PASSWORD:-}" ]]; then + echo "FATAL: IRONIC_USE_MARIADB requires password, mount a secret under /auth/mariadb" + exit 1 + fi MARIADB_DATABASE=${MARIADB_DATABASE:-ironic} MARIADB_USER=${MARIADB_USER:-ironic} MARIADB_HOST=${MARIADB_HOST:-127.0.0.1} @@ -32,13 +33,9 @@ if [[ "$IRONIC_USE_MARIADB" == "true" ]]; then fi fi -# TODO(dtantsur): remove the explicit default once we get -# https://review.opendev.org/761185 in the repositories -NUMPROC="$(grep -c "^processor" /proc/cpuinfo)" -if [[ "$NUMPROC" -lt 4 ]]; then - NUMPROC=4 -fi -export NUMWORKERS=${NUMWORKERS:-$NUMPROC} +# zero makes it do cpu number detection on Ironic side +export NUMWORKERS=${NUMWORKERS:-0} + # Whether to enable fast_track provisioning or not export IRONIC_FAST_TRACK=${IRONIC_FAST_TRACK:-true} @@ -57,8 +54,6 @@ wait_for_interface_or_ip # Hostname to use for the current conductor instance. export IRONIC_CONDUCTOR_HOST=${IRONIC_CONDUCTOR_HOST:-${IRONIC_URL_HOST}} -export IRONIC_BASE_URL=${IRONIC_BASE_URL:-"${IRONIC_SCHEME}://${IRONIC_URL_HOST}:${IRONIC_ACCESS_PORT}"} - if [[ -n "$IRONIC_EXTERNAL_IP" ]]; then export IRONIC_EXTERNAL_CALLBACK_URL=${IRONIC_EXTERNAL_CALLBACK_URL:-"${IRONIC_SCHEME}://${IRONIC_EXTERNAL_IP}:${IRONIC_ACCESS_PORT}"} if [[ "$IRONIC_VMEDIA_TLS_SETUP" == "true" ]]; then @@ -68,15 +63,15 @@ if [[ -n "$IRONIC_EXTERNAL_IP" ]]; then fi fi -IMAGE_CACHE_PREFIX="/shared/html/images/ironic-python-agent-${DEPLOY_ARCHITECTURE}" +IMAGE_CACHE_PREFIX=/shared/html/images/ironic-python-agent if [[ -f "${IMAGE_CACHE_PREFIX}.kernel" ]] && [[ -f "${IMAGE_CACHE_PREFIX}.initramfs" ]]; then export IRONIC_DEFAULT_KERNEL="${IMAGE_CACHE_PREFIX}.kernel" export IRONIC_DEFAULT_RAMDISK="${IMAGE_CACHE_PREFIX}.initramfs" fi -if [[ -f /etc/ironic/ironic.conf ]]; then +if [[ -f "${IRONIC_CONF_DIR}/ironic.conf" ]]; then # Make a copy of the original supposed empty configuration file - cp /etc/ironic/ironic.conf /etc/ironic/ironic.conf_orig + cp "${IRONIC_CONF_DIR}/ironic.conf" "${IRONIC_CONF_DIR}/ironic.conf.orig" fi # oslo.config also supports Config Opts From Environment, log them to stdout @@ -86,34 +81,16 @@ env | grep "^OS_" || true mkdir -p /shared/html mkdir -p /shared/ironic_prometheus_exporter -configure_json_rpc_auth - if [[ -f /proc/sys/crypto/fips_enabled ]]; then ENABLE_FIPS_IPA=$(cat /proc/sys/crypto/fips_enabled) export ENABLE_FIPS_IPA fi # The original ironic.conf is empty, and can be found in ironic.conf_orig -render_j2_config /etc/ironic/ironic.conf.j2 /etc/ironic/ironic.conf +render_j2_config "/etc/ironic/ironic.conf.j2" \ + "${IRONIC_CONF_DIR}/ironic.conf" -configure_client_basic_auth ironic-rpc +configure_json_rpc_auth # Make sure ironic traffic bypasses any proxies export NO_PROXY="${NO_PROXY:-},$IRONIC_IP" - -PROBE_CURL_ARGS= -if [[ "${IRONIC_REVERSE_PROXY_SETUP}" == "true" ]]; then - if [[ "${IRONIC_PRIVATE_PORT}" == "unix" ]]; then - PROBE_URL="http://127.0.0.1:6385" - PROBE_CURL_ARGS="--unix-socket /shared/ironic.sock" - else - PROBE_URL="http://127.0.0.1:${IRONIC_PRIVATE_PORT}" - fi -else - PROBE_URL="${IRONIC_BASE_URL}" -fi -export PROBE_CURL_ARGS -export PROBE_URL - -PROBE_KIND=readiness render_j2_config /bin/ironic-probe.j2 /bin/ironic-readiness -PROBE_KIND=liveness render_j2_config /bin/ironic-probe.j2 /bin/ironic-liveness diff --git a/ironic-image/scripts/ironic-common.sh b/ironic-image/scripts/ironic-common.sh index fd740f3..58687c5 100644 --- a/ironic-image/scripts/ironic-common.sh +++ b/ironic-image/scripts/ironic-common.sh @@ -2,11 +2,36 @@ set -euxo pipefail -IRONIC_IP="${IRONIC_IP:-}" +# Export IRONIC_IP to avoid needing to lean on IRONIC_URL_HOST for consumption in +# e.g. dnsmasq configuration +export IRONIC_IP="${IRONIC_IP:-}" PROVISIONING_INTERFACE="${PROVISIONING_INTERFACE:-}" PROVISIONING_IP="${PROVISIONING_IP:-}" PROVISIONING_MACS="${PROVISIONING_MACS:-}" IPXE_CUSTOM_FIRMWARE_DIR="${IPXE_CUSTOM_FIRMWARE_DIR:-/shared/custom_ipxe_firmware}" +CUSTOM_CONFIG_DIR="${CUSTOM_CONFIG_DIR:-/conf}" +CUSTOM_DATA_DIR="${CUSTOM_DATA_DIR:-/data}" +export DNSMASQ_CONF_DIR="${CUSTOM_CONFIG_DIR}/dnsmasq" +export DNSMASQ_DATA_DIR="${CUSTOM_DATA_DIR}/dnsmasq" +export DNSMASQ_TEMP_DIR="${CUSTOM_CONFIG_DIR}/dnsmasq" +export HTTPD_DIR="${CUSTOM_CONFIG_DIR}/httpd" +export HTTPD_CONF_DIR="${HTTPD_DIR}/conf" +export HTTPD_CONF_DIR_D="${HTTPD_DIR}/conf.d" +export IRONIC_CONF_DIR="${CUSTOM_CONFIG_DIR}/ironic" +export IRONIC_DB_DIR="${CUSTOM_DATA_DIR}/db" +export IRONIC_GEN_CERT_DIR="${CUSTOM_DATA_DIR}/auto_gen_certs" +export IRONIC_TMP_DATA_DIR="${CUSTOM_DATA_DIR}/tmp" +export PROBE_CONF_DIR="${CUSTOM_CONFIG_DIR}/probes" + +mkdir -p "${IRONIC_CONF_DIR}" "${PROBE_CONF_DIR}" "${HTTPD_CONF_DIR}" \ + "${HTTPD_CONF_DIR_D}" "${DNSMASQ_CONF_DIR}" "${DNSMASQ_TEMP_DIR}" \ + "${IRONIC_DB_DIR}" "${IRONIC_GEN_CERT_DIR}" "${DNSMASQ_DATA_DIR}" \ + "${IRONIC_TMP_DATA_DIR}" + +export HTPASSWD_FILE="${IRONIC_CONF_DIR}/htpasswd" +export LOCAL_DB_URI="sqlite:///${IRONIC_DB_DIR}/ironic.sqlite" + +export IRONIC_USE_MARIADB=${IRONIC_USE_MARIADB:-false} get_provisioning_interface() { @@ -19,13 +44,13 @@ get_provisioning_interface() local interface="provisioning" if [[ -n "${PROVISIONING_IP}" ]]; then - if ip -br addr show | grep -qi " ${PROVISIONING_IP}/"; then + if ip -br addr show | grep -i " ${PROVISIONING_IP}/" &>/dev/null; then interface="$(ip -br addr show | grep -i " ${PROVISIONING_IP}/" | cut -f 1 -d ' ' | cut -f 1 -d '@')" fi fi for mac in ${PROVISIONING_MACS//,/ }; do - if ip -br link show up | grep -qi "$mac"; then + if ip -br link show up | grep -i "$mac" &>/dev/null; then interface="$(ip -br link show up | grep -i "$mac" | cut -f 1 -d ' ' | cut -f 1 -d '@')" break fi @@ -42,9 +67,12 @@ export LISTEN_ALL_INTERFACES="${LISTEN_ALL_INTERFACES:-true}" # Wait for the interface or IP to be up, sets $IRONIC_IP wait_for_interface_or_ip() { - # If $PROVISIONING_IP is specified, then we wait for that to become available on an interface, otherwise we look at $PROVISIONING_INTERFACE for an IP - if [[ -n "$PROVISIONING_IP" ]]; then - # Convert the address using ipcalc which strips out the subnet. For IPv6 addresses, this will give the short-form address + # If $PROVISIONING_IP is specified, then we wait for that to become + # available on an interface, otherwise we look at $PROVISIONING_INTERFACE + # for an IP + if [[ -n "${PROVISIONING_IP}" ]]; then + # Convert the address using ipcalc which strips out the subnet. + # For IPv6 addresses, this will give the short-form address IRONIC_IP="$(ipcalc "${PROVISIONING_IP}" | grep "^Address:" | awk '{print $2}')" export IRONIC_IP until grep -F " ${IRONIC_IP}/" <(ip -br addr show); do @@ -69,31 +97,37 @@ wait_for_interface_or_ip() export IPV=4 export IRONIC_URL_HOST="$IRONIC_IP" fi + + # Avoid having to construct full URL multiple times while allowing + # the override of IRONIC_HTTP_URL for environments in which IRONIC_IP + # is unreachable from hosts being provisioned. + export IRONIC_HTTP_URL="${IRONIC_HTTP_URL:-http://${IRONIC_URL_HOST}:${HTTP_PORT}}" + export IRONIC_TFTP_URL="${IRONIC_TFTP_URL:-tftp://${IRONIC_URL_HOST}}" + export IRONIC_BASE_URL=${IRONIC_BASE_URL:-"${IRONIC_SCHEME}://${IRONIC_URL_HOST}:${IRONIC_ACCESS_PORT}"} } render_j2_config() { - ls $1 # DEBUG - python3 -c 'import os; import sys; import jinja2; sys.stdout.write(jinja2.Template(sys.stdin.read()).render(env=os.environ))' < "$1" - python3 -c 'import os; import sys; import jinja2; sys.stdout.write(jinja2.Template(sys.stdin.read()).render(env=os.environ))' < "$1" > "$2" - ls $2 # DEBUG + python3.12 -c 'import os; import sys; import jinja2; sys.stdout.write(jinja2.Template(sys.stdin.read()).render(env=os.environ))' < "$1" > "$2" } run_ironic_dbsync() { - if [[ "${IRONIC_USE_MARIADB:-true}" == "true" ]]; then + if [[ "${IRONIC_USE_MARIADB}" == "true" ]]; then # It's possible for the dbsync to fail if mariadb is not up yet, so # retry until success - until ironic-dbsync --config-file /etc/ironic/ironic.conf upgrade; do + until ironic-dbsync --config-file "${IRONIC_CONF_DIR}/ironic.conf" upgrade; do echo "WARNING: ironic-dbsync failed, retrying" sleep 1 done else - # SQLite does not support some statements. Fortunately, we can just create - # the schema in one go if not already created, instead of going through an upgrade - DB_VERSION="$(ironic-dbsync --config-file /etc/ironic/ironic.conf version)" + # SQLite does not support some statements. Fortunately, we can just + # create the schema in one go if not already created, instead of going + # through an upgrade + cp "/var/lib/ironic/ironic.sqlite" "${IRONIC_DB_DIR}/ironic.sqlite" + DB_VERSION="$(ironic-dbsync --config-file "${IRONIC_CONF_DIR}/ironic.conf" version)" if [[ "${DB_VERSION}" == "None" ]]; then - ironic-dbsync --config-file /etc/ironic/ironic.conf create_schema + ironic-dbsync --config-file "${IRONIC_CONF_DIR}/ironic.conf" create_schema fi fi } diff --git a/ironic-image/scripts/ironic-probe.j2 b/ironic-image/scripts/ironic-probe.j2 deleted file mode 100644 index 85a5ca7..0000000 --- a/ironic-image/scripts/ironic-probe.j2 +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -set -eu -o pipefail - -curl -sSf {{ env.PROBE_CURL_ARGS }} "{{ env.PROBE_URL }}" - -# TODO(dtantsur): when PROBE_KIND==readiness, try the conductor and driver API -# to make sure the conductor is ready. This requires having access to secrets -# since these endpoints are authenticated. diff --git a/ironic-image/scripts/ironic-probe.sh b/ironic-image/scripts/ironic-probe.sh new file mode 100755 index 0000000..defe5c8 --- /dev/null +++ b/ironic-image/scripts/ironic-probe.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +set -eu -o pipefail + +# shellcheck disable=SC1091 +. /bin/ironic-common.sh +# shellcheck disable=SC1091 +. /bin/auth-common.sh + +PROBE_CURL_ARGS= +if [[ "${IRONIC_REVERSE_PROXY_SETUP}" == "true" ]]; then + if [[ "${IRONIC_PRIVATE_PORT}" == "unix" ]]; then + PROBE_URL="http://127.0.0.1:6385" + PROBE_CURL_ARGS="--unix-socket /shared/ironic.sock" + else + PROBE_URL="http://127.0.0.1:${IRONIC_PRIVATE_PORT}" + fi +else + PROBE_URL="${IRONIC_BASE_URL}" +fi + +# shellcheck disable=SC2086 +curl -sSf ${PROBE_CURL_ARGS} "${PROBE_URL}" diff --git a/ironic-image/scripts/rundatabase-upgrade b/ironic-image/scripts/rundatabase-upgrade new file mode 100755 index 0000000..26fb1f4 --- /dev/null +++ b/ironic-image/scripts/rundatabase-upgrade @@ -0,0 +1,10 @@ +#!/usr/bin/bash + +set -euxo pipefail + +# shellcheck disable=SC1091 +. /bin/configure-ironic.sh + +# NOTE(dtantsur): no retries here: this script is supposed to be run as a Job +# that is retried on failure. +exec ironic-dbsync --config-file "${IRONIC_CONF_DIR}/ironic.conf" upgrade diff --git a/ironic-image/scripts/rundnsmasq b/ironic-image/scripts/rundnsmasq index 16f4c76..53adf33 100644 --- a/ironic-image/scripts/rundnsmasq +++ b/ironic-image/scripts/rundnsmasq @@ -13,7 +13,11 @@ export DNS_PORT=${DNS_PORT:-0} wait_for_interface_or_ip if [[ "${DNS_IP:-}" == "provisioning" ]]; then - export DNS_IP="$IRONIC_URL_HOST" + if [[ "${IPV}" == "4" ]]; then + export DNS_IP="${IRONIC_IP}" + else + export DNS_IP="[${IRONIC_IP}]" + fi fi mkdir -p /shared/tftpboot @@ -32,12 +36,12 @@ fi # Template and write dnsmasq.conf # we template via /tmp as sed otherwise creates temp files in /etc directory # where we can't write -python3 -c 'import os; import sys; import jinja2; sys.stdout.write(jinja2.Template(sys.stdin.read()).render(env=os.environ))' /tmp/dnsmasq.conf +python3.12 -c 'import os; import sys; import jinja2; sys.stdout.write(jinja2.Template(sys.stdin.read()).render(env=os.environ))' <"/templates/dnsmasq.conf.j2" >"${DNSMASQ_TEMP_DIR}/dnsmasq_temp.conf" for iface in $(echo "$DNSMASQ_EXCEPT_INTERFACE" | tr ',' ' '); do - sed -i -e "/^interface=.*/ a\except-interface=${iface}" /tmp/dnsmasq.conf + sed -i -e "/^interface=.*/ a\except-interface=${iface}" "${DNSMASQ_TEMP_DIR}/dnsmasq_temp.conf" done -cat /tmp/dnsmasq.conf > /etc/dnsmasq.conf -rm /tmp/dnsmasq.conf +cat "${DNSMASQ_TEMP_DIR}/dnsmasq_temp.conf" > "${DNSMASQ_CONF_DIR}/dnsmasq.conf" +rm "${DNSMASQ_TEMP_DIR}/dnsmasq_temp.conf" -exec /usr/sbin/dnsmasq -d -q -C /etc/dnsmasq.conf +exec /usr/sbin/dnsmasq -d -q -C "${DNSMASQ_CONF_DIR}/dnsmasq.conf" diff --git a/ironic-image/scripts/runhttpd b/ironic-image/scripts/runhttpd index d6175ba..bbd973f 100644 --- a/ironic-image/scripts/runhttpd +++ b/ironic-image/scripts/runhttpd @@ -28,25 +28,28 @@ wait_for_interface_or_ip mkdir -p /shared/html chmod 0777 /shared/html -IRONIC_BASE_URL="${IRONIC_SCHEME}://${IRONIC_URL_HOST}" - -INSPECTOR_EXTRA_ARGS=" ipa-inspection-callback-url=${IRONIC_BASE_URL}:${IRONIC_ACCESS_PORT}/v1/continue_inspection" +INSPECTOR_EXTRA_ARGS=" ipa-inspection-callback-url=${IRONIC_BASE_URL}/v1/continue_inspection" if [[ "$IRONIC_FAST_TRACK" == "true" ]]; then - INSPECTOR_EXTRA_ARGS+=" ipa-api-url=${IRONIC_BASE_URL}:${IRONIC_ACCESS_PORT}" + INSPECTOR_EXTRA_ARGS+=" ipa-api-url=${IRONIC_BASE_URL}" fi export INSPECTOR_EXTRA_ARGS # Copy files to shared mount -render_j2_config /tmp/inspector.ipxe.j2 /shared/html/inspector.ipxe -cp /tmp/uefi_esp*.img /shared/html/ +render_j2_config /templates/inspector.ipxe.j2 /shared/html/inspector.ipxe +# cp -r /etc/httpd/* "${HTTPD_DIR}" +if [[ -f "${HTTPD_CONF_DIR}/httpd.conf" ]]; then + mv "${HTTPD_CONF_DIR}/httpd.conf" "${HTTPD_CONF_DIR}/httpd.conf.example" +fi # Render the core httpd config -render_j2_config /etc/httpd/conf/httpd.conf.j2 /etc/httpd/conf/httpd.conf +render_j2_config "/etc/httpd/conf/httpd.conf.j2" \ + "${HTTPD_CONF_DIR}/httpd.conf" if [[ "$IRONIC_TLS_SETUP" == "true" ]]; then if [[ "${IRONIC_REVERSE_PROXY_SETUP}" == "true" ]]; then - render_j2_config /tmp/httpd-ironic-api.conf.j2 /etc/httpd/conf.d/ironic.conf + render_j2_config "/templates/httpd-ironic-api.conf.j2" \ + "${HTTPD_CONF_DIR_D}/ironic.conf" fi else export IRONIC_REVERSE_PROXY_SETUP="false" # If TLS is not used, we have no reason to use the reverse proxy @@ -56,33 +59,24 @@ write_htpasswd_files # Render httpd TLS configuration for /shared/html/ if [[ "$IRONIC_VMEDIA_TLS_SETUP" == "true" ]]; then - render_j2_config /etc/httpd-vmedia.conf.j2 /etc/httpd/conf.d/vmedia.conf + render_j2_config "/templates/httpd-vmedia.conf.j2" \ + "${HTTPD_CONF_DIR_D}/vmedia.conf" fi # Render httpd TLS configuration for /shared/html if [[ "$IPXE_TLS_SETUP" == "true" ]]; then mkdir -p /shared/html/custom-ipxe chmod 0777 /shared/html/custom-ipxe - render_j2_config "/etc/httpd-ipxe.conf.j2" "/etc/httpd/conf.d/ipxe.conf" + render_j2_config "/templates/httpd-ipxe.conf.j2" "${HTTPD_CONF_DIR_D}/ipxe.conf" cp "${IPXE_CUSTOM_FIRMWARE_DIR}/undionly.kpxe" \ "${IPXE_CUSTOM_FIRMWARE_DIR}/snponly.efi" \ "/shared/html/custom-ipxe" fi # Set up inotify to kill the container (restart) whenever cert files for ironic api change -if [[ "$IRONIC_TLS_SETUP" == "true" ]] && [[ "${RESTART_CONTAINER_CERTIFICATE_UPDATED}" == "true" ]]; then - # shellcheck disable=SC2034 - python3.11 -m pyinotify --raw-format -e IN_DELETE_SELF -v "${IRONIC_CERT_FILE}" | while read -r file event; do - kill -WINCH $(pgrep httpd) - done & -fi +configure_restart_on_certificate_update "${IRONIC_TLS_SETUP}" httpd "${IRONIC_CERT_FILE}" # Set up inotify to kill the container (restart) whenever cert of httpd for /shared/html/ path change -if [[ "$IRONIC_VMEDIA_TLS_SETUP" == "true" ]] && [[ "${RESTART_CONTAINER_CERTIFICATE_UPDATED}" == "true" ]]; then - # shellcheck disable=SC2034 - python3.11 -m pyinotify --raw-format -e IN_DELETE_SELF -v "${IRONIC_VMEDIA_CERT_FILE}" | while read -r file event; do - kill -WINCH $(pgrep httpd) - done & -fi +configure_restart_on_certificate_update "${IRONIC_VMEDIA_TLS_SETUP}" httpd "${IRONIC_VMEDIA_CERT_FILE}" -exec /usr/sbin/httpd -DFOREGROUND -f /etc/httpd/conf/httpd.conf +exec /usr/sbin/httpd -DFOREGROUND -f "${HTTPD_CONF_DIR}/httpd.conf" diff --git a/ironic-image/scripts/runironic b/ironic-image/scripts/runironic index d782fe1..2d2b35e 100644 --- a/ironic-image/scripts/runironic +++ b/ironic-image/scripts/runironic @@ -1,23 +1,18 @@ #!/usr/bin/bash -# This setting must go before configure-ironic since it has different defaults. -export IRONIC_USE_MARIADB=${IRONIC_USE_MARIADB:-false} - # shellcheck disable=SC1091 . /bin/configure-ironic.sh # Ramdisk logs mkdir -p /shared/log/ironic/deploy -run_ironic_dbsync - -if [[ "$IRONIC_TLS_SETUP" == "true" ]] && [[ "${RESTART_CONTAINER_CERTIFICATE_UPDATED}" == "true" ]]; then - # shellcheck disable=SC2034 - python3.11 -m pyinotify --raw-format -e IN_DELETE_SELF -v "${IRONIC_CERT_FILE}" | while read -r file event; do - kill $(pgrep ironic) - done & +# Allows skipping dbsync if it's done by an external job +if [[ "${IRONIC_SKIP_DBSYNC:-false}" != true ]]; then + run_ironic_dbsync fi +configure_restart_on_certificate_update "${IRONIC_TLS_SETUP}" ironic "${IRONIC_CERT_FILE}" + configure_ironic_auth -exec /usr/bin/ironic +exec /usr/bin/ironic --config-dir "${IRONIC_CONF_DIR}" diff --git a/ironic-image/scripts/runironic-exporter b/ironic-image/scripts/runironic-exporter index f2f60f2..e429a45 100644 --- a/ironic-image/scripts/runironic-exporter +++ b/ironic-image/scripts/runironic-exporter @@ -2,11 +2,13 @@ # shellcheck disable=SC1091 . /bin/configure-ironic.sh +# shellcheck disable=SC1091 +. /bin/ironic-common.sh FLASK_RUN_HOST=${FLASK_RUN_HOST:-0.0.0.0} FLASK_RUN_PORT=${FLASK_RUN_PORT:-9608} -export IRONIC_CONFIG="/etc/ironic/ironic.conf" +export IRONIC_CONFIG="${IRONIC_CONF_DIR}/ironic.conf" exec gunicorn -b "${FLASK_RUN_HOST}:${FLASK_RUN_PORT}" -w 4 \ ironic_prometheus_exporter.app.wsgi:application diff --git a/ironic-image/scripts/runlogwatch.sh b/ironic-image/scripts/runlogwatch.sh index a2255d2..00b4625 100644 --- a/ironic-image/scripts/runlogwatch.sh +++ b/ironic-image/scripts/runlogwatch.sh @@ -3,17 +3,19 @@ # Ramdisk logs path LOG_DIR="/shared/log/ironic/deploy" -# The ironic container creates the directory, wait for -# it to exist before running inotifywait or it can fail causing -# a spurious restart -while [ ! -d "${LOG_DIR}" ]; do - echo "Waiting for ${LOG_DIR}" - sleep 5 -done +mkdir -p "${LOG_DIR}" -python3.11 -m pyinotify --raw-format -e IN_CLOSE_WRITE -v "${LOG_DIR}" | - while read -r path _action file; do - echo "************ Contents of ${path}/${file} ramdisk log file bundle **************" - tar -xOzvvf "${path}/${file}" | sed -e "s/^/${file}: /" - rm -f "${path}/${file}" +# shellcheck disable=SC2034 +python3.12 -m pyinotify --raw-format -e IN_CLOSE_WRITE -v "${LOG_DIR}" | + while read -r event dir mask maskname filename filepath pathname wd; do + #NOTE(elfosardo): a pyinotify event looks like this: + # + FILENAME=$(echo "${filename}" | cut -d'=' -f2-) + echo "************ Contents of ${LOG_DIR}/${FILENAME} ramdisk log file bundle **************" + tar -tzf "${LOG_DIR}/${FILENAME}" | while read -r entry; do + echo "${FILENAME}: **** Entry: ${entry} ****" + tar -xOzf "${LOG_DIR}/${FILENAME}" "${entry}" | sed -e "s/^/${FILENAME}: /" + echo + done + rm -f "${LOG_DIR}/${FILENAME}" done diff --git a/ironic-image/scripts/runonline-data-migrations b/ironic-image/scripts/runonline-data-migrations new file mode 100755 index 0000000..14383c4 --- /dev/null +++ b/ironic-image/scripts/runonline-data-migrations @@ -0,0 +1,10 @@ +#!/usr/bin/bash + +set -euxo pipefail + +# shellcheck disable=SC1091 +. /bin/configure-ironic.sh + +# NOTE(dtantsur): no retries here: this script is supposed to be run as a Job +# that is retried on failure. +exec ironic-dbsync --config-file "${IRONIC_CONF_DIR}/ironic.conf" online_data_migrations diff --git a/ironic-image/scripts/tls-common.sh b/ironic-image/scripts/tls-common.sh index 6805885..622d61b 100644 --- a/ironic-image/scripts/tls-common.sh +++ b/ironic-image/scripts/tls-common.sh @@ -20,11 +20,6 @@ export MARIADB_CACERT_FILE=/certs/ca/mariadb/tls.crt export IPXE_TLS_PORT="${IPXE_TLS_PORT:-8084}" -mkdir -p /certs/ironic -mkdir -p /certs/ca/ironic -mkdir -p /certs/ipxe -mkdir -p /certs/vmedia - if [[ -f "$IRONIC_CERT_FILE" ]] && [[ ! -f "$IRONIC_KEY_FILE" ]]; then echo "Missing TLS Certificate key file $IRONIC_KEY_FILE" exit 1 @@ -69,6 +64,7 @@ if [[ -f "$IRONIC_CERT_FILE" ]] || [[ -f "$IRONIC_CACERT_FILE" ]]; then export IRONIC_TLS_SETUP="true" export IRONIC_SCHEME="https" if [[ ! -f "$IRONIC_CACERT_FILE" ]]; then + mkdir -p "$(dirname "${IRONIC_CACERT_FILE}")" copy_atomic "$IRONIC_CERT_FILE" "$IRONIC_CACERT_FILE" fi else @@ -95,3 +91,21 @@ if [[ -f "$MARIADB_CACERT_FILE" ]]; then else export MARIADB_TLS_ENABLED="false" fi + +configure_restart_on_certificate_update() +{ + local enabled="$1" + local service="$2" + local cert_file="$3" + local signal="TERM" + + if [[ "${enabled}" == "true" ]] && [[ "${RESTART_CONTAINER_CERTIFICATE_UPDATED}" == "true" ]]; then + if [[ "${service}" == httpd ]]; then + signal="WINCH" + fi + python3.12 -m pyinotify --raw-format -e IN_DELETE_SELF -v "${cert_file}" | + while read -r; do + pkill "-${signal}" "${service}" + done & + fi +} -- 2.49.0 From dccfe7863b303fcc3bbf2e09d59f8f18e7c0c35f4da27ae0b4b2865b03de332c Mon Sep 17 00:00:00 2001 From: Marco Chiappero Date: Thu, 26 Jun 2025 13:17:22 +0000 Subject: [PATCH 06/14] Use correct paths and modules for Apache Correct the path of the Apache modules for a SUSE image. Also keep a couple of modules disabled. Signed-off-by: Marco Chiappero --- ironic-image/ironic-config/httpd-modules.conf | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/ironic-image/ironic-config/httpd-modules.conf b/ironic-image/ironic-config/httpd-modules.conf index 5984994..fd2bc99 100644 --- a/ironic-image/ironic-config/httpd-modules.conf +++ b/ironic-image/ironic-config/httpd-modules.conf @@ -1,20 +1,20 @@ # Bare minimum set of modules -LoadModule log_config_module /etc/httpd/modules/mod_log_config.so -LoadModule mime_module /etc/httpd/modules/mod_mime.so -LoadModule dir_module /etc/httpd/modules/mod_dir.so -LoadModule authz_core_module /etc/httpd/modules/mod_authz_core.so -LoadModule unixd_module /etc/httpd/modules/mod_unixd.so -LoadModule mpm_event_module /etc/httpd/modules/mod_mpm_event.so -LoadModule ssl_module /etc/httpd/modules/mod_ssl.so -LoadModule env_module /etc/httpd/modules/mod_env.so -LoadModule proxy_module /etc/httpd/modules/mod_proxy.so -LoadModule proxy_ajp_module /etc/httpd/modules/mod_proxy_ajp.so -LoadModule proxy_balancer_module /etc/httpd/modules/mod_proxy_balancer.so -LoadModule proxy_http_module /etc/httpd/modules/mod_proxy_http.so -LoadModule slotmem_shm_module /etc/httpd/modules/mod_slotmem_shm.so -LoadModule headers_module /etc/httpd/modules/mod_headers.so -LoadModule authn_core_module /etc/httpd/modules/mod_authn_core.so -LoadModule auth_basic_module /etc/httpd/modules/mod_auth_basic.so -LoadModule authn_file_module /etc/httpd/modules/mod_authn_file.so -LoadModule authz_user_module /etc/httpd/modules/mod_authz_user.so -LoadModule access_compat_module /etc/httpd/modules/mod_access_compat.so +LoadModule log_config_module /usr/lib64/apache2/mod_log_config.so +LoadModule mime_module /usr/lib64/apache2/mod_mime.so +LoadModule dir_module /usr/lib64/apache2/mod_dir.so +LoadModule authz_core_module /usr/lib64/apache2/mod_authz_core.so +#LoadModule unixd_module modules/mod_unixd.so +#LoadModule mpm_event_module modules/mod_mpm_event.so +LoadModule ssl_module /usr/lib64/apache2/mod_ssl.so +LoadModule env_module /usr/lib64/apache2/mod_env.so +LoadModule proxy_module /usr/lib64/apache2/mod_proxy.so +LoadModule proxy_ajp_module /usr/lib64/apache2/mod_proxy_ajp.so +LoadModule proxy_balancer_module /usr/lib64/apache2/mod_proxy_balancer.so +LoadModule proxy_http_module /usr/lib64/apache2/mod_proxy_http.so +LoadModule slotmem_shm_module /usr/lib64/apache2/mod_slotmem_shm.so +LoadModule headers_module /usr/lib64/apache2/mod_headers.so +LoadModule authn_core_module /usr/lib64/apache2/mod_authn_core.so +LoadModule auth_basic_module /usr/lib64/apache2/mod_auth_basic.so +LoadModule authn_file_module /usr/lib64/apache2/mod_authn_file.so +LoadModule authz_user_module /usr/lib64/apache2/mod_authz_user.so +LoadModule access_compat_module /usr/lib64/apache2/mod_access_compat.so -- 2.49.0 From 28c3565d52ef92833fe637ac14a741814734b80a41c46de86bfd8f4e1df4c7cf Mon Sep 17 00:00:00 2001 From: Marco Chiappero Date: Thu, 26 Jun 2025 13:32:48 +0000 Subject: [PATCH 07/14] Use ironic-suse user/group in Apache for media Signed-off-by: Marco Chiappero --- ironic-image/ironic-config/httpd.conf.j2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ironic-image/ironic-config/httpd.conf.j2 b/ironic-image/ironic-config/httpd.conf.j2 index aa78d73..e21f536 100644 --- a/ironic-image/ironic-config/httpd.conf.j2 +++ b/ironic-image/ironic-config/httpd.conf.j2 @@ -5,8 +5,8 @@ Listen {{ env.HTTP_PORT }} Listen {{ env.IRONIC_URL_HOST }}:{{ env.HTTP_PORT }} {% endif %} Include /etc/httpd/conf.modules.d/*.conf -User apache -Group apache +User ironic-suse +Group ironic-suse AllowOverride none -- 2.49.0 From 2377717803ae1fd5970cd9d5c4aa3e88dc9c05d8dee7b285d953dd89f22cfa9d Mon Sep 17 00:00:00 2001 From: Marco Chiappero Date: Thu, 26 Jun 2025 13:14:07 +0000 Subject: [PATCH 08/14] Use ironic-suse user/group in Apache for API Signed-off-by: Marco Chiappero --- ironic-image/ironic-config/httpd-ironic-api.conf.j2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ironic-image/ironic-config/httpd-ironic-api.conf.j2 b/ironic-image/ironic-config/httpd-ironic-api.conf.j2 index a374894..317118e 100644 --- a/ironic-image/ironic-config/httpd-ironic-api.conf.j2 +++ b/ironic-image/ironic-config/httpd-ironic-api.conf.j2 @@ -27,8 +27,8 @@ Listen {{ env.IRONIC_URL_HOST }}:{{ env.IRONIC_LISTEN_PORT }} ProxyPassReverse "/" "http://127.0.0.1:{{ env.IRONIC_PRIVATE_PORT }}/" {% endif %} - SetEnv APACHE_RUN_USER ironic - SetEnv APACHE_RUN_GROUP ironic + SetEnv APACHE_RUN_USER ironic-suse + SetEnv APACHE_RUN_GROUP ironic-suse ErrorLog /dev/stderr LogLevel debug -- 2.49.0 From d68fa72bc497c1eabc8cc0f2a54d164569a787d3eba37406bba3b950d3cfcc8f Mon Sep 17 00:00:00 2001 From: Marco Chiappero Date: Thu, 26 Jun 2025 14:06:13 +0000 Subject: [PATCH 09/14] Use arch named IPA file in IMAGE_CACHE_PREFIX Signed-off-by: Marco Chiappero --- ironic-image/scripts/configure-ironic.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ironic-image/scripts/configure-ironic.sh b/ironic-image/scripts/configure-ironic.sh index d2154d0..f7c3c21 100644 --- a/ironic-image/scripts/configure-ironic.sh +++ b/ironic-image/scripts/configure-ironic.sh @@ -63,7 +63,7 @@ if [[ -n "$IRONIC_EXTERNAL_IP" ]]; then fi fi -IMAGE_CACHE_PREFIX=/shared/html/images/ironic-python-agent +IMAGE_CACHE_PREFIX="/shared/html/images/ironic-python-agent-${DEPLOY_ARCHITECTURE}" if [[ -f "${IMAGE_CACHE_PREFIX}.kernel" ]] && [[ -f "${IMAGE_CACHE_PREFIX}.initramfs" ]]; then export IRONIC_DEFAULT_KERNEL="${IMAGE_CACHE_PREFIX}.kernel" export IRONIC_DEFAULT_RAMDISK="${IMAGE_CACHE_PREFIX}.initramfs" -- 2.49.0 From 49b8245bf88be1c20c91e76c7c36769627ebd29650b8f84c796520a42134a5f7 Mon Sep 17 00:00:00 2001 From: Marco Chiappero Date: Thu, 26 Jun 2025 13:36:24 +0000 Subject: [PATCH 10/14] Use arch specific file for IPA Signed-off-by: Marco Chiappero --- ironic-image/ironic-config/inspector.ipxe.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ironic-image/ironic-config/inspector.ipxe.j2 b/ironic-image/ironic-config/inspector.ipxe.j2 index 23b5e5e..dd47aa9 100644 --- a/ironic-image/ironic-config/inspector.ipxe.j2 +++ b/ironic-image/ironic-config/inspector.ipxe.j2 @@ -5,6 +5,6 @@ echo In inspector.ipxe imgfree # NOTE(dtantsur): keep inspection kernel params in [mdns]params in # ironic-inspector-image and configuration in configure-ironic.sh -kernel --timeout 60000 {{ env.IRONIC_HTTP_URL }}/images/ironic-python-agent.kernel ipa-insecure=1 ipa-inspection-collectors={{ env.IRONIC_IPA_COLLECTORS }} systemd.journald.forward_to_console=yes BOOTIF=${mac} ipa-debug=1 ipa-enable-vlan-interfaces={{ env.IRONIC_ENABLE_VLAN_INTERFACES }} ipa-inspection-dhcp-all-interfaces=1 ipa-collect-lldp=1 {{ env.INSPECTOR_EXTRA_ARGS }} initrd=ironic-python-agent.initramfs {% if env.IRONIC_RAMDISK_SSH_KEY %}sshkey="{{ env.IRONIC_RAMDISK_SSH_KEY|trim }}"{% endif %} {{ env.IRONIC_KERNEL_PARAMS|trim }} || goto retry_boot +kernel --timeout 60000 {{ env.IRONIC_HTTP_URL }}/images/ironic-python-agent-${buildarch}.kernel ipa-insecure=1 ipa-inspection-collectors={{ env.IRONIC_IPA_COLLECTORS }} systemd.journald.forward_to_console=yes BOOTIF=${mac} ipa-debug=1 ipa-enable-vlan-interfaces={{ env.IRONIC_ENABLE_VLAN_INTERFACES }} ipa-inspection-dhcp-all-interfaces=1 ipa-collect-lldp=1 {{ env.INSPECTOR_EXTRA_ARGS }} initrd=ironic-python-agent.initramfs {% if env.IRONIC_RAMDISK_SSH_KEY %}sshkey="{{ env.IRONIC_RAMDISK_SSH_KEY|trim }}"{% endif %} {{ env.IRONIC_KERNEL_PARAMS|trim }} || goto retry_boot initrd --timeout 60000 {{ env.IRONIC_HTTP_URL }}/images/ironic-python-agent.initramfs || goto retry_boot boot -- 2.49.0 From 411dddbedf30eac5d108ea4063966da0b3750f22c5bbe9b10ac82f6e963bf324 Mon Sep 17 00:00:00 2001 From: Marco Chiappero Date: Mon, 30 Jun 2025 11:43:07 +0000 Subject: [PATCH 11/14] Change GRUB path in ironic.conf Correct path for grub.cfg on a SUSE system. Signed-off-by: Marco Chiappero --- ironic-image/ironic-config/ironic.conf.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ironic-image/ironic-config/ironic.conf.j2 b/ironic-image/ironic-config/ironic.conf.j2 index ed7c87d..c947101 100644 --- a/ironic-image/ironic-config/ironic.conf.j2 +++ b/ironic-image/ironic-config/ironic.conf.j2 @@ -39,7 +39,7 @@ isolinux_bin = /usr/share/syslinux/isolinux.bin # NOTE(dtantsur): this path is specific to the GRUB image that is built into # the ESP provided in [conductor]bootloader. -grub_config_path = EFI/centos/grub.cfg +grub_config_path = EFI/BOOT/grub.cfg [agent] deploy_logs_collect = always -- 2.49.0 From 7a377d7d9096a3a6e38249b62b7f03dc578daf0690174bfb71ce0d291f928b7b Mon Sep 17 00:00:00 2001 From: Marco Chiappero Date: Fri, 4 Jul 2025 15:10:00 +0000 Subject: [PATCH 12/14] Disable the network schema check to allow for nmstate definitions Bypass the OpenStack network-data format validation, to allow for the nmstate based one we instead use (which would otherwise fail). Signed-off-by: Marco Chiappero --- ironic-image/Dockerfile | 3 +-- ironic-image/ironic-config/ironic.conf.j2 | 3 +++ ironic-image/ironic-config/network-data-schema-empty.json | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 ironic-image/ironic-config/network-data-schema-empty.json diff --git a/ironic-image/Dockerfile b/ironic-image/Dockerfile index 2f9f721..2f5d9a3 100644 --- a/ironic-image/Dockerfile +++ b/ironic-image/Dockerfile @@ -88,8 +88,7 @@ RUN if [ "$(uname -m)" = "aarch64" ]; then\ COPY --from=base /tmp/esp-x86_64.img /tmp/uefi_esp-x86_64.img COPY --from=base /tmp/esp-aarch64.img /tmp/uefi_esp-arm64.img -COPY ironic-config/ironic.conf.j2 /etc/ironic/ -COPY ironic-config/network-data-schema-empty.json /etc/ironic/ +COPY ironic-config/ironic.conf.j2 ironic-config/network-data-schema-empty.json /etc/ironic/ # DNSMASQ COPY ironic-config/dnsmasq.conf.j2 /etc/ diff --git a/ironic-image/ironic-config/ironic.conf.j2 b/ironic-image/ironic-config/ironic.conf.j2 index c947101..3813275 100644 --- a/ironic-image/ironic-config/ironic.conf.j2 +++ b/ironic-image/ironic-config/ironic.conf.j2 @@ -72,6 +72,9 @@ enable_ssl_api = true {% endif %} api_workers = {{ env.NUMWORKERS }} +# Disable schema validation so we can pass nmstate format +network_data_schema = /etc/ironic/network-data-schema-empty.json + [conductor] automated_clean = {{ env.IRONIC_AUTOMATED_CLEAN }} # NOTE(dtantsur): keep aligned with [pxe]boot_retry_timeout below. diff --git a/ironic-image/ironic-config/network-data-schema-empty.json b/ironic-image/ironic-config/network-data-schema-empty.json new file mode 100644 index 0000000..d31a3bc --- /dev/null +++ b/ironic-image/ironic-config/network-data-schema-empty.json @@ -0,0 +1 @@ +{} -- 2.49.0 From 98af6481c6e96ccfc17619491b18a720f811e6878b22c3d4ba196d5974dab675 Mon Sep 17 00:00:00 2001 From: Marco Chiappero Date: Mon, 30 Jun 2025 12:33:42 +0000 Subject: [PATCH 13/14] Update the destination path of Jinjia templates Previously .j2 files used to be copied to either /tmp or /etc directories before being instantiated. A new /templates directory is now used by the startup scripts, so update the Dockerfile accordingly. Signed-off-by: Marco Chiappero --- ironic-image/Dockerfile | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/ironic-image/Dockerfile b/ironic-image/Dockerfile index 2f5d9a3..ad4238b 100644 --- a/ironic-image/Dockerfile +++ b/ironic-image/Dockerfile @@ -72,7 +72,8 @@ COPY configure-nonroot.sh /bin/ RUN set -euo pipefail; chmod +x /bin/configure-ironic.sh /bin/rundnsmasq /bin/runhttpd /bin/runironic /bin/runironic-exporter /bin/runlogwatch.sh /bin/configure-nonroot.sh COPY ironic-config/inspector.ipxe.j2 ironic-config/httpd-ironic-api.conf.j2 \ - ironic-config/ipxe_config.template /tmp/ + ironic-config/ipxe_config.template ironic-config/dnsmasq.conf.j2 \ + /templates/ # IRONIC # RUN cp /usr/share/ipxe/undionly.kpxe /tftpboot/undionly.kpxe @@ -90,9 +91,6 @@ COPY --from=base /tmp/esp-aarch64.img /tmp/uefi_esp-arm64.img COPY ironic-config/ironic.conf.j2 ironic-config/network-data-schema-empty.json /etc/ironic/ -# DNSMASQ -COPY ironic-config/dnsmasq.conf.j2 /etc/ - # Workaround # Removing the 010-ironic.conf file that comes with the package RUN rm /etc/ironic/ironic.conf.d/010-ironic.conf @@ -100,8 +98,8 @@ RUN rm /etc/ironic/ironic.conf.d/010-ironic.conf # Custom httpd config, removes all but the bare minimum needed modules COPY ironic-config/httpd.conf.j2 /etc/httpd/conf/ COPY ironic-config/httpd-modules.conf /etc/httpd/conf.modules.d/ -COPY ironic-config/apache2-vmedia.conf.j2 /etc/httpd-vmedia.conf.j2 -COPY ironic-config/apache2-ipxe.conf.j2 /etc/httpd-ipxe.conf.j2 +COPY ironic-config/apache2-vmedia.conf.j2 /templates/httpd-vmedia.conf.j2 +COPY ironic-config/apache2-ipxe.conf.j2 /templates/httpd-ipxe.conf.j2 # configure non-root user and set relevant permissions RUN configure-nonroot.sh && rm -f /bin/configure-nonroot.sh -- 2.49.0 From 0efa970293c7a0a0f0502573ec5911230e5cd9057101764664440bc42e9d05bf Mon Sep 17 00:00:00 2001 From: Marco Chiappero Date: Thu, 26 Jun 2025 14:09:46 +0000 Subject: [PATCH 14/14] Use Python 3.11 instead of 3.12 SLE 15.6 the container is based on does not ship Python 3.12, the next packaged release will be 3.13, so stick to 3.11 until then. Signed-off-by: Marco Chiappero --- ironic-image/scripts/ironic-common.sh | 2 +- ironic-image/scripts/rundnsmasq | 2 +- ironic-image/scripts/runlogwatch.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ironic-image/scripts/ironic-common.sh b/ironic-image/scripts/ironic-common.sh index 58687c5..b47ff38 100644 --- a/ironic-image/scripts/ironic-common.sh +++ b/ironic-image/scripts/ironic-common.sh @@ -108,7 +108,7 @@ wait_for_interface_or_ip() render_j2_config() { - python3.12 -c 'import os; import sys; import jinja2; sys.stdout.write(jinja2.Template(sys.stdin.read()).render(env=os.environ))' < "$1" > "$2" + python3.11 -c 'import os; import sys; import jinja2; sys.stdout.write(jinja2.Template(sys.stdin.read()).render(env=os.environ))' < "$1" > "$2" } run_ironic_dbsync() diff --git a/ironic-image/scripts/rundnsmasq b/ironic-image/scripts/rundnsmasq index 53adf33..5368ef6 100644 --- a/ironic-image/scripts/rundnsmasq +++ b/ironic-image/scripts/rundnsmasq @@ -36,7 +36,7 @@ fi # Template and write dnsmasq.conf # we template via /tmp as sed otherwise creates temp files in /etc directory # where we can't write -python3.12 -c 'import os; import sys; import jinja2; sys.stdout.write(jinja2.Template(sys.stdin.read()).render(env=os.environ))' <"/templates/dnsmasq.conf.j2" >"${DNSMASQ_TEMP_DIR}/dnsmasq_temp.conf" +python3.11 -c 'import os; import sys; import jinja2; sys.stdout.write(jinja2.Template(sys.stdin.read()).render(env=os.environ))' <"/templates/dnsmasq.conf.j2" >"${DNSMASQ_TEMP_DIR}/dnsmasq_temp.conf" for iface in $(echo "$DNSMASQ_EXCEPT_INTERFACE" | tr ',' ' '); do sed -i -e "/^interface=.*/ a\except-interface=${iface}" "${DNSMASQ_TEMP_DIR}/dnsmasq_temp.conf" diff --git a/ironic-image/scripts/runlogwatch.sh b/ironic-image/scripts/runlogwatch.sh index 00b4625..1de5658 100644 --- a/ironic-image/scripts/runlogwatch.sh +++ b/ironic-image/scripts/runlogwatch.sh @@ -6,7 +6,7 @@ LOG_DIR="/shared/log/ironic/deploy" mkdir -p "${LOG_DIR}" # shellcheck disable=SC2034 -python3.12 -m pyinotify --raw-format -e IN_CLOSE_WRITE -v "${LOG_DIR}" | +python3.11 -m pyinotify --raw-format -e IN_CLOSE_WRITE -v "${LOG_DIR}" | while read -r event dir mask maskname filename filepath pathname wd; do #NOTE(elfosardo): a pyinotify event looks like this: # -- 2.49.0