Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion ironic-config/apache2-ipxe.conf.j2
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Listen {{ env.IPXE_TLS_PORT }}
Listen 0.0.0.0:{{ env.IPXE_TLS_PORT }}
Listen [::]:{{ env.IPXE_TLS_PORT }}

<VirtualHost *:{{ env.IPXE_TLS_PORT }}>
ErrorLog /dev/stderr
Expand Down
3 changes: 2 additions & 1 deletion ironic-config/apache2-vmedia.conf.j2
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Listen {{ env.VMEDIA_TLS_PORT }}
Listen 0.0.0.0:{{ env.VMEDIA_TLS_PORT }}
Listen [::]:{{ env.VMEDIA_TLS_PORT }}

<VirtualHost *:{{ env.VMEDIA_TLS_PORT }}>
ErrorLog /dev/stderr
Expand Down
13 changes: 10 additions & 3 deletions ironic-config/httpd-ironic-api.conf.j2
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,18 @@


{% if env.LISTEN_ALL_INTERFACES | lower == "true" %}
Listen {{ env.IRONIC_LISTEN_PORT }}
Listen 0.0.0.0:{{ env.IRONIC_LISTEN_PORT }}
Listen [::]:{{ env.IRONIC_LISTEN_PORT }}
<VirtualHost *:{{ env.IRONIC_LISTEN_PORT }}>
{% else %}
Listen {{ env.IRONIC_URL_HOST }}:{{ env.IRONIC_LISTEN_PORT }}
<VirtualHost {{ env.IRONIC_URL_HOST }}:{{ env.IRONIC_LISTEN_PORT }}>
{% if env.ENABLE_IPV4 %}
Listen {{ env.IRONIC_IP }}:{{ env.IRONIC_LISTEN_PORT }}
{% endif %}
{% if env.ENABLE_IPV6 %}
Listen [{{ env.IRONIC_IPV6 }}]:{{ env.IRONIC_LISTEN_PORT }}
{% endif %}
<VirtualHost {% if env.ENABLE_IPV4 %}{{ env.IRONIC_IP }}:{{ env.IRONIC_LISTEN_PORT }}{% endif %} {% if env.ENABLE_IPV6 %}[{{ env.IRONIC_IPV6 }}]:{{ env.IRONIC_LISTEN_PORT }}{% endif %}>
{% endif %}
{% endif %}

DocumentRoot "/shared/html"
Expand Down
10 changes: 8 additions & 2 deletions ironic-config/httpd.conf.j2
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
ServerRoot {{ env.HTTPD_DIR }}
{%- if env.LISTEN_ALL_INTERFACES | lower == "true" %}
Listen {{ env.HTTP_PORT }}
Listen 0.0.0.0:{{ env.HTTP_PORT }}
Listen [::]:{{ env.HTTP_PORT }}
{% else %}
Listen {{ env.IRONIC_URL_HOST }}:{{ env.HTTP_PORT }}
{% if env.ENABLE_IPV4 %}
Listen {{ env.IRONIC_IP }}:{{ env.HTTP_PORT }}
{% endif %}
{% if env.ENABLE_IPV6 %}
Listen [{{ env.IRONIC_IPV6 }}]:{{ env.HTTP_PORT }}
{% endif %}
{% endif %}
Include /etc/httpd/conf.modules.d/*.conf
User apache
Expand Down
10 changes: 8 additions & 2 deletions ironic-config/ironic.conf.j2
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,13 @@ rpc_transport = none
use_stderr = true
# NOTE(dtantsur): the default md5 is not compatible with FIPS mode
hash_ring_algorithm = sha256
{% if env.ENABLE_IPV4 %}
my_ip = {{ env.IRONIC_IP }}
{% endif %}
{% if env.ENABLE_IPV6 %}
my_ipv6 = {{ env.IRONIC_IPV6 }}
{% endif %}

host = {{ env.IRONIC_CONDUCTOR_HOST }}

# If a path to a certificate is defined, use that first for webserver
Expand Down Expand Up @@ -68,7 +74,7 @@ port = {{ env.IRONIC_PRIVATE_PORT }}
{% endif %}
public_endpoint = {{ env.IRONIC_BASE_URL }}
{% else %}
host_ip = {% if env.LISTEN_ALL_INTERFACES | lower == "true" %}::{% else %}{{ env.IRONIC_IP }}{% endif %}
host_ip = {{ env.IRONIC_HOST_IP }}
port = {{ env.IRONIC_LISTEN_PORT }}
{% if env.IRONIC_TLS_SETUP == "true" %}
enable_ssl_api = true
Expand Down Expand Up @@ -186,7 +192,7 @@ cipher_suite_versions = 3,17
# containers are in host networking.
auth_strategy = http_basic
http_basic_auth_user_file = {{ env.IRONIC_RPC_HTPASSWD_FILE }}
host_ip = {% if env.LISTEN_ALL_INTERFACES | lower == "true" %}::{% else %}{{ env.IRONIC_IP }}{% endif %}
host_ip = {{ env.IRONIC_HOST_IP }}
port = {{ env.IRONIC_JSON_RPC_PORT }}
{% if env.IRONIC_TLS_SETUP == "true" %}
use_ssl = true
Expand Down
17 changes: 16 additions & 1 deletion scripts/configure-ironic.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ 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

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

Expand Down Expand Up @@ -130,4 +138,11 @@ render_j2_config "/etc/ironic/ironic.conf.j2" \
configure_json_rpc_auth

# Make sure ironic traffic bypasses any proxies
export NO_PROXY="${NO_PROXY:-},$IRONIC_IP"
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
177 changes: 147 additions & 30 deletions scripts/ironic-common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ 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:-}"
export IRONIC_IPV6=""
PROVISIONING_INTERFACE="${PROVISIONING_INTERFACE:-}"
PROVISIONING_IP="${PROVISIONING_IP:-}"
PROVISIONING_MACS="${PROVISIONING_MACS:-}"
Expand Down Expand Up @@ -46,13 +47,7 @@ get_provisioning_interface()
return
fi

local interface="provisioning"

if [[ -n "${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
local interface=""

for mac in ${PROVISIONING_MACS//,/ }; do
if ip -br link show up | grep -i "$mac" &>/dev/null; then
Expand All @@ -69,38 +64,160 @@ export PROVISIONING_INTERFACE

export LISTEN_ALL_INTERFACES="${LISTEN_ALL_INTERFACES:-true}"

get_ip_of_interface()
{
local IP_VERS
local IP_ADDR

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

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

IFACE="$1"

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

get_interface_of_ip()
{
local IP_VERS
local IP_ADDR

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

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

IP_ADDR="$1"

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

parse_ip_address()
{
local IP_ADDR

if [[ $# -ne 1 ]]; then
echo "ERROR: ${FUNCNAME[0]}: please provide a single IP address as input" >&2
return 1
fi

IP_ADDR="$1"

if ipcalc "${IP_ADDR}" | grep ^INVALID &>/dev/null; then
echo "ERROR: ${FUNCNAME[0]}: Failed to parse ${IP_ADDR}" >&2
return 2
fi

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

# 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
IRONIC_IP="$(ipcalc "${PROVISIONING_IP}" | grep "^Address:" | awk '{print $2}')"
export IRONIC_IP
until grep -F " ${IRONIC_IP}/" <(ip -br addr show); do
echo "Waiting for ${IRONIC_IP} to be configured on an interface"
# IRONIC_IP already defined overrides everything else
if [[ -n "${IRONIC_IP}" ]]; then
local PARSED_IP
PARSED_IP="$(parse_ip_address "${IRONIC_IP}")"
if [[ -z "${PARSED_IP}" ]]; then
echo "ERROR: PROVISIONING_IP contains an invalid IP address, failed to start ironic"
exit 1
fi

if [[ "${PARSED_IP}" =~ .*:.* ]]; then
export IRONIC_IPV6="${PARSED_IP}"
export IRONIC_IP=""
else
export IRONIC_IP="${PARSED_IP}"
fi
elif [[ -n "${PROVISIONING_IP}" ]]; then
# 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
local PARSED_IP
PARSED_IP="$(parse_ip_address "${PROVISIONING_IP}")"
if [[ -z "${PARSED_IP}" ]]; then
echo "ERROR: PROVISIONING_IP contains an invalid IP address, failed to start ironic"
exit 1
fi

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 "${PARSED_IP}")"
sleep 1
done
else
until [[ -n "$IRONIC_IP" ]]; do
echo "Waiting for ${PROVISIONING_INTERFACE} interface to be configured"
IRONIC_IP="$(ip -br add show scope global up dev "${PROVISIONING_INTERFACE}" | awk '{print $3}' | sed -e 's%/.*%%' | head -n 1)"
export IRONIC_IP

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 [[ "${PARSED_IP}" =~ .*:.* ]]; then
export IRONIC_IPV6="${PARSED_IP}"
else
export IRONIC_IP="${PARSED_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
fi

# If the IP contains a colon, then it's an IPv6 address, and the HTTP
# host needs surrounding with brackets
if [[ "$IRONIC_IP" =~ .*:.* ]]; then
export IPV=6
export IRONIC_URL_HOST="[$IRONIC_IP]"
# Add some debugging output
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
else
export IPV=4
export IRONIC_URL_HOST="$IRONIC_IP"
echo "ERROR: 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

# Avoid having to construct full URL multiple times while allowing
Expand Down