b0a94a9249
This requires a patched version of diskimage-builder, and right now we have an ugly version wedge in delorean that prevents us from using it. In order to unblock all of the other work going on, disable localboot until we can resolve the delorean issue. Change-Id: I57a9e8ac6614c6097831f60372fe754fb2fcbf8a
391 lines
13 KiB
Bash
Executable File
391 lines
13 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -eu
|
|
set -o pipefail
|
|
|
|
SCRIPT_NAME=$(basename $0)
|
|
|
|
OS_AUTH_URL=${OS_AUTH_URL:-""}
|
|
if [ -z "$OS_AUTH_URL" ]; then
|
|
echo "You must source a stackrc file for the Undercloud."
|
|
exit 1
|
|
fi
|
|
|
|
function show_options () {
|
|
echo "Usage: $SCRIPT_NAME [options]"
|
|
echo
|
|
echo "Deploys instances via Ironic in preparation for an Overcloud deployment."
|
|
echo
|
|
echo "Options:"
|
|
echo " --register-nodes -- register nodes from a nodes json file"
|
|
echo " --nodes-json -- nodes json file containing node data"
|
|
echo " for registration."
|
|
echo " Default: nodes.json in the current directory"
|
|
echo " --discover-nodes -- Perform discovery of registered nodes."
|
|
echo " Powers on registered nodes to complete"
|
|
echo " the discovery process."
|
|
echo " --configure-bios -- Configure BIOS settings of "
|
|
echo " registered nodes."
|
|
echo " --configure-root-raid-volume -- Configure RAID volumes of registered"
|
|
echo " nodes."
|
|
echo " --configure-nonroot-raid-volumes -- Configure RAID volumes of registered"
|
|
echo " nodes."
|
|
echo " --setup-flavors -- Setup Nova flavors to match discovered"
|
|
echo " profiles"
|
|
echo " --show-profile -- Show matching profile of nodes"
|
|
echo " --deploy-nodes -- Deploy nodes"
|
|
echo " --check-ssh -- Check the root ssh connection to each"
|
|
echo " deployed node."
|
|
echo " --delete-stack -- Wait until the stack has deleted."
|
|
echo " --delete-nodes -- Delete all nodes."
|
|
echo " -x -- enable tracing"
|
|
echo " --help, -h -- Print this help message."
|
|
echo
|
|
exit $1
|
|
}
|
|
|
|
TEMP=$(getopt -o ,h -l,register-nodes,nodes-json:,discover-nodes,configure-bios,configure-root-raid-volume,configure-nonroot-raid-volumes,deploy-nodes,help,setup-flavors,show-profile,check-ssh,delete-stack,delete-nodes,config-tools-provision -o,x,h -n $SCRIPT_NAME -- "$@")
|
|
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
|
|
|
|
# Note the quotes around `$TEMP': they are essential!
|
|
eval set -- "$TEMP"
|
|
|
|
REGISTER_NODES=
|
|
NODES_JSON=
|
|
DISCOVER_NODES=
|
|
CONFIGURE_BIOS=
|
|
CONFIGURE_RAID_ROOT_VOLUMES=
|
|
CONFIGURE_RAID_NONROOT_VOLUMES=
|
|
DEPLOY_NODES=
|
|
SETUP_FLAVORS=
|
|
SHOW_PROFILE=
|
|
CHECK_SSH=
|
|
DELETE_STACK=
|
|
DELETE_NODES=
|
|
STDERR=/dev/null
|
|
|
|
# NOTE(bnemec): Can be removed once Ironic is updated to fix the
|
|
# novaclient.v1_1 deprecation warning
|
|
export PYTHONWARNINGS="ignore"
|
|
|
|
DEPLOY_NAME=${DEPLOY_NAME:-"ironic-discover"}
|
|
IRONIC=$(keystone endpoint-get --service baremetal | grep publicURL | awk '{ print $4; }')
|
|
IRONIC=${IRONIC%/}
|
|
|
|
while true ; do
|
|
case "$1" in
|
|
--register-nodes) REGISTER_NODES="1"; shift 1;;
|
|
--nodes-json) NODES_JSON="$2"; shift 2;;
|
|
--discover-nodes) DISCOVER_NODES="1"; shift 1;;
|
|
--configure-bios) CONFIGURE_BIOS="1"; shift 1;;
|
|
--configure-root-raid-volume) CONFIGURE_RAID_ROOT_VOLUMES="1"; shift 1;;
|
|
--configure-nonroot-raid-volumes) CONFIGURE_RAID_NONROOT_VOLUMES="1"; shift 1;;
|
|
--show-profile) SHOW_PROFILE="1"; shift 1;;
|
|
--deploy-nodes) DEPLOY_NODES="1"; shift 1;;
|
|
--setup-flavors) SETUP_FLAVORS="1"; shift 1;;
|
|
--check-ssh) CHECK_SSH="1"; shift 1;;
|
|
--delete-stack) DELETE_STACK="1"; shift 1;;
|
|
--delete-nodes) DELETE_NODES="1"; shift 1;;
|
|
-x) set -x; STDERR=/dev/stderr; shift 1;;
|
|
-h | --help) show_options 0;;
|
|
--) shift ; break ;;
|
|
*) echo "Error: unsupported option $1." ; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
function register_nodes {
|
|
NODES_JSON=${NODES_JSON:-"nodes.json"}
|
|
NULL_STATS=${NULL_STATS:-0}
|
|
tmp_json=$NODES_JSON
|
|
if [ "$NULL_STATS" = "1" ]; then
|
|
tmp_json=$(mktemp)
|
|
jq '.nodes[].memory=null | .nodes[].disk=null | .nodes[].arch=null | .nodes[].cpu=null' $NODES_JSON > $tmp_json
|
|
fi
|
|
echo " Registering nodes from $NODES_JSON"
|
|
register-nodes --service-host undercloud --nodes <(jq '.nodes' $tmp_json) 1>/dev/null
|
|
if [ "$NULL_STATS" = "1" ]; then
|
|
rm -f $tmp_json
|
|
fi
|
|
|
|
deploy_kernel_id=$(glance image-show bm-deploy-kernel | awk ' / id / {print $4}')
|
|
deploy_ramdisk_id=$(glance image-show bm-deploy-ramdisk | awk ' / id / {print $4}')
|
|
|
|
# Add the local boot capability and deploy_{kernel, ramdisk} parameters
|
|
node_list=$(ironic node-list --limit 0)
|
|
node_ids=$(echo "$node_list" | tail -n +4 | head -n -1 | awk -F "| " '{print $2}')
|
|
for node_id in $node_ids; do
|
|
ironic node-update $node_id add properties/capabilities="boot_option:local" driver_info/deploy_ramdisk=$deploy_ramdisk_id driver_info/deploy_kernel=$deploy_kernel_id 1> /dev/null
|
|
done
|
|
|
|
echo " Nodes registered."
|
|
echo
|
|
echo "$node_list"
|
|
echo
|
|
}
|
|
|
|
function discover_nodes {
|
|
echo " Discovering nodes."
|
|
node_ids=$(ironic node-list | tail -n +4 | head -n -1 | awk -F "| " '{print $2}')
|
|
for node_id in $node_ids; do
|
|
echo -n " Sending node ID $node_id to discoverd for discovery ... "
|
|
openstack baremetal introspection start $node_id
|
|
# tftpd chokes when serving 4 or more clients. Seeing less than 3Mb/s
|
|
# throughput. As a workaround, sleep for some time in between sending
|
|
# each node to discovery to give each node enough time to download the
|
|
# kernel/ramdisk before the next node is powered on.
|
|
sleep 15
|
|
echo "DONE."
|
|
done
|
|
|
|
echo " Polling discoverd for discovery results ... "
|
|
for node_id in $node_ids; do
|
|
echo -n " Result for node $node_id is ... "
|
|
while true; do
|
|
finished=$(openstack baremetal introspection status $node_id -f value -c finished)
|
|
if [ "$finished" = "True" ]; then
|
|
error=$(openstack baremetal introspection status $node_id -f value -c error)
|
|
if [ "$error" = "None" ]; then
|
|
echo "DISCOVERED."
|
|
else
|
|
echo "ERROR: $error"
|
|
fi
|
|
break
|
|
fi
|
|
sleep 15
|
|
done
|
|
done
|
|
echo
|
|
}
|
|
|
|
function configure_bios {
|
|
echo " Configuring BIOS."
|
|
node_ids=$(ironic node-list | tail -n +4 | head -n -1 | awk -F "| " '{print $2}')
|
|
for node_id in $node_ids; do
|
|
|
|
driver=$(ironic node-show $node_id | grep 'driver[ \t]' | awk -F "|" '{print $3}' | xargs)
|
|
|
|
if [ "$driver" == "pxe_drac" ]; then
|
|
echo -n " Configuring BIOS for node ID $node_id ... "
|
|
ironic node-vendor-passthru $node_id --http_method POST configure_bios_settings
|
|
echo "DONE. You might need to reboot the machine to apply the changes."
|
|
fi
|
|
done
|
|
echo
|
|
}
|
|
|
|
function configure_raid_volumes {
|
|
create_root_volume=$1
|
|
create_nonroot_volumes=$2
|
|
|
|
echo " Configuring RAID volumes."
|
|
node_ids=$(ironic node-list | tail -n +4 | head -n -1 | awk -F "| " '{print $2}')
|
|
for node_id in $node_ids; do
|
|
|
|
driver=$(ironic node-show $node_id | grep 'driver[ \t]' | awk -F "|" '{print $3}' | xargs)
|
|
|
|
if [ "$driver" == "pxe_drac" ]; then
|
|
echo -n " Configuring RAID volumes for node ID $node_id ... "
|
|
ironic node-vendor-passthru $node_id --http_method POST prepare_for_ready_state
|
|
ironic node-vendor-passthru $node_id --http_method POST create_raid_configuration \
|
|
create_root_volume=$create_root_volume \
|
|
create_nonroot_volumes=$create_nonroot_volumes
|
|
echo "DONE."
|
|
fi
|
|
done
|
|
echo
|
|
|
|
wait_for_drac_config_jobs
|
|
}
|
|
|
|
function wait_for_drac_config_jobs {
|
|
echo " Waiting for DRAC config jobs to finish ... "
|
|
|
|
node_ids=$(ironic node-list | tail -n +4 | head -n -1 | awk -F "| " '{print $2}')
|
|
for node_id in $node_ids; do
|
|
|
|
driver=$(ironic node-show $node_id | grep 'driver[ \t]' | awk -F "|" '{print $3}' | xargs)
|
|
|
|
if [ "$driver" == "pxe_drac" ]; then
|
|
echo -n " Waiting for node $node_id ... "
|
|
|
|
while true; do
|
|
jobs=$(ironic node-vendor-passthru $node_id --http_method GET list_unfinished_jobs)
|
|
|
|
if [[ $jobs == *"'unfinished_jobs': []"* ]]; then
|
|
break
|
|
fi
|
|
|
|
sleep 30
|
|
done
|
|
echo "DONE."
|
|
fi
|
|
done
|
|
echo
|
|
}
|
|
|
|
function wait_for_ssh {
|
|
echo " Waiting for ssh as root to be enabled ... "
|
|
echo
|
|
ips=$(nova list | tail -n +4 | head -n -1 | awk '{print $12}' | cut -d= -f2)
|
|
for ip in $ips; do
|
|
echo -n " checking $ip ... "
|
|
tripleo wait_for 300 1 ssh -o "PasswordAuthentication=no" -o "StrictHostKeyChecking=no" root@$ip ls
|
|
echo "DONE."
|
|
done
|
|
echo
|
|
}
|
|
|
|
|
|
function deploy_nodes {
|
|
wait_for_hypervisor_stats
|
|
DEPLOY_HEAT_TEMPLATE=${DEPLOY_HEAT_TEMPLATE:-"/usr/share/instack-undercloud/heat-templates/ironic-deployment.yaml"}
|
|
CONTROL_COUNT=${CONTROL_COUNT:-"1"}
|
|
COMPUTE_COUNT=${COMPUTE_COUNT:-"3"}
|
|
echo " Creating heat stack ... "
|
|
heat stack-create $DEPLOY_NAME -f $DEPLOY_HEAT_TEMPLATE -P "control_count=$CONTROL_COUNT" -P "compute_count=$COMPUTE_COUNT"
|
|
echo " Created."
|
|
echo
|
|
echo -n " Waiting for stack to finish ... "
|
|
echo
|
|
tripleo wait_for_stack_ready 60 10 $DEPLOY_NAME
|
|
echo "DONE."
|
|
heat stack-show $DEPLOY_NAME
|
|
heat stack-list
|
|
wait_for_ssh
|
|
echo
|
|
}
|
|
|
|
function setup_flavors {
|
|
if ! nova flavor-show baremetal_control 2>$STDERR 1>/dev/null; then
|
|
echo " Creating baremetal_control flavor ... "
|
|
nova flavor-create baremetal_control auto 2048 40 1
|
|
else
|
|
echo " baremetal_control flavor already exists."
|
|
fi
|
|
|
|
if ! nova flavor-show baremetal_compute 2>$STDERR 1>/dev/null; then
|
|
echo " Creating baremetal_compute flavor ... "
|
|
nova flavor-create baremetal_compute auto 4096 40 1
|
|
else
|
|
echo " baremetal_compute flavor already exists."
|
|
fi
|
|
|
|
echo
|
|
nova flavor-list
|
|
echo
|
|
|
|
echo " Setting baremetal_control flavor keys ... "
|
|
nova flavor-key baremetal_control set \
|
|
"cpu_arch"="x86_64" \
|
|
"profile=control"
|
|
nova flavor-show baremetal_control
|
|
|
|
echo " Setting baremetal_compute flavor keys ... "
|
|
nova flavor-key baremetal_compute set \
|
|
"cpu_arch"="x86_64" \
|
|
"profile=compute"
|
|
nova flavor-show baremetal_compute
|
|
}
|
|
|
|
function show_profile {
|
|
node_ids=$(ironic node-list | tail -n +4 | head -n -1 | awk -F "| " '{print $2}')
|
|
token=$(keystone token-get | grep ' id ' | awk '{print $4}')
|
|
echo " Querying assigned profiles ... "
|
|
echo
|
|
for node_id in $node_ids; do
|
|
echo " $node_id"
|
|
echo -n " "
|
|
curl -s -H "x-auth-token: $token" $IRONIC/v1/nodes/$node_id | jq '.properties.capabilities'
|
|
echo
|
|
done
|
|
echo
|
|
echo " DONE."
|
|
echo
|
|
}
|
|
|
|
function wait_for_hypervisor_stats {
|
|
node_ids=$(ironic node-list | tail -n +4 | head -n -1 | awk -F "| " '{print $2}')
|
|
expected_nodes=$(echo $node_ids | wc -w)
|
|
expected_memory=0
|
|
expected_vcpus=0
|
|
|
|
token=$(keystone token-get | grep ' id ' | awk '{print $4}')
|
|
echo -n " Wating for nova hypervisor stats ... "
|
|
for node_id in $node_ids; do
|
|
mem=$(curl -s -H "x-auth-token: $token" $IRONIC/v1/nodes/$node_id | jq '.properties.memory_mb | tonumber')
|
|
vcpu=$(curl -s -H "x-auth-token: $token" $IRONIC/v1/nodes/$node_id | jq '.properties.cpus | tonumber')
|
|
expected_memory=$(($expected_memory + $mem))
|
|
expected_vcpus=$(($expected_vcpus + $vcpu))
|
|
done
|
|
|
|
tripleo wait_for 180 1 wait_for_hypervisor_stats $expected_nodes $expected_memory $expected_vcpus
|
|
|
|
echo "DONE."
|
|
echo
|
|
}
|
|
|
|
function delete_stack {
|
|
heat stack-delete $DEPLOY_NAME
|
|
tripleo wait_for 90 2 ! heat stack-show $DEPLOY_NAME
|
|
}
|
|
|
|
function delete_nodes {
|
|
for n in $(ironic node-list | tail -n +4 | head -n -1 | awk '{print $2}'); do
|
|
ironic node-delete $n;
|
|
done
|
|
}
|
|
|
|
echo "Preparing for deployment..."
|
|
|
|
if [ "$REGISTER_NODES" = 1 ]; then
|
|
register_nodes
|
|
fi
|
|
|
|
if [ "$DISCOVER_NODES" = 1 ]; then
|
|
discover_nodes
|
|
fi
|
|
|
|
if [ "$CONFIGURE_BIOS" = 1 ]; then
|
|
configure_bios
|
|
fi
|
|
|
|
if [ "$CONFIGURE_RAID_ROOT_VOLUMES" = 1 ]; then
|
|
create_root_volume=true
|
|
create_nonroot_volumes=false
|
|
configure_raid_volumes $create_root_volume $create_nonroot_volumes
|
|
fi
|
|
|
|
if [ "$CONFIGURE_RAID_NONROOT_VOLUMES" = 1 ]; then
|
|
create_root_volume=false
|
|
create_nonroot_volumes=true
|
|
configure_raid_volumes $create_root_volume $create_nonroot_volumes
|
|
fi
|
|
|
|
if [ "$SETUP_FLAVORS" = 1 ]; then
|
|
setup_flavors
|
|
fi
|
|
|
|
if [ "$SHOW_PROFILE" = 1 ]; then
|
|
show_profile
|
|
fi
|
|
|
|
if [ "$CHECK_SSH" = 1 ]; then
|
|
wait_for_ssh
|
|
fi
|
|
|
|
if [ "$DELETE_STACK" = 1 ]; then
|
|
delete_stack
|
|
fi
|
|
|
|
if [ "$DELETE_NODES" = 1 ]; then
|
|
delete_nodes
|
|
fi
|
|
|
|
echo "Prepared."
|
|
|
|
if [ "$DEPLOY_NODES" = 1 ]; then
|
|
echo "Deploying..."
|
|
deploy_nodes
|
|
echo "Deployed."
|
|
fi
|