Files
ironic/devstack/lib/ironic
Jim Rollenhagen 8ad0a424b3 Move CONF.service_available.ironic to our plugin
This is unwanted in tempest's plugin, bring it here instead.

Also add skip checks for our tests to skip the tests if ironic is not
enabled. This allows the plugin to be installed in a tempest
environment, without breaking if ironic isn't present.

Last, drop 'baremetal' from the test.services decorators used, as it is
no longer in tempest's service list, and we use the skip check mentioned
above instead.

Change-Id: I0b7e32dfad2ed63f9dd4d7cad130da39bc869a8a
Depends-On: Idede322190d57491d4f7e18090aa8c29b5b87353
2016-12-12 14:39:32 -08:00

1659 lines
67 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
# Save trace 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
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
# 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:
# <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_IPMIINFO_FILE is deprecated, please use IRONIC_HWINFO_FILE. IRONIC_IPMIINFO_FILE will be removed in Ocata.
IRONIC_IPMIINFO_FILE=${IRONIC_IPMIINFO_FILE:-""}
if [ ! -z "$IRONIC_IPMIINFO_FILE" ]; then
deprecated "IRONIC_IPMIINFO_FILE is deprecated, please switch to IRONIC_HWINFO_FILE. IRONIC_IPMIINFO_FILE will be removed in Ocata."
fi
IRONIC_HWINFO_FILE=${IRONIC_HWINFO_FILE:-${IRONIC_IPMIINFO_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_ENABLED_DRIVERS=${IRONIC_ENABLED_DRIVERS:-fake,pxe_ssh,pxe_ipmitool}
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:-}
IRONIC_VM_ENGINE=${IRONIC_VM_ENGINE:-}
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}
# NOTE(vsaienko) nova already pick right libvirt type at
# https://review.openstack.org/#/c/31177/4/lib/nova@240
# pick hardware virtualization if possible while it is not set explicitly
if [[ -z "$IRONIC_VM_ENGINE" ]]; 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
# 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)
# 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:-}
IRONIC_DEPLOY_KERNEL=${IRONIC_DEPLOY_KERNEL:-}
IRONIC_DEPLOY_ISO=${IRONIC_DEPLOY_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)
if [[ "$IRONIC_TEMPEST_WHOLE_DISK_IMAGE" == "True" ]]; then
IRONIC_IMAGE_NAME=${IRONIC_IMAGE_NAME:-cirros-${CIRROS_VERSION}-x86_64-disk}
else
IRONIC_IMAGE_NAME=${IRONIC_IMAGE_NAME:-cirros-${CIRROS_VERSION}-x86_64-uec}
fi
# 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`` and ``agent_ipmitool``.
#
# 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_ssh}
# 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}
# 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)
# 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}
# 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)
# Functions
# ---------
# 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 {
[[ -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_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
}
# 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 "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
}
# 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 [[ "$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_IPXE_ENABLED" == "True" ]] ; then
install_apache_wsgi
fi
if is_deployed_by_ipmitool && [[ "$IRONIC_IS_HARDWARE" == "False" ]]; then
setup_virtualbmc
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
disable_apache_site ironic
sudo rm -f $(apache_site_config_for ironic)
restart_apache_server
}
# _config_ironic_apache_wsgi() - Set WSGI config files of Ironic
function _config_ironic_apache_wsgi {
local ironic_apache_conf
ironic_apache_conf=$(apache_site_config_for ironic)
sudo cp $IRONIC_DEVSTACK_FILES_DIR/apache-ironic.template $ironic_apache_conf
sudo sed -e "
s|%PUBLICPORT%|$IRONIC_HTTP_PORT|g;
s|%HTTPROOT%|$IRONIC_HTTP_DIR|g;
" -i $ironic_apache_conf
enable_apache_site ironic
}
# 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
if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
_cleanup_ironic_apache_wsgi
fi
# 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
# 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
sudo 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 {
local cleaning_network_uuid
cleaning_network_uuid=$(openstack network show "$IRONIC_CLEAN_NET_NAME" -c id -f value)
die_if_not_set $LINENO cleaning_network_uuid "Failed to get ironic cleaning network id"
iniset $IRONIC_CONF_FILE neutron cleaning_network_uuid ${cleaning_network_uuid}
}
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.$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_uuid $net_id
}
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
if [[ "$IRONIC_IPXE_ENABLED" == "True" ]]; then
_config_ironic_apache_wsgi
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
iniset $IRONIC_CONF_FILE DEFAULT rootwrap_config $IRONIC_ROOTWRAP_CONF
iniset $IRONIC_CONF_FILE DEFAULT enabled_drivers $IRONIC_ENABLED_DRIVERS
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 ipa-debug=1"
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`
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 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
# 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
}
# start_ironic_api() - Used by start_ironic().
# Starts Ironic API server.
function start_ironic_api {
run_process ir-api "$IRONIC_BIN_DIR/ironic-api --config-file=$IRONIC_CONF_FILE"
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.
}
# stop_ironic() - Stop running processes
function stop_ironic {
stop_process ir-api
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 {
local libvirt_service_name
# 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 $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 the libvirt daemon
libvirt_service_name="libvirt-bin"
if is_fedora; then
libvirt_service_name="libvirtd"
fi
restart_service $libvirt_service_name
}
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 vm_name
local vm_opts=""
if [[ -n "$IRONIC_VM_EMULATOR" ]]; then
vm_opts+=" -e $IRONIC_VM_EMULATOR"
fi
vm_opts+=" -E $IRONIC_VM_ENGINE"
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 -f $IRONIC_VM_SPECS_DISK_FORMAT $log_arg" >> $IRONIC_VM_MACS_CSV_FILE
vbmc_port=$((vbmc_port+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 {
# 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=127.0.0.1 \
-i ipmi_username=admin \
-i ipmi_password=password"
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
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"
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 $3}')
switch_id=$(echo $hardware_info |awk '{print $4}')
port_id=$(echo $hardware_info |awk '{print $5}')
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
node_options+=" -p capabilities="
node_options+="server_hardware_type_uri:$server_hardware_type_uri,"
node_options+="enclosure_group_uri:$enclosure_group_uri,"
node_options+="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 -ne "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_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
total_nodes=$((total_nodes+1))
total_cpus=$((total_cpus+$ironic_node_cpu))
done < $ironic_hwinfo_file
if [[ "$HOST_TOPOLOGY_ROLE" != 'subnode' ]]; then
if [ "$VIRT_DRIVER" == "ironic" ]; then
local adjusted_disk
adjusted_disk=$(($ironic_node_disk - $ironic_ephemeral_disk))
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"
# 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
wait_for_nova_resources "count" $total_nodes
wait_for_nova_resources "vcpus" $total_cpus
fi
fi
}
function configure_iptables {
# enable tftp natting for allowing connections to HOST_IP's tftp server
sudo modprobe nf_conntrack_tftp
sudo modprobe nf_nat_tftp
# 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
if [ -z "$IRONIC_DEPLOY_KERNEL" -o -z "$IRONIC_DEPLOY_RAMDISK" -o -z "$IRONIC_DEPLOY_ISO" ]; then
local IRONIC_DEPLOY_KERNEL_PATH=$TOP_DIR/files/ir-deploy-$IRONIC_DEPLOY_DRIVER.kernel
local IRONIC_DEPLOY_RAMDISK_PATH=$TOP_DIR/files/ir-deploy-$IRONIC_DEPLOY_DRIVER.initramfs
local IRONIC_DEPLOY_ISO_PATH=$TOP_DIR/files/ir-deploy-$IRONIC_DEPLOY_DRIVER.iso
else
local IRONIC_DEPLOY_KERNEL_PATH=$IRONIC_DEPLOY_KERNEL
local IRONIC_DEPLOY_RAMDISK_PATH=$IRONIC_DEPLOY_RAMDISK
local IRONIC_DEPLOY_ISO_PATH=$IRONIC_DEPLOY_ISO
fi
local ironic_deploy_kernel_name
local ironic_deploy_ramdisk_name
ironic_deploy_kernel_name=$(basename $IRONIC_DEPLOY_KERNEL_PATH)
ironic_deploy_ramdisk_name=$(basename $IRONIC_DEPLOY_RAMDISK_PATH)
if [[ "$HOST_TOPOLOGY_ROLE" != 'subnode' ]]; then
echo_summary "Creating and uploading baremetal images for ironic"
if [ ! -e "$IRONIC_DEPLOY_RAMDISK_PATH" ] || \
[ ! -e "$IRONIC_DEPLOY_KERNEL_PATH" ] || \
( is_deploy_iso_required && [ ! -e "$IRONIC_DEPLOY_ISO_PATH" ] ); 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_PATH $IRONIC_DEPLOY_RAMDISK_PATH $IRONIC_DEPLOY_ISO_PATH
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_PATH
wget "$IRONIC_AGENT_RAMDISK_URL" -O $IRONIC_DEPLOY_RAMDISK_PATH
fi
fi
# load them into glance
IRONIC_DEPLOY_KERNEL_ID=$(openstack \
image create \
$ironic_deploy_kernel_name \
--public --disk-format=aki \
--container-format=aki \
< $IRONIC_DEPLOY_KERNEL_PATH | 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_PATH | grep ' id ' | get_field 2)
die_if_not_set $LINENO IRONIC_DEPLOY_RAMDISK_ID "Failed to load ramdisk image into glance"
if is_deploy_iso_required; then
IRONIC_DEPLOY_ISO_ID=$(openstack \
image create \
$(basename $IRONIC_DEPLOY_ISO_PATH) \
--public --disk-format=iso \
--container-format=bare \
< $IRONIC_DEPLOY_ISO_PATH -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
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
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
if [[ -n "${IRONIC_PROVISION_NETWORK_NAME}" ]]; then
iniset $TEMPEST_CONFIG baremetal use_provision_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
iniset $TEMPEST_CONFIG auth create_isolated_networks False
# 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 network shared_physical_network True
}
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: