#!/bin/bash # # lib/tacker # functions - functions specific to tacker # Dependencies: # ``functions`` file # ``DEST`` must be defined # ``STACK_USER`` must be defined # ``stack.sh`` calls the entry points in this order: # # - install_tacker # - configure_tacker # - create_tacker_accounts # - create_keystone_endpoint # - init_tacker # - start_tacker # - tacker_horizon_install # - tacker_create_initial_network # # ``unstack.sh`` calls the entry points in this order: # # - stop_tacker # - cleanup_tacker # Tacker # --------------- # Save trace setting XTRACE=$(set +o | grep xtrace) set +o xtrace # Defaults # -------- # Set up default directories GITREPO["tacker-horizon"]=${TACKERHORIZON_REPO:-${GIT_BASE}/openstack/tacker-horizon.git} GITBRANCH["tacker-horizon"]=${TACKERHORIZON_BRANCH:-master} GITDIR["tacker-horizon"]=$DEST/tacker-horizon GITREPO["python-tackerclient"]=${TACKERCLIENT_REPO:-${GIT_BASE}/openstack/python-tackerclient.git} GITBRANCH["python-tackerclient"]=${TACKERCLIENT_BRANCH:-master} GITDIR["python-tackerclient"]=$DEST/python-tackerclient TACKER_DIR=$DEST/tacker # Support entry points installation of console scripts if [[ -d $TACKER_DIR/bin/tacker-server ]]; then TACKER_BIN_DIR=$TACKER_DIR/bin else TACKER_BIN_DIR=$(get_python_exec_prefix) fi TACKER_CONF_DIR=/etc/tacker TACKER_CONF=$TACKER_CONF_DIR/tacker.conf TACKER_DATA_DIR=${TACKER_DATA_DIR:=$DATA_DIR/tacker} # Default name for Tacker database TACKER_DB_NAME=${TACKER_DB_NAME:-tacker} # Default Tacker Port TACKER_PORT=${TACKER_PORT:-9890} # Default Tacker Host TACKER_HOST=${TACKER_HOST:-$SERVICE_HOST} # Default protocol TACKER_PROTOCOL=${TACKER_PROTOCOL:-$SERVICE_PROTOCOL} # Default admin username TACKER_ADMIN_USERNAME=${TACKER_ADMIN_USERNAME:-tacker} # Default auth strategy TACKER_AUTH_STRATEGY=${TACKER_AUTH_STRATEGY:-keystone} TACKER_NOVA_URL=${TACKER_NOVA_URL:-http://127.0.0.1:8774/v2} TACKER_NOVA_CA_CERTIFICATES_FILE=${TACKER_NOVA_CA_CERTIFICATES_FILE:-} TACKER_NOVA_API_INSECURE=${TACKER_NOVA_API_INSECURE:-False} VNF_PACKAGE_CSAR_PATH=${VNF_PACKAGE_CSAR_PATH:=$TACKER_DATA_DIR/vnfpackage} FILESYSTEM_STORE_DATA_DIR=${FILESYSTEM_STORE_DATA_DIR:=$TACKER_DATA_DIR/csar_files} GLANCE_DEFAULT_BACKEND=${GLANCE_DEFAULT_BACKEND:=file} # Functions # --------- # install_tackerclient - Collect source and prepare function install_tackerclient { if use_library_from_git "python-tackerclient"; then git_clone_by_name "python-tackerclient" setup_dev_lib "python-tackerclient" fi } # function install_db_client_mysql() - ensure mysql client is installed function install_db_client_mysql { if is_oraclelinux; then install_package mysql-community-client elif is_fedora || is_suse; then install_package mariadb-client elif is_ubuntu; then install_package mysql-client else exit_distro_not_supported "mysql client installation" fi } # function install_db_client_postgresql() - ensure postgresql client is installed function install_db_client_postgresql { if is_ubuntu || is_fedora || is_suse; then install_package postgresql-client else exit_distro_not_supported "postgresql client installation" fi } # create_tacker_accounts() - Set up common required tacker accounts # Tenant User Roles # ------------------------------------------------------------------ # service tacker admin # if enabled # Migrated from keystone_data.sh function create_tacker_accounts { if is_service_enabled tacker; then create_service_user "tacker" get_or_create_role "advsvc" create_service_user "tacker" "advsvc" create_service_user "tacker" "admin" local tacker_service=$(get_or_create_service "tacker" \ "nfv-orchestration" "Tacker NFV Orchestration Service") get_or_create_endpoint $tacker_service \ "$REGION_NAME" \ "$TACKER_PROTOCOL://$TACKER_HOST:$TACKER_PORT/" \ "$TACKER_PROTOCOL://$TACKER_HOST:$TACKER_PORT/" \ "$TACKER_PROTOCOL://$TACKER_HOST:$TACKER_PORT/" fi } # create_keystone_endpoint() - create admin endpoint for keystone function create_keystone_endpoint { KEYSTONE_SERVICE=$(get_or_create_service "keystone" \ "identity" "Keystone Identity Service") get_or_create_endpoint $KEYSTONE_SERVICE \ "$REGION_NAME" \ "${KEYSTONE_SERVICE_PROTOCOL}://${KEYSTONE_SERVICE_HOST}/identity" \ "${KEYSTONE_SERVICE_PROTOCOL}://${KEYSTONE_SERVICE_HOST}/identity" \ "${KEYSTONE_SERVICE_PROTOCOL}://${KEYSTONE_SERVICE_HOST}/identity" } # stack.sh entry points # --------------------- # init_tacker() - Initialize databases, etc. function init_tacker { # In case db service is disabled, which would have installed cli commands. install_db_client_$DATABASE_TYPE recreate_database $TACKER_DB_NAME # Run Tacker db migrations $TACKER_BIN_DIR/tacker-db-manage --config-file $TACKER_CONF upgrade head } # install_tacker() - Collect source and prepare function install_tacker { setup_develop $TACKER_DIR } function start_tacker { local cfg_file_options="--config-file $TACKER_CONF" local service_port=$TACKER_PORT local service_protocol=$TACKER_PROTOCOL # Start the Tacker service sudo cp $TACKER_DIR/etc/systemd/system/tacker.service $SYSTEMD_DIR/devstack@tacker.service iniset -sudo $SYSTEMD_DIR/devstack@tacker.service "Service" "User" $STACK_USER iniset -sudo $SYSTEMD_DIR/devstack@tacker.service "Service" "ExecStart" "$TACKER_BIN_DIR/tacker-server $cfg_file_options" sudo systemctl enable devstack@tacker.service sudo systemctl restart devstack@tacker.service # Start the Tacker conductor service sudo cp $TACKER_DIR/etc/systemd/system/tacker-conductor.service $SYSTEMD_DIR/devstack@tacker-conductor.service iniset -sudo $SYSTEMD_DIR/devstack@tacker-conductor.service "Service" "User" $STACK_USER iniset -sudo $SYSTEMD_DIR/devstack@tacker-conductor.service "Service" "ExecStart" "$TACKER_BIN_DIR/tacker-conductor $cfg_file_options" sudo systemctl enable devstack@tacker-conductor.service sudo systemctl restart devstack@tacker-conductor.service echo "Waiting for Tacker to start..." if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget --no-proxy -q -O- $service_protocol://$TACKER_HOST:$service_port; do sleep 1; done"; then die $LINENO "Tacker did not start" fi } # stop_tacker() - Stop running processes (non-screen) function stop_tacker { stop_process tacker stop_process tacker-conductor } # cleanup_tacker() - Remove residual data files, anything left over from previous # runs that a clean run would need to clean up function cleanup_tacker { sudo rm -rf $VNF_PACKAGE_CSAR_PATH sudo rm -rf $FILESYSTEM_STORE_DATA_DIR } function _create_tacker_conf_dir { # Put config files in ``TACKER_CONF_DIR`` for everyone to find sudo install -d -o $STACK_USER $TACKER_CONF_DIR } function _create_tacker_data_dirs { # Create tacker data folder sudo install -d -o $STACK_USER $TACKER_DATA_DIR # Create vnf package csar extract path folder sudo install -d -o $STACK_USER ${VNF_PACKAGE_CSAR_PATH} # Create folder for storing csar files in the glance store. sudo install -d -o $STACK_USER ${FILESYSTEM_STORE_DATA_DIR} } # configure_tacker() # Set common config for all tacker server and agents. function configure_tacker { _create_tacker_conf_dir cd $TACKER_DIR ./tools/generate_config_file_sample.sh cd - cp $TACKER_DIR/etc/tacker/tacker.conf.sample $TACKER_CONF cp $TACKER_DIR/etc/tacker/prometheus-plugin.yaml $TACKER_CONF_DIR/prometheus-plugin.yaml iniset_rpc_backend tacker $TACKER_CONF iniset $TACKER_CONF database connection `database_connection_url $TACKER_DB_NAME` iniset $TACKER_CONF DEFAULT state_path $TACKER_DATA_DIR iniset $TACKER_CONF DEFAULT use_syslog $SYSLOG iniset $TACKER_CONF vnf_package vnf_package_csar_path "$VNF_PACKAGE_CSAR_PATH" iniset $TACKER_CONF glance_store filesystem_store_datadir "$FILESYSTEM_STORE_DATA_DIR" iniset $TACKER_CONF glance_store default_backend "$GLANCE_DEFAULT_BACKEND" # Create the required data folders _create_tacker_data_dirs # Format logging setup_logging $TACKER_CONF # server TACKER_API_PASTE_FILE=$TACKER_CONF_DIR/api-paste.ini cp $TACKER_DIR/etc/tacker/api-paste.ini $TACKER_API_PASTE_FILE iniset $TACKER_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL iniset $TACKER_CONF DEFAULT auth_strategy $TACKER_AUTH_STRATEGY _tacker_setup_keystone $TACKER_CONF keystone_authtoken if [[ "${TACKER_MODE}" == "all" || "${IS_ZUUL_FT}" == "True" ]]; then iniset "/$Q_PLUGIN_CONF_FILE" ml2_type_flat flat_networks $PUBLIC_PHYSICAL_NETWORK,$MGMT_PHYS_NET iniset "/$Q_PLUGIN_CONF_FILE" ovs bridge_mappings $PUBLIC_PHYSICAL_NETWORK:$PUBLIC_BRIDGE,$MGMT_PHYS_NET:$BR_MGMT echo "Creating bridge" sudo ovs-vsctl --may-exist add-br ${BR_MGMT} fi if [[ "${USE_BARBICAN}" == "True" ]]; then iniset $TACKER_CONF vim_keys use_barbican True fi } # Utility Functions #------------------ # Configures keystone integration for tacker service and agents function _tacker_setup_keystone { local conf_file=$1 local section=$2 local use_auth_url=$3 # Configures keystone for metadata_agent # metadata_agent needs auth_url to communicate with keystone if [[ "$use_auth_url" == "True" ]]; then iniset $conf_file $section auth_url $KEYSTONE_SERVICE_URI fi configure_keystone_authtoken_middleware $conf_file $TACKER_ADMIN_USERNAME $section } function tacker_horizon_install { git_clone_by_name "tacker-horizon" setup_dev_lib "tacker-horizon" sudo cp $DEST/tacker-horizon/tacker_horizon/enabled/* $DEST/horizon/openstack_dashboard/enabled/ # make sure NFV's dashboard static files get loaded when deploying $PYTHON $DEST/tacker-horizon/manage.py collectstatic --noinput echo yes | $PYTHON $DEST/tacker-horizon/manage.py compress restart_apache_server } function tacker_horizon_uninstall { sudo rm -f $DEST/horizon/openstack_dashboard/enabled/_80_nfv.py restart_apache_server } function openstack_image_create { image=$1 container_format=bare image_name=$2 disk_format=$3 openstack --os-cloud=devstack-admin image create $image_name --public --container-format=$container_format --disk-format $disk_format --file ${image} openstack image show $image_name -f value -c id } function tacker_check_and_download_images { local image_url image_url[0]="http://download.cirros-cloud.net/0.5.2/cirros-0.5.2-x86_64-disk.img" local image_fname image_name glance_name local gz_pattern="\.gz$" local length=${#image_url[@]} local index=0 install_package jq while [ $index -lt $length ] do image_fname=`basename "${image_url[$index]}"` glance_name=${image_fname%.*} image_name=`openstack image list | grep "$glance_name" | awk '{print $4}'` if [[ $image_name == "" ]]; then if [[ ! -f $FILES/$image_fname || "$(stat -c "%s" $FILES/$image_fname)" = "0" ]]; then if [[ -f ${image_url[$index]} ]]; then cp ${image_url[$index]} $FILES/$image_fname else { wget --progress=dot:giga -c ${image_url[$index]} -O $FILES/$image_fname }||{ echo "WARNING: download image ${image_url[$index]} failed" index=$(($index+1)) continue } fi if [[ $image_fname =~ $gz_pattern ]]; then new_image_fname=${image_fname%.*} gunzip -c $FILES/$image_fname > $FILES/$new_image_fname image_fname=$new_image_fname fi fi { disk_format=`qemu-img info --output=json $FILES/$image_fname | jq -r '.format'` openstack_image_create $FILES/$image_fname $glance_name $disk_format }||{ echo "ERROR: tacker image create for $image_fname failed" image_fname=$image_fname"*" sudo rm -rf $FILES/$image_fname exit 1 } fi index=$(($index+1)) done } function tacker_create_initial_network { # create necessary networks # prepare network echo "Deleting networks" for net in ${NET_MGMT} ${NET0} ${NET1} do for i in $(openstack network list | awk "/${net}/{print \$2}") do openstack network delete $i done done echo "Creating networks" NET_MGMT_ID=$(openstack network create --provider-network-type flat --provider-physical-network ${MGMT_PHYS_NET} --share ${NET_MGMT} | awk '/ id /{print $4}') SUBNET_MGMT_ID=$(openstack subnet create ${SUBNET_MGMT} --ip-version 4 --gateway ${NETWORK_GATEWAY_MGMT} --network ${NET_MGMT_ID} --subnet-range ${FIXED_RANGE_MGMT} | awk '/ id /{print $4}') NET0_ID=$(openstack network create --share ${NET0} | awk '/ id /{print $4}') SUBNET0_ID=$(openstack subnet create ${SUBNET0} --ip-version 4 --gateway ${NETWORK_GATEWAY0} --network ${NET0_ID} --subnet-range ${FIXED_RANGE0} | awk '/ id /{print $4}') NET1_ID=$(openstack network create --share ${NET1} | awk '/ id /{print $4}') SUBNET1_ID=$(openstack subnet create ${SUBNET1} --ip-version 4 --gateway ${NETWORK_GATEWAY1} --network ${NET1_ID} --subnet-range ${FIXED_RANGE1} | awk '/ id /{print $4}') echo "Assign ip address to BR_MGMT" sudo ip link set ${BR_MGMT} up sudo ip -4 address flush dev ${BR_MGMT} sudo ip address add ${NETWORK_GATEWAY_MGMT_IP} dev ${BR_MGMT} } function tacker_setup_default_vim_resources { # Note: These must be the same as in samples/tests/etc/samples/local-vim.yaml # and devstack/vim_config.yaml DEFAULT_VIM_PROJECT_NAME="nfv" DEFAULT_VIM_USER="nfv_user" DEFAULT_VIM_PASSWORD="devstack" echo "Create NFV VIM project $DEFAULT_VIM_PROJECT_NAME ..." get_or_create_project $DEFAULT_VIM_PROJECT_NAME echo "Create NFV VIM user $DEFAULT_VIM_USER ..." get_or_create_user $DEFAULT_VIM_USER $DEFAULT_VIM_PASSWORD default get_or_add_user_project_role admin $DEFAULT_VIM_USER $DEFAULT_VIM_PROJECT_NAME # get_or_add_user_project_role advsvc $DEFAULT_VIM_USER $DEFAULT_VIM_PROJECT_NAME echo "Set register default VIM sh which is called by ansible role..." cp $TACKER_DIR/devstack/vim_config.yaml $TACKER_DATA_DIR VIM_CONFIG_FILE="$TACKER_DATA_DIR/vim_config.yaml" sed -e "s|^auth_url:.*$|auth_url: \'${KEYSTONE_SERVICE_URI}\'|" -i $VIM_CONFIG_FILE echo "The content of VIM config file $VIM_CONFIG_FILE :" cat $VIM_CONFIG_FILE echo "Set up target openstack vim resources ..." openstack --os-cloud=devstack-admin quota set \ --default --instances -1 --cores -1 --ram -1 default openstack --os-cloud=devstack-admin \ quota set --ports -1 $DEFAULT_VIM_PROJECT_NAME --force openstack --os-region-name $REGION_NAME --os-project-name $DEFAULT_VIM_PROJECT_NAME \ --os-user-domain-id default --os-username $DEFAULT_VIM_USER \ --os-project-domain-id default --os-auth-url $KEYSTONE_SERVICE_URI \ --os-password $DEFAULT_VIM_PASSWORD --os-cloud "" keypair create userKey openstack --os-region-name $REGION_NAME --os-project-name $DEFAULT_VIM_PROJECT_NAME \ --os-user-domain-id default --os-username $DEFAULT_VIM_USER \ --os-project-domain-id default --os-auth-url $KEYSTONE_SERVICE_URI \ --os-password $DEFAULT_VIM_PASSWORD --os-cloud "" \ security group create \ --description "tacker functest security group" test_secgrp openstack --os-region-name $REGION_NAME --os-project-name $DEFAULT_VIM_PROJECT_NAME \ --os-user-domain-id default --os-username $DEFAULT_VIM_USER \ --os-project-domain-id default --os-auth-url $KEYSTONE_SERVICE_URI \ --os-password $DEFAULT_VIM_PASSWORD --os-cloud "" \ security group rule create \ --ingress --protocol icmp test_secgrp openstack --os-region-name $REGION_NAME --os-project-name $DEFAULT_VIM_PROJECT_NAME \ --os-user-domain-id default --os-username $DEFAULT_VIM_USER \ --os-project-domain-id default --os-auth-url $KEYSTONE_SERVICE_URI \ --os-password $DEFAULT_VIM_PASSWORD --os-cloud "" \ security group rule create \ --ingress --protocol tcp --dst-port 22 test_secgrp } function setup_k8s_service { # These kernel modules and configurations are required to build # a kubernetes cluster and communicate between pods. cat < /dev/null 2>&1; then sudo ip link set cni0 down sudo ip link delete cni0 fi if ip link show flannel.1 > /dev/null 2>&1; then sudo ip link set flannel.1 down sudo ip link delete flannel.1 fi sudo systemctl restart kubelet kubectl delete pod -n kube-system \ $(kubectl get pod -n kube-system --no-headers -o custom-columns=":metadata.name" | grep coredns | tr -s '\n' ' ') kubectl delete -f $flannel_path kubectl apply -f $flannel_path }