Copy devstack code to ironic tree
This begins work toward moving our devstack code to a devstack plugin within our tree. This allows us to experiment with the devstack code more easily, as well as take some load off of the devstack team. Note that the plugin is not enabled until we enable it in project-config, so this doesn't actually affect devstack runs yet. The files that exist for us in devstack are listed below. $ find . -name *ironic* ./lib/ironic ./lib/nova_plugins/hypervisor-ironic ./files/rpms/ironic ./files/apache-ironic.template ./files/debs/ironic ./extras.d/50-ironic.sh ./tools/ironic $ tree tools/ironic tools/ironic ├── scripts │ ├── cleanup-node │ ├── configure-vm │ ├── create-node │ └── setup-network └── templates ├── brbm.xml ├── tftpd-xinetd.template └── vm.xml All of these files are copied here, except: lib/nova_plugins/hypervisor-ironic: this is nova code and will not move. extras.d/50-ironic.sh: this will become the base for plugin.sh. Change-Id: I3fabefa686cad4bc50f6a5603fd95c96d1a21e68 Depends-On: Id01d97fd13fa9f866d645ec5077834ddb78b2b89
This commit is contained in:
parent
7b13f3b0a6
commit
b21873588a
12
devstack/files/apache-ironic.template
Normal file
12
devstack/files/apache-ironic.template
Normal file
@ -0,0 +1,12 @@
|
||||
Listen %PUBLICPORT%
|
||||
|
||||
<VirtualHost *:%PUBLICPORT%>
|
||||
DocumentRoot "%HTTPROOT%"
|
||||
<Directory "%HTTPROOT%">
|
||||
Options Indexes FollowSymLinks
|
||||
AllowOverride None
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
Require all granted
|
||||
</Directory>
|
||||
</VirtualHost>
|
19
devstack/files/debs/ironic
Normal file
19
devstack/files/debs/ironic
Normal file
@ -0,0 +1,19 @@
|
||||
docker.io
|
||||
ipmitool
|
||||
iptables
|
||||
ipxe
|
||||
libguestfs0
|
||||
libvirt-bin
|
||||
open-iscsi
|
||||
openssh-client
|
||||
openvswitch-datapath-dkms
|
||||
openvswitch-switch
|
||||
python-libguestfs
|
||||
python-libvirt
|
||||
qemu
|
||||
qemu-kvm
|
||||
qemu-utils
|
||||
sgabios
|
||||
syslinux
|
||||
tftpd-hpa
|
||||
xinetd
|
14
devstack/files/rpms/ironic
Normal file
14
devstack/files/rpms/ironic
Normal file
@ -0,0 +1,14 @@
|
||||
docker-io
|
||||
ipmitool
|
||||
iptables
|
||||
ipxe-bootimgs
|
||||
libguestfs
|
||||
libvirt
|
||||
libvirt-python
|
||||
net-tools
|
||||
openssh-clients
|
||||
openvswitch
|
||||
sgabios
|
||||
syslinux
|
||||
tftp-server
|
||||
xinetd
|
867
devstack/lib/ironic
Normal file
867
devstack/lib/ironic
Normal file
@ -0,0 +1,867 @@
|
||||
#!/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
|
||||
|
||||
IRONIC_DIR=$DEST/ironic
|
||||
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}
|
||||
# The file is composed of multiple lines, each line includes four field
|
||||
# separated by white space: IPMI address, MAC address, IPMI username
|
||||
# and IPMI password.
|
||||
#
|
||||
# 192.168.110.107 00:1e:67:57:50:4c root otc123
|
||||
IRONIC_IPMIINFO_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:-$TOP_DIR/tools/ironic/scripts}
|
||||
IRONIC_TEMPLATES_DIR=${IRONIC_TEMPLATES_DIR:-$TOP_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_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:-512}
|
||||
IRONIC_VM_SPECS_DISK=${IRONIC_VM_SPECS_DISK:-10}
|
||||
IRONIC_VM_EPHEMERAL_DISK=${IRONIC_VM_EPHEMERAL_DISK:-0}
|
||||
IRONIC_VM_EMULATOR=${IRONIC_VM_EMULATOR:-/usr/bin/qemu-system-x86_64}
|
||||
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}
|
||||
|
||||
# By default, baremetal VMs will console output to file.
|
||||
IRONIC_VM_LOG_CONSOLE=${IRONIC_VM_LOG_CONSOLE:-True}
|
||||
IRONIC_VM_LOG_DIR=${IRONIC_VM_LOG_DIR:-$IRONIC_DATA_DIR/logs/}
|
||||
|
||||
# Use DIB to create deploy ramdisk and kernel.
|
||||
IRONIC_BUILD_DEPLOY_RAMDISK=$(trueorfalse True IRONIC_BUILD_DEPLOY_RAMDISK)
|
||||
# If not use DIB, 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_ELEMENT=${IRONIC_DEPLOY_ELEMENT:-deploy-ironic}
|
||||
|
||||
IRONIC_AGENT_KERNEL_URL=${IRONIC_AGENT_KERNEL_URL:-http://tarballs.openstack.org/ironic-python-agent/coreos/files/coreos_production_pxe.vmlinuz}
|
||||
IRONIC_AGENT_RAMDISK_URL=${IRONIC_AGENT_RAMDISK_URL:-http://tarballs.openstack.org/ironic-python-agent/coreos/files/coreos_production_pxe_image-oem.cpio.gz}
|
||||
|
||||
# Which deploy driver to use - valid choices right now
|
||||
# are ``pxe_ssh``, ``pxe_ipmitool``, ``agent_ssh`` and ``agent_ipmitool``.
|
||||
IRONIC_DEPLOY_DRIVER=${IRONIC_DEPLOY_DRIVER:-pxe_ssh}
|
||||
|
||||
# TODO(agordeev): replace 'ubuntu' with host distro name getting
|
||||
IRONIC_DEPLOY_FLAVOR=${IRONIC_DEPLOY_FLAVOR:-ubuntu $IRONIC_DEPLOY_ELEMENT}
|
||||
|
||||
# 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=http
|
||||
IRONIC_SERVICE_PORT=${IRONIC_SERVICE_PORT:-6385}
|
||||
IRONIC_HOSTPORT=${IRONIC_HOSTPORT:-$SERVICE_HOST:$IRONIC_SERVICE_PORT}
|
||||
|
||||
# Enable iPXE
|
||||
IRONIC_IPXE_ENABLED=$(trueorfalse False IRONIC_IPXE_ENABLED)
|
||||
IRONIC_HTTP_DIR=${IRONIC_HTTP_DIR:-$IRONIC_DATA_DIR/httpboot}
|
||||
IRONIC_HTTP_SERVER=${IRONIC_HTTP_SERVER:-$HOST_IP}
|
||||
IRONIC_HTTP_PORT=${IRONIC_HTTP_PORT:-8088}
|
||||
|
||||
# NOTE(lucasagomes): This flag is used to differentiate the nodes that
|
||||
# uses IPA as their deploy ramdisk from nodes that uses the agent_* drivers
|
||||
# (which also uses IPA but depends on Swift Temp URLs to work). At present,
|
||||
# all drivers that uses the iSCSI approach for their deployment supports
|
||||
# using both, IPA or bash ramdisks for the deployment. In the future we
|
||||
# want to remove the support for the bash ramdisk in favor of IPA, once
|
||||
# we get there this flag can be removed, and all conditionals that uses
|
||||
# it should just run by default.
|
||||
IRONIC_DEPLOY_DRIVER_ISCSI_WITH_IPA=$(trueorfalse False IRONIC_DEPLOY_DRIVER_ISCSI_WITH_IPA)
|
||||
|
||||
# get_pxe_boot_file() - Get the PXE/iPXE boot file path
|
||||
function get_pxe_boot_file {
|
||||
local relpath=syslinux/pxelinux.0
|
||||
if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
|
||||
relpath=ipxe/undionly.kpxe
|
||||
fi
|
||||
|
||||
local pxe_boot_file
|
||||
if is_ubuntu; then
|
||||
pxe_boot_file=/usr/lib/$relpath
|
||||
elif is_fedora || is_suse; then
|
||||
pxe_boot_file=/usr/share/$relpath
|
||||
fi
|
||||
|
||||
echo $pxe_boot_file
|
||||
}
|
||||
|
||||
# PXE boot image
|
||||
IRONIC_PXE_BOOT_IMAGE=${IRONIC_PXE_BOOT_IMAGE:-$(get_pxe_boot_file)}
|
||||
|
||||
|
||||
# Functions
|
||||
# ---------
|
||||
|
||||
# Test if any Ironic services are enabled
|
||||
# is_ironic_enabled
|
||||
function is_ironic_enabled {
|
||||
[[ ,${ENABLED_SERVICES} =~ ,"ir-" ]] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
function is_ironic_hardware {
|
||||
is_ironic_enabled && [[ -n "${IRONIC_DEPLOY_DRIVER##*_ssh}" ]] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
function is_deployed_by_agent {
|
||||
[[ -z "${IRONIC_DEPLOY_DRIVER%%agent*}" ]] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
function is_deployed_with_ipa_ramdisk {
|
||||
is_deployed_by_agent || [[ "$IRONIC_DEPLOY_DRIVER_ISCSI_WITH_IPA" == "True" ]] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
# install_ironic() - Collect source and prepare
|
||||
function install_ironic {
|
||||
# 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
|
||||
|
||||
if use_library_from_git "ironic-lib"; then
|
||||
git_clone_by_name "ironic-lib"
|
||||
setup_dev_lib "ironic-lib"
|
||||
fi
|
||||
|
||||
git_clone $IRONIC_REPO $IRONIC_DIR $IRONIC_BRANCH
|
||||
setup_develop $IRONIC_DIR
|
||||
|
||||
if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
|
||||
install_apache_wsgi
|
||||
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 $FILES/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() - Remove residual data files, anything left over from previous
|
||||
# runs that would need to clean up.
|
||||
function cleanup_ironic {
|
||||
sudo rm -rf $IRONIC_AUTH_CACHE_DIR $IRONIC_CONF_DIR
|
||||
}
|
||||
|
||||
# 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
|
||||
if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
|
||||
cp $IRONIC_PXE_BOOT_IMAGE $IRONIC_TFTPBOOT_DIR
|
||||
else
|
||||
# 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
|
||||
cp -aR $(dirname $IRONIC_PXE_BOOT_IMAGE)/*.{c32,0} $IRONIC_TFTPBOOT_DIR
|
||||
fi
|
||||
}
|
||||
|
||||
# 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
|
||||
# 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 keystone
|
||||
iniset $IRONIC_CONF_FILE oslo_policy policy_file $IRONIC_POLICY_JSON
|
||||
|
||||
# TODO(Yuki Nishiwaki): This is a temporary work-around until Ironic is fixed(bug#1422632).
|
||||
# These codes need to be changed to use the function of configure_auth_token_middleware
|
||||
# after Ironic conforms to the new auth plugin.
|
||||
iniset $IRONIC_CONF_FILE keystone_authtoken identity_uri $KEYSTONE_AUTH_URI
|
||||
iniset $IRONIC_CONF_FILE keystone_authtoken auth_uri $KEYSTONE_SERVICE_URI/v2.0
|
||||
iniset $IRONIC_CONF_FILE keystone_authtoken admin_user ironic
|
||||
iniset $IRONIC_CONF_FILE keystone_authtoken admin_password $SERVICE_PASSWORD
|
||||
iniset $IRONIC_CONF_FILE keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME
|
||||
iniset $IRONIC_CONF_FILE keystone_authtoken cafile $SSL_BUNDLE_FILE
|
||||
iniset $IRONIC_CONF_FILE keystone_authtoken signing_dir $IRONIC_AUTH_CACHE_DIR/api
|
||||
|
||||
iniset_rpc_backend ironic $IRONIC_CONF_FILE
|
||||
iniset $IRONIC_CONF_FILE api port $IRONIC_SERVICE_PORT
|
||||
|
||||
cp -p $IRONIC_DIR/etc/ironic/policy.json $IRONIC_POLICY_JSON
|
||||
}
|
||||
|
||||
# configure_ironic_conductor() - Is used by configure_ironic().
|
||||
# Sets conductor specific settings.
|
||||
function configure_ironic_conductor {
|
||||
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://$HOST_IP:$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
|
||||
|
||||
local pxe_params=""
|
||||
if [[ "$IRONIC_VM_LOG_CONSOLE" == "True" ]] ; then
|
||||
pxe_params+="nofb nomodeset vga=normal console=ttyS0"
|
||||
if is_deployed_with_ipa_ramdisk; then
|
||||
pxe_params+=" systemd.journald.forward_to_console=yes"
|
||||
fi
|
||||
fi
|
||||
# When booting with less than 1GB, we need to switch from default tmpfs
|
||||
# to ramfs for ramdisks to decompress successfully.
|
||||
if (is_ironic_hardware && [[ "$IRONIC_HW_NODE_RAM" -lt 1024 ]]) ||
|
||||
(! is_ironic_hardware && [[ "$IRONIC_VM_SPECS_RAM" -lt 1024 ]]); then
|
||||
pxe_params+=" rootfstype=ramfs"
|
||||
fi
|
||||
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_deployed_by_agent; 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 to use agent_ssh driver in Ironic."
|
||||
fi
|
||||
iniset $IRONIC_CONF_FILE glance swift_endpoint_url http://${HOST_IP}:${SWIFT_DEFAULT_BIND_PORT:-8080}
|
||||
iniset $IRONIC_CONF_FILE glance swift_api_version v1
|
||||
local tenant_id
|
||||
tenant_id=$(get_or_create_project $SERVICE_TENANT_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 agent heartbeat_timeout 30
|
||||
fi
|
||||
|
||||
# FIXME: this really needs to be tested in the gate.
|
||||
# For now, any test using the agent ramdisk should skip cleaning
|
||||
# because it is too slow to run in the gate.
|
||||
iniset $IRONIC_CONF_FILE agent agent_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 pxe http_root $IRONIC_HTTP_DIR
|
||||
iniset $IRONIC_CONF_FILE pxe http_url "http://$IRONIC_HTTP_SERVER:$IRONIC_HTTP_PORT"
|
||||
fi
|
||||
}
|
||||
|
||||
# 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
|
||||
|
||||
# Tenant User Roles
|
||||
# ------------------------------------------------------------------
|
||||
# service ironic admin # if enabled
|
||||
function create_ironic_accounts {
|
||||
|
||||
# Ironic
|
||||
if [[ "$ENABLED_SERVICES" =~ "ir-api" ]]; then
|
||||
# Get ironic user if exists
|
||||
|
||||
# NOTE(Shrews): This user MUST have admin level privileges!
|
||||
create_service_user "ironic" "admin"
|
||||
|
||||
if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then
|
||||
|
||||
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"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# init_ironic() - Initialize databases, etc.
|
||||
function init_ironic {
|
||||
# Save private network as cleaning network
|
||||
local cleaning_network_uuid
|
||||
cleaning_network_uuid=$(neutron net-list | grep private | get_field 1)
|
||||
iniset $IRONIC_CONF_FILE neutron cleaning_network_uuid ${cleaning_network_uuid}
|
||||
|
||||
# (Re)create ironic database
|
||||
recreate_database ironic
|
||||
|
||||
# Migrate ironic database
|
||||
$IRONIC_BIN_DIR/ironic-dbsync --config-file=$IRONIC_CONF_FILE
|
||||
|
||||
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 "baremetal${IRONIC_VM_NETWORK_BRIDGE}_${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
|
||||
|
||||
# Cleanup the WSGI files
|
||||
if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
|
||||
_cleanup_ironic_apache_wsgi
|
||||
fi
|
||||
}
|
||||
|
||||
function create_ovs_taps {
|
||||
local ironic_net_id
|
||||
ironic_net_id=$(neutron net-list | grep private | get_field 1)
|
||||
|
||||
# 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 private | grep " id " | get_field 2)
|
||||
|
||||
# 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-)
|
||||
local tag_id
|
||||
tag_id=$(sudo ovs-vsctl show |grep ${tapdev} -A1 -m1 | grep tag | cut -d':' -f2 | cut -b2-)
|
||||
|
||||
# make sure veth pair is not existing, otherwise delete its links
|
||||
sudo ip link show ovs-tap1 && sudo ip link delete ovs-tap1
|
||||
sudo ip link show brbm-tap1 && sudo ip link delete brbm-tap1
|
||||
# create veth pair for future interconnection between br-int and brbm
|
||||
sudo ip link add brbm-tap1 type veth peer name ovs-tap1
|
||||
sudo ip link set dev brbm-tap1 up
|
||||
sudo ip link set dev ovs-tap1 up
|
||||
|
||||
sudo ovs-vsctl -- --if-exists del-port ovs-tap1 -- add-port br-int ovs-tap1 tag=$tag_id
|
||||
sudo ovs-vsctl -- --if-exists del-port brbm-tap1 -- add-port $IRONIC_VM_NETWORK_BRIDGE brbm-tap1
|
||||
|
||||
# Remove the port needed only for workaround.
|
||||
neutron 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.
|
||||
neutron net-update $ironic_net_id --shared true
|
||||
}
|
||||
|
||||
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"
|
||||
if [[ "$IRONIC_VM_LOG_CONSOLE" == "True" ]] ; then
|
||||
local log_arg="$IRONIC_VM_LOG_DIR"
|
||||
else
|
||||
local log_arg=""
|
||||
fi
|
||||
local vm_name
|
||||
for vm_name in $(_ironic_bm_vm_names); do
|
||||
sudo su $STACK_USER -c "$IRONIC_SCRIPTS_DIR/create-node $vm_name \
|
||||
$IRONIC_VM_SPECS_CPU $IRONIC_VM_SPECS_RAM $IRONIC_VM_SPECS_DISK \
|
||||
amd64 $IRONIC_VM_NETWORK_BRIDGE $IRONIC_VM_EMULATOR \
|
||||
$log_arg" >> $IRONIC_VM_MACS_CSV_FILE
|
||||
done
|
||||
create_ovs_taps
|
||||
}
|
||||
|
||||
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 [ $(nova hypervisor-stats | grep " $resource " | get_field 2) -ge $expected_count ]; then
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
die $LINENO "Timed out waiting for Nova hypervisor-stats $resource >= $expected_count"
|
||||
}
|
||||
|
||||
function enroll_nodes {
|
||||
local chassis_id
|
||||
chassis_id=$(ironic chassis-create -d "ironic test chassis" | grep " uuid " | get_field 2)
|
||||
|
||||
if ! is_ironic_hardware; 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_hwinfo_file=$IRONIC_VM_MACS_CSV_FILE
|
||||
local node_options="\
|
||||
-i deploy_kernel=$IRONIC_DEPLOY_KERNEL_ID \
|
||||
-i deploy_ramdisk=$IRONIC_DEPLOY_RAMDISK_ID \
|
||||
-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"
|
||||
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
|
||||
if [[ -z "${IRONIC_DEPLOY_DRIVER##*_ipmitool}" ]]; then
|
||||
local ironic_hwinfo_file=$IRONIC_IPMIINFO_FILE
|
||||
fi
|
||||
fi
|
||||
|
||||
local total_nodes=0
|
||||
local total_cpus=0
|
||||
while read hardware_info; do
|
||||
if ! is_ironic_hardware; then
|
||||
local mac_address=$hardware_info
|
||||
elif [[ -z "${IRONIC_DEPLOY_DRIVER##*_ipmitool}" ]]; then
|
||||
local ipmi_address
|
||||
ipmi_address=$(echo $hardware_info |awk '{print $1}')
|
||||
local mac_address
|
||||
mac_address=$(echo $hardware_info |awk '{print $2}')
|
||||
local ironic_ipmi_username
|
||||
ironic_ipmi_username=$(echo $hardware_info |awk '{print $3}')
|
||||
local ironic_ipmi_passwd
|
||||
ironic_ipmi_passwd=$(echo $hardware_info |awk '{print $4}')
|
||||
# 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 node_options="-i ipmi_address=$ipmi_address -i ipmi_password=$ironic_ipmi_passwd\
|
||||
-i ipmi_username=$ironic_ipmi_username"
|
||||
node_options+=" -i deploy_kernel=$IRONIC_DEPLOY_KERNEL_ID"
|
||||
node_options+=" -i deploy_ramdisk=$IRONIC_DEPLOY_RAMDISK_ID"
|
||||
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-$total_nodes \
|
||||
-p cpus=$ironic_node_cpu\
|
||||
-p memory_mb=$ironic_node_ram\
|
||||
-p local_gb=$ironic_node_disk\
|
||||
-p cpu_arch=x86_64 \
|
||||
$node_options \
|
||||
| grep " uuid " | get_field 2)
|
||||
|
||||
ironic port-create --address $mac_address --node $node_id
|
||||
|
||||
total_nodes=$((total_nodes+1))
|
||||
total_cpus=$((total_cpus+$ironic_node_cpu))
|
||||
done < $ironic_hwinfo_file
|
||||
|
||||
local adjusted_disk
|
||||
adjusted_disk=$(($ironic_node_disk - $ironic_ephemeral_disk))
|
||||
nova flavor-create --ephemeral $ironic_ephemeral_disk baremetal auto $ironic_node_ram $adjusted_disk $ironic_node_cpu
|
||||
|
||||
nova flavor-key baremetal set "cpu_arch"="x86_64"
|
||||
|
||||
if [ "$VIRT_DRIVER" == "ironic" ]; then
|
||||
wait_for_nova_resources "count" $total_nodes
|
||||
wait_for_nova_resources "vcpus" $total_cpus
|
||||
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 $HOST_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
|
||||
fi
|
||||
|
||||
if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
|
||||
sudo iptables -I INPUT -d $HOST_IP -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
|
||||
if [[ ! -e $IRONIC_KEY_FILE ]]; 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
|
||||
cat $IRONIC_KEY_FILE.pub | tee -a $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 active_timeout=$5
|
||||
if ! timeout $active_timeout sh -c "while ! ssh -p $port -o StrictHostKeyChecking=no -i $key_file ${default_instance_user}@$floating_ip echo success; do sleep 1; done"; 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_TIMEOUT
|
||||
}
|
||||
|
||||
function build_ipa_coreos_ramdisk {
|
||||
echo "Building ironic-python-agent deploy ramdisk"
|
||||
local kernel_path=$1
|
||||
local ramdisk_path=$2
|
||||
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
|
||||
sudo rm -rf UPLOAD
|
||||
cd -
|
||||
}
|
||||
|
||||
# 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
|
||||
echo_summary "Creating and uploading baremetal images for ironic"
|
||||
|
||||
# install diskimage-builder
|
||||
if [[ $(type -P ramdisk-image-create) == "" ]]; then
|
||||
pip_install_gr "diskimage-builder"
|
||||
fi
|
||||
|
||||
if [ -z "$IRONIC_DEPLOY_KERNEL" -o -z "$IRONIC_DEPLOY_RAMDISK" ]; 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
|
||||
else
|
||||
local IRONIC_DEPLOY_KERNEL_PATH=$IRONIC_DEPLOY_KERNEL
|
||||
local IRONIC_DEPLOY_RAMDISK_PATH=$IRONIC_DEPLOY_RAMDISK
|
||||
fi
|
||||
|
||||
if [ ! -e "$IRONIC_DEPLOY_RAMDISK_PATH" -o ! -e "$IRONIC_DEPLOY_KERNEL_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
|
||||
if is_deployed_with_ipa_ramdisk; then
|
||||
build_ipa_coreos_ramdisk $IRONIC_DEPLOY_KERNEL_PATH $IRONIC_DEPLOY_RAMDISK_PATH
|
||||
else
|
||||
ramdisk-image-create $IRONIC_DEPLOY_FLAVOR \
|
||||
-o $TOP_DIR/files/ir-deploy-$IRONIC_DEPLOY_DRIVER
|
||||
fi
|
||||
else
|
||||
die $LINENO "Deploy kernel+ramdisk files don't exist and cannot be build in OFFLINE mode"
|
||||
fi
|
||||
else
|
||||
if is_deployed_with_ipa_ramdisk; then
|
||||
# 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
|
||||
else
|
||||
die $LINENO "Deploy kernel+ramdisk files don't exist and their building was disabled explicitly by IRONIC_BUILD_DEPLOY_RAMDISK"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
local token
|
||||
token=$(openstack token issue -c id -f value)
|
||||
die_if_not_set $LINENO token "Keystone fail to get token"
|
||||
|
||||
# load them into glance
|
||||
IRONIC_DEPLOY_KERNEL_ID=$(openstack \
|
||||
--os-token $token \
|
||||
--os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT \
|
||||
image create \
|
||||
$(basename $IRONIC_DEPLOY_KERNEL_PATH) \
|
||||
--public --disk-format=aki \
|
||||
--container-format=aki \
|
||||
< $IRONIC_DEPLOY_KERNEL_PATH | grep ' id ' | get_field 2)
|
||||
IRONIC_DEPLOY_RAMDISK_ID=$(openstack \
|
||||
--os-token $token \
|
||||
--os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT \
|
||||
image create \
|
||||
$(basename $IRONIC_DEPLOY_RAMDISK_PATH) \
|
||||
--public --disk-format=ari \
|
||||
--container-format=ari \
|
||||
< $IRONIC_DEPLOY_RAMDISK_PATH | grep ' id ' | get_field 2)
|
||||
}
|
||||
|
||||
function prepare_baremetal_basic_ops {
|
||||
if ! is_ironic_hardware; then
|
||||
configure_ironic_auxiliary
|
||||
fi
|
||||
upload_baremetal_ironic_deploy
|
||||
if ! is_ironic_hardware; then
|
||||
create_bridge_and_vms
|
||||
fi
|
||||
enroll_nodes
|
||||
configure_tftpd
|
||||
configure_iptables
|
||||
}
|
||||
|
||||
function cleanup_baremetal_basic_ops {
|
||||
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 $vm_name $IRONIC_VM_NETWORK_BRIDGE"
|
||||
done
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
# Restore xtrace + pipefail
|
||||
$_XTRACE_IRONIC
|
||||
$_PIPEFAIL_IRONIC
|
||||
|
||||
# Tell emacs to use shell-script-mode
|
||||
## Local variables:
|
||||
## mode: shell-script
|
||||
## End:
|
25
devstack/tools/ironic/scripts/cleanup-node
Executable file
25
devstack/tools/ironic/scripts/cleanup-node
Executable file
@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# **cleanup-nodes**
|
||||
|
||||
# Cleans up baremetal poseur nodes and volumes created during ironic setup
|
||||
# Assumes calling user has proper libvirt group membership and access.
|
||||
|
||||
set -exu
|
||||
|
||||
LIBVIRT_STORAGE_POOL=${LIBVIRT_STORAGE_POOL:-"default"}
|
||||
LIBVIRT_CONNECT_URI=${LIBVIRT_CONNECT_URI:-"qemu:///system"}
|
||||
|
||||
NAME=$1
|
||||
NETWORK_BRIDGE=$2
|
||||
|
||||
export VIRSH_DEFAULT_CONNECT_URI=$LIBVIRT_CONNECT_URI
|
||||
|
||||
VOL_NAME="$NAME.qcow2"
|
||||
virsh list | grep -q $NAME && virsh destroy $NAME
|
||||
virsh list --inactive | grep -q $NAME && virsh undefine $NAME
|
||||
|
||||
if virsh pool-list | grep -q $LIBVIRT_STORAGE_POOL ; then
|
||||
virsh vol-list $LIBVIRT_STORAGE_POOL | grep -q $VOL_NAME &&
|
||||
virsh vol-delete $VOL_NAME --pool $LIBVIRT_STORAGE_POOL
|
||||
fi
|
93
devstack/tools/ironic/scripts/configure-vm
Executable file
93
devstack/tools/ironic/scripts/configure-vm
Executable file
@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import argparse
|
||||
import os.path
|
||||
|
||||
import libvirt
|
||||
|
||||
templatedir = os.path.join(os.path.dirname(os.path.dirname(__file__)),
|
||||
'templates')
|
||||
|
||||
|
||||
CONSOLE_LOG = """
|
||||
<serial type='file'>
|
||||
<source path='%(console_log)s'/>
|
||||
<target port='0'/>
|
||||
<alias name='serial0'/>
|
||||
</serial>
|
||||
<serial type='pty'>
|
||||
<source path='/dev/pts/49'/>
|
||||
<target port='1'/>
|
||||
<alias name='serial1'/>
|
||||
</serial>
|
||||
<console type='file'>
|
||||
<source path='%(console_log)s'/>
|
||||
<target type='serial' port='0'/>
|
||||
<alias name='serial0'/>
|
||||
</console>
|
||||
"""
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Configure a kvm virtual machine for the seed image.")
|
||||
parser.add_argument('--name', default='seed',
|
||||
help='the name to give the machine in libvirt.')
|
||||
parser.add_argument('--image',
|
||||
help='Use a custom image file (must be qcow2).')
|
||||
parser.add_argument('--engine', default='qemu',
|
||||
help='The virtualization engine to use')
|
||||
parser.add_argument('--arch', default='i686',
|
||||
help='The architecture to use')
|
||||
parser.add_argument('--memory', default='2097152',
|
||||
help="Maximum memory for the VM in KB.")
|
||||
parser.add_argument('--cpus', default='1',
|
||||
help="CPU count for the VM.")
|
||||
parser.add_argument('--bootdev', default='hd',
|
||||
help="What boot device to use (hd/network).")
|
||||
parser.add_argument('--network', default="brbm",
|
||||
help='The libvirt network name to use')
|
||||
parser.add_argument('--libvirt-nic-driver', default='e1000',
|
||||
help='The libvirt network driver to use')
|
||||
parser.add_argument('--console-log',
|
||||
help='File to log console')
|
||||
parser.add_argument('--emulator', default=None,
|
||||
help='Path to emulator bin for vm template')
|
||||
args = parser.parse_args()
|
||||
with file(templatedir + '/vm.xml', 'rb') as f:
|
||||
source_template = f.read()
|
||||
params = {
|
||||
'name': args.name,
|
||||
'imagefile': args.image,
|
||||
'engine': args.engine,
|
||||
'arch': args.arch,
|
||||
'memory': args.memory,
|
||||
'cpus': args.cpus,
|
||||
'bootdev': args.bootdev,
|
||||
'network': args.network,
|
||||
'nicdriver': args.libvirt_nic_driver,
|
||||
'emulator': args.emulator,
|
||||
}
|
||||
|
||||
if args.emulator:
|
||||
params['emulator'] = args.emulator
|
||||
else:
|
||||
if os.path.exists("/usr/bin/kvm"): # Debian
|
||||
params['emulator'] = "/usr/bin/kvm"
|
||||
elif os.path.exists("/usr/bin/qemu-kvm"): # Redhat
|
||||
params['emulator'] = "/usr/bin/qemu-kvm"
|
||||
|
||||
if args.console_log:
|
||||
params['bios_serial'] = "<bios useserial='yes'/>"
|
||||
params['console_log'] = CONSOLE_LOG % {'console_log': args.console_log}
|
||||
else:
|
||||
params['bios_serial'] = ''
|
||||
params['console_log'] = ''
|
||||
libvirt_template = source_template % params
|
||||
conn = libvirt.open("qemu:///system")
|
||||
|
||||
a = conn.defineXML(libvirt_template)
|
||||
print ("Created machine %s with UUID %s" % (args.name, a.UUIDString()))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
79
devstack/tools/ironic/scripts/create-node
Executable file
79
devstack/tools/ironic/scripts/create-node
Executable file
@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# **create-nodes**
|
||||
|
||||
# Creates baremetal poseur nodes for ironic testing purposes
|
||||
|
||||
set -ex
|
||||
|
||||
# Keep track of the DevStack directory
|
||||
TOP_DIR=$(cd $(dirname "$0")/.. && pwd)
|
||||
|
||||
NAME=$1
|
||||
CPU=$2
|
||||
MEM=$(( 1024 * $3 ))
|
||||
# Extra G to allow fuzz for partition table : flavor size and registered size
|
||||
# need to be different to actual size.
|
||||
DISK=$(( $4 + 1))
|
||||
|
||||
case $5 in
|
||||
i386) ARCH='i686' ;;
|
||||
amd64) ARCH='x86_64' ;;
|
||||
*) echo "Unsupported arch $4!" ; exit 1 ;;
|
||||
esac
|
||||
|
||||
BRIDGE=$6
|
||||
EMULATOR=$7
|
||||
LOGDIR=$8
|
||||
|
||||
LIBVIRT_NIC_DRIVER=${LIBVIRT_NIC_DRIVER:-"e1000"}
|
||||
LIBVIRT_STORAGE_POOL=${LIBVIRT_STORAGE_POOL:-"default"}
|
||||
LIBVIRT_CONNECT_URI=${LIBVIRT_CONNECT_URI:-"qemu:///system"}
|
||||
|
||||
export VIRSH_DEFAULT_CONNECT_URI=$LIBVIRT_CONNECT_URI
|
||||
|
||||
if ! virsh pool-list --all | grep -q $LIBVIRT_STORAGE_POOL; then
|
||||
virsh pool-define-as --name $LIBVIRT_STORAGE_POOL dir --target /var/lib/libvirt/images >&2
|
||||
virsh pool-autostart $LIBVIRT_STORAGE_POOL >&2
|
||||
virsh pool-start $LIBVIRT_STORAGE_POOL >&2
|
||||
fi
|
||||
|
||||
pool_state=$(virsh pool-info $LIBVIRT_STORAGE_POOL | grep State | awk '{ print $2 }')
|
||||
if [ "$pool_state" != "running" ] ; then
|
||||
[ ! -d /var/lib/libvirt/images ] && sudo mkdir /var/lib/libvirt/images
|
||||
virsh pool-start $LIBVIRT_STORAGE_POOL >&2
|
||||
fi
|
||||
|
||||
if [ -n "$LOGDIR" ] ; then
|
||||
mkdir -p "$LOGDIR"
|
||||
fi
|
||||
|
||||
PREALLOC=
|
||||
if [ -f /etc/debian_version ]; then
|
||||
PREALLOC="--prealloc-metadata"
|
||||
fi
|
||||
|
||||
if [ -n "$LOGDIR" ] ; then
|
||||
VM_LOGGING="--console-log $LOGDIR/${NAME}_console.log"
|
||||
else
|
||||
VM_LOGGING=""
|
||||
fi
|
||||
VOL_NAME="${NAME}.qcow2"
|
||||
|
||||
if ! virsh list --all | grep -q $NAME; then
|
||||
virsh vol-list --pool $LIBVIRT_STORAGE_POOL | grep -q $VOL_NAME &&
|
||||
virsh vol-delete $VOL_NAME --pool $LIBVIRT_STORAGE_POOL >&2
|
||||
virsh vol-create-as $LIBVIRT_STORAGE_POOL ${VOL_NAME} ${DISK}G --format qcow2 $PREALLOC >&2
|
||||
volume_path=$(virsh vol-path --pool $LIBVIRT_STORAGE_POOL $VOL_NAME)
|
||||
# Pre-touch the VM to set +C, as it can only be set on empty files.
|
||||
sudo touch "$volume_path"
|
||||
sudo chattr +C "$volume_path" || true
|
||||
$TOP_DIR/scripts/configure-vm \
|
||||
--bootdev network --name $NAME --image "$volume_path" \
|
||||
--arch $ARCH --cpus $CPU --memory $MEM --libvirt-nic-driver $LIBVIRT_NIC_DRIVER \
|
||||
--emulator $EMULATOR --network $BRIDGE $VM_LOGGING >&2
|
||||
|
||||
fi
|
||||
|
||||
# echo mac
|
||||
virsh dumpxml $NAME | grep "mac address" | head -1 | cut -d\' -f2
|
28
devstack/tools/ironic/scripts/setup-network
Executable file
28
devstack/tools/ironic/scripts/setup-network
Executable file
@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# **setup-network**
|
||||
|
||||
# Setups openvswitch libvirt network suitable for
|
||||
# running baremetal poseur nodes for ironic testing purposes
|
||||
|
||||
set -exu
|
||||
|
||||
LIBVIRT_CONNECT_URI=${LIBVIRT_CONNECT_URI:-"qemu:///system"}
|
||||
|
||||
# Keep track of the DevStack directory
|
||||
TOP_DIR=$(cd $(dirname "$0")/.. && pwd)
|
||||
BRIDGE_SUFFIX=${1:-''}
|
||||
BRIDGE_NAME=brbm$BRIDGE_SUFFIX
|
||||
|
||||
export VIRSH_DEFAULT_CONNECT_URI="$LIBVIRT_CONNECT_URI"
|
||||
|
||||
# Only add bridge if missing
|
||||
(sudo ovs-vsctl list-br | grep ${BRIDGE_NAME}$) || sudo ovs-vsctl add-br ${BRIDGE_NAME}
|
||||
|
||||
# Remove bridge before replacing it.
|
||||
(virsh net-list | grep "${BRIDGE_NAME} ") && virsh net-destroy ${BRIDGE_NAME}
|
||||
(virsh net-list --inactive | grep "${BRIDGE_NAME} ") && virsh net-undefine ${BRIDGE_NAME}
|
||||
|
||||
virsh net-define <(sed s/brbm/$BRIDGE_NAME/ $TOP_DIR/templates/brbm.xml)
|
||||
virsh net-autostart ${BRIDGE_NAME}
|
||||
virsh net-start ${BRIDGE_NAME}
|
6
devstack/tools/ironic/templates/brbm.xml
Normal file
6
devstack/tools/ironic/templates/brbm.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<network>
|
||||
<name>brbm</name>
|
||||
<forward mode='bridge'/>
|
||||
<bridge name='brbm'/>
|
||||
<virtualport type='openvswitch'/>
|
||||
</network>
|
14
devstack/tools/ironic/templates/tftpd-xinetd.template
Normal file
14
devstack/tools/ironic/templates/tftpd-xinetd.template
Normal file
@ -0,0 +1,14 @@
|
||||
service tftp
|
||||
{
|
||||
protocol = udp
|
||||
port = 69
|
||||
socket_type = dgram
|
||||
wait = yes
|
||||
user = root
|
||||
server = /usr/sbin/in.tftpd
|
||||
server_args = -v -v -v -v -v --map-file %TFTPBOOT_DIR%/map-file %TFTPBOOT_DIR%
|
||||
disable = no
|
||||
# This is a workaround for Fedora, where TFTP will listen only on
|
||||
# IPv6 endpoint, if IPv4 flag is not used.
|
||||
flags = IPv4
|
||||
}
|
49
devstack/tools/ironic/templates/vm.xml
Normal file
49
devstack/tools/ironic/templates/vm.xml
Normal file
@ -0,0 +1,49 @@
|
||||
<domain type='%(engine)s'>
|
||||
<name>%(name)s</name>
|
||||
<memory unit='KiB'>%(memory)s</memory>
|
||||
<vcpu>%(cpus)s</vcpu>
|
||||
<os>
|
||||
<type arch='%(arch)s' machine='pc-1.0'>hvm</type>
|
||||
<boot dev='%(bootdev)s'/>
|
||||
<bootmenu enable='no'/>
|
||||
%(bios_serial)s
|
||||
</os>
|
||||
<features>
|
||||
<acpi/>
|
||||
<apic/>
|
||||
<pae/>
|
||||
</features>
|
||||
<clock offset='utc'/>
|
||||
<on_poweroff>destroy</on_poweroff>
|
||||
<on_reboot>restart</on_reboot>
|
||||
<on_crash>restart</on_crash>
|
||||
<devices>
|
||||
<emulator>%(emulator)s</emulator>
|
||||
<disk type='file' device='disk'>
|
||||
<driver name='qemu' type='qcow2' cache='writeback'/>
|
||||
<source file='%(imagefile)s'/>
|
||||
<target dev='vda' bus='virtio'/>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
|
||||
</disk>
|
||||
<controller type='ide' index='0'>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
|
||||
</controller>
|
||||
<interface type='network'>
|
||||
<source network='%(network)s'/>
|
||||
<virtualport type='openvswitch'/>
|
||||
<model type='%(nicdriver)s'/>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
|
||||
</interface>
|
||||
<input type='mouse' bus='ps2'/>
|
||||
<graphics type='vnc' port='-1' autoport='yes'/>
|
||||
<video>
|
||||
<model type='cirrus' vram='9216' heads='1'/>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
|
||||
</video>
|
||||
%(console_log)s
|
||||
<memballoon model='virtio'>
|
||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
|
||||
</memballoon>
|
||||
</devices>
|
||||
</domain>
|
||||
|
Loading…
Reference in New Issue
Block a user