0ef474a70c
Since Trove already supports to specify a Nova keypair when creating instance for management convenience, devstack needs to be changed to create the management keypair and add to Trove config file. One extra change in this patch is to use a single config file for Trove API, task-manager and conductor. Change-Id: I1e6c4f4305104815bdf89b31776a4955de61bc89 Story: 2005429 Task: 30463
754 lines
31 KiB
Bash
754 lines
31 KiB
Bash
#!/bin/bash
|
|
#
|
|
# lib/trove
|
|
# Functions to control the configuration and operation of the **Trove** service
|
|
|
|
# Dependencies:
|
|
# ``functions`` file
|
|
# ``DEST``, ``STACK_USER`` must be defined
|
|
# ``SERVICE_{HOST|PROTOCOL|TOKEN}`` must be defined
|
|
|
|
# ``stack.sh`` calls the entry points in this order:
|
|
#
|
|
# install_trove
|
|
# install_python_troveclient
|
|
# configure_trove
|
|
# init_trove
|
|
# start_trove
|
|
# stop_trove
|
|
# cleanup_trove
|
|
|
|
# Save trace setting
|
|
XTRACE=$(set +o | grep xtrace)
|
|
set +o xtrace
|
|
|
|
# Functions
|
|
# ---------
|
|
|
|
# Test if any Trove services are enabled
|
|
# is_trove_enabled
|
|
function is_trove_enabled {
|
|
[[ ,${ENABLED_SERVICES} =~ ,"tr-" ]] && return 0
|
|
return 1
|
|
}
|
|
|
|
# setup_trove_logging() - Adds logging configuration to conf files
|
|
function setup_trove_logging {
|
|
local CONF=$1
|
|
iniset $CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
|
|
iniset $CONF DEFAULT use_syslog $SYSLOG
|
|
if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then
|
|
# Add color to logging output
|
|
setup_colorized_logging $CONF DEFAULT tenant user
|
|
fi
|
|
}
|
|
|
|
# create_trove_accounts() - Set up common required trove accounts
|
|
|
|
# Tenant User Roles
|
|
# ------------------------------------------------------------------
|
|
# service trove admin # if enabled
|
|
|
|
function create_trove_accounts {
|
|
if [[ "$ENABLED_SERVICES" =~ "trove" ]]; then
|
|
create_service_user "trove" "admin"
|
|
|
|
# Add trove user to the clouds.yaml
|
|
CLOUDS_YAML=${CLOUDS_YAML:-/etc/openstack/clouds.yaml}
|
|
$PYTHON $TOP_DIR/tools/update_clouds_yaml.py \
|
|
--file $CLOUDS_YAML \
|
|
--os-cloud trove \
|
|
--os-region-name $REGION_NAME \
|
|
$CA_CERT_ARG \
|
|
--os-auth-url $KEYSTONE_SERVICE_URI \
|
|
--os-username trove \
|
|
--os-password $SERVICE_PASSWORD \
|
|
--os-project-name $SERVICE_PROJECT_NAME
|
|
|
|
local trove_service=$(get_or_create_service "trove" \
|
|
"database" "Trove Service")
|
|
get_or_create_endpoint $trove_service \
|
|
"$REGION_NAME" \
|
|
"http://$SERVICE_HOST:8779/v1.0/\$(tenant_id)s" \
|
|
"http://$SERVICE_HOST:8779/v1.0/\$(tenant_id)s" \
|
|
"http://$SERVICE_HOST:8779/v1.0/\$(tenant_id)s"
|
|
fi
|
|
}
|
|
|
|
# _cleanup_trove_apache_wsgi - Removes all the WSGI related files and
|
|
# restart apache.
|
|
function _cleanup_trove_apache_wsgi {
|
|
sudo rm -rf $TROVE_WSGI_DIR
|
|
sudo rm -f $(apache_site_config_for trove-api)
|
|
restart_apache_server
|
|
}
|
|
|
|
# stack.sh entry points
|
|
# ---------------------
|
|
|
|
# cleanup_trove() - Remove residual data files, anything left over from previous
|
|
# runs that a clean run would need to clean up
|
|
function cleanup_trove {
|
|
# Clean up dirs
|
|
rm -fr $TROVE_CONF_DIR/*
|
|
|
|
if is_service_enabled horizon; then
|
|
cleanup_trove_dashboard
|
|
fi
|
|
|
|
if [[ "${TROVE_USE_MOD_WSGI}" == "TRUE" ]]; then
|
|
echo "Cleaning up Trove's WSGI setup"
|
|
_cleanup_trove_apache_wsgi
|
|
fi
|
|
}
|
|
|
|
|
|
# cleanup_trove_dashboard() - Remove Trove dashboard files from Horizon
|
|
function cleanup_trove_dashboard {
|
|
rm -f $HORIZON_DIR/openstack_dashboard/local/enabled/_17*database*.py
|
|
}
|
|
|
|
|
|
# iniset_conditional() - Sets the value in the inifile, but only if it's
|
|
# actually got a value
|
|
function iniset_conditional {
|
|
local FILE=$1
|
|
local SECTION=$2
|
|
local OPTION=$3
|
|
local VALUE=$4
|
|
|
|
if [[ -n "$VALUE" ]]; then
|
|
iniset ${FILE} ${SECTION} ${OPTION} ${VALUE}
|
|
fi
|
|
}
|
|
|
|
# configure_keystone_token_life() - update the keystone token life to 3h
|
|
function configure_keystone_token_life() {
|
|
KEYSTONE_CONF_DIR=${KEYSTONE_CONF_DIR:-/etc/nova}
|
|
KEYSTONE_CONF=${KEYSTONE_CONF:-${KEYSTONE_CONF_DIR}/keystone.conf}
|
|
KEYSTONE_TOKEN_LIFE=${KEYSTONE_TOKEN_LIFE:-10800}
|
|
iniset $KEYSTONE_CONF token expiration ${KEYSTONE_TOKEN_LIFE}
|
|
echo "configure_keystone_token_life: setting keystone token life to ${KEYSTONE_TOKEN_LIFE}"
|
|
echo "configure_keystone_token_life: restarting Keystone"
|
|
stop_keystone
|
|
start_keystone
|
|
}
|
|
|
|
# configure_nova_kvm() - update the nova hypervisor configuration if possible
|
|
function configure_nova_kvm {
|
|
cpu="unknown"
|
|
|
|
if [ -e /sys/module/kvm_*/parameters/nested ]; then
|
|
reconfigure_nova="F"
|
|
|
|
if [ -e /sys/module/kvm_intel/parameters/nested ]; then
|
|
cpu="Intel"
|
|
if [[ "$(cat /sys/module/kvm_*/parameters/nested)" == "Y" ]]; then
|
|
reconfigure_nova="Y"
|
|
fi
|
|
elif [ -e /sys/module/kvm_amd/parameters/nested ]; then
|
|
cpu="AMD"
|
|
if [[ "$(cat /sys/module/kvm_*/parameters/nested)" == "1" ]]; then
|
|
reconfigure_nova="Y"
|
|
fi
|
|
fi
|
|
|
|
if [ "${reconfigure_nova}" == "Y" ]; then
|
|
NOVA_CONF_DIR=${NOVA_CONF_DIR:-/etc/nova}
|
|
NOVA_CONF=${NOVA_CONF:-${NOVA_CONF_DIR}/nova.conf}
|
|
iniset $NOVA_CONF libvirt cpu_mode "none"
|
|
iniset $NOVA_CONF libvirt virt_type "kvm"
|
|
fi
|
|
fi
|
|
|
|
virt_type=$(iniget $NOVA_CONF libvirt virt_type)
|
|
echo "configure_nova_kvm: using virt_type: ${virt_type} for cpu: ${cpu}."
|
|
}
|
|
|
|
# _config_trove_apache_wsgi() - Setup WSGI config files for Trove and
|
|
# enable the site
|
|
function _config_trove_apache_wsgi {
|
|
local trove_apache_conf
|
|
|
|
sudo mkdir -p ${TROVE_WSGI_DIR}
|
|
sudo cp $TROVE_DIR/trove/cmd/app.wsgi $TROVE_WSGI_DIR/app.wsgi
|
|
trove_apache_conf=$(apache_site_config_for trove-api)
|
|
sudo cp $TROVE_DEVSTACK_FILES/apache-trove-api.template ${trove_apache_conf}
|
|
sudo sed -e "
|
|
s|%TROVE_SERVICE_PORT%|${TROVE_SERVICE_PORT}|g;
|
|
s|%TROVE_WSGI_DIR%|${TROVE_WSGI_DIR}|g;
|
|
s|%USER%|${STACK_USER}|g;
|
|
s|%APACHE_NAME%|${APACHE_NAME}|g;
|
|
s|%APIWORKERS%|${API_WORKERS}|g;
|
|
" -i ${trove_apache_conf}
|
|
enable_apache_site trove-api
|
|
tail_log trove-access /var/log/${APACHE_NAME}/trove-api-access.log
|
|
tail_log trove-api /var/log/${APACHE_NAME}/trove-api.log
|
|
}
|
|
|
|
function _config_nova_keypair {
|
|
export SSH_DIR=${SSH_DIR:-"$HOME/.ssh"}
|
|
|
|
if [[ ! -f ${SSH_DIR}/id_rsa.pub ]]; then
|
|
mkdir -p ${SSH_DIR}
|
|
/usr/bin/ssh-keygen -f ${SSH_DIR}/id_rsa -q -N ""
|
|
# This is to allow guest agent ssh into the controller in dev mode.
|
|
cat ${SSH_DIR}/id_rsa.pub >> ${SSH_DIR}/authorized_keys
|
|
else
|
|
# This is to allow guest agent ssh into the controller in dev mode.
|
|
cat ${SSH_DIR}/id_rsa.pub >> ${SSH_DIR}/authorized_keys
|
|
sort ${SSH_DIR}/authorized_keys | uniq > ${SSH_DIR}/authorized_keys.uniq
|
|
mv ${SSH_DIR}/authorized_keys.uniq ${SSH_DIR}/authorized_keys
|
|
chmod 600 ${SSH_DIR}/authorized_keys
|
|
fi
|
|
|
|
echo "Creating Trove management keypair ${TROVE_MGMT_KEYPAIR_NAME}"
|
|
openstack --os-region-name RegionOne --os-password ${SERVICE_PASSWORD} --os-project-name service --os-username trove \
|
|
keypair create --public-key ${SSH_DIR}/id_rsa.pub ${TROVE_MGMT_KEYPAIR_NAME}
|
|
|
|
iniset $TROVE_CONF DEFAULT nova_keypair ${TROVE_MGMT_KEYPAIR_NAME}
|
|
}
|
|
# configure_trove() - Set config files, create data dirs, etc
|
|
function configure_trove {
|
|
setup_develop $TROVE_DIR
|
|
|
|
# Temporarily disable re-configuring nova_kvm until
|
|
# more nodes in the pool can support it without crashing.
|
|
# configure_nova_kvm
|
|
configure_keystone_token_life
|
|
|
|
# Create the trove conf dir and cache dirs if they don't exist
|
|
sudo install -d -o $STACK_USER ${TROVE_CONF_DIR}
|
|
|
|
# Copy api-paste file over to the trove conf dir
|
|
cp $TROVE_LOCAL_API_PASTE_INI $TROVE_API_PASTE_INI
|
|
|
|
# (Re)create trove conf files
|
|
rm -f $TROVE_CONF
|
|
|
|
TROVE_AUTH_ENDPOINT=$KEYSTONE_AUTH_URI/v$IDENTITY_API_VERSION
|
|
|
|
# Set common configuration values (but only if they're defined)
|
|
iniset_conditional $TROVE_CONF DEFAULT max_accepted_volume_size $TROVE_MAX_ACCEPTED_VOLUME_SIZE
|
|
iniset_conditional $TROVE_CONF DEFAULT max_instances_per_tenant $TROVE_MAX_INSTANCES_PER_TENANT
|
|
iniset_conditional $TROVE_CONF DEFAULT max_volumes_per_tenant $TROVE_MAX_VOLUMES_PER_TENANT
|
|
iniset_conditional $TROVE_CONF DEFAULT agent_call_low_timeout $TROVE_AGENT_CALL_LOW_TIMEOUT
|
|
iniset_conditional $TROVE_CONF DEFAULT agent_call_high_timeout $TROVE_AGENT_CALL_HIGH_TIMEOUT
|
|
iniset_conditional $TROVE_CONF DEFAULT resize_time_out $TROVE_RESIZE_TIME_OUT
|
|
iniset_conditional $TROVE_CONF DEFAULT usage_timeout $TROVE_USAGE_TIMEOUT
|
|
iniset_conditional $TROVE_CONF DEFAULT state_change_wait_time $TROVE_STATE_CHANGE_WAIT_TIME
|
|
|
|
# For message queue
|
|
iniset $TROVE_CONF DEFAULT rpc_backend "rabbit"
|
|
iniset $TROVE_CONF DEFAULT control_exchange trove
|
|
iniset $TROVE_CONF DEFAULT transport_url rabbit://$RABBIT_USERID:$RABBIT_PASSWORD@$RABBIT_HOST:5672/
|
|
# For database
|
|
iniset $TROVE_CONF database connection `database_connection_url trove`
|
|
# For logging
|
|
setup_trove_logging $TROVE_CONF
|
|
|
|
iniset $TROVE_CONF DEFAULT trove_api_workers "$API_WORKERS"
|
|
configure_keystone_authtoken_middleware $TROVE_CONF trove
|
|
|
|
iniset $TROVE_CONF DEFAULT taskmanager_manager trove.taskmanager.manager.Manager
|
|
|
|
iniset $TROVE_CONF DEFAULT trove_auth_url $TROVE_AUTH_ENDPOINT
|
|
iniset $TROVE_CONF DEFAULT nova_proxy_admin_user trove
|
|
iniset $TROVE_CONF DEFAULT nova_proxy_admin_tenant_name $SERVICE_PROJECT_NAME
|
|
iniset $TROVE_CONF DEFAULT nova_proxy_admin_pass $SERVICE_PASSWORD
|
|
iniset $TROVE_CONF DEFAULT nova_proxy_admin_user_domain_name default
|
|
iniset $TROVE_CONF DEFAULT nova_proxy_admin_project_domain_name default
|
|
iniset $TROVE_CONF DEFAULT os_region_name $REGION_NAME
|
|
iniset $TROVE_CONF DEFAULT remote_nova_client trove.common.single_tenant_remote.nova_client_trove_admin
|
|
iniset $TROVE_CONF DEFAULT remote_cinder_client trove.common.single_tenant_remote.cinder_client_trove_admin
|
|
iniset $TROVE_CONF DEFAULT remote_neutron_client trove.common.single_tenant_remote.neutron_client_trove_admin
|
|
|
|
iniset $TROVE_CONF DEFAULT default_datastore $TROVE_DATASTORE_TYPE
|
|
iniset $TROVE_CONF cassandra tcp_ports 22,7000,7001,7199,9042,9160
|
|
iniset $TROVE_CONF couchbase tcp_ports 22,8091,8092,4369,11209-11211,21100-21199
|
|
iniset $TROVE_CONF couchdb tcp_ports 22,5984
|
|
iniset $TROVE_CONF db2 tcp_ports 22,50000
|
|
iniset $TROVE_CONF mariadb tcp_ports 22,3306,4444,4567,4568
|
|
iniset $TROVE_CONF mongodb tcp_ports 22,2500,27017,27019
|
|
iniset $TROVE_CONF mysql tcp_ports 22,3306
|
|
iniset $TROVE_CONF percona tcp_ports 22,3306
|
|
iniset $TROVE_CONF postgresql tcp_ports 22,5432
|
|
iniset $TROVE_CONF pxc tcp_ports 22,3306,4444,4567,4568
|
|
iniset $TROVE_CONF redis tcp_ports 22,6379,16379
|
|
iniset $TROVE_CONF vertica tcp_ports 22,5433,5434,5444,5450,4803
|
|
|
|
# configure apache related files
|
|
if [[ "${TROVE_USE_MOD_WSGI}" == "TRUE" ]]; then
|
|
echo "Configuring Trove to use mod-wsgi and Apache"
|
|
_config_trove_apache_wsgi
|
|
fi
|
|
|
|
# Use these values only if they're set
|
|
iniset_conditional $TROVE_GUESTAGENT_CONF DEFAULT state_change_wait_time $TROVE_STATE_CHANGE_WAIT_TIME
|
|
iniset_conditional $TROVE_GUESTAGENT_CONF DEFAULT command_process_timeout $TROVE_COMMAND_PROCESS_TIMEOUT
|
|
|
|
# Set up Guest Agent conf
|
|
iniset $TROVE_GUESTAGENT_CONF DEFAULT rpc_backend "rabbit"
|
|
iniset $TROVE_GUESTAGENT_CONF DEFAULT transport_url rabbit://$RABBIT_USERID:$RABBIT_PASSWORD@$TROVE_HOST_GATEWAY:5672/
|
|
iniset $TROVE_GUESTAGENT_CONF DEFAULT trove_auth_url $TROVE_AUTH_ENDPOINT
|
|
iniset $TROVE_GUESTAGENT_CONF DEFAULT control_exchange trove
|
|
iniset $TROVE_GUESTAGENT_CONF DEFAULT ignore_users os_admin
|
|
iniset $TROVE_GUESTAGENT_CONF DEFAULT log_dir /var/log/trove/
|
|
iniset $TROVE_GUESTAGENT_CONF DEFAULT log_file trove-guestagent.log
|
|
setup_trove_logging $TROVE_GUESTAGENT_CONF
|
|
|
|
# To avoid 'Connection timed out' error of sudo command inside the guest agent
|
|
CLOUDINIT_PATH=/etc/trove/cloudinit/${TROVE_DATASTORE_TYPE}.cloudinit
|
|
sudo mkdir -p $(dirname "$CLOUDINIT_PATH")
|
|
sudo touch "$CLOUDINIT_PATH"
|
|
sudo tee $CLOUDINIT_PATH >/dev/null <<'EOF'
|
|
#cloud-config
|
|
manage_etc_hosts: "localhost"
|
|
EOF
|
|
}
|
|
|
|
# install_trove() - Collect source and prepare
|
|
function install_trove {
|
|
echo "Changing stack user sudoers"
|
|
echo "stack ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/60_stack_sh_allow_all
|
|
|
|
setup_develop $TROVE_DIR
|
|
|
|
if [[ "${TROVE_USE_MOD_WSGI}" == "TRUE" ]]; then
|
|
echo "Installing apache wsgi"
|
|
install_apache_wsgi
|
|
fi
|
|
|
|
if is_service_enabled horizon; then
|
|
install_trove_dashboard
|
|
fi
|
|
}
|
|
|
|
# install_trove_dashboard() - Collect source and prepare
|
|
function install_trove_dashboard {
|
|
git_clone $TROVE_DASHBOARD_REPO $TROVE_DASHBOARD_DIR $TROVE_DASHBOARD_BRANCH
|
|
setup_develop $TROVE_DASHBOARD_DIR
|
|
cp $TROVE_DASHBOARD_DIR/trove_dashboard/enabled/_17*database*.py $HORIZON_DIR/openstack_dashboard/local/enabled
|
|
}
|
|
|
|
# install_python_troveclient() - Collect source and prepare
|
|
function install_python_troveclient {
|
|
if use_library_from_git "python-troveclient"; then
|
|
git_clone $TROVE_CLIENT_REPO $TROVE_CLIENT_DIR $TROVE_CLIENT_BRANCH
|
|
setup_develop $TROVE_CLIENT_DIR
|
|
fi
|
|
}
|
|
|
|
# init_trove() - Initializes Trove Database as a Service
|
|
function init_trove {
|
|
# (Re)Create trove db
|
|
recreate_database trove
|
|
|
|
# Initialize the trove database
|
|
$TROVE_MANAGE db_sync
|
|
|
|
# build and upload sample Trove mysql instance if not set otherwise.
|
|
# We recommend to use trovestack tooling for image build.
|
|
TROVE_DISABLE_IMAGE_SETUP=`echo ${TROVE_DISABLE_IMAGE_SETUP,,}`
|
|
if [[ ${TROVE_DISABLE_IMAGE_SETUP} != "true" ]]; then
|
|
echo "Setup datastore image."
|
|
_setup_minimal_image
|
|
else
|
|
echo "Skip datastore image building."
|
|
fi
|
|
[ -z "$TROVE_GUEST_IMAGE_URL" ] && return 0
|
|
|
|
# Find the glance id for the trove guest image
|
|
# The image is uploaded by stack.sh -- see $IMAGE_URLS handling
|
|
GUEST_IMAGE_NAME=$(basename "$TROVE_GUEST_IMAGE_URL")
|
|
GUEST_IMAGE_NAME=${GUEST_IMAGE_NAME%.*}
|
|
|
|
TOKEN=$(openstack token issue -c id -f value)
|
|
TROVE_GUEST_IMAGE_ID=$(openstack --os-token $TOKEN --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image list | grep "${GUEST_IMAGE_NAME}" | get_field 1)
|
|
if [ -z "$TROVE_GUEST_IMAGE_ID" ]; then
|
|
# If no glance id is found, skip remaining setup
|
|
echo "Datastore ${TROVE_DATASTORE_TYPE} will not be created: guest image ${GUEST_IMAGE_NAME} not found."
|
|
return 1
|
|
fi
|
|
|
|
# Now that we have the guest image id, initialize appropriate datastores / datastore versions
|
|
$TROVE_MANAGE datastore_update "$TROVE_DATASTORE_TYPE" ""
|
|
$TROVE_MANAGE datastore_version_update "$TROVE_DATASTORE_TYPE" "$TROVE_DATASTORE_VERSION" "$TROVE_DATASTORE_TYPE" \
|
|
"$TROVE_GUEST_IMAGE_ID" "$TROVE_DATASTORE_PACKAGE" 1
|
|
$TROVE_MANAGE datastore_version_update "$TROVE_DATASTORE_TYPE" "inactive_version" "inactive_manager" "$TROVE_GUEST_IMAGE_ID" "" 0
|
|
$TROVE_MANAGE datastore_update "$TROVE_DATASTORE_TYPE" "$TROVE_DATASTORE_VERSION"
|
|
$TROVE_MANAGE datastore_update "Inactive_Datastore" ""
|
|
|
|
# Some datastores provide validation rules.
|
|
# if one is provided, configure it.
|
|
if [ -f "${TROVE_DIR}/trove/templates/${TROVE_DATASTORE_TYPE}"/validation-rules.json ]; then
|
|
echo "Configuring validation rules for ${TROVE_DATASTORE_TYPE}"
|
|
$TROVE_MANAGE db_load_datastore_config_parameters \
|
|
"$TROVE_DATASTORE_TYPE" "$TROVE_DATASTORE_VERSION" \
|
|
"${TROVE_DIR}/trove/templates/${TROVE_DATASTORE_TYPE}"/validation-rules.json
|
|
fi
|
|
}
|
|
|
|
function create_mgmt_subnet_v4 {
|
|
local project_id=$1
|
|
local net_id=$2
|
|
local name=$3
|
|
local ip_range=$4
|
|
|
|
subnet_id=$(openstack subnet create --project ${project_id} --ip-version 4 --subnet-range ${ip_range} --gateway none --dns-nameserver 8.8.8.8 --network ${net_id} $name -c id -f value)
|
|
die_if_not_set $LINENO subnet_id "Failed to create private IPv4 subnet for network: ${net_id}, project: ${project_id}"
|
|
echo $subnet_id
|
|
}
|
|
|
|
# Create private IPv6 subnet
|
|
# Note: Trove is not fully tested in IPv6.
|
|
function _create_subnet_v6 {
|
|
local project_id=$1
|
|
local net_id=$2
|
|
local name=$3
|
|
local subnet_params="--ip-version 6 "
|
|
|
|
die_if_not_set $LINENO IPV6_RA_MODE "IPV6 RA Mode not set"
|
|
die_if_not_set $LINENO IPV6_ADDRESS_MODE "IPV6 Address Mode not set"
|
|
local ipv6_modes="--ipv6-ra-mode $IPV6_RA_MODE --ipv6-address-mode $IPV6_ADDRESS_MODE"
|
|
|
|
if [[ -n "$IPV6_PRIVATE_NETWORK_GATEWAY" ]]; then
|
|
subnet_params+="--gateway $IPV6_PRIVATE_NETWORK_GATEWAY "
|
|
fi
|
|
if [ -n $SUBNETPOOL_V6_ID ]; then
|
|
subnet_params+="--subnet-pool $SUBNETPOOL_V6_ID "
|
|
else
|
|
subnet_params+="--subnet-range $FIXED_RANGE_V6 $ipv6_modes} "
|
|
fi
|
|
subnet_params+="--network $net_id $name "
|
|
|
|
ipv6_subnet_id=$(openstack --project ${project_id} subnet create $subnet_params | grep ' id ' | get_field 2)
|
|
die_if_not_set $LINENO ipv6_subnet_id "Failed to create private IPv6 subnet for network: ${net_id}, project: ${project_id}"
|
|
echo $ipv6_subnet_id
|
|
}
|
|
|
|
function setup_mgmt_network() {
|
|
local PROJECT_ID=$1
|
|
local NET_NAME=$2
|
|
local SUBNET_NAME=$3
|
|
local SUBNET_RANGE=$4
|
|
local SHARED=$5
|
|
|
|
local share_flag=""
|
|
if [[ "${SHARED}" == "TRUE" ]]; then
|
|
share_flag="--share"
|
|
fi
|
|
|
|
network_id=$(openstack network create --project ${PROJECT_ID} ${share_flag} $NET_NAME -c id -f value)
|
|
die_if_not_set $LINENO network_id "Failed to create network: $NET_NAME, project: ${PROJECT_ID}"
|
|
|
|
if [[ "$IP_VERSION" =~ 4.* ]]; then
|
|
NEW_SUBNET_ID=$(create_mgmt_subnet_v4 ${PROJECT_ID} ${network_id} ${SUBNET_NAME} ${SUBNET_RANGE})
|
|
openstack router add subnet $ROUTER_ID $NEW_SUBNET_ID
|
|
fi
|
|
# Trove doesn't support IPv6 for now.
|
|
# if [[ "$IP_VERSION" =~ .*6 ]]; then
|
|
# NEW_IPV6_SUBNET_ID=$(_create_subnet_v6 ${PROJECT_ID} ${network_id} ${IPV6_SUBNET_NAME})
|
|
# openstack router add subnet $ROUTER_ID $NEW_IPV6_SUBNET_ID
|
|
# fi
|
|
}
|
|
|
|
# Set up Trove management network and make configuration change.
|
|
function finalize_trove_network {
|
|
echo "Finalizing Neutron networking for Trove"
|
|
echo "Dumping current network parameters:"
|
|
echo " SERVICE_HOST: $SERVICE_HOST"
|
|
echo " BRIDGE_IP: $BRIDGE_IP"
|
|
echo " PUBLIC_NETWORK_GATEWAY: $PUBLIC_NETWORK_GATEWAY"
|
|
echo " NETWORK_GATEWAY: $NETWORK_GATEWAY"
|
|
echo " IPV4_ADDRS_SAFE_TO_USE: $IPV4_ADDRS_SAFE_TO_USE"
|
|
echo " IPV6_ADDRS_SAFE_TO_USE: $IPV6_ADDRS_SAFE_TO_USE"
|
|
echo " FIXED_RANGE: $FIXED_RANGE"
|
|
echo " FLOATING_RANGE: $FLOATING_RANGE"
|
|
echo " SUBNETPOOL_PREFIX_V4: $SUBNETPOOL_PREFIX_V4"
|
|
echo " SUBNETPOOL_SIZE_V4: $SUBNETPOOL_SIZE_V4"
|
|
echo " SUBNETPOOL_V4_ID: $SUBNETPOOL_V4_ID"
|
|
echo " ROUTER_GW_IP: $ROUTER_GW_IP"
|
|
echo " TROVE_MGMT_SUBNET_RANGE: ${TROVE_MGMT_SUBNET_RANGE}"
|
|
|
|
echo "Creating Trove management network/subnet for Trove service project."
|
|
trove_service_project_id=$(openstack project show $SERVICE_PROJECT_NAME -c id -f value)
|
|
setup_mgmt_network ${trove_service_project_id} ${TROVE_MGMT_NETWORK_NAME} ${TROVE_MGMT_SUBNET_NAME} ${TROVE_MGMT_SUBNET_RANGE}
|
|
mgmt_net_id=$(openstack network show ${TROVE_MGMT_NETWORK_NAME} -c id -f value)
|
|
echo "Created Trove management network ${TROVE_MGMT_NETWORK_NAME}(${mgmt_net_id})"
|
|
|
|
# Create security group for trove management network. For testing purpose,
|
|
# we allow everything. In production, the security group should be managed
|
|
# by the cloud admin.
|
|
SG_NAME=trove-mgmt
|
|
openstack security group create --project ${trove_service_project_id} ${SG_NAME}
|
|
openstack security group rule create --proto icmp --project ${trove_service_project_id} ${SG_NAME}
|
|
openstack security group rule create --protocol tcp --dst-port 1:65535 --project ${trove_service_project_id} ${SG_NAME}
|
|
openstack security group rule create --protocol udp --dst-port 1:65535 --project ${trove_service_project_id} ${SG_NAME}
|
|
|
|
# Share the private network to other projects for testing purpose. We make
|
|
# the private network accessible to control plane below so that we could
|
|
# reach the private network for integration tests without floating ips
|
|
# associated, no matter which user the tests are using.
|
|
shared=$(openstack network show ${PRIVATE_NETWORK_NAME} -c shared -f value)
|
|
if [[ "$shared" == "False" ]]; then
|
|
openstack network set ${PRIVATE_NETWORK_NAME} --share
|
|
fi
|
|
sudo ip route replace ${IPV4_ADDRS_SAFE_TO_USE} via $ROUTER_GW_IP
|
|
|
|
# Make sure we can reach the management port of the service VM, this
|
|
# configuration is only for testing purpose. In production, it's
|
|
# recommended to config the router in the cloud infrastructure for the
|
|
# communication between Trove control plane and service VMs.
|
|
INTERFACE=trove-mgmt
|
|
MGMT_PORT_ID=$(openstack port create --project ${trove_service_project_id} --security-group ${SG_NAME} --device-owner trove --network ${TROVE_MGMT_NETWORK_NAME} --host=$(hostname) -c id -f value ${INTERFACE}-port)
|
|
MGMT_PORT_MAC=$(openstack port show -c mac_address -f value $MGMT_PORT_ID)
|
|
MGMT_PORT_IP=$(openstack port show -f value -c fixed_ips $MGMT_PORT_ID | awk '{FS=",| "; gsub(",",""); gsub("'\''",""); for(i = 1; i <= NF; ++i) {if ($i ~ /^ip_address/) {n=index($i, "="); if (substr($i, n+1) ~ "\\.") print substr($i, n+1)}}}')
|
|
sudo ovs-vsctl -- --may-exist add-port ${OVS_BRIDGE:-br-int} $INTERFACE -- set Interface $INTERFACE type=internal -- set Interface $INTERFACE external-ids:iface-status=active -- set Interface $INTERFACE external-ids:attached-mac=$MGMT_PORT_MAC -- set Interface $INTERFACE external-ids:iface-id=$MGMT_PORT_ID -- set Interface $INTERFACE external-ids:skip_cleanup=true
|
|
sudo ip link set dev $INTERFACE address $MGMT_PORT_MAC
|
|
mask=$(echo ${TROVE_MGMT_SUBNET_RANGE} | awk -F'/' '{print $2}')
|
|
sudo ip addr add ${MGMT_PORT_IP}/${mask} dev $INTERFACE
|
|
sudo ip link set $INTERFACE up
|
|
|
|
echo "Neutron network list:"
|
|
openstack network list
|
|
echo "Neutron subnet list:"
|
|
openstack subnet list
|
|
echo "ip route:"
|
|
sudo ip route
|
|
|
|
# Now make sure the conf settings are right
|
|
iniset $TROVE_CONF DEFAULT network_label_regex ${PRIVATE_NETWORK_NAME}
|
|
iniset $TROVE_CONF DEFAULT ip_regex ""
|
|
iniset $TROVE_CONF DEFAULT black_list_regex ""
|
|
iniset $TROVE_CONF DEFAULT management_networks ${mgmt_net_id}
|
|
iniset $TROVE_CONF DEFAULT network_driver trove.network.neutron.NeutronDriver
|
|
}
|
|
|
|
# start_trove() - Start running processes, including screen
|
|
function start_trove {
|
|
if [[ ${TROVE_USE_MOD_WSGI}" == TRUE" ]]; then
|
|
echo "Restarting Apache server ..."
|
|
enable_apache_site trove-api
|
|
restart_apache_server
|
|
else
|
|
run_process tr-api "$TROVE_BIN_DIR/trove-api --config-file=$TROVE_CONF --debug"
|
|
fi
|
|
run_process tr-tmgr "$TROVE_BIN_DIR/trove-taskmanager --config-file=$TROVE_CONF --debug"
|
|
run_process tr-cond "$TROVE_BIN_DIR/trove-conductor --config-file=$TROVE_CONF --debug"
|
|
}
|
|
|
|
# stop_trove() - Stop running processes
|
|
function stop_trove {
|
|
# Kill the trove screen windows
|
|
local serv
|
|
if [[ ${TROVE_USE_MOD_WSGI} == "TRUE" ]]; then
|
|
echo "Disabling Trove API in Apache"
|
|
disable_apache_site trove-api
|
|
else
|
|
stop_process tr-api
|
|
fi
|
|
for serv in tr-tmgr tr-cond; do
|
|
stop_process $serv
|
|
done
|
|
}
|
|
|
|
# configure_tempest_for_trove() - Set Trove related setting on Tempest
|
|
# NOTE (gmann): Configure all the Tempest setting for Trove service in
|
|
# this function.
|
|
function configure_tempest_for_trove {
|
|
if is_service_enabled tempest; then
|
|
iniset $TEMPEST_CONFIG service_available trove True
|
|
fi
|
|
}
|
|
|
|
# _setup_minimal_image() - build and register in Trove a vm image with mysql
|
|
# - datastore can be set via env variables
|
|
# (lxkong): This function is deprecated in favor of trovestack script.
|
|
function _setup_minimal_image {
|
|
##### Prerequisites:
|
|
##### - SSH KEYS has to be created on controller
|
|
##### - trove will access controller ip to get trove source code by using HOST_SCP_USERNAME and an ssh key
|
|
##### - we assume tripleo elements and all other elements have been downloaded
|
|
|
|
echo "Exporting image-related environmental variables"
|
|
PRIMARY_IP=$(ip route get 8.8.8.8 | head -1 | awk '{print $7}')
|
|
export CONTROLLER_IP=${CONTROLLER_IP:-$PRIMARY_IP}
|
|
export HOST_USERNAME=${HOST_USERNAME:-'stack'}
|
|
export HOST_SCP_USERNAME=${HOST_SCP_USERNAME:-'stack'}
|
|
export GUEST_USERNAME=${GUEST_USERNAME:-'ubuntu'}
|
|
export PATH_TROVE=${PATH_TROVE:-'/opt/stack/trove'}
|
|
export ESCAPED_PATH_TROVE=$(echo $PATH_TROVE | sed 's/\//\\\//g')
|
|
export TROVESTACK_SCRIPTS=${TROVESTACK_SCRIPTS:-'/opt/stack/trove/integration/scripts'}
|
|
export TROVE_DATASTORE_TYPE=${TROVE_DATASTORE_TYPE:-'mysql'}
|
|
export TROVE_DATASTORE_VERSION=${TROVE_DATASTORE_VERSION:-'5.7'}
|
|
export TROVE_DATASTORE_PACKAGE=${TROVE_DATASTORE_PACKAGE:-"${TROVE_DATASTORE_TYPE}-${TROVE_DATASTORE_VERSION}"}
|
|
export SSH_DIR=${SSH_DIR:-'/opt/stack/.ssh'}
|
|
export GUEST_LOGDIR=${GUEST_LOGDIR:-'/var/log/trove/'}
|
|
export ESCAPED_GUEST_LOGDIR=$(echo $GUEST_LOGDIR | sed 's/\//\\\//g')
|
|
export DIB_CLOUD_INIT_DATASOURCES="ConfigDrive"
|
|
export DISTRO="ubuntu"
|
|
export VM=${VM:-"/opt/stack/images/${DISTRO}_${TROVE_DATASTORE_TYPE}/${DISTRO}_${TROVE_DATASTORE_TYPE}"}
|
|
|
|
if [ -d "$TROVESTACK_SCRIPTS/files/elements" ]; then
|
|
export ELEMENTS_PATH=$TROVESTACK_SCRIPTS/files/elements
|
|
else
|
|
export ELEMENTS_PATH=.
|
|
fi
|
|
|
|
if [ ! -z "$PATH_DISKIMAGEBUILDER" ]; then
|
|
export ELEMENTS_PATH+=:$PATH_DISKIMAGEBUILDER/elements
|
|
elif [ -d "/usr/local/lib/python2.7/dist-packages/diskimage_builder" ]; then
|
|
PATH_DISKIMG="/usr/local/lib/python2.7/dist-packages/diskimage_builder"
|
|
export ELEMENTS_PATH+=:$PATH_DISKIMG/elements
|
|
fi
|
|
|
|
if [ ! -z "$PATH_TRIPLEO_ELEMENTS" ]; then
|
|
export ELEMENTS_PATH+=:$PATH_TRIPLEO_ELEMENTS/elements
|
|
else
|
|
git_clone $TRIPLEO_IMAGES_REPO $TRIPLEO_IMAGES_DIR $TRIPLEO_IMAGES_BRANCH
|
|
setup_develop $TRIPLEO_IMAGES_DIR
|
|
|
|
export ELEMENTS_PATH+=:$TRIPLEO_IMAGES_DIR/elements
|
|
fi
|
|
|
|
export QEMU_IMG_OPTIONS="--qemu-img-options compat=1.1"
|
|
export RELEASE=${RELEASE:-'xenial'}
|
|
export DIB_APT_CONF_DIR=/etc/apt/apt.conf.d
|
|
export DIB_CLOUD_INIT_ETC_HOSTS=true
|
|
export DIB_RELEASE=${RELEASE:-'xenial'}
|
|
|
|
# https://cloud-images.ubuntu.com/releases is more stable than the daily
|
|
# builds(https://cloud-images.ubuntu.com/xenial/current/),
|
|
# e.g. sometimes SHA256SUMS file is missing in the daily builds
|
|
declare -A releasemapping=( ["xenial"]="16.04" ["bionic"]="18.04")
|
|
export DIB_CLOUD_IMAGES="https://cloud-images.ubuntu.com/releases/${DIB_RELEASE}/release/"
|
|
export BASE_IMAGE_FILE="ubuntu-${releasemapping[${DIB_RELEASE}]}-server-cloudimg-amd64-root.tar.gz"
|
|
|
|
export TROVE_GUESTAGENT_CONF=${TROVE_GUESTAGENT_CONF:-'/etc/trove/trove-guestagent.conf'}
|
|
|
|
if [[ -d ${SSH_DIR} && -f ${SSH_DIR}/id_rsa.pub ]]; then
|
|
cat ${SSH_DIR}/id_rsa.pub >> ${SSH_DIR}/authorized_keys
|
|
sort ${SSH_DIR}/authorized_keys | uniq > ${SSH_DIR}/authorized_keys.uniq
|
|
mv ${SSH_DIR}/authorized_keys.uniq ${SSH_DIR}/authorized_keys
|
|
else
|
|
mkdir -p ${SSH_DIR}
|
|
/usr/bin/ssh-keygen -f ${SSH_DIR}/id_rsa -q -N ""
|
|
cat ${SSH_DIR}/id_rsa.pub >> ${SSH_DIR}/authorized_keys
|
|
chmod 600 ${SSH_DIR}/authorized_keys
|
|
fi
|
|
|
|
# Make sure the guest agent has permission to ssh into the devstack host
|
|
# in order to download trove code during the service initialization.
|
|
home_keys=$HOME/.ssh/authorized_keys
|
|
cat ${SSH_DIR}/id_rsa.pub >> ${home_keys}
|
|
sort ${home_keys} | uniq > ${home_keys}.uniq
|
|
mv ${home_keys}.uniq ${home_keys}
|
|
|
|
echo "Run disk image create to actually create a new image"
|
|
disk-image-create -a amd64 -o "${VM}" -x ${QEMU_IMG_OPTIONS} ${DISTRO} \
|
|
vm cloud-init-datasources ${DISTRO}-guest ${DISTRO}-${RELEASE}-guest \
|
|
${DISTRO}-${TROVE_DATASTORE_TYPE} ${DISTRO}-${RELEASE}-${TROVE_DATASTORE_TYPE}
|
|
|
|
QCOW_IMAGE="$VM.qcow2"
|
|
|
|
if [ ! -f $QCOW_IMAGE ]; then
|
|
echo "Image file was not found at $QCOW_IMAGE. Probably it was not created."
|
|
return 1
|
|
fi
|
|
|
|
ACTIVE=1
|
|
INACTIVE=0
|
|
|
|
echo "Add image to glance"
|
|
GLANCE_OUT=$(openstack --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT \
|
|
image create $DISTRO-${TROVE_DATASTORE_TYPE}-${TROVE_DATASTORE_VERSION} \
|
|
--public --disk-format qcow2 --container-format bare --file $QCOW_IMAGE)
|
|
glance_image_id=$(echo "$GLANCE_OUT" | grep '| id ' | awk '{print $4}')
|
|
|
|
echo "Create datastore specific entry in Trove AFAIK one per datastore, do not need when changing image"
|
|
$TROVE_MANAGE datastore_update $TROVE_DATASTORE_TYPE ""
|
|
|
|
echo "Connect datastore entry to glance image"
|
|
$TROVE_MANAGE datastore_version_update $TROVE_DATASTORE_TYPE $TROVE_DATASTORE_VERSION $TROVE_DATASTORE_TYPE $glance_image_id "" $ACTIVE
|
|
|
|
echo "Set default datastore version"
|
|
$TROVE_MANAGE datastore_update $TROVE_DATASTORE_TYPE $TROVE_DATASTORE_VERSION
|
|
|
|
# just for tests
|
|
$TROVE_MANAGE datastore_version_update "$TROVE_DATASTORE_TYPE" "inactive_version" "manager1" $glance_image_id "" $INACTIVE
|
|
$TROVE_MANAGE datastore_update Test_Datastore_1 ""
|
|
|
|
echo "Add validation rules if available"
|
|
if [ -f "$PATH_TROVE"/trove/templates/$TROVE_DATASTORE_TYPE/validation-rules.json ]; then
|
|
$TROVE_MANAGE db_load_datastore_config_parameters "$TROVE_DATASTORE_TYPE" "$TROVE_DATASTORE_VERSION" \
|
|
"$PATH_TROVE"/trove/templates/$TROVE_DATASTORE_TYPE/validation-rules.json
|
|
fi
|
|
|
|
echo "Generate cloudinit"
|
|
CLOUDINIT_PATH=/etc/trove/cloudinit/mysql.cloudinit
|
|
|
|
if [ ! -f $CLOUDINIT_PATH ]; then
|
|
sudo mkdir -p $(dirname $CLOUDINIT_PATH)
|
|
|
|
sudo echo "#!/usr/bin/env bash" | sudo tee $CLOUDINIT_PATH
|
|
PUBKEY=`cat ${SSH_DIR}/id_rsa.pub`
|
|
sudo echo "echo '${PUBKEY}' > /home/${GUEST_USERNAME}/.ssh/authorized_keys" | sudo tee --append $CLOUDINIT_PATH
|
|
fi
|
|
}
|
|
|
|
# Dispatcher for trove plugin
|
|
if is_service_enabled trove; then
|
|
if [[ "$1" == "stack" && "$2" == "install" ]]; then
|
|
echo_summary "Installing Trove"
|
|
install_trove
|
|
install_python_troveclient
|
|
elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
|
|
if is_service_enabled key; then
|
|
create_trove_accounts
|
|
fi
|
|
|
|
echo_summary "Configuring Trove"
|
|
configure_trove
|
|
elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
|
|
# Initialize trove
|
|
init_trove
|
|
|
|
# finish the last step in trove network configuration
|
|
echo_summary "Finalizing Trove Network Configuration"
|
|
|
|
if is_service_enabled neutron; then
|
|
echo "finalize_trove_network: Neutron is enabled."
|
|
finalize_trove_network
|
|
else
|
|
echo "finalize_trove_network: Neutron is not enabled. Nothing to do."
|
|
fi
|
|
|
|
_config_nova_keypair
|
|
|
|
# Start the trove API and trove taskmgr components
|
|
echo_summary "Starting Trove"
|
|
start_trove
|
|
|
|
# Guarantee the file permission in the trove code repo in order to
|
|
# download trove code from trove-guestagent.
|
|
sudo chown -R $STACK_USER:$STACK_USER "$DEST/trove"
|
|
elif [[ "$1" == "stack" && "$2" == "test-config" ]]; then
|
|
echo_summary "Configuring Tempest for Trove"
|
|
configure_tempest_for_trove
|
|
fi
|
|
|
|
if [[ "$1" == "unstack" ]]; then
|
|
stop_trove
|
|
cleanup_trove
|
|
fi
|
|
fi
|
|
|
|
# Restore xtrace
|
|
$XTRACE
|
|
|
|
# Tell emacs to use shell-script-mode
|
|
## Local variables:
|
|
## mode: shell-script
|
|
## End:
|