ironic/devstack/lib/ironic

2086 lines
83 KiB
Bash

#!/bin/bash
#
# lib/ironic
# Functions to control the configuration and operation of the **Ironic** service
# Dependencies:
#
# - ``functions`` file
# - ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined
# - ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined
# - ``SERVICE_HOST``
# - ``KEYSTONE_TOKEN_FORMAT`` must be defined
# ``stack.sh`` calls the entry points in this order:
#
# - install_ironic
# - install_ironicclient
# - init_ironic
# - start_ironic
# - stop_ironic
# - cleanup_ironic
# ensure we don't re-source this in the same environment
[[ -z "$_IRONIC_DEVSTACK_LIB" ]] || return 0
declare -r -g _IRONIC_DEVSTACK_LIB=1
# Save xtrace and pipefail settings
_XTRACE_IRONIC=$(set +o | grep xtrace)
_PIPEFAIL_IRONIC=$(set +o | grep pipefail)
set -o xtrace
set +o pipefail
# Defaults
# --------
# Set up default directories
GITDIR["python-ironicclient"]=$DEST/python-ironicclient
GITDIR["ironic-lib"]=$DEST/ironic-lib
GITREPO["pyghmi"]=${PYGHMI_REPO:-${GIT_BASE}/openstack/pyghmi.git}
GITBRANCH["pyghmi"]=${PYGHMI_BRANCH:-master}
GITDIR["pyghmi"]=$DEST/pyghmi
GITREPO["virtualbmc"]=${VIRTUALBMC_REPO:-${GIT_BASE}/openstack/virtualbmc.git}
GITBRANCH["virtualbmc"]=${VIRTUALBMC_BRANCH:-master}
GITDIR["virtualbmc"]=$DEST/virtualbmc
GITREPO["virtualpdu"]=${VIRTUALPDU_REPO:-${GIT_BASE}/openstack/virtualpdu.git}
GITBRANCH["virtualpdu"]=${VIRTUALPDU_BRANCH:-master}
GITDIR["virtualpdu"]=$DEST/virtualpdu
IRONIC_DIR=$DEST/ironic
IRONIC_DEVSTACK_DIR=$IRONIC_DIR/devstack
IRONIC_DEVSTACK_FILES_DIR=$IRONIC_DEVSTACK_DIR/files
IRONIC_PYTHON_AGENT_DIR=$DEST/ironic-python-agent
IRONIC_DATA_DIR=$DATA_DIR/ironic
IRONIC_STATE_PATH=/var/lib/ironic
IRONIC_AUTH_CACHE_DIR=${IRONIC_AUTH_CACHE_DIR:-/var/cache/ironic}
IRONIC_CONF_DIR=${IRONIC_CONF_DIR:-/etc/ironic}
IRONIC_CONF_FILE=$IRONIC_CONF_DIR/ironic.conf
IRONIC_ROOTWRAP_CONF=$IRONIC_CONF_DIR/rootwrap.conf
IRONIC_POLICY_JSON=$IRONIC_CONF_DIR/policy.json
if is_suse; then
IRONIC_WSGI_DIR=${IRONIC_WSGI_DIR:-/srv/www/htdocs/ironic}
else
IRONIC_WSGI_DIR=${IRONIC_WSGI_DIR:-/var/www/ironic}
fi
IRONIC_USE_MOD_WSGI=$(trueorfalse False IRONIC_USE_MOD_WSGI)
# Deploy callback timeout can be changed from its default (1800), if required.
IRONIC_CALLBACK_TIMEOUT=${IRONIC_CALLBACK_TIMEOUT:-}
# Deploy to hardware platform
IRONIC_HW_NODE_CPU=${IRONIC_HW_NODE_CPU:-1}
IRONIC_HW_NODE_RAM=${IRONIC_HW_NODE_RAM:-512}
IRONIC_HW_NODE_DISK=${IRONIC_HW_NODE_DISK:-10}
IRONIC_HW_EPHEMERAL_DISK=${IRONIC_HW_EPHEMERAL_DISK:-0}
IRONIC_HW_ARCH=${IRONIC_HW_ARCH:-x86_64}
# The file is composed of multiple lines, each line includes fields
# separated by white space, in the format:
#
# <BMC address> <MAC address> <BMC username> <BMC password> [<driver specific fields>]
#
# For example:
#
# 192.168.110.107 00:1e:67:57:50:4c root otc123
#
# Supported IRONIC_DEPLOY_DRIVERs:
# *_ipmitool or ipmi:
# <BMC address> <MAC address> <BMC username> <BMC password>
#
# *_cimc:
# <BMC address> <MAC address> <BMC username> <BMC password>
#
# *_ucs:
# <BMC address> <MAC address> <BMC username> <BMC password> <UCS service profile>
#
# *_oneview:
# <Server Hardware URI> <Server Hardware Type URI> <Enclosure Group URI> <Server Profile Template URI> <MAC of primary connection> <Applied Server Profile URI>
#
# *_drac:
# <BMC address> <MAC address> <BMC username> <BMC password>
#
IRONIC_HWINFO_FILE=${IRONIC_HWINFO_FILE:-$IRONIC_DATA_DIR/hardware_info}
# Set up defaults for functional / integration testing
IRONIC_NODE_UUID=${IRONIC_NODE_UUID:-`uuidgen`}
IRONIC_SCRIPTS_DIR=${IRONIC_SCRIPTS_DIR:-$IRONIC_DEVSTACK_DIR/tools/ironic/scripts}
IRONIC_TEMPLATES_DIR=${IRONIC_TEMPLATES_DIR:-$IRONIC_DEVSTACK_DIR/tools/ironic/templates}
IRONIC_BAREMETAL_BASIC_OPS=$(trueorfalse False IRONIC_BAREMETAL_BASIC_OPS)
IRONIC_SSH_USERNAME=${IRONIC_SSH_USERNAME:-`whoami`}
IRONIC_SSH_TIMEOUT=${IRONIC_SSH_TIMEOUT:-15}
IRONIC_SSH_ATTEMPTS=${IRONIC_SSH_ATTEMPTS:-5}
IRONIC_SSH_KEY_DIR=${IRONIC_SSH_KEY_DIR:-$IRONIC_DATA_DIR/ssh_keys}
IRONIC_SSH_KEY_FILENAME=${IRONIC_SSH_KEY_FILENAME:-ironic_key}
IRONIC_KEY_FILE=${IRONIC_KEY_FILE:-$IRONIC_SSH_KEY_DIR/$IRONIC_SSH_KEY_FILENAME}
IRONIC_SSH_VIRT_TYPE=${IRONIC_SSH_VIRT_TYPE:-virsh}
IRONIC_TFTPBOOT_DIR=${IRONIC_TFTPBOOT_DIR:-$IRONIC_DATA_DIR/tftpboot}
IRONIC_TFTPSERVER_IP=${IRONIC_TFTPSERVER_IP:-$HOST_IP}
IRONIC_VM_SSH_PORT=${IRONIC_VM_SSH_PORT:-22}
IRONIC_VM_SSH_ADDRESS=${IRONIC_VM_SSH_ADDRESS:-$HOST_IP}
IRONIC_VM_COUNT=${IRONIC_VM_COUNT:-1}
IRONIC_VM_SPECS_CPU=${IRONIC_VM_SPECS_CPU:-1}
IRONIC_VM_SPECS_RAM=${IRONIC_VM_SPECS_RAM:-1280}
IRONIC_VM_SPECS_CPU_ARCH=${IRONIC_VM_SPECS_CPU_ARCH:-'x86_64'}
IRONIC_VM_SPECS_DISK=${IRONIC_VM_SPECS_DISK:-10}
IRONIC_VM_SPECS_DISK_FORMAT=${IRONIC_VM_SPECS_DISK_FORMAT:-qcow2}
IRONIC_VM_EPHEMERAL_DISK=${IRONIC_VM_EPHEMERAL_DISK:-0}
IRONIC_VM_EMULATOR=${IRONIC_VM_EMULATOR:-'/usr/bin/qemu-system-x86_64'}
IRONIC_VM_ENGINE=${IRONIC_VM_ENGINE:-qemu}
IRONIC_VM_NETWORK_BRIDGE=${IRONIC_VM_NETWORK_BRIDGE:-brbm}
IRONIC_VM_NETWORK_RANGE=${IRONIC_VM_NETWORK_RANGE:-192.0.2.0/24}
IRONIC_VM_MACS_CSV_FILE=${IRONIC_VM_MACS_CSV_FILE:-$IRONIC_DATA_DIR/ironic_macs.csv}
IRONIC_AUTHORIZED_KEYS_FILE=${IRONIC_AUTHORIZED_KEYS_FILE:-$HOME/.ssh/authorized_keys}
IRONIC_CLEAN_NET_NAME=${IRONIC_CLEAN_NET_NAME:-${IRONIC_PROVISION_NETWORK_NAME:-${PRIVATE_NETWORK_NAME}}}
IRONIC_EXTRA_PXE_PARAMS=${IRONIC_EXTRA_PXE_PARAMS:-}
IRONIC_TTY_DEV=${IRONIC_TTY_DEV:-ttyS0}
IRONIC_TEMPEST_BUILD_TIMEOUT=${IRONIC_TEMPEST_BUILD_TIMEOUT:-${BUILD_TIMEOUT:-}}
if [[ -n "$BUILD_TIMEOUT" ]]; then
echo "WARNING: BUILD_TIMEOUT variable is renamed to IRONIC_TEMPEST_BUILD_TIMEOUT and will be deprecated in Pike."
fi
# driver / hardware type options
IRONIC_ENABLED_DRIVERS=${IRONIC_ENABLED_DRIVERS:-fake,pxe_ipmitool,agent_ipmitool}
# TODO(jroll) add enabled/default interfaces here
IRONIC_ENABLED_HARDWARE_TYPES=${IRONIC_ENABLED_HARDWARE_TYPES:-ipmi}
# If IRONIC_VM_ENGING is explicitly set to "auto" or "kvm",
# devstack will attempt to use hardware virtualization
# (aka nested kvm). We do not enable it in the infra gates
# because it is not consistently supported/working across
# all gate infrastructure providers.
if [[ "$IRONIC_VM_ENGINE" == "auto" ]]; then
sudo modprobe kvm || true
if [ ! -e /dev/kvm ]; then
echo "WARNING: Switching to QEMU"
IRONIC_VM_ENGINE=qemu
if [[ -z "$IRONIC_VM_EMULATOR" ]]; then
IRONIC_VM_EMULATOR='/usr/bin/qemu-system-x86_64'
fi
else
IRONIC_VM_ENGINE=kvm
fi
fi
if [[ "$IRONIC_VM_ENGINE" == "kvm" ]]; then
# Set this to empty, so configure-vm.py can autodetect location
# of KVM binary
IRONIC_VM_EMULATOR=""
fi
# By default, baremetal VMs will console output to file.
IRONIC_VM_LOG_CONSOLE=$(trueorfalse True IRONIC_VM_LOG_CONSOLE)
IRONIC_VM_LOG_DIR=${IRONIC_VM_LOG_DIR:-$IRONIC_DATA_DIR/logs/}
IRONIC_VM_LOG_ROTATE=$(trueorfalse True IRONIC_VM_LOG_ROTATE)
# Set resource_classes for nodes to use Nova's placement engine
IRONIC_USE_RESOURCE_CLASSES=$(trueorfalse False IRONIC_USE_RESOURCE_CLASSES)
# Whether to build the ramdisk or download a prebuilt one.
IRONIC_BUILD_DEPLOY_RAMDISK=$(trueorfalse True IRONIC_BUILD_DEPLOY_RAMDISK)
# Ironic IPA ramdisk type, supported types are:
IRONIC_SUPPORTED_RAMDISK_TYPES_RE="^(coreos|tinyipa|dib)$"
IRONIC_RAMDISK_TYPE=${IRONIC_RAMDISK_TYPE:-tinyipa}
# Confirm we have a supported ramdisk type or fail early.
if [[ ! "$IRONIC_RAMDISK_TYPE" =~ $IRONIC_SUPPORTED_RAMDISK_TYPES_RE ]]; then
die $LINENO "Unrecognized IRONIC_RAMDISK_TYPE: $IRONIC_RAMDISK_TYPE. Expected 'coreos', 'tinyipa' or 'dib'"
fi
# If present, these files are used as deploy ramdisk/kernel.
# (The value must be an absolute path)
IRONIC_DEPLOY_RAMDISK=${IRONIC_DEPLOY_RAMDISK:-$TOP_DIR/files/ir-deploy-$IRONIC_DEPLOY_DRIVER.initramfs}
IRONIC_DEPLOY_KERNEL=${IRONIC_DEPLOY_KERNEL:-$TOP_DIR/files/ir-deploy-$IRONIC_DEPLOY_DRIVER.kernel}
IRONIC_DEPLOY_ISO=${IRONIC_DEPLOY_ISO:-$TOP_DIR/files/ir-deploy-$IRONIC_DEPLOY_DRIVER.iso}
# These parameters describe which image will be used to provision a node in
# tempest tests
if [[ -z "$IRONIC_TEMPEST_WHOLE_DISK_IMAGE" && "$IRONIC_VM_EPHEMERAL_DISK" == 0 ]]; then
IRONIC_TEMPEST_WHOLE_DISK_IMAGE=True
fi
IRONIC_TEMPEST_WHOLE_DISK_IMAGE=$(trueorfalse False IRONIC_TEMPEST_WHOLE_DISK_IMAGE)
# NOTE(jroll) this needs to be updated when stable branches are cut
IPA_DOWNLOAD_BRANCH=${IPA_DOWNLOAD_BRANCH:-master}
IPA_DOWNLOAD_BRANCH=$(echo $IPA_DOWNLOAD_BRANCH | tr / -)
# Configure URLs required to download ramdisk if we're not building it, and
# IRONIC_DEPLOY_RAMDISK/KERNEL or the RAMDISK/KERNEL_URLs have not been
# preconfigured.
if [[ "$IRONIC_BUILD_DEPLOY_RAMDISK" == "False" && \
! (-e "$IRONIC_DEPLOY_RAMDISK" && -e "$IRONIC_DEPLOY_KERNEL") && \
(-z "$IRONIC_AGENT_KERNEL_URL" || -z "$IRONIC_AGENT_RAMDISK_URL") ]]; then
case $IRONIC_RAMDISK_TYPE in
coreos)
IRONIC_AGENT_KERNEL_URL=${IRONIC_AGENT_KERNEL_URL:-https://tarballs.openstack.org/ironic-python-agent/coreos/files/coreos_production_pxe-${IPA_DOWNLOAD_BRANCH}.vmlinuz}
IRONIC_AGENT_RAMDISK_URL=${IRONIC_AGENT_RAMDISK_URL:-https://tarballs.openstack.org/ironic-python-agent/coreos/files/coreos_production_pxe_image-oem-${IPA_DOWNLOAD_BRANCH}.cpio.gz}
;;
tinyipa)
IRONIC_AGENT_KERNEL_URL=${IRONIC_AGENT_KERNEL_URL:-https://tarballs.openstack.org/ironic-python-agent/tinyipa/files/tinyipa-${IPA_DOWNLOAD_BRANCH}.vmlinuz}
IRONIC_AGENT_RAMDISK_URL=${IRONIC_AGENT_RAMDISK_URL:-https://tarballs.openstack.org/ironic-python-agent/tinyipa/files/tinyipa-${IPA_DOWNLOAD_BRANCH}.gz}
;;
dib)
die "IRONIC_RAMDISK_TYPE 'dib' has no official pre-built "\
"images. To fix this select a different ramdisk type, set "\
"IRONIC_BUILD_DEPLOY_RAMDISK=True, or manually configure "\
"IRONIC_DEPLOY_RAMDISK(_URL) and IRONIC_DEPLOY_KERNEL(_URL) "\
"to use your own pre-built ramdisk."
;;
esac
fi
# This refers the options for disk-image-create and the platform on which
# to build the dib based ironic-python-agent ramdisk.
# "ubuntu" is set as the default value.
IRONIC_DIB_RAMDISK_OPTIONS=${IRONIC_DIB_RAMDISK_OPTIONS:-'ubuntu'}
# Some drivers in Ironic require deploy ramdisk in bootable ISO format.
# Set this variable to "true" to build an ISO for deploy ramdisk and
# upload to Glance.
IRONIC_DEPLOY_ISO_REQUIRED=$(trueorfalse False IRONIC_DEPLOY_ISO_REQUIRED)
if [[ "$IRONIC_DEPLOY_ISO_REQUIRED" = "True" \
&& "$IRONIC_BUILD_DEPLOY_RAMDISK" = "False" \
&& -n "$IRONIC_DEPLOY_ISO" ]]; then
die "Prebuilt ISOs are not available, provide an ISO via IRONIC_DEPLOY_ISO \
or set IRONIC_BUILD_DEPLOY_RAMDISK=True to use ISOs"
fi
# Which deploy driver to use - valid choices right now
# are ``pxe_ssh``, ``pxe_ipmitool``, ``agent_ssh``, ``agent_ipmitool``,
# ``pxe_snmp`` and ``ipmi``.
#
# Additional valid choices if IRONIC_IS_HARDWARE == true are:
# ``pxe_iscsi_cimc``, ``pxe_agent_cimc``, ``pxe_ucs``, ``pxe_cimc``,
# ``*_pxe_oneview`` and ``pxe_drac``
IRONIC_DEPLOY_DRIVER=${IRONIC_DEPLOY_DRIVER:-pxe_ipmitool}
# If the requested driver is not yet enable, enable it, if it is not it will fail anyway
if [[ -z "$(echo ${IRONIC_ENABLED_DRIVERS},${IRONIC_ENABLED_HARDWARE_TYPES} | grep -w ${IRONIC_DEPLOY_DRIVER})" ]]; then
die "The deploy driver $IRONIC_DEPLOY_DRIVER is not in the list of enabled \
drivers $IRONIC_ENABLED_DRIVERS or hardware types $IRONIC_ENABLED_HARDWARE_TYPES"
fi
# Support entry points installation of console scripts
IRONIC_BIN_DIR=$(get_python_exec_prefix)
# Ironic connection info. Note the port must be specified.
IRONIC_SERVICE_PROTOCOL=${IRONIC_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL}
IRONIC_SERVICE_PORT=${IRONIC_SERVICE_PORT:-6385}
IRONIC_HOSTPORT=${IRONIC_HOSTPORT:-$SERVICE_HOST:$IRONIC_SERVICE_PORT}
# Enable iPXE
IRONIC_IPXE_ENABLED=$(trueorfalse True IRONIC_IPXE_ENABLED)
# Options below are only applied when IRONIC_IPXE_ENABLED is True
IRONIC_IPXE_USE_SWIFT=$(trueorfalse False IRONIC_IPXE_USE_SWIFT)
IRONIC_HTTP_DIR=${IRONIC_HTTP_DIR:-$IRONIC_DATA_DIR/httpboot}
IRONIC_HTTP_PORT=${IRONIC_HTTP_PORT:-3928}
# Whether DevStack will be setup for bare metal or VMs
IRONIC_IS_HARDWARE=$(trueorfalse False IRONIC_IS_HARDWARE)
# The first port in the range to bind the Virtual BMCs. The number of
# ports that will be used depends on $IRONIC_VM_COUNT variable, e.g if
# $IRONIC_VM_COUNT=3 the ports 6230, 6231 and 6232 will be used for the
# Virtual BMCs, one for each VM.
IRONIC_VBMC_PORT_RANGE_START=${IRONIC_VBMC_PORT_RANGE_START:-6230}
IRONIC_VBMC_CONFIG_FILE=${IRONIC_VBMC_CONFIG_FILE:-$HOME/.vbmc/virtualbmc.conf}
IRONIC_VBMC_LOGFILE=${IRONIC_VBMC_LOGFILE:-$IRONIC_VM_LOG_DIR/virtualbmc.log}
# Virtual PDU configs
IRONIC_VPDU_CONFIG_FILE=${IRONIC_VPDU_CONFIG_FILE:-$HOME/.vpdu/virtualpdu.conf}
IRONIC_VPDU_PORT_RANGE_START=${IRONIC_VPDU_PORT_RANGE_START:-1}
IRONIC_VPDU_LISTEN_PORT=${IRONIC_VPDU_LISTEN_PORT:-1161}
IRONIC_VPDU_COMMUNITY=${IRONIC_VPDU_COMMUNITY:-private}
IRONIC_VPDU_SNMPDRIVER=${IRONIC_VPDU_SNMPDRIVER:-apc_rackpdu}
# To explicitly enable configuration of Glance with Swift
# (which is required by some vendor drivers), set this
# variable to true.
IRONIC_CONFIGURE_GLANCE_WITH_SWIFT=$(trueorfalse False IRONIC_CONFIGURE_GLANCE_WITH_SWIFT)
# The path to the libvirt hooks directory, used if IRONIC_VM_LOG_ROTATE is True
IRONIC_LIBVIRT_HOOKS_PATH=${IRONIC_LIBVIRT_HOOKS_PATH:-/etc/libvirt/hooks/}
# The authentication strategy used by ironic-api. Valid values are:
# keystone and noauth.
IRONIC_AUTH_STRATEGY=${IRONIC_AUTH_STRATEGY:-keystone}
# By default, terminal SSL certificate is disabled.
IRONIC_TERMINAL_SSL=$(trueorfalse False IRONIC_TERMINAL_SSL)
IRONIC_TERMINAL_CERT_DIR=${IRONIC_TERMINAL_CERT_DIR:-$IRONIC_DATA_DIR/terminal_cert/}
# This flag is used to allow adding Link-Local-Connection info
# to ironic port-create command. LLC info is obtained from
# IRONIC_{VM,HW}_NODES_FILE
IRONIC_USE_LINK_LOCAL=$(trueorfalse False IRONIC_USE_LINK_LOCAL)
# Allow selecting dhcp provider
IRONIC_DHCP_PROVIDER=${IRONIC_DHCP_PROVIDER:-neutron}
# This flag is used to specify enabled network drivers
IRONIC_ENABLED_NETWORK_INTERFACES=${IRONIC_ENABLED_NETWORK_INTERFACES:-}
# This is the network interface to use for a node
IRONIC_NETWORK_INTERFACE=${IRONIC_NETWORK_INTERFACE:-}
# Ironic provision network name
IRONIC_PROVISION_NETWORK_NAME=${IRONIC_PROVISION_NETWORK_NAME:-}
# Provision network provider type. Can be flat or vlan.
IRONIC_PROVISION_PROVIDER_NETWORK_TYPE=${IRONIC_PROVISION_PROVIDER_NETWORK_TYPE:-'vlan'}
# If IRONIC_PROVISION_PROVIDER_NETWORK_TYPE is vlan. VLAN_ID may be specified. If it is not set,
# vlan will be allocated dynamically.
IRONIC_PROVISION_SEGMENTATION_ID=${IRONIC_PROVISION_SEGMENTATION_ID:-}
# Allocation network pool for provision network
# Example: IRONIC_PROVISION_ALLOCATION_POOL=start=10.0.5.10,end=10.0.5.100
IRONIC_PROVISION_ALLOCATION_POOL=${IRONIC_PROVISION_ALLOCATION_POOL:-'start=10.0.5.10,end=10.0.5.100'}
# Ironic provision subnet name.
IRONIC_PROVISION_PROVIDER_SUBNET_NAME=${IRONIC_PROVISION_PROVIDER_SUBNET_NAME:-${IRONIC_PROVISION_NETWORK_NAME}-subnet}
# With multinode case all ironic-conductors should have IP from provisioning network.
# IRONIC_PROVISION_SUBNET_GATEWAY - is configured on primary node.
# Ironic provision subnet gateway.
IRONIC_PROVISION_SUBNET_GATEWAY=${IRONIC_PROVISION_SUBNET_GATEWAY:-'10.0.5.1'}
IRONIC_PROVISION_SUBNET_SUBNODE_IP=${IRONIC_PROVISION_SUBNET_SUBNODE_IP:-'10.0.5.2'}
# Ironic provision subnet prefix
# Example: IRONIC_PROVISION_SUBNET_PREFIX=10.0.5.0/24
IRONIC_PROVISION_SUBNET_PREFIX=${IRONIC_PROVISION_SUBNET_PREFIX:-'10.0.5.0/24'}
if [[ "$HOST_TOPOLOGY_ROLE" == 'primary' ]]; then
IRONIC_TFTPSERVER_IP=$IRONIC_PROVISION_SUBNET_GATEWAY
IRONIC_HTTP_SERVER=$IRONIC_PROVISION_SUBNET_GATEWAY
fi
if [[ "$HOST_TOPOLOGY_ROLE" == 'subnode' ]]; then
IRONIC_TFTPSERVER_IP=$IRONIC_PROVISION_SUBNET_SUBNODE_IP
IRONIC_HTTP_SERVER=$IRONIC_PROVISION_SUBNET_SUBNODE_IP
fi
IRONIC_HTTP_SERVER=${IRONIC_HTTP_SERVER:-$IRONIC_TFTPSERVER_IP}
# Retrieving logs from the deploy ramdisk
#
# IRONIC_DEPLOY_LOGS_COLLECT possible values are:
# * always: Collect the ramdisk logs from the deployment on success or
# failure (Default in DevStack for debugging purpose).
# * on_failure: Collect the ramdisk logs upon a deployment failure
# (Default in Ironic).
# * never: Never collect the ramdisk logs.
IRONIC_DEPLOY_LOGS_COLLECT=${IRONIC_DEPLOY_LOGS_COLLECT:-always}
# IRONIC_DEPLOY_LOGS_STORAGE_BACKEND possible values are:
# * local: To store the logs in the local filesystem (Default in Ironic and DevStack).
# * swift: To store the logs in Swift.
IRONIC_DEPLOY_LOGS_STORAGE_BACKEND=${IRONIC_DEPLOY_LOGS_STORAGE_BACKEND:-local}
# The path to the directory where Ironic should put the logs when IRONIC_DEPLOY_LOGS_STORAGE_BACKEND is set to "local"
IRONIC_DEPLOY_LOGS_LOCAL_PATH=${IRONIC_DEPLOY_LOGS_LOCAL_PATH:-$IRONIC_VM_LOG_DIR/deploy_logs}
# Define baremetal min_microversion in tempest config. Default value None is picked from tempest.
TEMPEST_BAREMETAL_MIN_MICROVERSION=${TEMPEST_BAREMETAL_MIN_MICROVERSION:-}
# Define baremetal max_microversion in tempest config. No default value means that it is picked from tempest.
TEMPEST_BAREMETAL_MAX_MICROVERSION=${TEMPEST_BAREMETAL_MAX_MICROVERSION:-}
# get_pxe_boot_file() - Get the PXE/iPXE boot file path
function get_pxe_boot_file {
local pxe_boot_file
if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
if is_ubuntu; then
pxe_boot_file=/usr/lib/ipxe/undionly.kpxe
elif is_fedora || is_suse; then
pxe_boot_file=/usr/share/ipxe/undionly.kpxe
fi
else
# Standard PXE
if is_ubuntu; then
# Ubuntu Xenial (16.04) places the file under /usr/lib/PXELINUX
pxe_paths="/usr/lib/syslinux/pxelinux.0 /usr/lib/PXELINUX/pxelinux.0"
for p in $pxe_paths; do
if [[ -f $p ]]; then
pxe_boot_file=$p
fi
done
elif is_fedora || is_suse; then
pxe_boot_file=/usr/share/syslinux/pxelinux.0
fi
fi
echo $pxe_boot_file
}
# PXE boot image
IRONIC_PXE_BOOT_IMAGE=${IRONIC_PXE_BOOT_IMAGE:-$(get_pxe_boot_file)}
IRONIC_AUTOMATED_CLEAN_ENABLED=$(trueorfalse True IRONIC_AUTOMATED_CLEAN_ENABLED)
# Whether configure the nodes to boot in Legacy BIOS or UEFI mode. Accepted
# values are: "bios" or "uefi", defaults to "bios".
#
# WARNING: UEFI is EXPERIMENTAL. The CirrOS images uploaded by DevStack by
# default WILL NOT WORK with UEFI. You will need to download the UEFI capable
# images manually from [0] and upload it to Glance before deploying.
IRONIC_BOOT_MODE=${IRONIC_BOOT_MODE:-bios}
IRONIC_UEFI_FILES_DIR=${IRONIC_UEFI_FILES_DIR:-/var/lib/libvirt/images}
UEFI_LOADER_PATH=$IRONIC_UEFI_FILES_DIR/OVMF_CODE.fd
UEFI_NVRAM_PATH=$IRONIC_UEFI_FILES_DIR/OVMF_VARS.fd
# Sanity checks
if [[ "$IRONIC_BOOT_MODE" == "uefi" ]]; then
if [[ "$IRONIC_IPXE_ENABLED" == "False" ]]; then
die $LINENO "Boot mode UEFI is only supported when used with iPXE for now."
fi
if ! is_fedora && ! is_ubuntu; then
die $LINENO "Boot mode UEFI only works in Ubuntu or Fedora for now."
fi
fi
# Functions
# ---------
# UEFI related functions
function get_uefi_ipxe_boot_file {
if is_ubuntu; then
echo /usr/lib/ipxe/ipxe.efi
elif is_fedora; then
echo /usr/share/ipxe/ipxe-x86_64.efi
fi
}
function get_uefi_loader {
if is_ubuntu; then
echo /usr/share/OVMF/OVMF_CODE.fd
elif is_fedora; then
echo /usr/share/edk2/ovmf/OVMF_CODE.fd
fi
}
function get_uefi_nvram {
if is_ubuntu; then
echo /usr/share/OVMF/OVMF_VARS.fd
elif is_fedora; then
echo /usr/share/edk2/ovmf/OVMF_VARS.fd
fi
}
# Misc
function restart_libvirt {
local libvirt_service_name="libvirtd"
if is_ubuntu && [ ! -f /etc/init.d/libvirtd ]; then
libvirt_service_name="libvirt-bin"
fi
restart_service $libvirt_service_name
}
# Test if any Ironic services are enabled
# is_ironic_enabled
function is_ironic_enabled {
[[ ,${ENABLED_SERVICES} =~ ,"ir-" ]] && return 0
return 1
}
function is_deployed_by_agent {
[[ -z "${IRONIC_DEPLOY_DRIVER%%agent*}" ]] && return 0
return 1
}
function is_deployed_by_ipmitool {
[[ "$IRONIC_DEPLOY_DRIVER" == ipmi || -z "${IRONIC_DEPLOY_DRIVER##*_ipmitool}" ]] && return 0
return 1
}
function is_deployed_by_cimc {
[[ -z "${IRONIC_DEPLOY_DRIVER##*_cimc}" ]] && return 0
return 1
}
function is_deployed_by_ucs {
[[ -z "${IRONIC_DEPLOY_DRIVER##*_ucs}" ]] && return 0
return 1
}
function is_deployed_by_oneview {
[[ -z "${IRONIC_DEPLOY_DRIVER##*_oneview}" ]] && return 0
}
function is_deployed_by_ilo {
[[ -z "${IRONIC_DEPLOY_DRIVER##*_ilo}" ]] && return 0
return 1
}
function is_deployed_by_drac {
[[ -z "${IRONIC_DEPLOY_DRIVER##*_drac}" ]] && return 0
return 1
}
function is_deployed_by_snmp {
[[ -z "${IRONIC_DEPLOY_DRIVER##*_snmp}" ]] && return 0
return 1
}
function is_drac_enabled {
[[ -z "${IRONIC_ENABLED_DRIVERS##*_drac}" ]] && return 0
return 1
}
function is_glance_configuration_required {
is_deployed_by_agent || [[ "$IRONIC_CONFIGURE_GLANCE_WITH_SWIFT" == "True" ]] && return 0
return 1
}
function is_deploy_iso_required {
[[ "$IRONIC_IS_HARDWARE" == "True" && "$IRONIC_DEPLOY_ISO_REQUIRED" == "True" ]] && return 0
return 1
}
IRONIC_DEFAULT_IMAGE_NAME=cirros-${CIRROS_VERSION}-x86_64-uec
if [[ "$IRONIC_BOOT_MODE" == "uefi" ]]; then
IRONIC_DEFAULT_IMAGE_NAME=cirros-d160722-x86_64-uec
fi
IRONIC_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-$IRONIC_DEFAULT_IMAGE_NAME}
# Add link to download queue, ignore if already exist.
# TODO(vsaienko) Move to devstack https://review.openstack.org/420656
function add_image_link {
local i_link="$1"
if ! [[ "$IMAGE_URLS" =~ "$i_link" ]]; then
if [[ -z "$IMAGE_URLS" || "${IMAGE_URLS: -1}" == "," ]]; then
IMAGE_URLS+="$i_link"
else
IMAGE_URLS+=",$i_link"
fi
fi
}
if [[ "$IRONIC_BOOT_MODE" == "uefi" ]]; then
add_image_link http://download.cirros-cloud.net/daily/20160722/cirros-d160722-x86_64-uec.tar.gz
add_image_link http://download.cirros-cloud.net/daily/20160722/cirros-d160722-x86_64-disk.img
else
# NOTE (vsaienko) We are going to test mixed drivers/partitions in single setup.
# Do not restrict downloading image only for specific case. Download both disk and uec images.
add_image_link http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-x86_64-uec.tar.gz
add_image_link http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-x86_64-disk.img
fi
IRONIC_WHOLEDISK_IMAGE_NAME=${IRONIC_WHOLEDISK_IMAGE_NAME:-${IRONIC_IMAGE_NAME/-uec/-disk}}
IRONIC_PARTITIONED_IMAGE_NAME=${IRONIC_PARTITIONED_IMAGE_NAME:-${IRONIC_IMAGE_NAME/-disk/-uec}}
if [[ "$IRONIC_TEMPEST_WHOLE_DISK_IMAGE" == "True" ]]; then
IRONIC_IMAGE_NAME=$IRONIC_WHOLEDISK_IMAGE_NAME
else
IRONIC_IMAGE_NAME=$IRONIC_PARTITIONED_IMAGE_NAME
fi
# NOTE(vsaienko) set DEFAULT_IMAGE_NAME here, as it is still used by grenade
# https://github.com/openstack-dev/grenade/blob/90c4ead2f2a7ed48c873c51cef415b83d655752e/projects/60_nova/resources.sh#L31
export DEFAULT_IMAGE_NAME=$IRONIC_IMAGE_NAME
# Syslinux >= 5.00 pxelinux.0 binary is not "stand-alone" anymore,
# it depends on some c32 modules to work correctly.
# More info: http://www.syslinux.org/wiki/index.php/Library_modules
function setup_syslinux_modules {
# Ignore it for iPXE, it doesn't repend on syslinux modules
[[ "$IRONIC_IPXE_ENABLED" == "True" ]] && return 0
# Ubuntu Xenial keeps doesn't ship pxelinux.0 as part of syslinux anymore
if is_ubuntu && [[ -d /usr/lib/PXELINUX/ ]]; then
# TODO(lucasagomes): Figure out whether its UEFI or BIOS once
# we have UEFI support in DevStack
cp -aR /usr/lib/syslinux/modules/bios/*.c32 $IRONIC_TFTPBOOT_DIR
else
cp -aR $(dirname $IRONIC_PXE_BOOT_IMAGE)/*.c32 $IRONIC_TFTPBOOT_DIR
fi
}
function setup_virtualbmc {
# Install pyghmi from source, if requested, otherwise it will be
# downloaded as part of the virtualbmc installation
if use_library_from_git "pyghmi"; then
git_clone_by_name "pyghmi"
setup_dev_lib "pyghmi"
fi
if use_library_from_git "virtualbmc"; then
git_clone_by_name "virtualbmc"
setup_dev_lib "virtualbmc"
else
pip_install_gr "virtualbmc"
fi
if [[ ! -d $(dirname $IRONIC_VBMC_CONFIG_FILE) ]]; then
mkdir -p $(dirname $IRONIC_VBMC_CONFIG_FILE)
fi
iniset $IRONIC_VBMC_CONFIG_FILE log debug True
iniset $IRONIC_VBMC_CONFIG_FILE log logfile $IRONIC_VBMC_LOGFILE
}
function setup_virtualpdu {
if use_library_from_git "virtualpdu"; then
git_clone_by_name "virtualpdu"
setup_dev_lib "virtualpdu"
else
pip_install "virtualpdu"
fi
mkdir -p $(dirname $IRONIC_VPDU_CONFIG_FILE)
iniset $IRONIC_VPDU_CONFIG_FILE global debug True
iniset $IRONIC_VPDU_CONFIG_FILE global libvirt_uri "qemu:///system"
iniset $IRONIC_VPDU_CONFIG_FILE PDU listen_address ${HOST_IP}
iniset $IRONIC_VPDU_CONFIG_FILE PDU listen_port ${IRONIC_VPDU_LISTEN_PORT}
iniset $IRONIC_VPDU_CONFIG_FILE PDU community ${IRONIC_VPDU_COMMUNITY}
iniset $IRONIC_VPDU_CONFIG_FILE PDU ports $(_generate_pdu_ports)
iniset $IRONIC_VPDU_CONFIG_FILE PDU outlet_default_state "OFF"
enable_service ir-vpdu
}
# _generate_pdu_ports() - Generates list of port:node_name.
function _generate_pdu_ports {
pdu_port_number=${IRONIC_VPDU_PORT_RANGE_START}
port_config=()
for vm_name in $(_ironic_bm_vm_names); do
port_config+=("${pdu_port_number}:${vm_name}")
pdu_port_number=$(( pdu_port_number + 1 ))
done
echo ${port_config[*]} | tr ' ' ','
}
# install_ironic() - Install the things!
function install_ironic {
# NOTE(vsaienko) do not check required_services on subnode
if [[ "$HOST_TOPOLOGY_ROLE" != "subnode" ]]; then
# make sure all needed service were enabled
local req_services="key"
if is_service_enabled nova && [[ "$VIRT_DRIVER" == "ironic" ]]; then
req_services+=" nova glance neutron"
fi
for srv in $req_services; do
if ! is_service_enabled "$srv"; then
die $LINENO "$srv should be enabled for Ironic."
fi
done
fi
if use_library_from_git "ironic-lib"; then
git_clone_by_name "ironic-lib"
setup_dev_lib "ironic-lib"
fi
setup_develop $IRONIC_DIR
if [[ "$IRONIC_USE_MOD_WSGI" == "True" || "$IRONIC_IPXE_ENABLED" == "True" ]]; then
install_apache_wsgi
fi
if [[ "$IRONIC_BOOT_MODE" == "uefi" ]]; then
# Append the nvram configuration to libvirt if it's not present already
if ! sudo grep -q "^nvram" /etc/libvirt/qemu.conf; then
echo "nvram=[\"$UEFI_LOADER_PATH:$UEFI_NVRAM_PATH\"]" | sudo tee -a /etc/libvirt/qemu.conf
fi
# Replace the default virtio PXE ROM in QEMU with an EFI capable
# one. The EFI ROM should work on with both boot modes, Legacy
# BIOS and UEFI.
if is_ubuntu; then
# FIXME(lucasagomes): Enable the multiverse repository by
# default in the image running the gate tests. Also move the
# installation of the ovmf package to files/debs/ironic
sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc) multiverse"
sudo apt-get update
install_package ovmf
sudo rm /usr/share/qemu/pxe-virtio.rom
sudo ln -s /usr/lib/ipxe/qemu/efi-virtio.rom /usr/share/qemu/pxe-virtio.rom
elif is_fedora; then
sudo rm /usr/share/qemu/pxe-virtio.rom
sudo ln -s /usr/share/ipxe.efi/1af41000.rom /usr/share/qemu/pxe-virtio.rom
fi
# Restart libvirt to the changes to take effect
restart_libvirt
fi
if is_deployed_by_ipmitool && [[ "$IRONIC_IS_HARDWARE" == "False" ]]; then
setup_virtualbmc
fi
if is_deployed_by_snmp && [[ "$IRONIC_IS_HARDWARE" == "False" ]]; then
setup_virtualpdu
fi
if is_drac_enabled; then
pip_install python-dracclient
fi
}
# install_ironicclient() - Collect sources and prepare
function install_ironicclient {
if use_library_from_git "python-ironicclient"; then
git_clone_by_name "python-ironicclient"
setup_dev_lib "python-ironicclient"
sudo install -D -m 0644 -o $STACK_USER {${GITDIR["python-ironicclient"]}/tools/,/etc/bash_completion.d/}ironic.bash_completion
else
# nothing actually "requires" ironicclient, so force instally from pypi
pip_install_gr python-ironicclient
fi
}
# _cleanup_ironic_apache_wsgi() - Remove wsgi files, disable and remove apache vhost file
function _cleanup_ironic_apache_wsgi {
sudo rm -rf $IRONIC_HTTP_DIR
sudo rm -rf $IRONIC_WSGI_DIR
disable_apache_site ironic-api
disable_apache_site ipxe-ironic
sudo rm -f $(apache_site_config_for ironic-api)
sudo rm -f $(apache_site_config_for ipxe-ironic)
restart_apache_server
}
# _config_ironic_apache_wsgi() - Set WSGI config files of Ironic
function _config_ironic_apache_wsgi {
local ironic_apache_conf
local ipxe_apache_conf
if [[ "$IRONIC_USE_MOD_WSGI" == "True" ]]; then
sudo mkdir -p $IRONIC_WSGI_DIR
sudo cp $IRONIC_DIR/ironic/api/app.wsgi $IRONIC_WSGI_DIR/app.wsgi
ironic_apache_conf=$(apache_site_config_for ironic-api)
sudo cp $IRONIC_DEVSTACK_FILES_DIR/apache-ironic-api.template $ironic_apache_conf
sudo sed -e "
s|%IRONIC_SERVICE_PORT%|$IRONIC_SERVICE_PORT|g;
s|%IRONIC_WSGI_DIR%|$IRONIC_WSGI_DIR|g;
s|%USER%|$STACK_USER|g;
s|%APIWORKERS%|$API_WORKERS|g;
s|%APACHE_NAME%|$APACHE_NAME|g;
" -i $ironic_apache_conf
enable_apache_site ironic-api
tail_log ir-access /var/log/$APACHE_NAME/ironic-api-access.log
tail_log ir-api /var/log/$APACHE_NAME/ironic-api.log
fi
if [[ "$IRONIC_IPXE_ENABLED" == "True" ]]; then
ipxe_apache_conf=$(apache_site_config_for ipxe-ironic)
sudo cp $IRONIC_DEVSTACK_FILES_DIR/apache-ipxe-ironic.template $ipxe_apache_conf
sudo sed -e "
s|%PUBLICPORT%|$IRONIC_HTTP_PORT|g;
s|%HTTPROOT%|$IRONIC_HTTP_DIR|g;
" -i $ipxe_apache_conf
enable_apache_site ipxe-ironic
fi
}
# cleanup_ironic_config_files() - Remove residual cache/config/log files,
# left over from previous runs that would need to clean up.
function cleanup_ironic_config_files {
sudo rm -rf $IRONIC_AUTH_CACHE_DIR $IRONIC_CONF_DIR
sudo rm -rf $IRONIC_VM_LOG_DIR/*
}
# cleanup_ironic() - Clean everything left from Ironic
function cleanup_ironic {
cleanup_ironic_config_files
# Cleanup the WSGI files
_cleanup_ironic_apache_wsgi
# Remove the hook to disable log rotate
sudo rm -rf $IRONIC_LIBVIRT_HOOKS_PATH/qemu
}
# configure_ironic_dirs() - Create all directories required by Ironic and
# associated services.
function configure_ironic_dirs {
sudo install -d -o $STACK_USER $IRONIC_CONF_DIR $STACK_USER $IRONIC_DATA_DIR \
$IRONIC_STATE_PATH $IRONIC_TFTPBOOT_DIR $IRONIC_TFTPBOOT_DIR/pxelinux.cfg
sudo chown -R $STACK_USER:$LIBVIRT_GROUP $IRONIC_TFTPBOOT_DIR
if [[ "$IRONIC_IPXE_ENABLED" == "True" ]]; then
sudo install -d -o $STACK_USER -g $LIBVIRT_GROUP $IRONIC_HTTP_DIR
fi
if [ ! -f "$IRONIC_PXE_BOOT_IMAGE" ]; then
die $LINENO "PXE boot file $IRONIC_PXE_BOOT_IMAGE not found."
fi
# Copy PXE binary
cp $IRONIC_PXE_BOOT_IMAGE $IRONIC_TFTPBOOT_DIR
setup_syslinux_modules
if [[ "$IRONIC_BOOT_MODE" == "uefi" ]]; then
local uefi_ipxe_boot_file
local uefi_loader
local uefi_nvram
uefi_ipxe_boot_file=$(get_uefi_ipxe_boot_file)
if [ ! -f $uefi_ipxe_boot_file ]; then
die $LINENO "iPXE UEFI boot file $uefi_pxe_bootfile_name not found."
fi
cp $uefi_ipxe_boot_file $IRONIC_TFTPBOOT_DIR
# Copy the OVMF images to libvirt's path
uefi_loader=$(get_uefi_loader)
uefi_nvram=$(get_uefi_nvram)
sudo cp $uefi_loader $UEFI_LOADER_PATH
sudo cp $uefi_nvram $UEFI_NVRAM_PATH
fi
# Create the logs directory when saving the deploy logs to the filesystem
if [[ "$IRONIC_DEPLOY_LOGS_STORAGE_BACKEND" == "local" && "$IRONIC_DEPLOY_LOGS_COLLECT" != "never" ]]; then
install -d -o $STACK_USER $IRONIC_DEPLOY_LOGS_LOCAL_PATH
fi
}
function configure_ironic_networks {
if [[ -n "${IRONIC_PROVISION_NETWORK_NAME}" ]]; then
echo_summary "Configuring Ironic provisioning network"
configure_ironic_provision_network
fi
echo_summary "Configuring Ironic cleaning network"
configure_ironic_cleaning_network
}
function configure_ironic_cleaning_network {
iniset $IRONIC_CONF_FILE neutron cleaning_network $IRONIC_CLEAN_NET_NAME
}
function configure_ironic_provision_network {
local net_id
local ironic_provision_network_ip
# NOTE(vsaienko) For multinode case there is no need to create a new provisioning
# network on subnode, as it was created on primary node. Just get an existed network UUID.
if [[ "$HOST_TOPOLOGY_ROLE" != 'subnode' ]]; then
die_if_not_set $LINENO IRONIC_PROVISION_SUBNET_PREFIX "You must specify the IRONIC_PROVISION_SUBNET_PREFIX"
die_if_not_set $LINENO PHYSICAL_NETWORK "You must specify the PHYSICAL_NETWORK"
die_if_not_set $LINENO IRONIC_PROVISION_SUBNET_GATEWAY "You must specify the IRONIC_PROVISION_SUBNET_GATEWAY"
net_id=$(openstack network create --provider-network-type $IRONIC_PROVISION_PROVIDER_NETWORK_TYPE \
--provider-physical-network "$PHYSICAL_NETWORK" \
${IRONIC_PROVISION_SEGMENTATION_ID:+--provider-segment $IRONIC_PROVISION_SEGMENTATION_ID} \
${IRONIC_PROVISION_NETWORK_NAME} -f value -c id)
die_if_not_set $LINENO net_id "Failure creating net_id for $IRONIC_PROVISION_NETWORK_NAME"
local subnet_id
subnet_id="$(openstack subnet create --ip-version 4 \
${IRONIC_PROVISION_ALLOCATION_POOL:+--allocation-pool $IRONIC_PROVISION_ALLOCATION_POOL} \
$IRONIC_PROVISION_PROVIDER_SUBNET_NAME \
--gateway $IRONIC_PROVISION_SUBNET_GATEWAY --network $net_id \
--subnet-range $IRONIC_PROVISION_SUBNET_PREFIX -f value -c id)"
die_if_not_set $LINENO subnet_id "Failure creating SUBNET_ID for $IRONIC_PROVISION_NETWORK_NAME"
ironic_provision_network_ip=$IRONIC_PROVISION_SUBNET_GATEWAY
else
net_id=$(openstack network show $IRONIC_PROVISION_NETWORK_NAME -f value -c id)
ironic_provision_network_ip=$IRONIC_PROVISION_SUBNET_SUBNODE_IP
fi
IRONIC_PROVISION_SEGMENTATION_ID=${IRONIC_PROVISION_SEGMENTATION_ID:-`openstack network show ${net_id} -f value -c provider:segmentation_id`}
provision_net_prefix=${IRONIC_PROVISION_SUBNET_PREFIX##*/}
# Set provision network GW on physical interface
# Add vlan on br interface in case of IRONIC_PROVISION_PROVIDER_NETWORK_TYPE==vlan
# othervise assign ip to br interface directly.
if [[ "$IRONIC_PROVISION_PROVIDER_NETWORK_TYPE" == "vlan" ]]; then
sudo ip link add link $OVS_PHYSICAL_BRIDGE name $OVS_PHYSICAL_BRIDGE.$IRONIC_PROVISION_SEGMENTATION_ID type vlan id $IRONIC_PROVISION_SEGMENTATION_ID
sudo ip link set dev $OVS_PHYSICAL_BRIDGE up
sudo ip link set dev $OVS_PHYSICAL_BRIDGE.$IRONIC_PROVISION_SEGMENTATION_ID up
sudo ip addr add dev $OVS_PHYSICAL_BRIDGE.$IRONIC_PROVISION_SEGMENTATION_ID $ironic_provision_network_ip/$provision_net_prefix
else
sudo ip link set dev $OVS_PHYSICAL_BRIDGE up
sudo ip addr add dev $OVS_PHYSICAL_BRIDGE $ironic_provision_network_ip/$provision_net_prefix
fi
iniset $IRONIC_CONF_FILE neutron provisioning_network $IRONIC_PROVISION_NETWORK_NAME
}
function cleanup_ironic_provision_network {
# Cleanup OVS_PHYSICAL_BRIDGE subinterfaces
local bridge_subint
bridge_subint=$(cat /proc/net/dev | sed -n "s/^\(${OVS_PHYSICAL_BRIDGE}\.[0-9]*\).*/\1/p")
for sub_int in $bridge_subint; do
sudo ip link set dev $sub_int down
sudo ip link del dev $sub_int
done
}
# configure_ironic() - Set config files, create data dirs, etc
function configure_ironic {
configure_ironic_dirs
# Copy over ironic configuration file and configure common parameters.
cp $IRONIC_DIR/etc/ironic/ironic.conf.sample $IRONIC_CONF_FILE
iniset $IRONIC_CONF_FILE DEFAULT debug True
inicomment $IRONIC_CONF_FILE DEFAULT log_file
iniset $IRONIC_CONF_FILE database connection `database_connection_url ironic`
iniset $IRONIC_CONF_FILE DEFAULT state_path $IRONIC_STATE_PATH
iniset $IRONIC_CONF_FILE DEFAULT use_syslog $SYSLOG
# NOTE(vsaienko) with multinode each conductor should have its own host.
iniset $IRONIC_CONF_FILE DEFAULT host $LOCAL_HOSTNAME
# Retrieve deployment logs
iniset $IRONIC_CONF_FILE agent deploy_logs_collect $IRONIC_DEPLOY_LOGS_COLLECT
iniset $IRONIC_CONF_FILE agent deploy_logs_storage_backend $IRONIC_DEPLOY_LOGS_STORAGE_BACKEND
iniset $IRONIC_CONF_FILE agent deploy_logs_local_path $IRONIC_DEPLOY_LOGS_LOCAL_PATH
# Configure Ironic conductor, if it was enabled.
if is_service_enabled ir-cond; then
configure_ironic_conductor
fi
# Configure Ironic API, if it was enabled.
if is_service_enabled ir-api; then
configure_ironic_api
fi
# Format logging
if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then
setup_colorized_logging $IRONIC_CONF_FILE DEFAULT tenant user
fi
# Adds WSGI for Ironic API
if [[ "$IRONIC_USE_MOD_WSGI" == "True" || "$IRONIC_IPXE_ENABLED" == "True" ]]; then
_config_ironic_apache_wsgi
fi
# NOTE(vsaienko) Add stack to libvirt group when installing without nova.
if ! is_service_enabled nova; then
if [[ "$os_VENDOR" =~ (Debian) ]]; then
LIBVIRT_GROUP=libvirt
else
LIBVIRT_GROUP=libvirtd
fi
if ! getent group $LIBVIRT_GROUP >/dev/null; then
sudo groupadd $LIBVIRT_GROUP
fi
add_user_to_group $STACK_USER $LIBVIRT_GROUP
fi
}
# configure_ironic_api() - Is used by configure_ironic(). Performs
# API specific configuration.
function configure_ironic_api {
iniset $IRONIC_CONF_FILE DEFAULT auth_strategy $IRONIC_AUTH_STRATEGY
configure_auth_token_middleware $IRONIC_CONF_FILE ironic $IRONIC_AUTH_CACHE_DIR/api
iniset $IRONIC_CONF_FILE oslo_policy policy_file $IRONIC_POLICY_JSON
iniset_rpc_backend ironic $IRONIC_CONF_FILE
iniset $IRONIC_CONF_FILE api port $IRONIC_SERVICE_PORT
iniset $IRONIC_CONF_FILE conductor automated_clean $IRONIC_AUTOMATED_CLEAN_ENABLED
cp -p $IRONIC_DIR/etc/ironic/policy.json $IRONIC_POLICY_JSON
}
function configure_auth_for {
local service_config_section
service_config_section=$1
iniset $IRONIC_CONF_FILE $service_config_section auth_type password
iniset $IRONIC_CONF_FILE $service_config_section auth_url $KEYSTONE_SERVICE_URI
iniset $IRONIC_CONF_FILE $service_config_section username ironic
iniset $IRONIC_CONF_FILE $service_config_section password $SERVICE_PASSWORD
iniset $IRONIC_CONF_FILE $service_config_section project_name $SERVICE_PROJECT_NAME
iniset $IRONIC_CONF_FILE $service_config_section user_domain_id default
iniset $IRONIC_CONF_FILE $service_config_section project_domain_id default
iniset $IRONIC_CONF_FILE $service_config_section cafile $SSL_BUNDLE_FILE
}
# configure_ironic_conductor() - Is used by configure_ironic().
# Sets conductor specific settings.
function configure_ironic_conductor {
# set keystone region for all services
iniset $IRONIC_CONF_FILE keystone region_name $REGION_NAME
# set keystone auth plugin options for services
configure_auth_for neutron
configure_auth_for swift
configure_auth_for glance
configure_auth_for inspector
# this one is needed for lookup of Ironic API endpoint via Keystone
configure_auth_for service_catalog
cp $IRONIC_DIR/etc/ironic/rootwrap.conf $IRONIC_ROOTWRAP_CONF
cp -r $IRONIC_DIR/etc/ironic/rootwrap.d $IRONIC_CONF_DIR
local ironic_rootwrap
ironic_rootwrap=$(get_rootwrap_location ironic)
local rootwrap_isudoer_cmd="$ironic_rootwrap $IRONIC_CONF_DIR/rootwrap.conf *"
# Set up the rootwrap sudoers for ironic
local tempfile
tempfile=`mktemp`
echo "$STACK_USER ALL=(root) NOPASSWD: $rootwrap_isudoer_cmd" >$tempfile
chmod 0440 $tempfile
sudo chown root:root $tempfile
sudo mv $tempfile /etc/sudoers.d/ironic-rootwrap
# set up drivers / hardware types
iniset $IRONIC_CONF_FILE DEFAULT enabled_drivers $IRONIC_ENABLED_DRIVERS
iniset $IRONIC_CONF_FILE DEFAULT enabled_hardware_types $IRONIC_ENABLED_HARDWARE_TYPES
iniset $IRONIC_CONF_FILE DEFAULT rootwrap_config $IRONIC_ROOTWRAP_CONF
iniset $IRONIC_CONF_FILE conductor api_url $IRONIC_SERVICE_PROTOCOL://$SERVICE_HOST:$IRONIC_SERVICE_PORT
if [[ -n "$IRONIC_CALLBACK_TIMEOUT" ]]; then
iniset $IRONIC_CONF_FILE conductor deploy_callback_timeout $IRONIC_CALLBACK_TIMEOUT
fi
iniset $IRONIC_CONF_FILE pxe tftp_server $IRONIC_TFTPSERVER_IP
iniset $IRONIC_CONF_FILE pxe tftp_root $IRONIC_TFTPBOOT_DIR
iniset $IRONIC_CONF_FILE pxe tftp_master_path $IRONIC_TFTPBOOT_DIR/master_images
if [[ "$IRONIC_TERMINAL_SSL" == "True" ]]; then
# Make sure the cert directory exist
sudo mkdir -p $IRONIC_TERMINAL_CERT_DIR
sudo chown $STACK_USER $IRONIC_TERMINAL_CERT_DIR
iniset $IRONIC_CONF_FILE console terminal_cert_dir $IRONIC_TERMINAL_CERT_DIR
# Generate the SSL certificate
openssl req \
-x509 \
-days 365 \
-newkey rsa:1024 \
-nodes \
-keyout $IRONIC_TERMINAL_CERT_DIR/certificate.pem.key \
-out $IRONIC_TERMINAL_CERT_DIR/certificate.pem \
-subj '/O=OpenStack/OU=DevStack Servers'
fi
local pxe_params="nofb nomodeset vga=normal console=${IRONIC_TTY_DEV}"
pxe_params+=" systemd.journald.forward_to_console=yes"
pxe_params+=" $IRONIC_EXTRA_PXE_PARAMS"
if [[ -n "$pxe_params" ]]; then
iniset $IRONIC_CONF_FILE pxe pxe_append_params "$pxe_params"
fi
# Set these options for scenarios in which the agent fetches the image
# directly from glance, and don't set them where the image is pushed
# over iSCSI.
if is_glance_configuration_required; then
if [[ "$SWIFT_ENABLE_TEMPURLS" == "True" ]] ; then
iniset $IRONIC_CONF_FILE glance swift_temp_url_key $SWIFT_TEMPURL_KEY
else
die $LINENO "SWIFT_ENABLE_TEMPURLS must be True. This is " \
"required either because IRONIC_DEPLOY_DRIVER was " \
"set to some agent_* driver OR configuration of " \
"Glance with Swift was explicitly requested with " \
"IRONIC_CONFIGURE_GLANCE_WITH_SWIFT=True"
fi
iniset $IRONIC_CONF_FILE glance swift_endpoint_url ${SWIFT_SERVICE_PROTOCOL}://${SERVICE_HOST}:${SWIFT_DEFAULT_BIND_PORT:-8080}
iniset $IRONIC_CONF_FILE glance swift_api_version v1
local tenant_id
tenant_id=$(get_or_create_project $SERVICE_PROJECT_NAME default)
iniset $IRONIC_CONF_FILE glance swift_account AUTH_${tenant_id}
iniset $IRONIC_CONF_FILE glance swift_container glance
iniset $IRONIC_CONF_FILE glance swift_temp_url_duration 3600
iniset $IRONIC_CONF_FILE glance glance_protocol $GLANCE_SERVICE_PROTOCOL
iniset $IRONIC_CONF_FILE glance glance_host $SERVICE_HOST
iniset $IRONIC_CONF_FILE glance glance_port $GLANCE_SERVICE_PORT
fi
if is_deployed_by_agent; then
iniset $IRONIC_CONF_FILE api ramdisk_heartbeat_timeout 30
fi
# FIXME: this really needs to be tested in the gate. For now, any
# test using the agent ramdisk should skip the erase_devices clean
# step because it is too slow to run in the gate.
iniset $IRONIC_CONF_FILE deploy erase_devices_priority 0
if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
local pxebin
pxebin=`basename $IRONIC_PXE_BOOT_IMAGE`
uefipxebin=`basename $(get_uefi_ipxe_boot_file)`
iniset $IRONIC_CONF_FILE pxe ipxe_enabled True
iniset $IRONIC_CONF_FILE pxe pxe_config_template '$pybasedir/drivers/modules/ipxe_config.template'
iniset $IRONIC_CONF_FILE pxe pxe_bootfile_name $pxebin
iniset $IRONIC_CONF_FILE pxe uefi_pxe_config_template '$pybasedir/drivers/modules/ipxe_config.template'
iniset $IRONIC_CONF_FILE pxe uefi_pxe_bootfile_name $uefipxebin
iniset $IRONIC_CONF_FILE deploy http_root $IRONIC_HTTP_DIR
iniset $IRONIC_CONF_FILE deploy http_url "http://$IRONIC_HTTP_SERVER:$IRONIC_HTTP_PORT"
if [[ "$IRONIC_IPXE_USE_SWIFT" == "True" ]]; then
iniset $IRONIC_CONF_FILE pxe ipxe_use_swift True
fi
fi
if [[ "$IRONIC_IS_HARDWARE" == "False" ]]; then
iniset $IRONIC_CONF_FILE neutron port_setup_delay 15
fi
if [[ -n "$IRONIC_ENABLED_NETWORK_INTERFACES" ]]; then
iniset $IRONIC_CONF_FILE DEFAULT enabled_network_interfaces $IRONIC_ENABLED_NETWORK_INTERFACES
fi
iniset $IRONIC_CONF_FILE dhcp dhcp_provider $IRONIC_DHCP_PROVIDER
# TODO(dtantsur): change this when we change the default value.
iniset $IRONIC_CONF_FILE deploy default_boot_option netboot
}
# create_ironic_cache_dir() - Part of the init_ironic() process
function create_ironic_cache_dir {
# Create cache dir
sudo mkdir -p $IRONIC_AUTH_CACHE_DIR/api
sudo chown $STACK_USER $IRONIC_AUTH_CACHE_DIR/api
rm -f $IRONIC_AUTH_CACHE_DIR/api/*
sudo mkdir -p $IRONIC_AUTH_CACHE_DIR/registry
sudo chown $STACK_USER $IRONIC_AUTH_CACHE_DIR/registry
rm -f $IRONIC_AUTH_CACHE_DIR/registry/*
}
# create_ironic_accounts() - Set up common required ironic accounts
# Project User Roles
# ------------------------------------------------------------------
# service ironic admin
# service nova baremetal_admin
# demo demo baremetal_observer
function create_ironic_accounts {
if [[ "$ENABLED_SERVICES" =~ "ir-api" && "$ENABLED_SERVICES" =~ "key" ]]; then
# Define service and endpoints in Keystone
get_or_create_service "ironic" "baremetal" "Ironic baremetal provisioning service"
get_or_create_endpoint "baremetal" \
"$REGION_NAME" \
"$IRONIC_SERVICE_PROTOCOL://$IRONIC_HOSTPORT" \
"$IRONIC_SERVICE_PROTOCOL://$IRONIC_HOSTPORT" \
"$IRONIC_SERVICE_PROTOCOL://$IRONIC_HOSTPORT"
# Create ironic service user
# TODO(deva): make this work with the 'service' role
# https://bugs.launchpad.net/ironic/+bug/1605398
create_service_user "ironic" "admin"
# Create additional bare metal tenant and roles
get_or_create_role baremetal_admin
get_or_create_role baremetal_observer
if is_service_enabled nova; then
get_or_add_user_project_role baremetal_admin nova $SERVICE_PROJECT_NAME
fi
get_or_add_user_project_role baremetal_observer demo demo
fi
}
# init_ironic() - Initialize databases, etc.
function init_ironic {
if [[ "$HOST_TOPOLOGY_ROLE" != "subnode" ]]; then
# (Re)create ironic database
recreate_database ironic
# Migrate ironic database
$IRONIC_BIN_DIR/ironic-dbsync --config-file=$IRONIC_CONF_FILE
fi
create_ironic_cache_dir
}
# _ironic_bm_vm_names() - Generates list of names for baremetal VMs.
function _ironic_bm_vm_names {
local idx
local num_vms
num_vms=$(($IRONIC_VM_COUNT - 1))
for idx in $(seq 0 $num_vms); do
echo "$(get_ironic_node_prefix)-${idx}"
done
}
# start_ironic() - Start running processes, including screen
function start_ironic {
# Start Ironic API server, if enabled.
if is_service_enabled ir-api; then
start_ironic_api
fi
# Start Ironic conductor, if enabled.
if is_service_enabled ir-cond; then
start_ironic_conductor
fi
# Start Apache if iPXE is enabled
if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
restart_apache_server
fi
if is_service_enabled ir-vpdu; then
start_virtualpdu
fi
}
# start_ironic_api() - Used by start_ironic().
# Starts Ironic API server.
function start_ironic_api {
if [[ "$IRONIC_USE_MOD_WSGI" == "True" ]]; then
restart_apache_server
else
run_process ir-api "$IRONIC_BIN_DIR/ironic-api --config-file=$IRONIC_CONF_FILE"
fi
echo "Waiting for ir-api ($IRONIC_HOSTPORT) to start..."
if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget --no-proxy -q -O- $IRONIC_SERVICE_PROTOCOL://$IRONIC_HOSTPORT; do sleep 1; done"; then
die $LINENO "ir-api did not start"
fi
}
# start_ironic_conductor() - Used by start_ironic().
# Starts Ironic conductor.
function start_ironic_conductor {
run_process ir-cond "$IRONIC_BIN_DIR/ironic-conductor --config-file=$IRONIC_CONF_FILE"
# TODO(romcheg): Find a way to check whether the conductor has started.
}
# Starts VirtualPDU
function start_virtualpdu {
run_process ir-vpdu "virtualpdu $IRONIC_VPDU_CONFIG_FILE" libvirtd
}
# stop_ironic() - Stop running processes
function stop_ironic {
if [[ "$IRONIC_USE_MOD_WSGI" == "True" ]]; then
disable_apache_site ironic-api
else
stop_process ir-api
fi
stop_process ir-cond
}
# create_ovs_taps is also called by the devstack/upgrade/resources.sh script
#
# create_ovs_taps ironic_network_id
# NOTE(vsaienko) Ironic supports only Flat Neutron network.
# create_ovs_taps are needed in order to provide connectivity from ironic-conductor
# to VM. With Neutron Flat network it will be not needed.
function create_ovs_taps {
local ironic_net_id
ironic_net_id=$1
die_if_not_set $LINENO ironic_net_id "Failed to get ironic network id"
# Work around: No netns exists on host until a Neutron port is created. We
# need to create one in Neutron to know what netns to tap into prior to the
# first node booting.
local port_id
port_id=$(neutron port-create ${ironic_net_id} | grep " id " | get_field 2)
# NOTE(vsaienko) openstack port create was introduced in Newton.
# Since the function is used during upgrade, it should be backward compatible with Mitaka.
# Switch to openstack port create in Ocata release.
#port_id=$(openstack port create --network ${ironic_net_id} temp_port -c id -f value)
die_if_not_set $LINENO port_id "Failed to create neutron port"
# intentional sleep to make sure the tag has been set to port
sleep 10
local tapdev
tapdev=$(sudo ip netns exec qdhcp-${ironic_net_id} ip link list | grep " tap" | cut -d':' -f2 | cut -d'@' -f1 | cut -b2-)
die_if_not_set $LINENO tapdev "Failed to get tap device id"
local tag_id
tag_id=$(sudo ovs-vsctl get port ${tapdev} tag)
die_if_not_set $LINENO tag_id "Failed to get tag id"
local ovs_tap=ovs-tap
local brbm_tap=brbm-tap
# make sure veth pair is not existing, otherwise delete its links
sudo ip link show $ovs_tap && sudo ip link delete $ovs_tap
sudo ip link show $brbm_tap && sudo ip link delete $brbm_tap
# create veth pair for future interconnection between br-int and brbm
sudo ip link add $brbm_tap type veth peer name $ovs_tap
sudo ip link set dev $brbm_tap up
sudo ip link set dev $ovs_tap up
sudo ovs-vsctl -- --if-exists del-port $ovs_tap -- add-port br-int $ovs_tap tag=$tag_id
sudo ovs-vsctl -- --if-exists del-port $brbm_tap -- add-port $IRONIC_VM_NETWORK_BRIDGE $brbm_tap
# Remove the port needed only for workaround.
openstack port delete $port_id
# Finally, share the fixed tenant network across all tenants. This allows the host
# to serve TFTP to a single network namespace via the tap device created above.
openstack network set $ironic_net_id --share
}
function setup_qemu_log_hook {
# Make sure the libvirt hooks directory exist
sudo mkdir -p $IRONIC_LIBVIRT_HOOKS_PATH
# Copy the qemu hook to the right directory
sudo cp $IRONIC_DEVSTACK_FILES_DIR/hooks/qemu.py $IRONIC_LIBVIRT_HOOKS_PATH/qemu
sudo chmod -v +x $IRONIC_LIBVIRT_HOOKS_PATH/qemu
sudo sed -e "
s|%LOG_DIR%|$IRONIC_VM_LOG_DIR|g;
" -i $IRONIC_LIBVIRT_HOOKS_PATH/qemu
restart_libvirt
mkdir -p $IRONIC_VM_LOG_DIR
cat >${IRONIC_VM_LOG_DIR}/README << EOF
This directory contains the serial console log files from the virtual Ironic
bare-metal nodes. The *_console_* log files are the original log files and
include ANSI control codes which can make the output difficult to read. The
*_no_ansi_* log files have had ANSI control codes removed from the file and are
easier to read.
On some occasions there won't be a corresponding *_no_ansi_* log file, for
example if the job failed due to a time-out. You may see a log file without a
date/time in the file name. In that case you can display the logfile in your
console by doing:
$ curl URL_TO_LOGFILE
This will have your terminal process the ANSI escape codes.
Another option, if you have the 'pv' executable installed, is to simulate a
low-speed connection. In this example simulate a 300 Bytes/second connection.
$ curl URL_TO_LOGFILE | pv -q -L 300
This can allow you to see some of the content before the screen is cleared by
an ANSI escape sequence.
EOF
}
function create_bridge_and_vms {
# Call libvirt setup scripts in a new shell to ensure any new group membership
sudo su $STACK_USER -c "$IRONIC_SCRIPTS_DIR/setup-network.sh $IRONIC_VM_NETWORK_BRIDGE $PUBLIC_BRIDGE_MTU"
if [[ "$IRONIC_VM_LOG_CONSOLE" == "True" ]] ; then
local log_arg="-l $IRONIC_VM_LOG_DIR"
if [[ "$IRONIC_VM_LOG_ROTATE" == "True" ]] ; then
setup_qemu_log_hook
fi
else
local log_arg=""
fi
local vbmc_port=$IRONIC_VBMC_PORT_RANGE_START
local pdu_outlet=$IRONIC_VPDU_PORT_RANGE_START
local vm_name
local vm_opts=""
if [[ -n "$IRONIC_VM_EMULATOR" ]]; then
vm_opts+=" -e $IRONIC_VM_EMULATOR"
fi
vm_opts+=" -E $IRONIC_VM_ENGINE"
if [[ "$IRONIC_BOOT_MODE" == "uefi" ]]; then
vm_opts+=" -L $UEFI_LOADER_PATH -N $UEFI_NVRAM_PATH"
fi
for vm_name in $(_ironic_bm_vm_names); do
sudo -E su $STACK_USER -c "$IRONIC_SCRIPTS_DIR/create-node.sh -n $vm_name \
-c $IRONIC_VM_SPECS_CPU -m $IRONIC_VM_SPECS_RAM -d $IRONIC_VM_SPECS_DISK \
-a $IRONIC_VM_SPECS_CPU_ARCH -b $IRONIC_VM_NETWORK_BRIDGE $vm_opts \
-p $vbmc_port -o $pdu_outlet -f $IRONIC_VM_SPECS_DISK_FORMAT $log_arg" >> $IRONIC_VM_MACS_CSV_FILE
vbmc_port=$((vbmc_port+1))
pdu_outlet=$((pdu_outlet+1))
done
if [[ -z "${IRONIC_PROVISION_NETWORK_NAME}" ]]; then
local ironic_net_id
ironic_net_id=$(openstack network show "$PRIVATE_NETWORK_NAME" -c id -f value)
create_ovs_taps $ironic_net_id
# NOTE(vsaienko) Neutron no longer setup routing to private network.
# https://github.com/openstack-dev/devstack/commit/1493bdeba24674f6634160d51b8081c571df4017
# Add route here to have connection to VMs during provisioning.
local pub_router_id
local r_net_gateway
pub_router_id=$(openstack router show $Q_ROUTER_NAME -f value -c id)
r_net_gateway=$(sudo ip netns exec qrouter-$pub_router_id ip -4 route get 8.8.8.8 |grep dev | awk '{print $7}')
local replace_range=${SUBNETPOOL_PREFIX_V4}
if [[ -z "${SUBNETPOOL_V4_ID}" ]]; then
replace_range=${FIXED_RANGE}
fi
sudo ip route replace $replace_range via $r_net_gateway
fi
}
function wait_for_nova_resources {
# TODO(jroll) if IRONIC_USE_RESOURCE_CLASSES, use the placement engine instead
# After nodes have been enrolled, we need to wait for both ironic and
# nova's periodic tasks to populate the resource tracker with available
# nodes and resources. Wait up to 2 minutes for a given resource before
# timing out.
local resource=$1
local expected_count=$2
local i
echo_summary "Waiting 2 minutes for Nova resource tracker to pick up $resource >= $expected_count"
for i in $(seq 1 120); do
if [ $(openstack hypervisor stats show -f value -c $resource) -ge $expected_count ]; then
return 0
fi
sleep 1
done
die $LINENO "Timed out waiting for Nova hypervisor-stats $resource >= $expected_count"
}
function _clean_ncpu_failure {
SCREEN_NAME=${SCREEN_NAME:-stack}
SERVICE_DIR=${SERVICE_DIR:-${DEST}/status}
n_cpu_failure="$SERVICE_DIR/$SCREEN_NAME/n-cpu.failure"
if [ -f ${n_cpu_failure} ]; then
mv ${n_cpu_failure} "${n_cpu_failure}.before-restart-by-ironic"
fi
}
function enroll_nodes {
local chassis_id
chassis_id=$(ironic chassis-create -d "ironic test chassis" | grep " uuid " | get_field 2)
die_if_not_set $LINENO chassis_id "Failed to create chassis"
local node_prefix
node_prefix=$(get_ironic_node_prefix)
if [[ "$IRONIC_IS_HARDWARE" == "False" ]]; then
local ironic_node_cpu=$IRONIC_VM_SPECS_CPU
local ironic_node_ram=$IRONIC_VM_SPECS_RAM
local ironic_node_disk=$IRONIC_VM_SPECS_DISK
local ironic_ephemeral_disk=$IRONIC_VM_EPHEMERAL_DISK
local ironic_node_arch=x86_64
local ironic_hwinfo_file=$IRONIC_VM_MACS_CSV_FILE
if is_deployed_by_ipmitool; then
local node_options="\
-i ipmi_address=${HOST_IP} \
-i ipmi_username=admin \
-i ipmi_password=password"
elif is_deployed_by_snmp; then
local node_options="\
-i snmp_driver=${IRONIC_VPDU_SNMPDRIVER} \
-i snmp_address=${HOST_IP} \
-i snmp_port=${IRONIC_VPDU_LISTEN_PORT} \
-i snmp_protocol=2c \
-i snmp_community=${IRONIC_VPDU_COMMUNITY}"
else
local node_options="\
-i ssh_virt_type=$IRONIC_SSH_VIRT_TYPE \
-i ssh_address=$IRONIC_VM_SSH_ADDRESS \
-i ssh_port=$IRONIC_VM_SSH_PORT \
-i ssh_username=$IRONIC_SSH_USERNAME \
-i ssh_key_filename=$IRONIC_KEY_FILE"
fi
node_options="\
$node_options \
-i deploy_kernel=$IRONIC_DEPLOY_KERNEL_ID \
-i deploy_ramdisk=$IRONIC_DEPLOY_RAMDISK_ID"
else
local ironic_node_cpu=$IRONIC_HW_NODE_CPU
local ironic_node_ram=$IRONIC_HW_NODE_RAM
local ironic_node_disk=$IRONIC_HW_NODE_DISK
local ironic_ephemeral_disk=$IRONIC_HW_EPHEMERAL_DISK
local ironic_node_arch=$IRONIC_HW_ARCH
local ironic_hwinfo_file=$IRONIC_HWINFO_FILE
fi
local total_nodes=0
local total_cpus=0
while read hardware_info; do
local node_capabilities=""
if [[ "$IRONIC_BOOT_MODE" == "uefi" ]]; then
node_capabilities+=" -p capabilities=boot_mode:uefi"
fi
if [[ "$IRONIC_IS_HARDWARE" == "False" ]]; then
local mac_address
mac_address=$(echo $hardware_info | awk '{print $1}')
if is_deployed_by_ipmitool; then
local vbmc_port
vbmc_port=$(echo $hardware_info | awk '{print $2}')
node_options+=" -i ipmi_port=$vbmc_port"
elif is_deployed_by_snmp; then
local pdu_outlet
pdu_outlet=$(echo $hardware_info | awk '{print $3}')
node_options+=" -i snmp_outlet=$pdu_outlet"
fi
# Local-link-connection options
if [[ "${IRONIC_USE_LINK_LOCAL}" == "True" ]]; then
local llc_opts=""
local switch_info
local switch_id
local port_id
switch_info=$(echo $hardware_info |awk '{print $4}')
switch_id=$(echo $hardware_info |awk '{print $5}')
port_id=$(echo $hardware_info |awk '{print $6}')
llc_opts="-l switch_id=${switch_id} -l switch_info=${switch_info} -l port_id=${port_id}"
local ironic_api_version='--ironic-api-version latest'
fi
else
# Currently we require all hardware platform have same CPU/RAM/DISK info
# in future, this can be enhanced to support different type, and then
# we create the bare metal flavor with minimum value
local bmc_address
bmc_address=$(echo $hardware_info |awk '{print $1}')
local mac_address
mac_address=$(echo $hardware_info |awk '{print $2}')
local bmc_username
bmc_username=$(echo $hardware_info |awk '{print $3}')
local bmc_passwd
bmc_passwd=$(echo $hardware_info |awk '{print $4}')
local node_options="-i deploy_kernel=$IRONIC_DEPLOY_KERNEL_ID"
node_options+=" -i deploy_ramdisk=$IRONIC_DEPLOY_RAMDISK_ID"
if is_deployed_by_ipmitool; then
node_options+=" -i ipmi_address=$bmc_address -i ipmi_password=$bmc_passwd\
-i ipmi_username=$bmc_username"
elif is_deployed_by_cimc; then
node_options+=" -i cimc_address=$bmc_address -i cimc_password=$bmc_passwd\
-i cimc_username=$bmc_username"
elif is_deployed_by_ucs; then
local ucs_service_profile
ucs_service_profile=$(echo $hardware_info |awk '{print $5}')
node_options+=" -i ucs_address=$bmc_address -i ucs_password=$bmc_passwd\
-i ucs_username=$bmc_username -i ucs_service_profile=$ucs_service_profile"
elif is_deployed_by_oneview; then
local server_hardware_uri
server_hardware_uri=$(echo $hardware_info |awk '{print $1}')
local server_hardware_type_uri
server_hardware_type_uri=$(echo $hardware_info |awk '{print $2}')
local enclosure_group_uri
enclosure_group_uri=$(echo $hardware_info |awk '{print $3}')
local server_profile_template_uri
server_profile_template_uri=$(echo $hardware_info |awk '{print $4}')
mac_address=$(echo $hardware_info |awk '{print $5}')
local applied_server_profile_uri
applied_server_profile_uri=$(echo $hardware_info |awk '{print $6}')
local dynamic_allocation
dynamic_allocation=$(echo $hardware_info |awk '{print $7}')
dynamic_allocation=$(trueorfalse False dynamic_allocation)
node_options+=" -i server_hardware_uri=$server_hardware_uri"
if [[ -n "$applied_server_profile_uri" ]]; then
node_options+=" -i applied_server_profile_uri=$applied_server_profile_uri"
fi
if [[ "$dynamic_allocation" == "True" ]]; then
node_options+=" -i dynamic_allocation=$dynamic_allocation"
fi
if [[ "$node_capabilities" ]]; then
node_capabilities+=","
else
node_capabilities+=" -p capabilities="
fi
node_capabilities+="server_hardware_type_uri:$server_hardware_type_uri,"
node_capabilities+="enclosure_group_uri:$enclosure_group_uri,"
node_capabilities+="server_profile_template_uri:$server_profile_template_uri"
elif is_deployed_by_ilo; then
node_options+=" -i ilo_address=$bmc_address -i ilo_password=$bmc_passwd\
-i ilo_username=$bmc_username"
if [[ $IRONIC_DEPLOY_DRIVER != "pxe_ilo" ]]; then
node_options+=" -i ilo_deploy_iso=$IRONIC_DEPLOY_ISO_ID"
fi
elif is_deployed_by_drac; then
node_options+=" -i drac_host=$bmc_address -i drac_password=$bmc_passwd\
-i drac_username=$bmc_username"
fi
fi
# First node created will be used for testing in ironic w/o glance
# scenario, so we need to know its UUID.
local standalone_node_uuid=""
if [ $total_nodes -eq 0 ]; then
standalone_node_uuid="--uuid $IRONIC_NODE_UUID"
fi
local node_id
node_id=$(ironic \
node-create $standalone_node_uuid \
--chassis_uuid $chassis_id \
--driver $IRONIC_DEPLOY_DRIVER \
--name $node_prefix-$total_nodes \
-p cpus=$ironic_node_cpu\
-p memory_mb=$ironic_node_ram\
-p local_gb=$ironic_node_disk\
-p cpu_arch=$ironic_node_arch \
$node_capabilities \
$node_options \
| grep " uuid " | get_field 2)
# NOTE(vsaienko) IPA didn't automatically recognize root devices less than 4Gb.
# Setting root hint allows to install OS on such devices.
# 0x1af4 is VirtIO vendor device ID.
if [[ "$ironic_node_disk" -lt "4" && is_deployed_by_agent ]]; then
ironic node-update $node_id add properties/root_device='{"vendor": "0x1af4"}'
fi
# In case we using portgroups, we should API version that support them.
# Othervise API will return 406 ERROR
ironic $ironic_api_version port-create --address $mac_address --node $node_id $llc_opts
# NOTE(vsaienko) use node-update instead of specifying network_interface
# during node creation. If node is added with latest version of API it
# will NOT go to available state automatically.
if [[ -n "${IRONIC_NETWORK_INTERFACE}" ]]; then
local n_id
ironic node-set-maintenance $node_id true
n_id=$(ironic $ironic_api_version node-update $node_id add network_interface=$IRONIC_NETWORK_INTERFACE | grep " uuid " | awk '{ print $4; }')
die_if_not_set $LINENO n_id "Failed to update network interface for node"
ironic node-set-maintenance $node_id false
fi
local resource_class
if [[ "$IRONIC_USE_RESOURCE_CLASSES" == "True" ]]; then
# TODO(jroll) consider making this configurable, for now just make it unique per hardware combo
# this will look like baremetal_1cpu_256mbram_10gbdisk
resource_class="baremetal_${ironic_node_cpu}cpu_${ironic_node_ram}mbram_${ironic_node_disk}gbdisk"
openstack --os-baremetal-api-version 1.21 baremetal node set \
--resource-class $resource_class $node_id
fi
total_nodes=$((total_nodes+1))
total_cpus=$((total_cpus+$ironic_node_cpu))
done < $ironic_hwinfo_file
if is_service_enabled nova && [[ "$VIRT_DRIVER" == "ironic" ]]; then
if [[ "$HOST_TOPOLOGY_ROLE" != 'subnode' ]]; then
local adjusted_disk
adjusted_disk=$(($ironic_node_disk - $ironic_ephemeral_disk))
# TODO(jroll) use (yet to be defined) new-style flavor here,
# if IRONIC_USE_RESOURCE_CLASSES == True
openstack flavor create --ephemeral $ironic_ephemeral_disk --ram $ironic_node_ram --disk $adjusted_disk --vcpus $ironic_node_cpu baremetal
openstack flavor set baremetal --property "cpu_arch"="$ironic_node_arch"
if [[ "$IRONIC_BOOT_MODE" == "uefi" ]]; then
openstack flavor set baremetal --property "capabilities:boot_mode"="uefi"
fi
# NOTE(dtantsur): sometimes nova compute fails to start with ironic due
# to keystone restarting and not being able to authenticate us.
# Restart it just to be sure (and avoid gate problems like bug 1537076)
stop_nova_compute || /bin/true
# NOTE(pas-ha) if nova compute failed before restart, .failure file
# that was created will fail the service_check in the end of the deployment
_clean_ncpu_failure
start_nova_compute
else
# NOTE(vsaienko) we enrolling IRONIC_VM_COUNT on each node. So on subnode
# we expect to have 2 x total_cpus
total_nodes=$(( total_nodes * 2 ))
total_cpus=$(( total_cpus * 2 ))
fi
wait_for_nova_resources "count" $total_nodes
wait_for_nova_resources "vcpus" $total_cpus
fi
}
function die_if_module_not_loaded {
if ! grep -q $1 /proc/modules; then
die $LINENO "$1 kernel module is not loaded"
fi
}
function configure_iptables {
# enable tftp natting for allowing connections to HOST_IP's tftp server
if ! running_in_container; then
sudo modprobe nf_conntrack_tftp
sudo modprobe nf_nat_tftp
else
die_if_module_not_loaded nf_conntrack_tftp
die_if_module_not_loaded nf_nat_tftp
fi
# explicitly allow DHCP - packets are occasionally being dropped here
sudo iptables -I INPUT -p udp --dport 67:68 --sport 67:68 -j ACCEPT || true
# nodes boot from TFTP and callback to the API server listening on $HOST_IP
sudo iptables -I INPUT -d $IRONIC_TFTPSERVER_IP -p udp --dport 69 -j ACCEPT || true
sudo iptables -I INPUT -d $HOST_IP -p tcp --dport $IRONIC_SERVICE_PORT -j ACCEPT || true
if is_deployed_by_agent; then
# agent ramdisk gets instance image from swift
sudo iptables -I INPUT -d $HOST_IP -p tcp --dport ${SWIFT_DEFAULT_BIND_PORT:-8080} -j ACCEPT || true
sudo iptables -I INPUT -d $HOST_IP -p tcp --dport $GLANCE_SERVICE_PORT -j ACCEPT || true
fi
if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
sudo iptables -I INPUT -d $IRONIC_HTTP_SERVER -p tcp --dport $IRONIC_HTTP_PORT -j ACCEPT || true
fi
}
function configure_tftpd {
# stop tftpd and setup serving via xinetd
stop_service tftpd-hpa || true
[ -f /etc/init/tftpd-hpa.conf ] && echo "manual" | sudo tee /etc/init/tftpd-hpa.override
sudo cp $IRONIC_TEMPLATES_DIR/tftpd-xinetd.template /etc/xinetd.d/tftp
sudo sed -e "s|%TFTPBOOT_DIR%|$IRONIC_TFTPBOOT_DIR|g" -i /etc/xinetd.d/tftp
# setup tftp file mapping to satisfy requests at the root (booting) and
# /tftpboot/ sub-dir (as per deploy-ironic elements)
echo "r ^([^/]) $IRONIC_TFTPBOOT_DIR/\1" >$IRONIC_TFTPBOOT_DIR/map-file
echo "r ^(/tftpboot/) $IRONIC_TFTPBOOT_DIR/\2" >>$IRONIC_TFTPBOOT_DIR/map-file
chmod -R 0755 $IRONIC_TFTPBOOT_DIR
restart_service xinetd
}
function configure_ironic_ssh_keypair {
if [[ ! -d $HOME/.ssh ]]; then
mkdir -p $HOME/.ssh
chmod 700 $HOME/.ssh
fi
# recreate ssh if any part is missing
if [[ ! -e $IRONIC_KEY_FILE ]] || [[ ! -e $IRONIC_KEY_FILE.pub ]]; then
if [[ ! -d $(dirname $IRONIC_KEY_FILE) ]]; then
mkdir -p $(dirname $IRONIC_KEY_FILE)
fi
echo -e 'n\n' | ssh-keygen -q -t rsa -P '' -f $IRONIC_KEY_FILE
fi
# NOTE(vsaienko) check for new line character, add if doesn't exist.
if [[ "$(tail -c1 $IRONIC_AUTHORIZED_KEYS_FILE | wc -l)" == "0" ]]; then
echo "" >> $IRONIC_AUTHORIZED_KEYS_FILE
fi
cat $IRONIC_KEY_FILE.pub | tee -a $IRONIC_AUTHORIZED_KEYS_FILE
# remove duplicate keys.
sort -u -o $IRONIC_AUTHORIZED_KEYS_FILE $IRONIC_AUTHORIZED_KEYS_FILE
}
function ironic_ssh_check {
local key_file=$1
local floating_ip=$2
local port=$3
local default_instance_user=$4
local attempt=$5
local status=false
local ssh_options="-o BatchMode=yes -o ConnectTimeout=$IRONIC_SSH_TIMEOUT -o StrictHostKeyChecking=no"
while [[ $attempt -gt 0 ]]; do
ssh -p $port $ssh_options -i $key_file ${default_instance_user}@$floating_ip exit
if [[ "$?" == "0" ]]; then
status=true
break
fi
attempt=$((attempt - 1))
echo "SSH connection failed. $attempt attempts left."
done
if ! $status; then
die $LINENO "server didn't become ssh-able!"
fi
}
function configure_ironic_auxiliary {
configure_ironic_ssh_keypair
ironic_ssh_check $IRONIC_KEY_FILE $IRONIC_VM_SSH_ADDRESS $IRONIC_VM_SSH_PORT $IRONIC_SSH_USERNAME $IRONIC_SSH_ATTEMPTS
}
function build_ipa_ramdisk {
local kernel_path=$1
local ramdisk_path=$2
local iso_path=$3
case $IRONIC_RAMDISK_TYPE in
'coreos')
build_ipa_coreos_ramdisk $kernel_path $ramdisk_path $iso_path
;;
'tinyipa')
build_tinyipa_ramdisk $kernel_path $ramdisk_path $iso_path
;;
'dib')
build_ipa_dib_ramdisk $kernel_path $ramdisk_path $iso_path
;;
*)
die $LINENO "Unrecognised IRONIC_RAMDISK_TYPE: $IRONIC_RAMDISK_TYPE. Expected either of 'dib', 'coreos', or 'tinyipa'."
;;
esac
}
function build_ipa_coreos_ramdisk {
echo "Building coreos ironic-python-agent deploy ramdisk"
local kernel_path=$1
local ramdisk_path=$2
local iso_path=$3
# on fedora services do not start by default
restart_service docker
git_clone $IRONIC_PYTHON_AGENT_REPO $IRONIC_PYTHON_AGENT_DIR $IRONIC_PYTHON_AGENT_BRANCH
cd $IRONIC_PYTHON_AGENT_DIR
imagebuild/coreos/build_coreos_image.sh
cp imagebuild/coreos/UPLOAD/coreos_production_pxe_image-oem.cpio.gz $ramdisk_path
cp imagebuild/coreos/UPLOAD/coreos_production_pxe.vmlinuz $kernel_path
if is_deploy_iso_required; then
imagebuild/coreos/iso-image-create -k $kernel_path -i $ramdisk_path -o $iso_path
fi
sudo rm -rf UPLOAD
cd -
}
function build_tinyipa_ramdisk {
echo "Building ironic-python-agent deploy ramdisk"
local kernel_path=$1
local ramdisk_path=$2
local iso_path=$3
git_clone $IRONIC_PYTHON_AGENT_REPO $IRONIC_PYTHON_AGENT_DIR $IRONIC_PYTHON_AGENT_BRANCH
cd $IRONIC_PYTHON_AGENT_DIR/imagebuild/tinyipa
export BUILD_AND_INSTALL_TINYIPA=true
make
cp tinyipa.gz $ramdisk_path
cp tinyipa.vmlinuz $kernel_path
if is_deploy_iso_required; then
make iso
cp tinyipa.iso $iso_path
fi
make clean
cd -
}
# install_diskimage_builder() - Collect source and prepare or install from pip
function install_diskimage_builder {
if use_library_from_git "diskimage-builder"; then
git_clone_by_name "diskimage-builder"
setup_dev_lib "diskimage-builder"
else
pip_install_gr "diskimage-builder"
fi
}
function build_ipa_dib_ramdisk {
local kernel_path=$1
local ramdisk_path=$2
local iso_path=$3
local tempdir
tempdir=$(mktemp -d --tmpdir=${DEST})
# install diskimage-builder if not present
if ! $(type -P disk-image-create > /dev/null); then
install_diskimage_builder
fi
echo "Building IPA ramdisk with DIB options: $IRONIC_DIB_RAMDISK_OPTIONS"
if is_deploy_iso_required; then
IRONIC_DIB_RAMDISK_OPTIONS+=" iso"
fi
disk-image-create "$IRONIC_DIB_RAMDISK_OPTIONS" \
-o "$tempdir/ironic-agent" \
ironic-agent
chmod -R +r $tempdir
mv "$tempdir/ironic-agent.kernel" "$kernel_path"
mv "$tempdir/ironic-agent.initramfs" "$ramdisk_path"
if is_deploy_iso_required; then
mv "$tempdir/ironic-agent.iso" "$iso_path"
fi
rm -rf $tempdir
}
# build deploy kernel+ramdisk, then upload them to glance
# this function sets ``IRONIC_DEPLOY_KERNEL_ID``, ``IRONIC_DEPLOY_RAMDISK_ID``
function upload_baremetal_ironic_deploy {
declare -g IRONIC_DEPLOY_KERNEL_ID IRONIC_DEPLOY_RAMDISK_ID
local ironic_deploy_kernel_name
local ironic_deploy_ramdisk_name
ironic_deploy_kernel_name=$(basename $IRONIC_DEPLOY_KERNEL)
ironic_deploy_ramdisk_name=$(basename $IRONIC_DEPLOY_RAMDISK)
if [[ "$HOST_TOPOLOGY_ROLE" != 'subnode' ]]; then
echo_summary "Creating and uploading baremetal images for ironic"
if [ ! -e "$IRONIC_DEPLOY_RAMDISK" ] || \
[ ! -e "$IRONIC_DEPLOY_KERNEL" ] || \
( is_deploy_iso_required && [ ! -e "$IRONIC_DEPLOY_ISO" ] ); then
# files don't exist, need to build them
if [ "$IRONIC_BUILD_DEPLOY_RAMDISK" = "True" ]; then
# we can build them only if we're not offline
if [ "$OFFLINE" != "True" ]; then
build_ipa_ramdisk $IRONIC_DEPLOY_KERNEL $IRONIC_DEPLOY_RAMDISK $IRONIC_DEPLOY_ISO
else
die $LINENO "Deploy kernel+ramdisk or iso files don't exist and cannot be built in OFFLINE mode"
fi
else
# download the agent image tarball
wget "$IRONIC_AGENT_KERNEL_URL" -O $IRONIC_DEPLOY_KERNEL
wget "$IRONIC_AGENT_RAMDISK_URL" -O $IRONIC_DEPLOY_RAMDISK
fi
fi
# load them into glance
if ! is_deploy_iso_required; then
IRONIC_DEPLOY_KERNEL_ID=$(openstack \
image create \
$ironic_deploy_kernel_name \
--public --disk-format=aki \
--container-format=aki \
< $IRONIC_DEPLOY_KERNEL | grep ' id ' | get_field 2)
die_if_not_set $LINENO IRONIC_DEPLOY_KERNEL_ID "Failed to load kernel image into glance"
IRONIC_DEPLOY_RAMDISK_ID=$(openstack \
image create \
$ironic_deploy_ramdisk_name \
--public --disk-format=ari \
--container-format=ari \
< $IRONIC_DEPLOY_RAMDISK | grep ' id ' | get_field 2)
die_if_not_set $LINENO IRONIC_DEPLOY_RAMDISK_ID "Failed to load ramdisk image into glance"
else
IRONIC_DEPLOY_ISO_ID=$(openstack \
image create \
$(basename $IRONIC_DEPLOY_ISO) \
--public --disk-format=iso \
--container-format=bare \
< $IRONIC_DEPLOY_ISO -f value -c id)
die_if_not_set $LINENO IRONIC_DEPLOY_ISO_ID "Failed to load deploy iso into glance"
fi
else
IRONIC_DEPLOY_KERNEL_ID=$(openstack image show $ironic_deploy_kernel_name -f value -c id)
IRONIC_DEPLOY_RAMDISK_ID=$(openstack image show $ironic_deploy_ramdisk_name -f value -c id)
fi
}
function prepare_baremetal_basic_ops {
if [[ "$IRONIC_BAREMETAL_BASIC_OPS" != "True" ]]; then
return 0
fi
if [[ "$IRONIC_IS_HARDWARE" == "False" ]]; then
configure_ironic_auxiliary
fi
if ! is_service_enabled nova && [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
sudo install -g $LIBVIRT_GROUP -o $STACK_USER -m 644 $FILES/${IRONIC_WHOLEDISK_IMAGE_NAME}.img $IRONIC_HTTP_DIR
fi
upload_baremetal_ironic_deploy
enroll_nodes
configure_tftpd
configure_iptables
}
function cleanup_baremetal_basic_ops {
if [[ "$IRONIC_BAREMETAL_BASIC_OPS" != "True" ]]; then
return 0
fi
rm -f $IRONIC_VM_MACS_CSV_FILE
if [ -f $IRONIC_KEY_FILE ]; then
local key
key=$(cat $IRONIC_KEY_FILE.pub)
# remove public key from authorized_keys
grep -v "$key" $IRONIC_AUTHORIZED_KEYS_FILE > temp && mv temp $IRONIC_AUTHORIZED_KEYS_FILE
chmod 0600 $IRONIC_AUTHORIZED_KEYS_FILE
fi
sudo rm -rf $IRONIC_DATA_DIR $IRONIC_STATE_PATH
local vm_name
for vm_name in $(_ironic_bm_vm_names); do
sudo su $STACK_USER -c "$IRONIC_SCRIPTS_DIR/cleanup-node.sh $vm_name"
# Cleanup node bridge/interfaces
sudo ip link set ovs-$vm_name down
sudo ip link set br-$vm_name down
sudo ovs-vsctl del-port ovs-$vm_name
sudo ip link del dev ovs-$vm_name
sudo ip link del dev br-$vm_name
done
sudo ovs-vsctl --if-exists del-br $IRONIC_VM_NETWORK_BRIDGE
sudo rm -rf /etc/xinetd.d/tftp /etc/init/tftpd-hpa.override
restart_service xinetd
sudo iptables -D INPUT -d $HOST_IP -p udp --dport 69 -j ACCEPT || true
sudo iptables -D INPUT -d $HOST_IP -p tcp --dport $IRONIC_SERVICE_PORT -j ACCEPT || true
if is_deployed_by_agent; then
# agent ramdisk gets instance image from swift
sudo iptables -D INPUT -d $HOST_IP -p tcp --dport ${SWIFT_DEFAULT_BIND_PORT:-8080} -j ACCEPT || true
fi
sudo rmmod nf_conntrack_tftp || true
sudo rmmod nf_nat_tftp || true
}
function ironic_configure_tempest {
iniset $TEMPEST_CONFIG service_available ironic True
if [[ -n "$TEMPEST_BAREMETAL_MIN_MICROVERSION" ]]; then
iniset $TEMPEST_CONFIG baremetal min_microversion $TEMPEST_BAREMETAL_MIN_MICROVERSION
fi
if [[ -n "$TEMPEST_BAREMETAL_MAX_MICROVERSION" ]]; then
iniset $TEMPEST_CONFIG baremetal max_microversion $TEMPEST_BAREMETAL_MAX_MICROVERSION
fi
if is_service_enabled nova; then
local bm_flavor_id
bm_flavor_id=$(openstack flavor show baremetal -f value -c id)
die_if_not_set $LINENO bm_flavor_id "Failed to get id of baremetal flavor"
iniset $TEMPEST_CONFIG compute flavor_ref $bm_flavor_id
iniset $TEMPEST_CONFIG compute flavor_ref_alt $bm_flavor_id
iniset $TEMPEST_CONFIG compute-feature-enabled disk_config False
fi
# NOTE(jlvillal): If IRONIC_PROVISION_NETWORK_NAME is set it means that
# nodes are using the neutron network driver / multi-tenant networking.
# Otherwise we are using a flat-network.
if [[ -n "${IRONIC_PROVISION_NETWORK_NAME}" ]]; then
# multi-tenant networking
iniset $TEMPEST_CONFIG baremetal use_provision_network True
else
# flat-network
iniset $TEMPEST_CONFIG compute fixed_network_name $PRIVATE_NETWORK_NAME
# NOTE(jroll) this disables multitenant network tests from tempest's
# tree, but not from our tree. This is a bit inconsistent, we should
# fix it.
iniset $TEMPEST_CONFIG auth create_isolated_networks False
iniset $TEMPEST_CONFIG network shared_physical_network True
fi
local image_uuid
image_uuid=$(openstack image show $IRONIC_IMAGE_NAME -f value -c id)
iniset $TEMPEST_CONFIG compute image_ref $image_uuid
iniset $TEMPEST_CONFIG compute image_ref_alt $image_uuid
image_uuid=$(openstack image show $IRONIC_WHOLEDISK_IMAGE_NAME -f value -c id)
iniset $TEMPEST_CONFIG baremetal whole_disk_image_ref $image_uuid
image_uuid=$(openstack image show $IRONIC_PARTITIONED_IMAGE_NAME -f value -c id)
iniset $TEMPEST_CONFIG baremetal partition_image_ref $image_uuid
if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
iniset $TEMPEST_CONFIG baremetal whole_disk_image_url "http://$IRONIC_HTTP_SERVER:$IRONIC_HTTP_PORT/${IRONIC_WHOLEDISK_IMAGE_NAME}.img"
iniset $TEMPEST_CONFIG baremetal whole_disk_image_checksum $(md5sum $FILES/${IRONIC_WHOLEDISK_IMAGE_NAME}.img)
fi
iniset $TEMPEST_CONFIG baremetal enabled_drivers $IRONIC_ENABLED_DRIVERS
iniset $TEMPEST_CONFIG baremetal enabled_hardware_types $IRONIC_ENABLED_HARDWARE_TYPES
local adjusted_root_disk_size_gb
if [[ "$IRONIC_IS_HARDWARE" == "False" ]]; then
adjusted_root_disk_size_gb=$(( ${IRONIC_VM_SPECS_DISK} - ${IRONIC_VM_EPHEMERAL_DISK} ))
else
adjusted_root_disk_size_gb=$(( ${IRONIC_HW_NODE_DISK} - ${IRONIC_HW_EPHEMERAL_DISK} ))
fi
iniset $TEMPEST_CONFIG baremetal adjusted_root_disk_size_gb $adjusted_root_disk_size_gb
if [[ -n "${IRONIC_TEMPEST_BUILD_TIMEOUT}" ]]; then
iniset $TEMPEST_CONFIG baremetal unprovision_timeout $IRONIC_TEMPEST_BUILD_TIMEOUT
iniset $TEMPEST_CONFIG baremetal active_timeout $IRONIC_TEMPEST_BUILD_TIMEOUT
iniset $TEMPEST_CONFIG baremetal deploywait_timeout $IRONIC_TEMPEST_BUILD_TIMEOUT
iniset $TEMPEST_CONFIG baremetal power_timeout $IRONIC_TEMPEST_BUILD_TIMEOUT
fi
# Enabled features
iniset $TEMPEST_CONFIG baremetal_feature_enabled ipxe_enabled $IRONIC_IPXE_ENABLED
}
function get_ironic_node_prefix {
local node_prefix="node"
if [[ "$HOST_TOPOLOGY_ROLE" == "subnode" ]]; then
node_prefix="$HOST_TOPOLOGY_ROLE"
fi
echo $node_prefix
}
function setup_vxlan_network {
sudo ovs-vsctl add-port $IRONIC_VM_NETWORK_BRIDGE phy-brbm-vxlan
sudo ovs-vsctl add-port br_ironic_vxlan phy-vxlan-brbm
sudo ovs-vsctl set interface phy-brbm-vxlan type=patch
sudo ovs-vsctl set interface phy-vxlan-brbm type=patch
sudo ovs-vsctl set interface phy-vxlan-brbm options:peer=phy-brbm-vxlan
sudo ovs-vsctl set interface phy-brbm-vxlan options:peer=phy-vxlan-brbm
}
# Restore xtrace + pipefail
$_XTRACE_IRONIC
$_PIPEFAIL_IRONIC
# Tell emacs to use shell-script-mode
## Local variables:
## mode: shell-script
## End: