#!/bin/bash # # Script that spawns an instance # Has 2 operational modes: # - workload: spawn VM with floating ip (default) # - sanity: spanw VM with floating ip assert it's ssh'able, # delete VM and associated resources # if [[ -n ${1} ]]; then MODE="${1}" else MODE="workload" fi function sanity_teardown { # remove auxiliary resources local timeout_seconds=180 local elapsed_seconds=0 echo "Remove ${INSTANCE_FIP} from ${INSTANCE_NAME}" openstack server remove floating ip ${INSTANCE_NAME} ${INSTANCE_FIP} echo "Delete floating ip ${INSTANCE_FIP}" openstack floating ip delete ${INSTANCE_FIP} echo "Remove VM ${INSTANCE_NAME}" openstack server delete ${INSTANCE_NAME} while true; do openstack server list -f value -c Name | grep -q ${INSTANCE_NAME} if [[ ${?} -eq 1 ]]; then echo "Instance ${INSTANCE_NAME} successfully removed" break fi elapsed_seconds=$(( ${elapsed_seconds} + 5 )) if [ $elapsed_seconds -ge $timeout_seconds ]; then echo "FAILURE: Failed to remove instance ${INSTANCE_NAME}" exit 1 fi done echo "Remove cinder volume ${CINDER_VOL_ID}" openstack volume delete ${CINDER_VOL_ID} echo "Clear default gateway from ${TENANT_NET_NAME}_router" openstack router unset --external-gateway ${TENANT_NET_NAME}_router echo "Remove subnet ${TENANT_NET_NAME}_subnet from router ${TENANT_NET_NAME}_router" openstack router remove subnet ${TENANT_NET_NAME}_router ${TENANT_NET_NAME}_subnet echo "Remove router ${TENANT_NET_NAME}_router" openstack router delete ${TENANT_NET_NAME}_router echo "Remove subnet ${TENANT_NET_NAME}_subnet" openstack subnet delete ${TENANT_NET_NAME}_subnet echo "Remove network ${TENANT_NET_NAME}" openstack network delete ${TENANT_NET_NAME} echo "Remove security group ${SECGROUP_NAME}" openstack security group delete ${SECGROUP_NAME} echo "Remove keypair ${KEYPAIR_NAME}" openstack keypair delete ${KEYPAIR_NAME} echo "Remove image ${IMAGE_NAME}" openstack image delete ${IMAGE_NAME} echo "Remove file ${IMAGE_FILE}" rm -Rf $(dirname ${IMAGE_FILE}) } SUFFIX=$(openssl rand -hex 5) OVERCLOUD_RC='{{ overcloud_rc }}' IMAGE_URL='{{ workload_image_url }}' IMAGE_NAME="upgrade_workload_${SUFFIX}" IMAGE_FILE="$(mktemp -d )/upgrade_workload_image.qcow2" INSTANCE_NAME="instance_${SUFFIX}" INSTANCE_USER='{{ workload_user }}' KEYPAIR_NAME="userkey_${SUFFIX}" FLAVOR_NAME="v1-1G-{{ workload_disk}}G-${SUFFIX}" SECGROUP_NAME="allow-icmp-ssh-${SUFFIX}" TENANT_NET_NAME="internal_net_${SUFFIX}" EXTERNAL_NET_NAME='{{ external_network_name }}' source ${OVERCLOUD_RC} ## create image openstack image list | grep ${IMAGE_NAME} if [ $? -ne 0 ]; then echo "Downloading image ${IMAGE_URL}" curl --silent --retry 3 -L -4 -o ${IMAGE_FILE} ${IMAGE_URL} if [ $? -ne 0 ]; then echo "Failed to download ${IMAGE_URL}" exit 1 fi echo "Uploading ${IMAGE_NAME} to Glance" openstack image create \ --file ${IMAGE_FILE} \ --disk-format qcow2 \ --container-format bare \ ${IMAGE_NAME} fi ## create user key openstack keypair list | grep ${KEYPAIR_NAME} if [ $? -ne 0 ]; then echo "Creating keypair ${KEYPAIR_NAME}" openstack keypair create --public-key ~/.ssh/id_rsa.pub ${KEYPAIR_NAME} fi ## create flavor openstack flavor list | grep ${FLAVOR_NAME} if [ $? -ne 0 ]; then echo "Creating flavor ${FLAVOR_NAME}" openstack flavor create --vcpus {{ workload_vcpu }} \ --ram {{ workload_memory }} \ --disk {{ workload_disk }} \ --swap {{ workload_swap }} \ $FLAVOR_NAME fi ## create networking openstack network list | grep ${TENANT_NET_NAME} if [ $? -ne 0 ]; then NAMESERVER=$(grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' /etc/resolv.conf | head -1) echo "Creating router ${TENANT_NET_NAME}_router" openstack router create ${TENANT_NET_NAME}_router echo "Creating network ${TENANT_NET_NAME}" openstack network create ${TENANT_NET_NAME} echo "Creating subnet ${TENANT_NET_NAME}_subnet" openstack subnet create \ --subnet-range 192.168.0.0/24 \ --allocation-pool start=192.168.0.10,end=192.168.0.100 \ --gateway 192.168.0.254 \ --dns-nameserver ${NAMESERVER} \ --network ${TENANT_NET_NAME} \ ${TENANT_NET_NAME}_subnet echo "Add subnet ${TENANT_NET_NAME}_subnet to router ${TENANT_NET_NAME}_router" openstack router add subnet ${TENANT_NET_NAME}_router ${TENANT_NET_NAME}_subnet echo "Set external-gateway for ${TENANT_NET_NAME}_router" openstack router set --external-gateway ${EXTERNAL_NET_NAME} ${TENANT_NET_NAME}_router fi ## create security group openstack security group list | grep ${SECGROUP_NAME} if [ $? -ne 0 ]; then echo "Creating security group ${SECGROUP_NAME}" openstack security group create ${SECGROUP_NAME} echo "Creating rules for ports 22,80,443 in security group ${SECGROUP_NAME}" openstack security group rule create --proto icmp ${SECGROUP_NAME} openstack security group rule create --proto tcp --dst-port 22 ${SECGROUP_NAME} openstack security group rule create --proto tcp --dst-port 80 ${SECGROUP_NAME} openstack security group rule create --proto tcp --dst-port 443 ${SECGROUP_NAME} fi ## create instance TENANT_NET_ID=$( openstack network show -f json ${TENANT_NET_NAME} | jq -r -c '.id' ) echo "Creating overcloud instance ${INSTANCE_NAME}" openstack server create \ --image ${IMAGE_NAME} \ --flavor ${FLAVOR_NAME} \ --security-group ${SECGROUP_NAME} \ --key-name ${KEYPAIR_NAME} \ --nic net-id=${TENANT_NET_ID} \ ${INSTANCE_NAME} timeout_seconds=120 elapsed_seconds=0 while true; do INSTANCE_STATUS=$(openstack server show ${INSTANCE_NAME} -f json | jq -r '.status') case "${INSTANCE_STATUS}" in "ACTIVE") echo "${INSTANCE_NAME} reached 'ACTIVE' status" break ;; "ERROR") echo "${INSTANCE_NAME} failed" exit 1 esac sleep 3 elapsed_seconds=$(expr $elapsed_seconds + 3) if [ $elapsed_seconds -ge $timeout_seconds ]; then echo "FAILURE: Instance failed to boot within ${elapsed_seconds} seconds" openstack server show ${INSTANCE_NAME} -f json 2>&1 exit 1 fi done ## assign floating ip INSTANCE_FIP=$(openstack floating ip create ${EXTERNAL_NET_NAME} -f json | jq -r -c '.floating_ip_address' ) echo "Assign FIP[${INSTANCE_FIP}] to server ${INSTANCE_NAME}" openstack server add floating ip ${INSTANCE_NAME} ${INSTANCE_FIP} ## create and attach a volume CINDER_VOL_ID=$(openstack volume create --size 1 vol_${SUFFIX} -f json | jq -r .id) echo "Attach volume vol_${SUFFIX} to instance ${INSTANCE_NAME}" openstack server add volume ${INSTANCE_NAME} ${CINDER_VOL_ID} ## SSH to VM through it's floating ip if [[ "${MODE}" == "sanity" ]]; then timeout_seconds=180 elapsed_seconds=0 while true; do # assert instance is reachable via FIP echo " [$(date)] Trying to ssh to ${INSTANCE_FIP}" ssh -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ ${INSTANCE_USER}@${INSTANCE_FIP} 'whoami' if [[ ${?} -eq 0 ]]; then echo "Instance ${INSTANCE_NAME} is reachable via ${INSTANCE_FIP}" break fi sleep 3 elapsed_seconds=$(expr $elapsed_seconds + 3) if [ $elapsed_seconds -ge $timeout_seconds ]; then echo "FAILURE: Instance failed to boot." sanity_teardown exit 1 fi done fi if [[ "${MODE}" == "workload" ]]; then echo "floating-ip: ${INSTANCE_FIP}" > ~/${INSTANCE_NAME} fi if [[ "${MODE}" == "sanity" ]]; then sanity_teardown fi