#!/usr/bin/env bash IRONIC_INSPECTOR_DEBUG=${IRONIC_INSPECTOR_DEBUG:-True} IRONIC_INSPECTOR_DIR=$DEST/ironic-inspector IRONIC_INSPECTOR_DATA_DIR=$DATA_DIR/ironic-inspector IRONIC_INSPECTOR_BIN_DIR=$(get_python_exec_prefix) IRONIC_INSPECTOR_BIN_FILE=$IRONIC_INSPECTOR_BIN_DIR/ironic-inspector IRONIC_INSPECTOR_BIN_FILE_API=$IRONIC_INSPECTOR_BIN_DIR/ironic-inspector-api-wsgi IRONIC_INSPECTOR_BIN_FILE_CONDUCTOR=$IRONIC_INSPECTOR_BIN_DIR/ironic-inspector-conductor IRONIC_INSPECTOR_DBSYNC_BIN_FILE=$IRONIC_INSPECTOR_BIN_DIR/ironic-inspector-dbsync IRONIC_INSPECTOR_CONF_DIR=${IRONIC_INSPECTOR_CONF_DIR:-/etc/ironic-inspector} IRONIC_INSPECTOR_CONF_FILE=$IRONIC_INSPECTOR_CONF_DIR/inspector.conf IRONIC_INSPECTOR_CMD="$IRONIC_INSPECTOR_BIN_FILE --config-file $IRONIC_INSPECTOR_CONF_FILE" IRONIC_INSPECTOR_CMD_CONDUCTOR="$IRONIC_INSPECTOR_BIN_FILE_CONDUCTOR --config-file $IRONIC_INSPECTOR_CONF_FILE" IRONIC_INSPECTOR_DHCP_CONF_FILE=$IRONIC_INSPECTOR_CONF_DIR/dnsmasq.conf IRONIC_INSPECTOR_ROOTWRAP_CONF_FILE=$IRONIC_INSPECTOR_CONF_DIR/rootwrap.conf IRONIC_INSPECTOR_ADMIN_USER=${IRONIC_INSPECTOR_ADMIN_USER:-ironic-inspector} IRONIC_INSPECTOR_AUTH_CACHE_DIR=${IRONIC_INSPECTOR_AUTH_CACHE_DIR:-/var/cache/ironic-inspector} IRONIC_INSPECTOR_DHCP_FILTER=${IRONIC_INSPECTOR_DHCP_FILTER:-iptables} IRONIC_INSPECTOR_STANDALONE=${IRONIC_INSPECTOR_STANDALONE:-True} # Support entry points installation of console scripts IRONIC_INSPECTOR_UWSGI=$IRONIC_INSPECTOR_BIN_DIR/ironic-inspector-api-wsgi IRONIC_INSPECTOR_UWSGI_CONF=$IRONIC_INSPECTOR_CONF_DIR/ironic-inspector-uwsgi.ini # Determine if ironic is in enforce scope node, infer that to mean our operating mode # explicitly unless otherwise set. IRONIC_INSPECTOR_ENFORCE_SCOPE=${IRONIC_INSPECTOR_ENFORCE_SCOPE:-${IRONIC_ENFORCE_SCOPE:-False}} # and then fallback to trueorfalse to put it into the standardized string format for the jobs. IRONIC_INSPECTOR_ENFORCE_SCOPE=$(trueorfalse False IRONIC_INSPECTOR_ENFORCE_SCOPE) # Reset the input in the event the plugin is running separately from ironic's # devstack plugin. IRONIC_ENFORCE_SCOPE=$(trueorfalse False IRONIC_ENFORCE_SCOPE) if [[ -n ${IRONIC_INSPECTOR_MANAGE_FIREWALL} ]] ; then echo "IRONIC_INSPECTOR_MANAGE_FIREWALL is deprecated." >&2 echo "Please, use IRONIC_INSPECTOR_DHCP_FILTER == noop/iptables/dnsmasq instead." >&2 if [[ "$IRONIC_INSPECTOR_DHCP_FILTER" != "iptables" ]] ; then # both manage firewall and filter driver set together but driver isn't iptables echo "Inconsistent configuration: IRONIC_INSPECTOR_MANAGE_FIREWALL used while" >&2 echo "IRONIC_INSPECTOR_DHCP_FILTER == $IRONIC_INSPECTOR_DHCP_FILTER" >&2 exit 1 fi if [[ $(trueorfalse True IRONIC_INSPECTOR_MANAGE_FIREWALL) == "False" ]] ; then echo "IRONIC_INSPECTOR_MANAGE_FIREWALL == False" >&2 echo "Setting IRONIC_INSPECTOR_DHCP_FILTER=noop" >&2 IRONIC_INSPECTOR_DHCP_FILTER=noop fi fi # dnsmasq dhcp filter configuration # override the default hostsdir so devstack collects the MAC files (/etc) IRONIC_INSPECTOR_DHCP_HOSTSDIR=${IRONIC_INSPECTOR_DHCP_HOSTSDIR:-/etc/ironic-inspector/dhcp-hostsdir} IRONIC_INSPECTOR_DNSMASQ_STOP_COMMAND=${IRONIC_INSPECTOR_DNSMASQ_STOP_COMMAND:-systemctl stop devstack@ironic-inspector-dhcp} IRONIC_INSPECTOR_DNSMASQ_START_COMMAND=${IRONIC_INSPECTOR_DNSMASQ_START_COMMAND:-systemctl start devstack@ironic-inspector-dhcp} IRONIC_INSPECTOR_HOST=$SERVICE_HOST IRONIC_INSPECTOR_PORT=5050 if [[ "$IRONIC_INSPECTOR_STANDALONE" == "False" ]]; then IRONIC_INSPECTOR_URI="http://$IRONIC_INSPECTOR_HOST/baremetal-introspection" else IRONIC_INSPECTOR_URI="http://$IRONIC_INSPECTOR_HOST:$IRONIC_INSPECTOR_PORT" fi IRONIC_INSPECTOR_BUILD_RAMDISK=$(trueorfalse False IRONIC_INSPECTOR_BUILD_RAMDISK) IRONIC_RAMDISK_BRANCH=${IRONIC_RAMDISK_BRANCH:-${ZUUL_BRANCH:-master}} IRONIC_AGENT_KERNEL_URL=${IRONIC_AGENT_KERNEL_URL:-http://tarballs.openstack.org/ironic-python-agent-builder/dib/files/ipa-centos8-$IRONIC_RAMDISK_BRANCH.kernel} IRONIC_AGENT_RAMDISK_URL=${IRONIC_AGENT_RAMDISK_URL:-http://tarballs.openstack.org/ironic-python-agent-builder/dib/files/ipa-centos8-$IRONIC_RAMDISK_BRANCH.initramfs} IRONIC_INSPECTOR_COLLECTORS=${IRONIC_INSPECTOR_COLLECTORS:-default,logs,pci-devices} IRONIC_INSPECTOR_RAMDISK_LOGDIR=${IRONIC_INSPECTOR_RAMDISK_LOGDIR:-$IRONIC_INSPECTOR_DATA_DIR/ramdisk-logs} IRONIC_INSPECTOR_ALWAYS_STORE_RAMDISK_LOGS=${IRONIC_INSPECTOR_ALWAYS_STORE_RAMDISK_LOGS:-True} IRONIC_INSPECTOR_TIMEOUT=${IRONIC_INSPECTOR_TIMEOUT:-600} IRONIC_INSPECTOR_CLEAN_UP_PERIOD=${IRONIC_INSPECTOR_CLEAN_UP_PERIOD:-} # These should not overlap with other ranges/networks IRONIC_INSPECTOR_INTERNAL_IP=${IRONIC_INSPECTOR_INTERNAL_IP:-172.24.42.254} IRONIC_INSPECTOR_INTERNAL_SUBNET_SIZE=${IRONIC_INSPECTOR_INTERNAL_SUBNET_SIZE:-24} IRONIC_INSPECTOR_DHCP_RANGE=${IRONIC_INSPECTOR_DHCP_RANGE:-172.24.42.100,172.24.42.253} IRONIC_INSPECTOR_INTERFACE=${IRONIC_INSPECTOR_INTERFACE:-br-inspector} IRONIC_INSPECTOR_INTERFACE_PHYSICAL=$(trueorfalse False IRONIC_INSPECTOR_INTERFACE_PHYSICAL) if [[ "$IRONIC_INSPECTOR_STANDALONE" == "False" ]]; then IRONIC_INSPECTOR_INTERNAL_URI="http://$IRONIC_INSPECTOR_INTERNAL_IP/baremetal-introspection" else IRONIC_INSPECTOR_INTERNAL_URI="http://$IRONIC_INSPECTOR_INTERNAL_IP:$IRONIC_INSPECTOR_PORT" fi IRONIC_INSPECTOR_INTERNAL_IP_WITH_NET="$IRONIC_INSPECTOR_INTERNAL_IP/$IRONIC_INSPECTOR_INTERNAL_SUBNET_SIZE" # Whether DevStack will be setup for bare metal or VMs IRONIC_IS_HARDWARE=$(trueorfalse False IRONIC_IS_HARDWARE) IRONIC_INSPECTOR_NODE_NOT_FOUND_HOOK=${IRONIC_INSPECTOR_NODE_NOT_FOUND_HOOK:-""} IRONIC_INSPECTOR_OVS_PORT=${IRONIC_INSPECTOR_OVS_PORT:-brbm-inspector} IRONIC_INSPECTOR_EXTRA_KERNEL_CMDLINE=${IRONIC_INSPECTOR_EXTRA_KERNEL_CMDLINE:-""} IRONIC_INSPECTOR_POWER_OFF=${IRONIC_INSPECTOR_POWER_OFF:-True} IRONIC_INSPECTOR_MANAGED_BOOT=$(trueorfalse False IRONIC_INSPECTOR_MANAGED_BOOT) IRONIC_INSPECTION_NET_NAME=${IRONIC_INSPECTION_NET_NAME:-$IRONIC_CLEAN_NET_NAME} if is_service_enabled swift; then DEFAULT_DATA_STORE=swift else DEFAULT_DATA_STORE=database fi IRONIC_INSPECTOR_INTROSPECTION_DATA_STORE=${IRONIC_INSPECTOR_INTROSPECTION_DATA_STORE:-$DEFAULT_DATA_STORE} GITDIR["python-ironic-inspector-client"]=$DEST/python-ironic-inspector-client GITREPO["python-ironic-inspector-client"]=${IRONIC_INSPECTOR_CLIENT_REPO:-${GIT_BASE}/openstack/python-ironic-inspector-client.git} GITBRANCH["python-ironic-inspector-client"]=${IRONIC_INSPECTOR_CLIENT_BRANCH:-master} # This is defined in ironic's devstack plugin. Redefine it just in case, and # insert "inspector" if it's missing. IRONIC_ENABLED_INSPECT_INTERFACES=${IRONIC_ENABLED_INSPECT_INTERFACES:-"inspector,no-inspect,fake"} if [[ "$IRONIC_ENABLED_INSPECT_INTERFACES" != *inspector* ]]; then IRONIC_ENABLED_INSPECT_INTERFACES="inspector,$IRONIC_ENABLED_INSPECT_INTERFACES" fi # Ironic Inspector tempest variables IRONIC_INSPECTOR_TEMPEST_DISCOVERY_TIMEOUT=${IRONIC_INSPECTOR_TEMPEST_DISCOVERY_TIMEOUT:-} IRONIC_INSPECTOR_TEMPEST_INTROSPECTION_TIMEOUT=${IRONIC_INSPECTOR_TEMPEST_INTROSPECTION_TIMEOUT:-} ### Utilities function mkdir_chown_stack { if [[ ! -d "$1" ]]; then sudo mkdir -p "$1" fi sudo chown $STACK_USER "$1" } function inspector_iniset { local section=$1 local option=$2 shift 2 # value in iniset is at $4; wrapping in quotes iniset "$IRONIC_INSPECTOR_CONF_FILE" $section $option "$*" } ### Install-start-stop function install_inspector { setup_develop $IRONIC_INSPECTOR_DIR # Check if things look okay ironic-inspector-status upgrade check if [[ "$IRONIC_INSPECTOR_STANDALONE" == "False" ]]; then install_apache_wsgi # NOTE(rpittau) since devstack doesn't install test-requirements # anymore we need to install dependencies for drivers before # starting inspector services pip_install_gr pymemcache fi } function install_inspector_dhcp { install_package dnsmasq } function install_inspector_client { if use_library_from_git python-ironic-inspector-client; then git_clone_by_name python-ironic-inspector-client setup_dev_lib python-ironic-inspector-client else pip_install_gr python-ironic-inspector-client fi } function start_inspector { if [[ "$IRONIC_INSPECTOR_STANDALONE" == "True" ]]; then run_process ironic-inspector "$IRONIC_INSPECTOR_CMD" else run_process ironic-inspector-api "$(which uwsgi) --procname-prefix ironic-inspector-api --ini $IRONIC_INSPECTOR_UWSGI_CONF --pyargv \"--config-file $IRONIC_INSPECTOR_CONF_FILE\"" run_process ironic-inspector-conductor "$IRONIC_INSPECTOR_CMD_CONDUCTOR" fi echo "Waiting for ironic-inspector API to start..." if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget --no-proxy -q -O- $IRONIC_INSPECTOR_URI; do sleep 1; done"; then die $LINENO "ironic-inspector API did not start" fi } function is_inspector_dhcp_required { [[ "$IRONIC_INSPECTOR_MANAGE_FIREWALL" == "True" ]] || \ [[ "${IRONIC_INSPECTOR_DHCP_FILTER:-iptables}" != "noop" ]] && \ [[ "$IRONIC_INSPECTOR_MANAGED_BOOT" == "False" ]] } function start_inspector_dhcp { # NOTE(dtantsur): USE_SYSTEMD requires an absolute path run_process ironic-inspector-dhcp \ "$(which dnsmasq) --conf-file=$IRONIC_INSPECTOR_DHCP_CONF_FILE" \ "" root } function stop_inspector { if [[ "$IRONIC_INSPECTOR_STANDALONE" == "True" ]]; then stop_process ironic-inspector else stop_process ironic-inspector-api stop_process ironic-inspector-conductor fi } function stop_inspector_dhcp { stop_process ironic-inspector-dhcp } ### Configuration function prepare_tftp { IRONIC_INSPECTOR_IMAGE_PATH="$TOP_DIR/files/ironic-inspector" IRONIC_INSPECTOR_KERNEL_PATH="$IRONIC_INSPECTOR_IMAGE_PATH.kernel" IRONIC_INSPECTOR_INITRAMFS_PATH="$IRONIC_INSPECTOR_IMAGE_PATH.initramfs" IRONIC_INSPECTOR_CALLBACK_URI="$IRONIC_INSPECTOR_INTERNAL_URI/v1/continue" IRONIC_INSPECTOR_KERNEL_CMDLINE="root=/dev/ram0 $IRONIC_INSPECTOR_EXTRA_KERNEL_CMDLINE" IRONIC_INSPECTOR_KERNEL_CMDLINE="$IRONIC_INSPECTOR_KERNEL_CMDLINE ipa-inspection-callback-url=$IRONIC_INSPECTOR_CALLBACK_URI" IRONIC_INSPECTOR_KERNEL_CMDLINE="$IRONIC_INSPECTOR_KERNEL_CMDLINE ipa-api-url=$SERVICE_PROTOCOL://$SERVICE_HOST/baremetal" IRONIC_INSPECTOR_KERNEL_CMDLINE="$IRONIC_INSPECTOR_KERNEL_CMDLINE ipa-insecure=1 systemd.journald.forward_to_console=yes" IRONIC_INSPECTOR_KERNEL_CMDLINE="$IRONIC_INSPECTOR_KERNEL_CMDLINE vga=normal console=tty0 console=ttyS0" IRONIC_INSPECTOR_KERNEL_CMDLINE="$IRONIC_INSPECTOR_KERNEL_CMDLINE ipa-inspection-collectors=$IRONIC_INSPECTOR_COLLECTORS" IRONIC_INSPECTOR_KERNEL_CMDLINE="$IRONIC_INSPECTOR_KERNEL_CMDLINE ipa-debug=1" if [[ "$IRONIC_INSPECTOR_BUILD_RAMDISK" == "True" ]]; then if [ ! -e "$IRONIC_INSPECTOR_KERNEL_PATH" -o ! -e "$IRONIC_INSPECTOR_INITRAMFS_PATH" ]; then build_ipa_ramdisk "$IRONIC_INSPECTOR_KERNEL_PATH" "$IRONIC_INSPECTOR_INITRAMFS_PATH" fi else # download the agent image tarball if [ ! -e "$IRONIC_INSPECTOR_KERNEL_PATH" -o ! -e "$IRONIC_INSPECTOR_INITRAMFS_PATH" ]; then if [ -e "$IRONIC_DEPLOY_KERNEL" -a -e "$IRONIC_DEPLOY_RAMDISK" ]; then cp $IRONIC_DEPLOY_KERNEL $IRONIC_INSPECTOR_KERNEL_PATH cp $IRONIC_DEPLOY_RAMDISK $IRONIC_INSPECTOR_INITRAMFS_PATH else wget "$IRONIC_AGENT_KERNEL_URL" -O $IRONIC_INSPECTOR_KERNEL_PATH wget "$IRONIC_AGENT_RAMDISK_URL" -O $IRONIC_INSPECTOR_INITRAMFS_PATH fi fi fi if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then cp $IRONIC_INSPECTOR_KERNEL_PATH $IRONIC_HTTP_DIR/ironic-inspector.kernel cp $IRONIC_INSPECTOR_INITRAMFS_PATH $IRONIC_HTTP_DIR cat > "$IRONIC_HTTP_DIR/ironic-inspector.ipxe" < "$IRONIC_TFTPBOOT_DIR/pxelinux.cfg/default" <> $IRONIC_INSPECTOR_DHCP_CONF_FILE } function _dnsmasq_rootwrap_ctl_tail { # cut off the command head and amend white-spaces with commas shift local bits=$* echo ${bits//\ /, } } function configure_inspector_dnsmasq_rootwrap { # turn the ctl commands into filter rules and dump the roorwrap file local stop_cmd=( $IRONIC_INSPECTOR_DNSMASQ_STOP_COMMAND ) local start_cmd=( $IRONIC_INSPECTOR_DNSMASQ_START_COMMAND ) local stop_cmd_tail=$( _dnsmasq_rootwrap_ctl_tail ${stop_cmd[@]} ) local start_cmd_tail=$( _dnsmasq_rootwrap_ctl_tail ${start_cmd[@]} ) cat > "$IRONIC_INSPECTOR_CONF_DIR/rootwrap.d/ironic-inspector-dnsmasq.filters" <$tempfile chmod 0640 $tempfile sudo chown root:root $tempfile sudo mv $tempfile /etc/sudoers.d/ironic-inspector-rootwrap inspector_iniset DEFAULT rootwrap_config $IRONIC_INSPECTOR_ROOTWRAP_CONF_FILE mkdir_chown_stack "$IRONIC_INSPECTOR_RAMDISK_LOGDIR" inspector_iniset processing ramdisk_logs_dir "$IRONIC_INSPECTOR_RAMDISK_LOGDIR" inspector_iniset processing always_store_ramdisk_logs "$IRONIC_INSPECTOR_ALWAYS_STORE_RAMDISK_LOGS" if [ -n "$IRONIC_INSPECTOR_NODE_NOT_FOUND_HOOK" ]; then inspector_iniset processing node_not_found_hook "$IRONIC_INSPECTOR_NODE_NOT_FOUND_HOOK" fi inspector_iniset DEFAULT timeout $IRONIC_INSPECTOR_TIMEOUT if [ -n "$IRONIC_INSPECTOR_CLEAN_UP_PERIOD" ]; then inspector_iniset DEFAULT clean_up_period "$IRONIC_INSPECTOR_CLEAN_UP_PERIOD" fi get_or_create_service "ironic-inspector" "baremetal-introspection" "Ironic Inspector baremetal introspection service" get_or_create_endpoint "baremetal-introspection" "$REGION_NAME" \ "$IRONIC_INSPECTOR_URI" "$IRONIC_INSPECTOR_URI" "$IRONIC_INSPECTOR_URI" if is_dnsmasq_filter_required ; then configure_inspector_dnsmasq_rootwrap configure_inspector_pxe_filter_dnsmasq fi # Set if inspector should also be running in a scope enforced mode. if [[ "$IRONIC_INSPECTOR_ENFORCE_SCOPE" == "True" ]]; then inspector_iniset oslo_policy enforce_scope true inspector_iniset oslo_policy enforce_new_defaults true fi } function configure_inspector_swift { inspector_configure_auth_for swift } function configure_inspector_dhcp { mkdir_chown_stack "$IRONIC_INSPECTOR_CONF_DIR" if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then cat > "$IRONIC_INSPECTOR_DHCP_CONF_FILE" < "$IRONIC_INSPECTOR_DHCP_CONF_FILE" <