#!/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 # - init_tacker # - start_tacker_api # - 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 # -------- if is_ssl_enabled_service "tacker" || is_service_enabled tls-proxy; then TACKER_PROTOCOL="https" fi # Set up default directories GITREPO["tacker-horizon"]=${TACKERHORIZON_REPO:-${GIT_BASE}/openstack/tacker-horizon.git} GITBRANCH["tacker-horizon"]=${TACKERHORZION_BRANCH:-master} GITDIR["tacker-horizon"]=$DEST/tacker-horizon TACKER_DIR=$DEST/tacker TACKER_AUTH_CACHE_DIR=${TACKER_AUTH_CACHE_DIR:-/var/cache/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 # Default name for Tacker database TACKER_DB_NAME=${TACKER_DB_NAME:-tacker} # Default Tacker Port TACKER_PORT=${TACKER_PORT:-9890} # Default Tacker Internal Port when using TLS proxy TACKER_PORT_INT=${TACKER_PORT_INT:-19890} # TODO(FIX) # 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_USE_ROOTWRAP=${TACKER_USE_ROOTWRAP:-True} TACKER_RR_CONF_FILE=$TACKER_CONF_DIR/rootwrap.conf if [[ "$TACKER_USE_ROOTWRAP" == "False" ]]; then TACKER_RR_COMMAND="sudo" else TACKER_ROOTWRAP=$(get_rootwrap_location tacker) TACKER_RR_COMMAND="sudo $TACKER_ROOTWRAP $TACKER_RR_CONF_FILE" fi 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} # Tell Tempest this project is present # TEMPEST_SERVICES+=,tacker HEAT_CONF_DIR=/etc/heat # Functions # --------- # Test if any Tacker services are enabled # is_tacker_enabled function is_tacker_enabled { [[ ,${ENABLED_SERVICES} =~ ,"tacker" ]] && return 0 return 1 } # create_tacker_cache_dir() - Part of the _tacker_setup_keystone() process function create_tacker_cache_dir { # Create cache dir sudo install -d -o $STACK_USER $TACKER_AUTH_CACHE_DIR rm -f $TACKER_AUTH_CACHE_DIR/* } # 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" if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then local tacker_service=$(get_or_create_service "tacker" \ "nfv-orchestration" "Tacker NFV Orchestration Service") get_or_create_endpoint $tacker_service \ "$REGION_NAME" \ "$TACKER_PROTOCOL://$SERVICE_HOST:$TACKER_PORT/" \ "$TACKER_PROTOCOL://$SERVICE_HOST:$TACKER_PORT/" \ "$TACKER_PROTOCOL://$SERVICE_HOST:$TACKER_PORT/" fi fi } # stack.sh entry points # --------------------- # init_tacker() - Initialize databases, etc. function init_tacker { 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_api { local cfg_file_options="--config-file $TACKER_CONF" local service_port=$TACKER_PORT local service_protocol=$TACKER_PROTOCOL if is_service_enabled tls-proxy; then service_port=$TACKER_PORT_INT service_protocol="http" fi # Start the Tacker service run_process tacker "python $TACKER_BIN_DIR/tacker-server $cfg_file_options" echo "Waiting for Tacker to start..." if is_ssl_enabled_service "tacker"; then ssl_ca="--ca-certificate=${SSL_BUNDLE_FILE}" fi if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget ${ssl_ca} --no-proxy -q -O- $service_protocol://$TACKER_HOST:$service_port; do sleep 1; done"; then die $LINENO "Tacker did not start" fi # Start proxy if enabled if is_service_enabled tls-proxy; then start_tls_proxy '*' $TACKER_PORT $TACKER_HOST $TACKER_PORT_INT & fi } # stop_tacker() - Stop running processes (non-screen) function stop_tacker { stop_process tacker } # 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 $TACKER_AUTH_CACHE_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 } # configure_tacker() # Set common config for all tacker server and agents. function configure_tacker { iniset "/$Q_PLUGIN_CONF_FILE" ml2 extension_drivers port_security 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 _create_tacker_conf_dir cd $TACKER_DIR ./tools/generate_config_file_sample.sh cd - cp $TACKER_DIR/etc/tacker/tacker.conf.sample $TACKER_CONF iniset_rpc_backend tacker $TACKER_CONF iniset $TACKER_CONF database connection `database_connection_url $TACKER_DB_NAME` iniset $TACKER_CONF DEFAULT state_path $DATA_DIR/tacker iniset $TACKER_CONF DEFAULT use_syslog $SYSLOG # Format logging if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then setup_colorized_logging $TACKER_CONF DEFAULT project_id else # Show user_name and project_name by default like in nova iniset $TACKER_CONF DEFAULT logging_context_format_string "%(asctime)s.%(msecs)03d %(levelname)s %(name)s [%(request_id)s %(user_name)s %(project_name)s] %(instance)s%(message)s" fi if is_service_enabled tls-proxy; then # Set the service port for a proxy to take the original iniset $TACKER_CONF DEFAULT bind_port "$TACKER_PORT_INT" fi if is_ssl_enabled_service "tacker"; then ensure_certificates TACKER iniset $TACKER_CONF DEFAULT use_ssl True iniset $TACKER_CONF DEFAULT ssl_cert_file "$TACKER_SSL_CERT" iniset $TACKER_CONF DEFAULT ssl_key_file "$TACKER_SSL_KEY" fi # server TACKER_API_PASTE_FILE=$TACKER_CONF_DIR/api-paste.ini TACKER_POLICY_FILE=$TACKER_CONF_DIR/policy.json cp $TACKER_DIR/etc/tacker/api-paste.ini $TACKER_API_PASTE_FILE cp $TACKER_DIR/etc/tacker/policy.json $TACKER_POLICY_FILE # allow tacker user to administer tacker to match tacker account sed -i 's/"context_is_admin": "role:admin"/"context_is_admin": "role:admin or user_name:tacker"/g' $TACKER_POLICY_FILE iniset $TACKER_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL iniset $TACKER_CONF DEFAULT policy_file $TACKER_POLICY_FILE iniset $TACKER_CONF DEFAULT auth_strategy $TACKER_AUTH_STRATEGY _tacker_setup_keystone $TACKER_CONF keystone_authtoken # Configuration for tacker requests to nova. iniset $TACKER_CONF DEFAULT nova_url $TACKER_NOVA_URL iniset $TACKER_CONF DEFAULT nova_admin_user_name nova iniset $TACKER_CONF DEFAULT nova_admin_password $SERVICE_PASSWORD iniset $TACKER_CONF DEFAULT nova_admin_tenant_id $SERVICE_TENANT_NAME iniset $TACKER_CONF DEFAULT nova_admin_auth_url $KEYSTONE_AUTH_URI iniset $TACKER_CONF DEFAULT nova_ca_certificates_file $TACKER_NOVA_CA_CERTIFICATES_FILE iniset $TACKER_CONF DEFAULT nova_api_insecure $TACKER_NOVA_API_INSECURE iniset $TACKER_CONF DEFAULT nova_region_name $REGION_NAME iniset $TACKER_CONF tacker_nova auth_plugin password iniset $TACKER_CONF tacker_nova auth_url $KEYSTONE_AUTH_URI iniset $TACKER_CONF tacker_nova username nova iniset $TACKER_CONF tacker_nova password $SERVICE_PASSWORD iniset $TACKER_CONF tacker_nova user_domain_id default iniset $TACKER_CONF tacker_nova project_name $SERVICE_TENANT_NAME iniset $TACKER_CONF tacker_nova project_domain_id default iniset $TACKER_CONF tacker_nova region_name $REGION_NAME iniset $TACKER_CONF tacker_heat heat_uri http://$SERVICE_HOST:8004/v1 iniset $TACKER_CONF tacker_heat stack_retries 60 iniset $TACKER_CONF tacker_heat stack_retry_wait 5 iniset $TACKER_CONF keystone_authtoken identity_uri http://127.0.0.1:5000 iniset $TACKER_CONF keystone_authtoken project_domain_id default iniset $TACKER_CONF keystone_authtoken user_domain_id default iniset $TACKER_CONF keystone_authtoken auth_plugin password iniset $TACKER_CONF nfvo_vim default_vim VIM0 _tacker_setup_rootwrap echo "Creating bridge" sudo ovs-vsctl --may-exist add-br ${BR_MGMT} } # Utility Functions #------------------ # _tacker_deploy_rootwrap_filters() - deploy rootwrap filters to $TACKER_CONF_ROOTWRAP_D (owned by root). function _tacker_deploy_rootwrap_filters { local srcdir=$1 sudo install -d -o root -m 755 $TACKER_CONF_ROOTWRAP_D sudo install -o root -m 644 $srcdir/etc/tacker/rootwrap.d/* $TACKER_CONF_ROOTWRAP_D/ } # _tacker_setup_rootwrap() - configure Tacker's rootwrap function _tacker_setup_rootwrap { if [[ "$TACKER_USE_ROOTWRAP" == "False" ]]; then return fi # Wipe any existing ``rootwrap.d`` files first TACKER_CONF_ROOTWRAP_D=$TACKER_CONF_DIR/rootwrap.d if [[ -d $TACKER_CONF_ROOTWRAP_D ]]; then sudo rm -rf $TACKER_CONF_ROOTWRAP_D fi _tacker_deploy_rootwrap_filters $TACKER_DIR sudo install -o root -g root -m 644 $TACKER_DIR/etc/tacker/rootwrap.conf $TACKER_RR_CONF_FILE sudo sed -e "s:^filters_path=.*$:filters_path=$TACKER_CONF_ROOTWRAP_D:" -i $TACKER_RR_CONF_FILE # Specify ``rootwrap.conf`` as first parameter to tacker-rootwrap ROOTWRAP_SUDOER_CMD="$TACKER_ROOTWRAP $TACKER_RR_CONF_FILE *" # Set up the rootwrap sudoers for tacker TEMPFILE=`mktemp` echo "$STACK_USER ALL=(root) NOPASSWD: $ROOTWRAP_SUDOER_CMD" >$TEMPFILE chmod 0440 $TEMPFILE sudo chown root:root $TEMPFILE sudo mv $TEMPFILE /etc/sudoers.d/tacker-rootwrap # Update the root_helper iniset $TACKER_CONF agent root_helper "$TACKER_RR_COMMAND" } # 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/v2.0 fi create_tacker_cache_dir configure_auth_token_middleware $conf_file $TACKER_ADMIN_USERNAME $TACKER_AUTH_CACHE_DIR $section } function tacker_horizon_install { git_clone_by_name "tacker-horizon" setup_dev_lib "tacker-horizon" sudo cp $DEST/tacker-horizon/openstack_dashboard_extensions/* $DEST/horizon/openstack_dashboard/enabled/ restart_apache_server } function openstack_image_create_openwrt { image=$1 disk_format=raw container_format=bare image_name="OpenWRT" openstack --os-cloud=devstack-admin image create $image_name --public --container-format=$container_format --disk-format $disk_format < <(zcat --force "${image}") glance image-list | grep OpenWRT | awk {print$2} } function tacker_create_openwrt_image { local image_url=https://downloads.openwrt.org/chaos_calmer/15.05/x86/kvm_guest/openwrt-15.05-x86-kvm_guest-combined-ext4.img.gz local image image_fname image_name image_fname=`basename "$image_url"` if [[ $image_url != file* ]]; then if [[ ! -f $FILES/$image_fname || "$(stat -c "%s" $FILES/$image_fname)" = "0" ]]; then { wget --progress=dot:giga -c $image_url -O $FILES/$image_fname \ && openstack_image_create_openwrt $FILES/$image_fname }||{ rm -rf $FILES/$image_fname echo "WARNING: openwrt image create for $image_fname failed" } fi fi } function tacker_create_initial_network { # create necessary networks # prepare network echo "Deleting networks" for net in ${NET_MGMT} ${NET0} ${NET1} do for i in $(neutron net-list | awk "/${net}/{print \$2}") do neutron net-delete $i done done echo "Creating networks" NET_MGMT_ID=$(neutron net-create --provider:network_type flat --provider:physical_network ${MGMT_PHYS_NET} --shared ${NET_MGMT} | awk '/ id /{print $4}') SUBNET_MGMT_ID=$(neutron subnet-create --name ${SUBNET_MGMT} --ip-version 4 --gateway ${NETWORK_GATEWAY_MGMT} ${NET_MGMT_ID} ${FIXED_RANGE_MGMT} | awk '/ id /{print $4}') NET0_ID=$(neutron net-create --shared ${NET0} | awk '/ id /{print $4}') SUBNET0_ID=$(neutron subnet-create --name ${SUBNET0} --ip-version 4 --gateway ${NETWORK_GATEWAY0} ${NET0_ID} ${FIXED_RANGE0} | awk '/ id /{print $4}') NET1_ID=$(neutron net-create --shared ${NET1} | awk '/ id /{print $4}') SUBNET1_ID=$(neutron subnet-create --name ${SUBNET1} --ip-version 4 --gateway ${NETWORK_GATEWAY1} ${NET1_ID} ${FIXED_RANGE1} | awk '/ id /{print $4}') echo "Assign ip address to BR_MGMT" sudo ifconfig ${BR_MGMT} inet 0.0.0.0 sudo ifconfig ${BR_MGMT} inet ${NETWORK_GATEWAY_MGMT_IP} } function tacker_register_default_vim { local default_vim_id DEFAULT_VIM_PROJECT_NAME="nfv" DEFAULT_VIM_USER="nfv_user" DEFAULT_VIM_PASSWORD="devstack" DEFAULT_VIM_NAME="VIM0" get_or_create_project $DEFAULT_VIM_PROJECT_NAME get_or_create_user $DEFAULT_VIM_USER $DEFAULT_VIM_PASSWORD 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 VIM_CONFIG_FILE="$TACKER_DIR/devstack/vim_config.yaml" default_vim_id=$(tacker vim-register --is-default --name $DEFAULT_VIM_NAME --config-file $VIM_CONFIG_FILE -f value -c id) echo $default_vim_id } function modify_heat_flavor_policy_rule { local policy_file=$HEAT_CONF_DIR/policy.json # Allow non-admin projects with 'admin' roles to create flavors in Heat sed -i 's/"resource_types:OS::Nova::Flavor": "rule:context_is_admin"/"resource_types:OS::Nova::Flavor": "role:admin"/' $policy_file }