#!/bin/bash set -eux 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 TUSKAR= TEMPEST= # Default stack create timeout, in minutes # Note heat defaults to 60mins, which may not be enough when # creating large overclouds, 240 aligns with the undercloud keystone # token expiry, which is increased from the default 1 hour to 4. TIMEOUT=240 function show_options () { echo "Usage: $SCRIPT_NAME [options]" echo echo "Deploys an Overcloud." echo echo "Options:" echo " --tuskar -- will use tuskar for building the heat Template" echo " --timeout -- create timeout in minutes, default $TIMEOUT" echo " --tempest -- run tempest tests after deployment" echo exit $1 } TEMP=$(getopt -o ,h -l,tuskar,timeout:,tempest,help -n $SCRIPT_NAME -- "$@") if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi # Note the quotes around `$TEMP': they are essential! eval set -- "$TEMP" while true ; do case "$1" in --tuskar) TUSKAR="1"; shift 1;; --timeout) TIMEOUT="$2"; shift 2;; --tempest) TEMPEST="1"; shift 1;; -h | --help) show_options 0;; --) shift ; break ;; *) echo "Error: unsupported option $1." ; exit 1 ;; esac done # setup-baremetal requires this to be set export TRIPLEO_ROOT=. export INSTACK_ROOT=${INSTACK_ROOT:-"/usr/share"} export NODES_JSON=${NODES_JSON:-"instackenv.json"} export USE_IRONIC=1 export ROOT_DISK=${ROOT_DISK:-10} # Must wait for baremetal nodes to register as nova hypervisors expected_nodes=$(jq ".nodes | length" $NODES_JSON) expected_memory=$(jq ".nodes | map(.memory | tonumber) | add" $NODES_JSON) expected_vcpus=$(jq ".nodes | map(.cpu | tonumber) | add" $NODES_JSON) tripleo wait_for 180 1 wait_for_hypervisor_stats $expected_nodes $expected_memory $expected_vcpus if heat stack-show overcloud > /dev/null; then HEAT_OP=${HEAT_OP:-stack-update} else HEAT_OP=${HEAT_OP:-stack-create} fi if [ "$HEAT_OP" = "stack-create" ]; then tripleo setup-overcloud-passwords -o tripleo-overcloud-passwords else tripleo setup-overcloud-passwords tripleo-overcloud-passwords fi source tripleo-overcloud-passwords # NOTE(bnemec): Hopefully this script will eventually be converted to # Python and then we can kill this sort of hackery. UNDERCLOUD_CEILOMETER_SNMPD_PASSWORD=$(python -c "import ConfigParser; p = ConfigParser.ConfigParser(); p.read('undercloud-passwords.conf'); print(p.get('auth', 'undercloud_ceilometer_snmpd_password'))") NeutronFlatNetworks=${NeutronFlatNetworks:-'datacentre'} NeutronPhysicalBridge=${NeutronPhysicalBridge:-'br-ex'} NeutronBridgeMappings=${NeutronBridgeMappings:-'datacentre:br-ex'} # Define the interface that will be bridged onto the Neutron defined # network. NeutronPublicInterface=${NeutronPublicInterface:-nic1} HypervisorNeutronPublicInterface=${HypervisorNeutronPublicInterface:-$NeutronPublicInterface} NEUTRON_NETWORK_TYPE=${NEUTRON_NETWORK_TYPE:-gre} NEUTRON_TUNNEL_TYPES=${NEUTRON_TUNNEL_TYPES:-gre} # Define the overcloud libvirt type for virtualization. kvm for # baremetal, qemu for an overcloud running in vm's. OVERCLOUD_LIBVIRT_TYPE=${OVERCLOUD_LIBVIRT_TYPE:-qemu} NtpServer=${NtpServer:-""} CONTROLSCALE=${CONTROLSCALE:-1} COMPUTESCALE=${COMPUTESCALE:-1} CEPHSTORAGESCALE=${CEPHSTORAGESCALE:-0} BLOCKSTORAGESCALE=${BLOCKSTORAGESCALE:-0} SWIFTSTORAGESCALE=${SWIFTSTORAGESCALE:-0} # Default all image parameters to use overcloud-full OVERCLOUD_CONTROLLER_IMAGE=${OVERCLOUD_CONTROLLER_IMAGE:-overcloud-full} OVERCLOUD_COMPUTE_IMAGE=${OVERCLOUD_COMPUTE_IMAGE:-overcloud-full} OVERCLOUD_BLOCKSTORAGE_IMAGE=${OVERCLOUD_BLOCKSTORAGE_IMAGE:-overcloud-full} OVERCLOUD_SWIFTSTORAGE_IMAGE=${OVERCLOUD_SWIFTSTORAGE_IMAGE:-overcloud-full} OVERCLOUD_CEPHSTORAGE_IMAGE=${OVERCLOUD_CEPHSTORAGE_IMAGE:-overcloud-full} # Default flavor parameters export OVERCLOUD_CONTROL_FLAVOR=${OVERCLOUD_CONTROL_FLAVOR:-"baremetal"} export OVERCLOUD_COMPUTE_FLAVOR=${OVERCLOUD_COMPUTE_FLAVOR:-"baremetal"} export OVERCLOUD_CEPHSTORAGE_FLAVOR=${OVERCLOUD_CEPHSTORAGE_FLAVOR:-"baremetal"} # Even though we are not deploying nodes with these roles, the templates will # still validate that a flavor exists, so just use the baremetal_compute flavor # for now. export OVERCLOUD_BLOCKSTORAGE_FLAVOR=${OVERCLOUD_BLOCKSTORAGE_FLAVOR:-"baremetal"} export OVERCLOUD_SWIFTSTORAGE_FLAVOR=${OVERCLOUD_SWIFTSTORAGE_FLAVOR:-"baremetal"} # Satellite parameters export REG_ACTIVATION_KEY=${REG_ACTIVATION_KEY:-"''"} export REG_ORG=${REG_ORG:-"''"} export REG_FORCE=${REG_FORCE:-"1"} export REG_SAT_URL=${REG_SAT_URL:-"''"} export REG_METHOD=${REG_METHOD:-"''"} export OVERCLOUD_RESOURCE_REGISTRY=${OVERCLOUD_RESOURCE_REGISTRY:-"/usr/share/openstack-tripleo-heat-templates/overcloud-resource-registry-puppet.yaml"} NeutronControlPlaneID=$(neutron net-show ctlplane | grep ' id ' | awk '{print $4}') # $OVERCLOUD_EXTRA is for passing any additional arbitrary options to heat # stack-{create,update} export OVERCLOUD_EXTRA=${OVERCLOUD_EXTRA:-""} if [ "$REG_METHOD" = "satellite" ]; then export OVERCLOUD_SATELLITE_ENV=${OVERCLOUD_SATELLITE_ENV:-overcloud-env-satellite.json} if [ -f $OVERCLOUD_SATELLITE_ENV ]; then SATELLITE_ENV_JSON=$(cat $OVERCLOUD_SATELLITE_ENV) else SATELLITE_ENV_JSON="{}" fi SATELLITE_ENV_JSON=$(jq ".parameter_defaults.rhel_reg_activation_key = \"$REG_ACTIVATION_KEY\"" <<< $SATELLITE_ENV_JSON) SATELLITE_ENV_JSON=$(jq ".parameter_defaults.rhel_reg_sat_url = \"$REG_SAT_URL\"" <<< $SATELLITE_ENV_JSON) SATELLITE_ENV_JSON=$(jq ".parameter_defaults.rhel_reg_org = \"$REG_ORG\"" <<< $SATELLITE_ENV_JSON) SATELLITE_ENV_JSON=$(jq ".parameter_defaults.rhel_reg_method = \"$REG_METHOD\"" <<< $SATELLITE_ENV_JSON) SATELLITE_ENV_JSON=$(jq ".parameter_defaults.rhel_reg_force = \"$REG_FORCE\"" <<< $SATELLITE_ENV_JSON) echo $SATELLITE_ENV_JSON > $OVERCLOUD_SATELLITE_ENV export OVERCLOUD_EXTRA="$OVERCLOUD_EXTRA -e /usr/share/openstack-tripleo-heat-templates/extraconfig/post_deploy/rhel-registration/rhel-registration-resource-registry.yaml" export OVERCLOUD_EXTRA="$OVERCLOUD_EXTRA -e /usr/share/openstack-tripleo-heat-templates/extraconfig/post_deploy/rhel-registration/environment-rhel-registration.yaml" export OVERCLOUD_EXTRA="$OVERCLOUD_EXTRA -e $OVERCLOUD_SATELLITE_ENV" fi # NOTE(gfidente): Taken from # https://github.com/ceph/ceph-deploy/blob/master/ceph_deploy/new.py#L21 function create_cephx_key() { local KEY=$(python -c 'import base64,os,struct,time;key = os.urandom(16);header = struct.pack(" "${HEAT_ENV}" <<< $ENV_JSON chmod 0600 "${HEAT_ENV}" if [ "$HEAT_OP" = "stack-create" ]; then generate-keystone-pki --heatenv $HEAT_ENV fi KeystoneCACertificate=$(os-apply-config -m $HEAT_ENV --key parameters.KeystoneCACertificate --type raw) KeystoneSigningCertificate=$(os-apply-config -m $HEAT_ENV --key parameters.KeystoneSigningCertificate --type raw) KeystoneSigningKey=$(os-apply-config -m $HEAT_ENV --key parameters.KeystoneSigningKey --type raw) # Sending the Certificates one by one, otherwise there are problems with escaping tuskar plan-update -A Controller-1::KeystoneCACertificate="${KeystoneCACertificate}" $PLAN_ID tuskar plan-update -A Controller-1::KeystoneSigningCertificate="${KeystoneSigningCertificate}" $PLAN_ID tuskar plan-update -A Controller-1::KeystoneSigningKey="${KeystoneSigningKey}" $PLAN_ID # Get templates from tuskar tuskar plan-templates -O tuskar_templates $PLAN_ID OVERCLOUD_YAML_PATH="tuskar_templates/plan.yaml" ENVIRONMENT_YAML_PATH="tuskar_templates/environment.yaml" heat $HEAT_OP -t $TIMEOUT -f $OVERCLOUD_YAML_PATH \ -e $ENVIRONMENT_YAML_PATH \ $OVERCLOUD_EXTRA \ overcloud else OVERCLOUD_YAML_PATH="$INSTACK_ROOT/openstack-tripleo-heat-templates/overcloud-without-mergepy.yaml" export OVERCLOUD_PARAMETERS=${OVERCLOUD_PARAMETERS:-"\ -P AdminPassword=${OVERCLOUD_ADMIN_PASSWORD} \ -P AdminToken=${OVERCLOUD_ADMIN_TOKEN} \ -P CeilometerPassword=${OVERCLOUD_CEILOMETER_PASSWORD} \ -P CeilometerMeteringSecret=${OVERCLOUD_CEILOMETER_SECRET} \ -P CinderPassword=${OVERCLOUD_CINDER_PASSWORD} \ -P CinderISCSIHelper=lioadm \ -P CloudName=overcloud \ -P GlancePassword=${OVERCLOUD_GLANCE_PASSWORD} \ -P HeatPassword=${OVERCLOUD_HEAT_PASSWORD} \ -P NeutronControlPlaneID=$NeutronControlPlaneID \ -P NeutronDnsmasqOptions=dhcp-option-force=26,1400 \ -P NeutronPassword=${OVERCLOUD_NEUTRON_PASSWORD} \ -P NeutronPublicInterface=$NeutronPublicInterface \ -P NeutronBridgeMappings=$NeutronBridgeMappings \ -P NeutronFlatNetworks=$NeutronFlatNetworks \ -P HypervisorNeutronPhysicalBridge=$NeutronPhysicalBridge \ -P HypervisorNeutronPublicInterface=$HypervisorNeutronPublicInterface \ -P NovaComputeLibvirtType=$OVERCLOUD_LIBVIRT_TYPE \ -P NovaPassword=${OVERCLOUD_NOVA_PASSWORD} \ -P SwiftHashSuffix=${OVERCLOUD_SWIFT_HASH} \ -P SwiftPassword=${OVERCLOUD_SWIFT_PASSWORD} \ -P NeutronNetworkType=${NEUTRON_NETWORK_TYPE} \ -P NeutronTunnelTypes=${NEUTRON_TUNNEL_TYPES} \ -P SnmpdReadonlyUserPassword=${UNDERCLOUD_CEILOMETER_SNMPD_PASSWORD} \ -P OvercloudControlFlavor=${OVERCLOUD_CONTROL_FLAVOR} \ -P OvercloudComputeFlavor=${OVERCLOUD_COMPUTE_FLAVOR} \ -P OvercloudBlockStorageFlavor=${OVERCLOUD_BLOCKSTORAGE_FLAVOR} \ -P OvercloudSwiftStorageFlavor=${OVERCLOUD_SWIFTSTORAGE_FLAVOR} \ -P OvercloudCephStorageFlavor=${OVERCLOUD_CEPHSTORAGE_FLAVOR} \ -P NtpServer=${NtpServer} \ -P controllerImage=${OVERCLOUD_CONTROLLER_IMAGE} \ -P NovaImage=${OVERCLOUD_COMPUTE_IMAGE} \ -P BlockStorageImage=${OVERCLOUD_BLOCKSTORAGE_IMAGE} \ -P SwiftStorageImage=${OVERCLOUD_SWIFTSTORAGE_IMAGE} \ -P CephStorageImage=${OVERCLOUD_SWIFTSTORAGE_IMAGE} \ -P Debug=True \ "} if [ $CONTROLSCALE -gt 1 ]; then export OVERCLOUD_PARAMETERS="$OVERCLOUD_PARAMETERS \ -P NeutronL3HA=True \ -P NeutronAllowL3AgentFailover=False \ " fi if [ $CEPHSTORAGESCALE -gt 0 ]; then FSID=$(uuidgen) MON_KEY=$(create_cephx_key) ADMIN_KEY=$(create_cephx_key) CINDER_ISCSI=${CINDER_ISCSI:-0} export OVERCLOUD_PARAMETERS="$OVERCLOUD_PARAMETERS \ -P CephClusterFSID=$FSID \ -P CephMonKey=$MON_KEY \ -P CephAdminKey=$ADMIN_KEY \ -P CinderEnableRbdBackend=True \ -P NovaEnableRbdBackend=True \ -P GlanceBackend=rbd \ " if [ $CINDER_ISCSI -eq 0 ]; then export OVERCLOUD_PARAMETERS="$OVERCLOUD_PARAMETERS \ -P CinderEnableIscsiBackend=False " else # (this is the default parameter value) export OVERCLOUD_PARAMETERS="$OVERCLOUD_PARAMETERS \ -P CinderEnableIscsiBackend=True " fi fi HEAT_ENV=${HEAT_ENV:-"overcloud-env.json"} if [ -f $HEAT_ENV -a "$HEAT_OP" = "stack-update" ]; then ENV_JSON=$(cat $HEAT_ENV) else ENV_JSON='{"parameters":{}}' fi RESOURCE_REGISTRY="-e $OVERCLOUD_RESOURCE_REGISTRY" ENV_JSON=$(jq '.parameters = .parameters + { "ControllerCount": '${CONTROLSCALE}', "ComputeCount": '${COMPUTESCALE}', "CephStorageCount": '${CEPHSTORAGESCALE}', "BlockStorageCount": '${BLOCKSTORAGESCALE}', "ObjectStorageCount": '${SWIFTSTORAGESCALE}' }' <<< $ENV_JSON) jq . > "${HEAT_ENV}" <<< $ENV_JSON chmod 0600 "${HEAT_ENV}" if [ "$HEAT_OP" = "stack-create" ]; then generate-keystone-pki --heatenv $HEAT_ENV fi HEAT_ENVIRONMENT="-e ${HEAT_ENV}" heat $HEAT_OP -t $TIMEOUT -f $OVERCLOUD_YAML_PATH \ $RESOURCE_REGISTRY \ $OVERCLOUD_PARAMETERS \ $HEAT_ENVIRONMENT \ $OVERCLOUD_EXTRA \ overcloud fi tripleo wait_for_stack_ready 220 10 overcloud if [ "$HEAT_OP" = "stack-create" ]; then echo "Overcloud CREATE_COMPLETE" else echo "Overcloud UPDATE_COMPLETE" exit 0 fi OVERCLOUD_ENDPOINT=$(heat output-show overcloud KeystoneURL|sed 's/^"\(.*\)"$/\1/') export OVERCLOUD_IP=$(echo $OVERCLOUD_ENDPOINT | awk -F '[/:]' '{print $4}') touch ~/.ssh/known_hosts chmod 600 ~/.ssh/known_hosts ssh-keygen -R $OVERCLOUD_IP NEW_JSON=$(jq '.overcloud.password="'${OVERCLOUD_ADMIN_PASSWORD}'" | .overcloud.endpoint="'${OVERCLOUD_ENDPOINT}'" | .overcloud.endpointhost="'${OVERCLOUD_IP}'"' $NODES_JSON) echo $NEW_JSON > $NODES_JSON export TE_DATAFILE=$NODES_JSON # We're done with TRIPLEO_ROOT at this point, and the value set above doesn't # work for creating the overcloudrc file. unset TRIPLEO_ROOT instack-create-overcloudrc source ~/overcloudrc init-keystone -o $OVERCLOUD_IP -t $OVERCLOUD_ADMIN_TOKEN \ -e admin.example.com -p $OVERCLOUD_ADMIN_PASSWORD -u heat-admin \ ${SSLBASE:+-s $PUBLIC_API_URL} REGISTER_SERVICE_OPTS="" openstack role create swiftoperator openstack role create ResellerAdmin tripleo setup-endpoints $OVERCLOUD_IP \ --cinder-password $OVERCLOUD_CINDER_PASSWORD \ --glance-password $OVERCLOUD_GLANCE_PASSWORD \ --heat-password $OVERCLOUD_HEAT_PASSWORD \ --neutron-password $OVERCLOUD_NEUTRON_PASSWORD \ --nova-password $OVERCLOUD_NOVA_PASSWORD \ --swift-password $OVERCLOUD_SWIFT_PASSWORD \ --ceilometer-password $OVERCLOUD_CEILOMETER_PASSWORD \ $REGISTER_SERVICE_OPTS \ ${SSLBASE:+--ssl $PUBLIC_API_URL} openstack role create heat_stack_user # setup-neutron "" "" 10.0.0.0/8 "" "" "" "" 192.0.2.45 192.0.2.64 192.0.2.0/24 NETWORK_CIDR=${NETWORK_CIDR:-"10.0.0.0/8"} FLOATING_IP_START=${FLOATING_IP_START:-"192.0.2.45"} FLOATING_IP_END=${FLOATING_IP_END:-"192.0.2.64"} FLOATING_IP_CIDR=${FLOATING_IP_CIDR:-"192.0.2.0/24"} OVERCLOUD_NAMESERVER="8.8.8.8" BM_NETWORK_GATEWAY=${BM_NETWORK_GATEWAY:-"192.0.2.1"} NETWORK_JSON=$(mktemp) jq "." < $NETWORK_JSON { "float": { "cidr": "$NETWORK_CIDR", "name": "default-net", "nameserver": "$OVERCLOUD_NAMESERVER" }, "external": { "name": "ext-net", "cidr": "$FLOATING_IP_CIDR", "allocation_start": "$FLOATING_IP_START", "allocation_end": "$FLOATING_IP_END", "gateway": "$BM_NETWORK_GATEWAY" } } EOF setup-neutron -n $NETWORK_JSON rm $NETWORK_JSON nova flavor-create m1.demo auto 512 10 1 echo "Overcloud Deployed" if [ -n "$TEMPEST" ]; then TEMPEST_ARGS=${TEMPEST_ARGS:-} $(dirname $0)/instack-tempest-test-overcloud $(dirname $0)/instack-test-overcloud fi