990287677b
This handle the senlin cluster disable/clean for disable it will detach the polices from the cluster and resize the cluster to zero (empty cluster) for clean it will deatach the policies from cluster clean the policies, receivers then clean the clusters then clean the profiles Change-Id: I09421d55c66d91a747bc786fdd250730c79dfd34
289 lines
11 KiB
Bash
Executable File
289 lines
11 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
# This script populates the project set in the environment variable
|
|
# OS_PROJECT_NAME with various resources. The purpose is to test
|
|
# ospurge.
|
|
|
|
# Be strict but don't exit automatically on error (exit_on_failure handles that)
|
|
set -xuo pipefail
|
|
|
|
# Set this so -x doesn't spam warnings
|
|
RC_DIR=$(cd $(dirname "${BASH_SOURCE:-$0}") && pwd)
|
|
|
|
function exit_on_failure {
|
|
RET_CODE=$?
|
|
ERR_MSG=$1
|
|
if [ ${RET_CODE} -ne 0 ]; then
|
|
echo $ERR_MSG
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
function exit_if_empty {
|
|
STRING=${1:-}
|
|
ERR_MSG=${2:-}
|
|
if [ -z "$STRING" ]; then
|
|
echo $ERR_MSG
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
function cleanup {
|
|
if [[ -f "${UUID}.raw" ]]; then
|
|
rm "${UUID}.raw"
|
|
fi
|
|
|
|
}
|
|
|
|
function wait_for_volume_to_be_available {
|
|
local vol_id=$1
|
|
|
|
vol_status=$(openstack volume show ${vol_id} | awk '/ status /{print $4}')
|
|
while [ ${vol_status} != "available" ]; do
|
|
echo "Status of volume $vol_id is $vol_status. Waiting 3 sec"
|
|
sleep 3
|
|
vol_status=$(openstack volume show ${vol_id} | awk '/ status /{print $4}')
|
|
done
|
|
}
|
|
|
|
function wait_for_lb_active {
|
|
LB_ID=$1
|
|
LB_STATUS=$(openstack loadbalancer show ${LB_ID} -c provisioning_status -f value)
|
|
while [ $LB_STATUS != "ACTIVE" ]; do
|
|
if [ $LB_STATUS == "ERROR" ]; then
|
|
echo "Status of LB ${LB_NAME} is $LB_STATUS. Failing." && false
|
|
exit_on_failure "Octavia LoadBalancer ${LB_NAME} entered $LB_STATUS status."
|
|
fi
|
|
|
|
echo "Status of LB ${LB_NAME} is $LB_STATUS. Waiting 3 sec"
|
|
sleep 3
|
|
LB_STATUS=$(openstack loadbalancer show ${LB_ID} -c provisioning_status -f value)
|
|
done
|
|
}
|
|
|
|
# Check if needed environment variable OS_PROJECT_NAME is set and non-empty.
|
|
: "${OS_PROJECT_NAME:?Need to set OS_PROJECT_NAME non-empty}"
|
|
|
|
# Some random UUID
|
|
# Commented to workaround a nova #1730756 with non-ASCII VM name:
|
|
# https://bugs.launchpad.net/nova/+bug/1730756
|
|
ASCII_UUID="$(cat /proc/sys/kernel/random/uuid)"
|
|
UUID="♫${ASCII_UUID}✓"
|
|
# Name of external network
|
|
EXTNET_NAME=${EXTNET_NAME:-public}
|
|
# Name of flavor used to spawn a VM
|
|
FLAVOR=${FLAVOR:-m1.nano}
|
|
# Image used for the VM
|
|
VMIMG_NAME=${VMIMG_NAME:-cirros-0.4.0-x86_64-disk}
|
|
# Zone name used for the Designate Zone
|
|
ZONE_NAME="${ASCII_UUID//-/}.com."
|
|
# LoadBalancer name used for the Octavia LoadBalancer
|
|
LB_NAME="lb-${UUID//-/}"
|
|
# For senlin
|
|
CL_NAME="cl-${ASCII_UUID//-/}"
|
|
PR_NAME="pr-${ASCII_UUID//-/}"
|
|
PL_NAME="pl-${ASCII_UUID//-/}"
|
|
RC_NAME="rc-${ASCII_UUID//-/}"
|
|
LB_LISTENER_NAME="listener-${UUID//-/}"
|
|
# Subnet used for the Octavia LoadBalancer VIP
|
|
LB_VIP_SUBNET_ID=${LB_VIP_SUBNET_ID:-$UUID}
|
|
|
|
|
|
|
|
################################
|
|
### Check resources exist
|
|
### Do that early to fail early
|
|
################################
|
|
# Retrieve external network ID
|
|
EXTNET_ID=$(openstack network show $EXTNET_NAME | awk '/ id /{print $4}')
|
|
exit_if_empty "$EXTNET_ID" "Unable to retrieve ID of external network $EXTNET_NAME"
|
|
|
|
exit_if_empty "$(openstack flavor list | grep ${FLAVOR})" "Flavor $FLAVOR is unknown to Nova"
|
|
|
|
# Look for the $VMIMG_NAME image and get its ID
|
|
IMAGE_ID=$(openstack image list | awk "/ $VMIMG_NAME /{print \$2}")
|
|
exit_if_empty "$IMAGE_ID" "Image $VMIMG_NAME could not be found"
|
|
|
|
# Create a file that will be used to populate Glance and Swift
|
|
dd if="/dev/zero" of="${UUID}.raw" bs=1M count=5
|
|
trap cleanup SIGHUP SIGINT SIGTERM EXIT
|
|
|
|
|
|
|
|
###############################
|
|
### Cinder
|
|
###############################
|
|
# Create a volume
|
|
VOL_ID=$(openstack volume create --size 1 ${UUID} | awk '/ id /{print $4}')
|
|
exit_on_failure "Unable to create volume"
|
|
exit_if_empty "$VOL_ID" "Unable to retrieve ID of volume ${UUID}"
|
|
wait_for_volume_to_be_available ${VOL_ID}
|
|
|
|
# Snapshot the volume (note that it has to be detached, unless using --force)
|
|
openstack volume snapshot create --volume $VOL_ID ${UUID}
|
|
exit_on_failure "Unable to snapshot volume ${UUID}"
|
|
|
|
# Backup volume
|
|
# Don't exit on failure as Cinder Backup is not available on all clouds
|
|
openstack volume backup create --name ${UUID} $VOL_ID || true
|
|
|
|
|
|
|
|
###############################
|
|
### Neutron
|
|
###############################
|
|
# Create a private network and check it exists
|
|
NET_ID=$(neutron net-create ${UUID} | awk '/ id /{print $4}')
|
|
exit_on_failure "Creation of network ${UUID} failed"
|
|
echo "Network ${UUID} created, id $NET_ID"
|
|
exit_if_empty "$NET_ID" "Unable to retrieve ID of network ${UUID}"
|
|
|
|
# Add network's subnet
|
|
SUBNET_ID=$(neutron subnet-create --name ${UUID} $NET_ID 192.168.0.0/24 | awk '/ id /{print $4}')
|
|
exit_on_failure "Unable to create subnet ${UUID} for network $NET_ID"
|
|
exit_if_empty "$SUBNET_ID" "Unable to retrieve ID of subnet ${UUID}"
|
|
|
|
# Create an unused port
|
|
neutron port-create $NET_ID
|
|
|
|
# Create a router
|
|
ROUT_ID=$(neutron router-create ${UUID} | awk '/ id /{print $4}')
|
|
exit_on_failure "Unable to create router ${UUID}"
|
|
exit_if_empty "$ROUT_ID" "Unable to retrieve ID of router ${UUID}"
|
|
|
|
# Set router's gateway
|
|
openstack router set --external-gateway $EXTNET_ID $ROUT_ID
|
|
exit_on_failure "Unable to set gateway to router ${UUID}"
|
|
|
|
# Connect router on internal network
|
|
openstack router add subnet $ROUT_ID $SUBNET_ID
|
|
exit_on_failure "Unable to add interface on subnet ${UUID} to router ${UUID}"
|
|
|
|
# Create a floating IP and retrieve its IP Address
|
|
FIP_ADD=$(openstack floating ip create $EXTNET_NAME | awk '/ floating_ip_address /{print $4}')
|
|
exit_if_empty "$FIP_ADD" "Unable to create or retrieve floating IP"
|
|
|
|
# Create a security group
|
|
SECGRP_ID=$(neutron security-group-create ${UUID} | awk '/ id /{print $4}')
|
|
exit_on_failure "Unable to create security group ${UUID}"
|
|
exit_if_empty "$SECGRP_ID" "Unable to retrieve ID of security group ${UUID}"
|
|
|
|
# Add a rule to previously created security group
|
|
neutron security-group-rule-create --direction ingress --protocol TCP \
|
|
--port-range-min 22 --port-range-max 22 --remote-ip-prefix 0.0.0.0/0 $SECGRP_ID
|
|
|
|
|
|
|
|
###############################
|
|
### Nova
|
|
###############################
|
|
# Launch a VM
|
|
VM_ID=$(openstack server create --flavor $FLAVOR --image $IMAGE_ID --nic net-id=$NET_ID ${UUID} | awk '/ id /{print $4}')
|
|
exit_on_failure "Unable to boot VM ${UUID}"
|
|
exit_if_empty "$VM_ID" "Unable to retrieve ID of VM ${UUID}"
|
|
|
|
|
|
|
|
###############################
|
|
### Glance
|
|
###############################
|
|
# Upload glance image
|
|
openstack image create --disk-format raw --container-format bare --file ${UUID}.raw ${UUID}
|
|
exit_on_failure "Unable to create Glance iamge ${UUID}"
|
|
|
|
|
|
|
|
###############################
|
|
### Swift
|
|
###############################
|
|
# Don't exit on failure as Swift is not available on all clouds
|
|
swift upload ${UUID} ${UUID}.raw || true
|
|
|
|
|
|
###############################
|
|
### Designate
|
|
###############################
|
|
# Create Designate Zone
|
|
openstack zone create --email hostmaster@example.com ${ZONE_NAME}
|
|
exit_on_failure "Unable to create Designate Zone ${ZONE_NAME}"
|
|
|
|
|
|
###############################
|
|
### Senlin
|
|
###############################
|
|
# Create a cluster
|
|
IMAGE_NAME=$(openstack image list | awk "/ $VMIMG_NAME /{print \$4}")
|
|
profile_spec="/tmp/profile_spec.yaml"
|
|
policy_spec="/tmp/policy_spec.yaml"
|
|
echo -e "type: senlin.policy.deletion\nversion: 1.0\ndescription: test " > $policy_spec
|
|
echo -e "properties:\n criteria: OLDEST_FIRST\n destroy_after_deletion: True" >> $policy_spec
|
|
echo -e "type: os.nova.server\nversion: 1.0\nproperties:\n name: clustering-test" > $profile_spec
|
|
echo -e " flavor: $FLAVOR\n image: "$IMAGE_NAME"\n networks:\n - network: $EXTNET_NAME" >> $profile_spec
|
|
profile_status=$(openstack cluster profile create --spec-file $profile_spec $PR_NAME)
|
|
exit_on_failure "Unable to create profile (${profile_status}) as $OS_USERNAME/$OS_PROJECT_NAME"
|
|
policy_status=$(openstack cluster policy create --spec-file $policy_spec $PL_NAME)
|
|
exit_on_failure "Unable to create policy (${policy_status}) as $OS_USERNAME/$OS_PROJECT_NAME"
|
|
cluster_status=$(openstack cluster create --desired-capacity 1 --min-size 0 --max-size 1 --profile $PR_NAME $CL_NAME)
|
|
exit_on_failure "Unable to create cluster (${cluster_status}) as $OS_USERNAME/$OS_PROJECT_NAME"
|
|
attach_policy=$(openstack cluster policy attach --policy $PL_NAME $CL_NAME)
|
|
exit_on_failure "Unable to attach policy to cluster (${attach_policy}) as $OS_USERNAME/$OS_PROJECT_NAME"
|
|
attach_receiver=$(openstack cluster receiver create --cluster $CL_NAME --action CLUSTER_SCALE_OUT --type webhook $RC_NAME)
|
|
exit_on_failure "Unable to attach receiver to cluster (${attach_receiver}) as $OS_USERNAME/$OS_PROJECT_NAME"
|
|
|
|
###############################
|
|
### Octavia
|
|
###############################
|
|
# Create Octavia LoadBalancer
|
|
LB_ID=$(openstack loadbalancer create --name ${LB_NAME} --vip-subnet-id ${LB_VIP_SUBNET_ID} -f value -c id)
|
|
exit_on_failure "Unable to create Octavia LoadBalancer ${LB_NAME} (${LB_ID}) as $OS_USERNAME/$OS_PROJECT_NAME"
|
|
# Wait for LB to be active
|
|
wait_for_lb_active $LB_ID
|
|
|
|
# Create Octavia Listener
|
|
openstack loadbalancer listener create \
|
|
--protocol HTTP --protocol-port 80 --name ${LB_LISTENER_NAME} \
|
|
${LB_NAME}
|
|
exit_on_failure "Unable to create Octavia Listener ${LB_LISTENER_NAME}"
|
|
# Wait for LB to be active
|
|
wait_for_lb_active $LB_ID
|
|
|
|
|
|
###############################
|
|
### Link resources
|
|
###############################
|
|
wait_for_volume_to_be_available $VOL_ID
|
|
|
|
|
|
# Wait for VM to be active
|
|
VM_STATUS=$(nova show --minimal $VM_ID | awk '/ status /{print $4}')
|
|
while [ $VM_STATUS != "ACTIVE" ]; do
|
|
echo "Status of VM ${UUID} is $VM_STATUS. Waiting 3 sec"
|
|
sleep 3
|
|
VM_STATUS=$(nova show --minimal $VM_ID | awk '/ status /{print $4}')
|
|
done
|
|
|
|
# Attach volume
|
|
# This must be done before instance snapshot otherwise we could run into
|
|
# ERROR (Conflict): Cannot 'attach_volume' while instance is in task_state
|
|
# image_pending_upload
|
|
openstack server add volume $VM_ID $VOL_ID
|
|
exit_on_failure "Unable to attach volume $VOL_ID to VM $VM_ID"
|
|
|
|
# Associate floating IP
|
|
# It as far away from the network creation as possible, because associating
|
|
# a FIP requires the network to be 'UP' (which could take several secs)
|
|
# See https://github.com/openstack/nova/blob/1a30fda13ae78f4e40b848cacbf6278a359a91cb/nova/api/openstack/compute/floating_ips.py#L229
|
|
openstack server add floating ip $VM_ID $FIP_ADD
|
|
exit_on_failure "Unable to associate floating IP $FIP_ADD to VM ${UUID}"
|