File scripts.obscpio of Package ironic-image

07070100000000000081a4000000000000000000000001693bc30600000ec4000000000000000000000000000000000000001700000000scripts/auth-common.sh#!/usr/bin/bash

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
else
    export IRONIC_EXPOSE_JSON_RPC="${IRONIC_EXPOSE_JSON_RPC:-false}"
fi

IRONIC_HTPASSWD_FILE="${IRONIC_CONF_DIR}/htpasswd"
export IRONIC_RPC_HTPASSWD_FILE="${IRONIC_HTPASSWD_FILE}-rpc"
if [[ -f "/auth/ironic/htpasswd" ]]; then
    IRONIC_HTPASSWD=$(</auth/ironic/htpasswd)
fi
if [[ -f "/auth/ironic-rpc/htpasswd" ]]; then
    IRONIC_RPC_HTPASSWD=$(</auth/ironic-rpc/htpasswd)
fi
export IRONIC_HTPASSWD=${IRONIC_HTPASSWD:-${HTTP_BASIC_HTPASSWD:-}}
export IRONIC_RPC_HTPASSWD=${IRONIC_RPC_HTPASSWD:-${IRONIC_HTPASSWD}}

if [[ -n "${MARIADB_PASSWORD:-}" ]]; then
    echo "WARNING: passing MARIADB_PASSWORD is deprecated, mount a secret under /auth/mariadb instead"
elif [[ -f /auth/mariadb/password ]]; then
    MARIADB_PASSWORD=$(</auth/mariadb/password)
fi

if [[ -z "${MARIADB_USER:-}" ]] && [[ -f /auth/mariadb/username ]]; then
    MARIADB_USER=$(</auth/mariadb/username)
fi

IRONIC_CONFIG="${IRONIC_CONF_DIR}/ironic.conf"

if [[ -z "${IRONIC_OCI_AUTH_CONFIG:-}" ]] && [[ -f "/auth/oci.json" ]]; then
    export IRONIC_OCI_AUTH_CONFIG="/auth/oci.json"
fi

configure_json_rpc_auth()
{
    if [[ "${IRONIC_EXPOSE_JSON_RPC}" != "true" ]]; then
        return
    fi

    local auth_config_file="/auth/ironic-rpc/auth-config"
    local username_file="/auth/ironic-rpc/username"
    local password_file="/auth/ironic-rpc/password"
    if [[ -f "${username_file}" ]] && [[ -f "${password_file}" ]]; then
        crudini --set "${IRONIC_CONFIG}" json_rpc username "$(<${username_file})"
        set +x
        crudini --set "${IRONIC_CONFIG}" json_rpc password "$(<${password_file})"
        set -x
    elif [[ -f "${auth_config_file}" ]]; then
        echo "WARNING: using auth-config is deprecated, mount a secret directly"
        # Merge configurations in the "auth" directory into the default ironic configuration file
        crudini --merge "${IRONIC_CONFIG}" < "${auth_config_file}"
    else
        echo "FATAL: no client-side credentials provided for JSON RPC"
        echo "HINT: mount a secret with username and password fields under /auth/ironic-rpc"
        exit 1
    fi

    if [[ -z "${IRONIC_RPC_HTPASSWD}" ]]; then
        if [[ -f "${username_file}" ]] && [[ -f "${password_file}" ]]; then
            htpasswd -c -i -B "${IRONIC_RPC_HTPASSWD_FILE}" "$(<${username_file})" <"${password_file}"
        else
            echo "FATAL: enabling JSON RPC requires authentication"
            echo "HINT: mount a secret with either username and password or htpasswd under /auth/ironic-rpc"
            exit 1
        fi
    else
        printf "%s\n" "${IRONIC_RPC_HTPASSWD}" > "${IRONIC_RPC_HTPASSWD_FILE}"
    fi
}

configure_ironic_auth()
{
    # 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 "${IRONIC_CONFIG}" DEFAULT auth_strategy http_basic
            crudini --set "${IRONIC_CONFIG}" DEFAULT http_basic_auth_user_file "${IRONIC_HTPASSWD_FILE}"
        fi
    fi
}

write_htpasswd_files()
{
    if [[ -n "${IRONIC_HTPASSWD:-}" ]]; then
        printf "%s\n" "${IRONIC_HTPASSWD}" > "${IRONIC_HTPASSWD_FILE}"
    fi
}
07070100000001000081ed000000000000000000000001693bc306000016b8000000000000000000000000000000000000001c00000000scripts/configure-ironic.sh#!/usr/bin/bash

set -euxo pipefail

IRONIC_EXTERNAL_IP="${IRONIC_EXTERNAL_IP:-}"
export VMEDIA_TLS_PORT="${VMEDIA_TLS_PORT:-}"

# Define the VLAN interfaces to be included in introspection report, e.g.
#   all - all VLANs on all interfaces using LLDP information
#   <interface> - all VLANs on a particular interface using LLDP information
#   <interface.vlan> - a particular VLAN on an interface, not relying on LLDP
export IRONIC_ENABLE_VLAN_INTERFACES=${IRONIC_ENABLE_VLAN_INTERFACES:-${IRONIC_INSPECTOR_VLAN_INTERFACES:-all}}

# shellcheck disable=SC1091
. /bin/tls-common.sh
# shellcheck disable=SC1091
. /bin/ironic-common.sh
# shellcheck disable=SC1091
. /bin/auth-common.sh

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}
    export MARIADB_CONNECTION="mysql+pymysql://${MARIADB_USER}:${MARIADB_PASSWORD}@${MARIADB_HOST}/${MARIADB_DATABASE}?charset=utf8"
    if [[ "$MARIADB_TLS_ENABLED" == "true" ]]; then
        export MARIADB_CONNECTION="${MARIADB_CONNECTION}&ssl=on&ssl_ca=${MARIADB_CACERT_FILE}"
    fi
fi

# 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}

# Whether cleaning disks before and after deployment
export IRONIC_AUTOMATED_CLEAN=${IRONIC_AUTOMATED_CLEAN:-true}

# Wheter to enable the sensor data collection
export SEND_SENSOR_DATA=${SEND_SENSOR_DATA:-false}

# Set of collectors that should be used with IPA inspection
export IRONIC_IPA_COLLECTORS=${IRONIC_IPA_COLLECTORS:-default,logs}

wait_for_interface_or_ip

if [[ "$(echo "$LISTEN_ALL_INTERFACES" | tr '[:upper:]' '[:lower:]')" == "true" ]]; then
export IRONIC_HOST_IP="::"
elif [[ -n "${ENABLE_IPV6}" ]]; then
export IRONIC_HOST_IP="$IRONIC_IPV6"
else
export IRONIC_HOST_IP="$IRONIC_IP"
fi

if [[ "${VMEDIA_TLS_PORT}" ]]; then
   export IRONIC_HTTPS_VMEDIA_URL="https://${IRONIC_URL_HOST}:${VMEDIA_TLS_PORT}"
fi

# Hostname to use for the current conductor instance.
export IRONIC_CONDUCTOR_HOST=${IRONIC_CONDUCTOR_HOST:-${IRONIC_URL_HOST}}

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
        export IRONIC_EXTERNAL_HTTP_URL=${IRONIC_EXTERNAL_HTTP_URL:-"https://${IRONIC_EXTERNAL_IP}:${VMEDIA_TLS_PORT}"}
    else
        export IRONIC_EXTERNAL_HTTP_URL=${IRONIC_EXTERNAL_HTTP_URL:-"http://${IRONIC_EXTERNAL_IP}:${HTTP_PORT}"}
    fi
fi

IMAGE_CACHE_PREFIX="/shared/html/images/ironic-python-agent"
if [[ -z "${DEPLOY_KERNEL_URL:-}" ]] && [[ -z "${DEPLOY_RAMDISK_URL:-}" ]] && \
       [[ -f "${IMAGE_CACHE_PREFIX}.kernel" ]] && [[ -f "${IMAGE_CACHE_PREFIX}.initramfs" ]]; then
    export DEPLOY_KERNEL_URL="file://${IMAGE_CACHE_PREFIX}.kernel"
    export DEPLOY_RAMDISK_URL="file://${IMAGE_CACHE_PREFIX}.initramfs"
fi

declare -A detected_arch
for var_arch in "${!DEPLOY_KERNEL_URL_@}"; do
    IPA_ARCH="${var_arch#DEPLOY_KERNEL_URL}"
    detected_arch["${IPA_ARCH,,}"]=1
done
for file_arch in "${IMAGE_CACHE_PREFIX}"_*.kernel; do
    if [[ -f "${file_arch}" ]]; then
        IPA_ARCH="$(basename "${file_arch#"${IMAGE_CACHE_PREFIX}"_}" .kernel)"
        detected_arch["${IPA_ARCH}"]=1
    fi
done

DEPLOY_KERNEL_BY_ARCH=""
DEPLOY_RAMDISK_BY_ARCH=""
for IPA_ARCH in "${!detected_arch[@]}"; do
    kernel_var="DEPLOY_KERNEL_URL_${IPA_ARCH^^}"
    ramdisk_var="DEPLOY_RAMDISK_URL_${IPA_ARCH^^}"
    if [[ -z "${!kernel_var:-}" ]] && [[ -z "${!ramdisk_var:-}" ]] && \
        [[ -f "${IMAGE_CACHE_PREFIX}_${IPA_ARCH}.kernel" ]] && [[ -f "${IMAGE_CACHE_PREFIX}_${IPA_ARCH}.initramfs" ]]; then
      export "${kernel_var}"="file://${IMAGE_CACHE_PREFIX}_${IPA_ARCH}.kernel"
      export "${ramdisk_var}"="file://${IMAGE_CACHE_PREFIX}_${IPA_ARCH}.initramfs"
    fi
    DEPLOY_KERNEL_BY_ARCH+="${!kernel_var:+${IPA_ARCH}:${!kernel_var},}"
    DEPLOY_RAMDISK_BY_ARCH+="${!ramdisk_var:+${IPA_ARCH}:${!ramdisk_var},}"
done
if [[ -n "${DEPLOY_KERNEL_BY_ARCH}" ]] && [[ -n "${DEPLOY_RAMDISK_BY_ARCH}" ]]; then
    export DEPLOY_KERNEL_BY_ARCH="${DEPLOY_KERNEL_BY_ARCH%?}"
    export DEPLOY_RAMDISK_BY_ARCH="${DEPLOY_RAMDISK_BY_ARCH%?}"
fi

if [[ -f "${IRONIC_CONF_DIR}/ironic.conf" ]]; then
    # Make a copy of the original supposed empty configuration file
    cp "${IRONIC_CONF_DIR}/ironic.conf" "${IRONIC_CONF_DIR}/ironic.conf.orig"
fi

BOOTLOADER_BY_ARCH=""
for bootloader in /templates/uefi_esp_*.img; do
    BOOTLOADER_ARCH="$(basename "${bootloader#/templates/uefi_esp_}" .img)"
    BOOTLOADER_BY_ARCH+="${BOOTLOADER_ARCH}:file://${bootloader},"
done
export BOOTLOADER_BY_ARCH="${BOOTLOADER_BY_ARCH%?}"

# oslo.config also supports Config Opts From Environment, log them to stdout
echo 'Options set from Environment variables'
env | grep "^OS_" || true

mkdir -p /shared/html
mkdir -p /shared/tmp
mkdir -p /shared/ironic_prometheus_exporter

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" \
    "${IRONIC_CONF_DIR}/ironic.conf"

configure_json_rpc_auth

# Make sure ironic traffic bypasses any proxies
export NO_PROXY="${NO_PROXY:-}"

if [[ -n "$IRONIC_IPV6" ]]; then
export NO_PROXY="${NO_PROXY},${IRONIC_IPV6}"
fi
if [[ -n "$IRONIC_IP" ]]; then
export NO_PROXY="${NO_PROXY},${IRONIC_IP}"
fi
07070100000002000081a4000000000000000000000001693bc306000028c9000000000000000000000000000000000000001900000000scripts/ironic-common.sh#!/usr/bin/bash

set -euxo pipefail

# Export IRONIC_IP to avoid needing to lean on IRONIC_URL_HOST for consumption in
# e.g. dnsmasq configuration
export IRONIC_IP="${IRONIC_IP:-}"
IRONIC_IPV6="${IRONIC_IPV6:-}"
PROVISIONING_INTERFACE="${PROVISIONING_INTERFACE:-}"
PROVISIONING_IP="${PROVISIONING_IP:-}"
PROVISIONING_MACS="${PROVISIONING_MACS:-}"
IRONIC_URL_HOSTNAME="${IRONIC_URL_HOSTNAME:-}"
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"

export HTTP_PORT=${HTTP_PORT:-80}
# NOTE(elfosardo): the default port for json_rpc in ironic is 8089, but
# we need to use a different port to avoid conflicts with other services
export IRONIC_JSON_RPC_PORT=${IRONIC_JSON_RPC_PORT:-6189}

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_ip_of_hostname()
{
    if [[ "$#" -ne 2 ]]; then
        echo "${FUNCNAME}: two parameters required, $# provided" >&2
        return 1
    fi

    case $2 in
        4)
            QUERY="a";;
        6)
            QUERY="aaaa";;
        *)
            echo "${FUNCNAME}: the second parameter should be [a|aaaa] for A and AAAA records"
            return 1;;
    esac

    local HOSTNAME=$1

    echo $(nslookup -type=${QUERY} "${HOSTNAME}" | tail -n2 | grep -w "Address:" | cut -d " " -f2)
}

get_interface_of_ip()
{
    local IP_VERS=""

    if [[ "$#" -gt 2 ]]; then
        echo "${FUNCNAME}: too many parameters" >&2
        return 1
    fi

    if [[ "$#" -eq 2 ]]; then
        case $2 in
        4|6)
            local IP_VERS="-${2}"
            ;;
        *)
            echo "${FUNCNAME}: the second parameter should be [4|6] (or missing for both)" >&2
            return 2
            ;;
        esac
    fi

    local IP_ADDR=$1

    # Convert the address using ipcalc which strips out the subnet.
    # For IPv6 addresses, this will give the short-form address
    IP_ADDR="$(ipcalc "${IP_ADDR}" | grep "^Address:" | awk '{print $2}')"

    echo $(ip ${IP_VERS} -br addr show scope global | grep -i " ${IP_ADDR}/" | cut -f 1 -d ' ' | cut -f 1 -d '@')
}

get_ip_of_interface()
{
    local IP_VERS=""

    if [[ "$#" -gt 2 ]]; then
        echo "${FUNCNAME}: too many parameters" >&2
        return 1
    fi

    if [[ "$#" -eq 2 ]]; then
        case $2 in
        4|6)
            local IP_VERS="-${2}"
            ;;
        *)
            echo "${FUNCNAME}: the second parameter should be [4|6] (or missing for both)" >&2
            return 2
            ;;
        esac
    fi

    local IFACE=$1

    echo $(ip ${IP_VERS} -br addr show scope global up dev ${IFACE} | awk '{print $3}' | sed -e 's%/.*%%' | head -n 1)
}

get_provisioning_interface()
{
    if [[ -n "$PROVISIONING_INTERFACE" ]]; then
        # don't override the PROVISIONING_INTERFACE if one is provided
        echo "$PROVISIONING_INTERFACE"
        return
    fi

    local interface=""

    for mac in ${PROVISIONING_MACS//,/ }; do
        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
    done

    echo "$interface"
}

PROVISIONING_INTERFACE="$(get_provisioning_interface)"
export PROVISIONING_INTERFACE

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
        local IFACE_OF_IP=""

        until [[ -n "$IFACE_OF_IP" ]]; do
            echo "Waiting for ${PROVISIONING_IP} to be configured on an interface..."
            IFACE_OF_IP="$(get_interface_of_ip "${PROVISIONING_IP}")"
            sleep 1
        done

        echo "Found $PROVISIONING_IP on interface \"${IFACE_OF_IP}\"!"

        export PROVISIONING_INTERFACE="$IFACE_OF_IP"
	# If the IP contains a colon, then it's an IPv6 address
        if [[ "$PROVISIONING_IP" =~ .*:.* ]]; then
            export IRONIC_IPV6="$PROVISIONING_IP"
            export IRONIC_IP=""
        else
            export IRONIC_IP="$PROVISIONING_IP"
        fi
    elif [[ -n "${IRONIC_IP}" ]]; then
        if [[ "$IRONIC_IP" =~ .*:.* ]]; then
            export IRONIC_IPV6="$IRONIC_IP"
            export IRONIC_IP=""
        fi
    elif [[ -n "${PROVISIONING_INTERFACE}" ]]; then
        until [[ -n "$IRONIC_IPV6" ]] || [[ -n "$IRONIC_IP" ]]; do
            echo "Waiting for ${PROVISIONING_INTERFACE} interface to be configured..."

            IRONIC_IPV6="$(get_ip_of_interface "${PROVISIONING_INTERFACE}" 6)"
            sleep 1

            IRONIC_IP="$(get_ip_of_interface "${PROVISIONING_INTERFACE}" 4)"
            sleep 1
        done

        if [[ -n "$IRONIC_IPV6" ]]; then
            echo "Found $IRONIC_IPV6 on interface \"${PROVISIONING_INTERFACE}\"!"
	    export IRONIC_IPV6
        fi
        if [[ -n "$IRONIC_IP" ]]; then
            echo "Found $IRONIC_IP on interface \"${PROVISIONING_INTERFACE}\"!"
	    export IRONIC_IP
        fi
    elif [[ -n "$IRONIC_URL_HOSTNAME" ]]; then
        local IPV6_IFACE=""
        local IPV4_IFACE=""
        
        # we should get at least one IP address
        until [[ -n "$IPV6_IFACE" ]] || [[ -n "$IPV4_IFACE" ]]; do
            local IPV6_RECORD=""
            local IPV4_RECORD=""

            IPV6_RECORD="$(get_ip_of_hostname "${IRONIC_URL_HOSTNAME}" 6)"
            IPV4_RECORD="$(get_ip_of_hostname "${IRONIC_URL_HOSTNAME}" 4)"

            # We couldn't get any IP
            if [[ -z "$IPV4_RECORD" ]] && [[ -z "$IPV6_RECORD" ]]; then
                echo "${FUNCNAME}: no valid IP found for hostname ${IRONIC_URL_HOSTNAME}" >&2
                return 1
            fi

            echo "Waiting for ${IPV6_RECORD} to be configured on an interface"
            IPV6_IFACE="$(get_interface_of_ip "${IPV6_RECORD}" 6)"
            sleep 1

            echo "Waiting for ${IPV4_RECORD} to be configured on an interface"
            IPV4_IFACE="$(get_interface_of_ip "${IPV4_RECORD}" 4)"
            sleep 1
        done

        # Add some debugging output
        if [[ -n "$IPV6_IFACE" ]]; then
            echo "Found $IPV6_RECORD on interface \"${IPV6_IFACE}\"!"
            export IRONIC_IPV6="$IPV6_RECORD"
        fi
        if [[ -n "$IPV4_IFACE" ]]; then
            echo "Found $IPV4_RECORD on interface \"${IPV4_IFACE}\"!"
            export IRONIC_IP="$IPV4_RECORD"
        fi

        # Make sure both IPs are asigned to the same interface
        if [[ -n "$IPV6_IFACE" ]] && [[ -n "$IPV4_IFACE" ]] && [[ "$IPV6_IFACE" != "$IPV4_IFACE" ]]; then
            echo "Warning, the IPv4 and IPv6 addresses from \"${HOSTNAME}\" are assigned to different " \
            "interfaces (\"${IPV6_IFACE}\" and \"${IPV4_IFACE}\")" >&2
        fi

    else
        echo "Cannot determine an interface or an IP for binding and creating URLs"
        return 1
    fi

    # Define the URLs based on the what we have found,
    # prioritize IPv6 for IRONIC_URL_HOST
    if [[ -n "$IRONIC_IP" ]]; then
        export ENABLE_IPV4=yes
        export IRONIC_URL_HOST="$IRONIC_IP"
    fi
    if [[ -n "$IRONIC_IPV6" ]]; then
        export ENABLE_IPV6=yes
        export IRONIC_URL_HOST="[${IRONIC_IPV6}]" # The HTTP host needs surrounding with brackets
    fi

    # Once determined if we have IPv4 and/or IPv6, override the hostname if provided
    if [[ -n "$IRONIC_URL_HOSTNAME" ]]; then
        IRONIC_URL_HOST=$IRONIC_URL_HOSTNAME
    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()
{
    python3.13 -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" ]]; then
        # It's possible for the dbsync to fail if mariadb is not up yet, so
        # retry until success
        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
        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 "${IRONIC_CONF_DIR}/ironic.conf" create_schema
        fi
    fi
}

# Use the special value "unix" for unix sockets
export IRONIC_PRIVATE_PORT=${IRONIC_PRIVATE_PORT:-unix}

export IRONIC_ACCESS_PORT=${IRONIC_ACCESS_PORT:-6385}
export IRONIC_LISTEN_PORT=${IRONIC_LISTEN_PORT:-$IRONIC_ACCESS_PORT}

export IRONIC_ENABLE_DISCOVERY=${IRONIC_ENABLE_DISCOVERY:-${IRONIC_INSPECTOR_ENABLE_DISCOVERY:-false}}
07070100000003000081ed000000000000000000000001693bc30600000233000000000000000000000000000000000000001800000000scripts/ironic-probe.sh#!/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}"
07070100000004000081ed000000000000000000000001693bc30600000113000000000000000000000000000000000000001c00000000scripts/rundatabase-upgrade#!/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
07070100000005000081ed000000000000000000000001693bc306000005d6000000000000000000000000000000000000001300000000scripts/rundnsmasq#!/usr/bin/bash

set -eux

# shellcheck disable=SC1091
. /bin/ironic-common.sh
# shellcheck disable=SC1091
. /bin/tls-common.sh

DNSMASQ_EXCEPT_INTERFACE=${DNSMASQ_EXCEPT_INTERFACE:-lo}
export DNS_PORT=${DNS_PORT:-0}

wait_for_interface_or_ip
if [[ "${DNS_IP:-}" == "provisioning" ]]; then
    if [[ "${IPV}" == "4" ]]; then
      export DNS_IP="${IRONIC_IP}"
    else
      export DNS_IP="[${IRONIC_IP}]"
    fi
fi

mkdir -p /shared/tftpboot
mkdir -p /shared/html/images
mkdir -p /shared/html/pxelinux.cfg

# Copy files to shared mount
if [[ -r "${IPXE_CUSTOM_FIRMWARE_DIR}" ]]; then
    cp "${IPXE_CUSTOM_FIRMWARE_DIR}/undionly.kpxe" \
        "${IPXE_CUSTOM_FIRMWARE_DIR}/snponly.efi" \
        "/shared/tftpboot"
else
    cp /tftpboot/undionly.kpxe /tftpboot/snponly.efi /shared/tftpboot
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.13 -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"
done
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 "${DNSMASQ_CONF_DIR}/dnsmasq.conf"
07070100000006000081ed000000000000000000000001693bc30600000b4f000000000000000000000000000000000000001100000000scripts/runhttpd#!/usr/bin/bash

# shellcheck disable=SC1091
. /bin/tls-common.sh
. /bin/ironic-common.sh
. /bin/auth-common.sh

export VMEDIA_TLS_PORT=${VMEDIA_TLS_PORT:-8083}

export IRONIC_REVERSE_PROXY_SETUP=${IRONIC_REVERSE_PROXY_SETUP:-false}

# In Metal3 context they are called node images in Ironic context they are
# called user images.
export HTTPD_SERVE_NODE_IMAGES="${HTTPD_SERVE_NODE_IMAGES:-true}"

# Whether to enable fast_track provisioning or not
IRONIC_FAST_TRACK=${IRONIC_FAST_TRACK:-true}

# Whether to activate the EnableSendfile apache directive for httpd
HTTPD_ENABLE_SENDFILE="${HTTPD_ENABLE_SENDFILE:-false}"

# Set of collectors that should be used with IPA inspection
export IRONIC_IPA_COLLECTORS=${IRONIC_IPA_COLLECTORS:-default,logs}

wait_for_interface_or_ip

mkdir -p /shared/html
chmod 0777 /shared/html

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}"
fi
export INSPECTOR_EXTRA_ARGS

# Copy files to shared mount
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" \
    "${HTTPD_CONF_DIR}/httpd.conf"

if [[ "$IRONIC_TLS_SETUP" == "true" ]]; then
    if [[ "${IRONIC_REVERSE_PROXY_SETUP}" == "true" ]]; then
        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
fi

write_htpasswd_files

# Render httpd TLS configuration for /shared/html/<redifsh;ilo>
if [[ "$IRONIC_VMEDIA_TLS_SETUP" == "true" ]]; then
    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 "/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
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/<redifsh;ilo> path change
configure_restart_on_certificate_update "${IRONIC_VMEDIA_TLS_SETUP}" httpd "${IRONIC_VMEDIA_CERT_FILE}"

exec /usr/sbin/httpd -DFOREGROUND -f "${HTTPD_CONF_DIR}/httpd.conf"
07070100000007000081ed000000000000000000000001693bc306000002ba000000000000000000000000000000000000001200000000scripts/runironic#!/usr/bin/bash

# shellcheck disable=SC1091
. /bin/configure-ironic.sh

# Ramdisk logs
mkdir -p /shared/log/ironic/deploy

# 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

if [[ -d "${BMC_CACERTS_PATH}" ]]; then
    # shellcheck disable=SC2034
    watchmedo shell-command \
        --patterns="*" \
        --ignore-directories \
        --command='cat "${BMC_CACERTS_PATH}"/* > "${BMC_CACERT_FILE}"' \
        "${BMC_CACERTS_PATH}" &
fi

exec /usr/bin/ironic --config-dir "${IRONIC_CONF_DIR}"
07070100000008000081ed000000000000000000000001693bc30600000305000000000000000000000000000000000000001b00000000scripts/runironic-exporter#!/usr/bin/bash

# Set dummy provisioning IP to avoid interface detection issues (not needed to run IPE to service `/metrics`)
export PROVISIONING_IP="127.0.0.1"
# Set to true since running this script implies sensor data metrics are needed
# ironic-prometheus-exporter (IPE) needs to read from oslo_messaging_notifications.location (i.e content under /shared) where Ironic writes to
export SEND_SENSOR_DATA=true

# 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="${IRONIC_CONF_DIR}/ironic.conf"

exec gunicorn -b "${FLASK_RUN_HOST}:${FLASK_RUN_PORT}" -w 4 \
    ironic_prometheus_exporter.app.wsgi:application
07070100000009000081ed000000000000000000000001693bc306000003a7000000000000000000000000000000000000001700000000scripts/runlogwatch.sh#!/usr/bin/bash

# Ramdisk logs path
export LOG_DIR="/shared/log/ironic/deploy"

mkdir -p "${LOG_DIR}"

# Function to process log files
process_log_file() {
    local FILEPATH="$1"
    # shellcheck disable=SC2155
    local FILENAME=$(basename "${FILEPATH}")

    echo "************ Contents of ${LOG_DIR}/${FILENAME} ramdisk log file bundle **************"
    tar -tzf "${FILEPATH}" | while read -r entry; do
        echo "${FILENAME}: **** Entry: ${entry} ****"
        tar -xOzf "${FILEPATH}" "${entry}" | sed -e "s/^/${FILENAME}: /"
        echo
    done
    rm -f "${FILEPATH}"
}

# Export the function so watchmedo can use it
export -f process_log_file

# Use watchmedo to monitor for file close events
# shellcheck disable=SC2016
watchmedo shell-command \
    --patterns="*" \
    --ignore-directories \
    --command='if [[ "${watch_event_type}" == "closed" ]]; then process_log_file "${watch_src_path}"; fi' \
    "${LOG_DIR}"0707010000000a000081ed000000000000000000000001693bc30600000122000000000000000000000000000000000000002200000000scripts/runonline-data-migrations#!/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
0707010000000b000081a4000000000000000000000001693bc30600000f81000000000000000000000000000000000000001600000000scripts/tls-common.sh#!/bin/bash

export IRONIC_INSECURE=${IRONIC_INSECURE:-false}
export IRONIC_SSL_PROTOCOL=${IRONIC_SSL_PROTOCOL:-"-ALL +TLSv1.2 +TLSv1.3"}
export IPXE_SSL_PROTOCOL=${IPXE_SSL_PROTOCOL:-"-ALL +TLSv1.2 +TLSv1.3"}
export IRONIC_VMEDIA_SSL_PROTOCOL=${IRONIC_VMEDIA_SSL_PROTOCOL:-"ALL"}

# Node image storage is using the same cert and port as the API
export IRONIC_CERT_FILE=/certs/ironic/tls.crt
export IRONIC_KEY_FILE=/certs/ironic/tls.key

export IRONIC_VMEDIA_CERT_FILE=/certs/vmedia/tls.crt
export IRONIC_VMEDIA_KEY_FILE=/certs/vmedia/tls.key

export IPXE_CERT_FILE=/certs/ipxe/tls.crt
export IPXE_KEY_FILE=/certs/ipxe/tls.key

export RESTART_CONTAINER_CERTIFICATE_UPDATED=${RESTART_CONTAINER_CERTIFICATE_UPDATED:-"false"}

# By default every cert has to be signed with Ironic's
# CA otherwise node image and IPA verification would fail
export MARIADB_CACERT_FILE=/certs/ca/mariadb/tls.crt
export BMC_CACERTS_PATH=/certs/ca/bmc
export BMC_CACERT_FILE=/conf/bmc-tls.pem
export IRONIC_CACERT_FILE=/certs/ca/ironic/tls.crt

export IPXE_TLS_PORT="${IPXE_TLS_PORT:-8084}"

if [[ -f "$IRONIC_CERT_FILE" ]] && [[ ! -f "$IRONIC_KEY_FILE" ]]; then
    echo "Missing TLS Certificate key file $IRONIC_KEY_FILE"
    exit 1
fi
if [[ ! -f "$IRONIC_CERT_FILE" ]] && [[ -f "$IRONIC_KEY_FILE" ]]; then
    echo "Missing TLS Certificate file $IRONIC_CERT_FILE"
    exit 1
fi

if [[ -f "$IRONIC_VMEDIA_CERT_FILE" ]] && [[ ! -f "$IRONIC_VMEDIA_KEY_FILE" ]]; then
    echo "Missing TLS Certificate key file $IRONIC_VMEDIA_KEY_FILE"
    exit 1
fi
if [[ ! -f "$IRONIC_VMEDIA_CERT_FILE" ]] && [[ -f "$IRONIC_VMEDIA_KEY_FILE" ]]; then
    echo "Missing TLS Certificate file $IRONIC_VMEDIA_CERT_FILE"
    exit 1
fi

if [[ -f "$IPXE_CERT_FILE" ]] && [[ ! -f "$IPXE_KEY_FILE" ]]; then
    echo "Missing TLS Certificate key file $IPXE_KEY_FILE"
    exit 1
fi
if [[ ! -f "$IPXE_CERT_FILE" ]] && [[ -f "$IPXE_KEY_FILE" ]]; then
    echo "Missing TLS Certificate file $IPXE_CERT_FILE"
    exit 1
fi

copy_atomic()
{
    local src="$1"
    local dest="$2"
    local tmpdest

    tmpdest=$(mktemp "$dest.XXX")
    cp "$src" "$tmpdest"
    # Hard linking is atomic, but only works on the same volume
    ln -f "$tmpdest" "$dest"
    rm -f "$tmpdest"
}

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
    export IRONIC_TLS_SETUP="false"
    export IRONIC_SCHEME="http"
fi

if [[ -f "$IRONIC_VMEDIA_CERT_FILE" ]]; then
    export IRONIC_VMEDIA_TLS_SETUP="true"
else
    export IRONIC_VMEDIA_TLS_SETUP="false"
fi

if [[ -f "$IPXE_CERT_FILE" ]]; then
    export IPXE_SCHEME="https"
    export IPXE_TLS_SETUP="true"
else
    export IPXE_SCHEME="http"
    export IPXE_TLS_SETUP="false"
fi

if [[ -f "$MARIADB_CACERT_FILE" ]]; then
    export MARIADB_TLS_ENABLED="true"
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
            # shellcheck disable=SC2034
            signal="WINCH"
        fi

        # Use watchmedo to monitor certificate file deletion
        # shellcheck disable=SC2016
        watchmedo shell-command \
            --patterns="$(basename "${cert_file}")" \
            --ignore-directories \
            --command='if [[ "${watch_event_type}" == "deleted" ]]; then pkill -'"${signal}"' '"${service}"'; fi' \
            "$(dirname "${cert_file}")" &
    fi
}

if [ -d "${BMC_CACERTS_PATH}" ]; then
    export BMC_TLS_ENABLED="true"
    cat "${BMC_CACERTS_PATH}"/* > "${BMC_CACERT_FILE}"
else
    export BMC_TLS_ENABLED="false"
fi
0707010000000c000041ed000000000000000000000001693bc30600000000000000000000000000000000000000000000000800000000scripts07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000b00000000TRAILER!!!
openSUSE Build Service is sponsored by