# lib/tempest
# Install and configure Tempest

# Dependencies:
#
# - ``functions`` file
# - ``lib/nova`` service is running
# - Global vars that are assumed to be defined:
#   - ``DEST``, ``FILES``
#   - ``ADMIN_PASSWORD``
#   - ``DEFAULT_IMAGE_NAME``
#   - ``S3_SERVICE_PORT``
#   - ``SERVICE_HOST``
#   - ``BASE_SQL_CONN`` ``lib/database`` declares
#   - ``PUBLIC_NETWORK_NAME``
#   - ``Q_USE_NAMESPACE``
#   - ``Q_ROUTER_NAME``
#   - ``Q_L3_ENABLED``
#   - ``VIRT_DRIVER``
#   - ``LIBVIRT_TYPE``
#   - ``KEYSTONE_SERVICE_PROTOCOL``, ``KEYSTONE_SERVICE_HOST`` from lib/keystone
#
# Optional Dependencies:
#
# - ``ALT_*`` (similar vars exists in keystone_data.sh)
# - ``LIVE_MIGRATION_AVAILABLE``
# - ``USE_BLOCK_MIGRATION_FOR_LIVE_MIGRATION``
# - ``DEFAULT_INSTANCE_TYPE``
# - ``DEFAULT_INSTANCE_USER``
# - ``CINDER_MULTI_LVM_BACKEND``
#
# ``stack.sh`` calls the entry points in this order:
#
# - install_tempest
# - configure_tempest
# - init_tempest

# Save trace setting
XTRACE=$(set +o | grep xtrace)
set +o xtrace


# Defaults
# --------

# Set up default directories
GITDIR["tempest-lib"]=$DEST/tempest-lib

TEMPEST_DIR=$DEST/tempest
TEMPEST_CONFIG_DIR=${TEMPEST_CONFIG_DIR:-$TEMPEST_DIR/etc}
TEMPEST_CONFIG=$TEMPEST_CONFIG_DIR/tempest.conf
TEMPEST_STATE_PATH=${TEMPEST_STATE_PATH:=$DATA_DIR/tempest}

NOVA_SOURCE_DIR=$DEST/nova

BUILD_INTERVAL=1

# This is the timeout that tempest will wait for a VM to change state,
# spawn, delete, etc.
# The default is set to 196 seconds.
BUILD_TIMEOUT=${BUILD_TIMEOUT:-196}


BOTO_MATERIALS_PATH="$FILES/images/s3-materials/cirros-${CIRROS_VERSION}"

# Cinder/Volume variables
TEMPEST_VOLUME_DRIVER=${TEMPEST_VOLUME_DRIVER:-default}
TEMPEST_VOLUME_VENDOR=${TEMPEST_VOLUME_VENDOR:-"Open Source"}
TEMPEST_STORAGE_PROTOCOL=${TEMPEST_STORAGE_PROTOCOL:-iSCSI}

# Neutron/Network variables
IPV6_ENABLED=$(trueorfalse True $IPV6_ENABLED)
IPV6_SUBNET_ATTRIBUTES_ENABLED=$(trueorfalse True $IPV6_SUBNET_ATTRIBUTES_ENABLED)

# Functions
# ---------

# configure_tempest() - Set config files, create data dirs, etc
function configure_tempest {
    # install testr since its used to process tempest logs
    pip_install_gr testrepository

    local image_lines
    local images
    local num_images
    local image_uuid
    local image_uuid_alt
    local password
    local line
    local flavors
    local available_flavors
    local flavors_ref
    local flavor_lines
    local public_network_id
    local public_router_id
    local tenant_networks_reachable
    local boto_instance_type="m1.tiny"
    local ssh_connect_method="fixed"

    # Save IFS
    ifs=$IFS

    # Glance should already contain images to be used in tempest
    # testing. Here we simply look for images stored in Glance
    # and set the appropriate variables for use in the tempest config
    # We ignore ramdisk and kernel images, look for the default image
    # ``DEFAULT_IMAGE_NAME``. If not found, we set the ``image_uuid`` to the
    # first image returned and set ``image_uuid_alt`` to the second,
    # if there is more than one returned...
    # ... Also ensure we only take active images, so we don't get snapshots in process
    declare -a images

    if is_service_enabled glance; then
        while read -r IMAGE_NAME IMAGE_UUID; do
            if [ "$IMAGE_NAME" = "$DEFAULT_IMAGE_NAME" ]; then
                image_uuid="$IMAGE_UUID"
                image_uuid_alt="$IMAGE_UUID"
            fi
            images+=($IMAGE_UUID)
        # TODO(stevemar): update this command to use openstackclient's `openstack image list`
        # when it supports listing by status.
        done < <(glance image-list --status=active | awk -F'|' '!/^(+--)|ID|aki|ari/ { print $3,$2 }')

        case "${#images[*]}" in
            0)
                echo "Found no valid images to use!"
                exit 1
                ;;
            1)
                if [ -z "$image_uuid" ]; then
                    image_uuid=${images[0]}
                    image_uuid_alt=${images[0]}
                fi
                ;;
            *)
                if [ -z "$image_uuid" ]; then
                    image_uuid=${images[0]}
                    image_uuid_alt=${images[1]}
                fi
                ;;
        esac
    fi

    # (Re)create ``tempest.conf``
    # Create every time because the image UUIDS are going to change
    if [[ ! -d $TEMPEST_CONFIG_DIR ]]; then
        sudo mkdir -p $TEMPEST_CONFIG_DIR
    fi
    sudo chown $STACK_USER $TEMPEST_CONFIG_DIR
    rm -f $TEMPEST_CONFIG

    password=${ADMIN_PASSWORD:-secrete}

    # See files/keystone_data.sh and stack.sh where admin, demo and alt_demo
    # user and tenant are set up...
    ADMIN_USERNAME=${ADMIN_USERNAME:-admin}
    ADMIN_TENANT_NAME=${ADMIN_TENANT_NAME:-admin}
    ADMIN_DOMAIN_NAME=${ADMIN_DOMAIN_NAME:-Default}
    TEMPEST_USERNAME=${TEMPEST_USERNAME:-demo}
    TEMPEST_TENANT_NAME=${TEMPEST_TENANT_NAME:-demo}
    ALT_USERNAME=${ALT_USERNAME:-alt_demo}
    ALT_TENANT_NAME=${ALT_TENANT_NAME:-alt_demo}
    ADMIN_TENANT_ID=$(openstack project list | awk "/ admin / { print \$2 }")

    if is_service_enabled nova; then
        # If the ``DEFAULT_INSTANCE_TYPE`` not declared, use the new behavior
        # Tempest creates instane types for himself
        if  [[ -z "$DEFAULT_INSTANCE_TYPE" ]]; then
            available_flavors=$(nova flavor-list)
            if [[ ! ( $available_flavors =~ 'm1.nano' ) ]]; then
                if is_arch "ppc64"; then
                    # qemu needs at least 128MB of memory to boot on ppc64
                    nova flavor-create m1.nano 42 128 0 1
                else
                    nova flavor-create m1.nano 42 64 0 1
                fi
            fi
            flavor_ref=42
            boto_instance_type=m1.nano
            if [[ ! ( $available_flavors =~ 'm1.micro' ) ]]; then
                if is_arch "ppc64"; then
                    nova flavor-create m1.micro 84 256 0 1
                else
                    nova flavor-create m1.micro 84 128 0 1
                fi
            fi
            flavor_ref_alt=84
        else
            # Check Nova for existing flavors and, if set, look for the
            # ``DEFAULT_INSTANCE_TYPE`` and use that.
            boto_instance_type=$DEFAULT_INSTANCE_TYPE
            flavor_lines=`nova flavor-list`
            IFS=$'\r\n'
            flavors=""
            for line in $flavor_lines; do
                f=$(echo $line | awk "/ $DEFAULT_INSTANCE_TYPE / { print \$2 }")
                flavors="$flavors $f"
            done

            for line in $flavor_lines; do
                flavors="$flavors `echo $line | grep -v "^\(|\s*ID\|+--\)" | cut -d' ' -f2`"
            done

            IFS=" "
            flavors=($flavors)
            num_flavors=${#flavors[*]}
            echo "Found $num_flavors flavors"
            if [[ $num_flavors -eq 0 ]]; then
                echo "Found no valid flavors to use!"
                exit 1
            fi
            flavor_ref=${flavors[0]}
            flavor_ref_alt=$flavor_ref

            # ensure flavor_ref and flavor_ref_alt have different values
            # some resize instance in tempest tests depends on this.
            for f in ${flavors[@]:1}; do
                if [[ $f -ne $flavor_ref ]]; then
                    flavor_ref_alt=$f
                    break
                fi
            done
        fi
    fi

    if [ "$Q_USE_NAMESPACE" != "False" ]; then
        tenant_networks_reachable=false
        if ! is_service_enabled n-net; then
            ssh_connect_method="floating"
        fi
    else
        tenant_networks_reachable=true
    fi

    ssh_connect_method=${TEMPEST_SSH_CONNECT_METHOD:-$ssh_connect_method}

    if [ "$Q_L3_ENABLED" = "True" ]; then
        public_network_id=$(neutron net-list | grep $PUBLIC_NETWORK_NAME | \
            awk '{print $2}')
        if [ "$Q_USE_NAMESPACE" == "False" ]; then
            # If namespaces are disabled, devstack will create a single
            # public router that tempest should be configured to use.
            public_router_id=$(neutron router-list | awk "/ $Q_ROUTER_NAME / \
                { print \$2 }")
        fi
    fi

    # Oslo
    iniset $TEMPEST_CONFIG DEFAULT lock_path $TEMPEST_STATE_PATH
    mkdir -p $TEMPEST_STATE_PATH
    iniset $TEMPEST_CONFIG DEFAULT use_stderr False
    iniset $TEMPEST_CONFIG DEFAULT log_file tempest.log
    iniset $TEMPEST_CONFIG DEFAULT debug True

    # Timeouts
    iniset $TEMPEST_CONFIG compute build_timeout $BUILD_TIMEOUT
    iniset $TEMPEST_CONFIG volume build_timeout $BUILD_TIMEOUT
    iniset $TEMPEST_CONFIG boto build_timeout $BUILD_TIMEOUT
    iniset $TEMPEST_CONFIG boto http_socket_timeout 5

    # Identity
    iniset $TEMPEST_CONFIG identity uri "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:5000/v2.0/"
    iniset $TEMPEST_CONFIG identity uri_v3 "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:5000/v3/"
    iniset $TEMPEST_CONFIG identity username $TEMPEST_USERNAME
    iniset $TEMPEST_CONFIG identity password "$password"
    iniset $TEMPEST_CONFIG identity tenant_name $TEMPEST_TENANT_NAME
    iniset $TEMPEST_CONFIG identity alt_username $ALT_USERNAME
    iniset $TEMPEST_CONFIG identity alt_password "$password"
    iniset $TEMPEST_CONFIG identity alt_tenant_name $ALT_TENANT_NAME
    iniset $TEMPEST_CONFIG identity admin_username $ADMIN_USERNAME
    iniset $TEMPEST_CONFIG identity admin_password "$password"
    iniset $TEMPEST_CONFIG identity admin_tenant_name $ADMIN_TENANT_NAME
    iniset $TEMPEST_CONFIG identity admin_tenant_id $ADMIN_TENANT_ID
    iniset $TEMPEST_CONFIG identity admin_domain_name $ADMIN_DOMAIN_NAME
    iniset $TEMPEST_CONFIG identity auth_version ${TEMPEST_AUTH_VERSION:-v2}

    # Identity Features
    iniset $TEMPEST_CONFIG identity-feature-enabled xml_api True

    # Image
    # for the gate we want to be able to override this variable so we aren't
    # doing an HTTP fetch over the wide internet for this test
    if [[ ! -z "$TEMPEST_HTTP_IMAGE" ]]; then
        iniset $TEMPEST_CONFIG image http_image $TEMPEST_HTTP_IMAGE
    fi

    # Compute
    iniset $TEMPEST_CONFIG compute allow_tenant_isolation ${TEMPEST_ALLOW_TENANT_ISOLATION:-True}
    iniset $TEMPEST_CONFIG auth tempest_roles "Member"
    iniset $TEMPEST_CONFIG compute ssh_user ${DEFAULT_INSTANCE_USER:-cirros} # DEPRECATED
    iniset $TEMPEST_CONFIG compute network_for_ssh $PRIVATE_NETWORK_NAME
    iniset $TEMPEST_CONFIG compute ip_version_for_ssh 4
    iniset $TEMPEST_CONFIG compute ssh_timeout $BUILD_TIMEOUT
    iniset $TEMPEST_CONFIG compute image_ref $image_uuid
    iniset $TEMPEST_CONFIG compute image_ssh_user ${DEFAULT_INSTANCE_USER:-cirros}
    iniset $TEMPEST_CONFIG compute image_ref_alt $image_uuid_alt
    iniset $TEMPEST_CONFIG compute image_alt_ssh_user ${DEFAULT_INSTANCE_USER:-cirros}
    iniset $TEMPEST_CONFIG compute flavor_ref $flavor_ref
    iniset $TEMPEST_CONFIG compute flavor_ref_alt $flavor_ref_alt
    iniset $TEMPEST_CONFIG compute ssh_connect_method $ssh_connect_method
    iniset $TEMPEST_CONFIG compute fixed_network_name $PRIVATE_NETWORK_NAME

    # Compute Features
    iniset $TEMPEST_CONFIG compute-feature-enabled resize True
    iniset $TEMPEST_CONFIG compute-feature-enabled live_migration ${LIVE_MIGRATION_AVAILABLE:-False}
    iniset $TEMPEST_CONFIG compute-feature-enabled change_password False
    iniset $TEMPEST_CONFIG compute-feature-enabled block_migration_for_live_migration ${USE_BLOCK_MIGRATION_FOR_LIVE_MIGRATION:-False}

    DEFAULT_COMPUTE_EXT="NMN, OS-DCF, OS-EXT-AZ, OS-EXT-IMG-SIZE, OS-EXT-IPS, OS-EXT-IPS-MAC, OS-EXT-SRV-ATTR, OS-EXT-STS"
    DEFAULT_COMPUTE_EXT+=", OS-EXT-VIF-NET, OS-FLV-DISABLED, OS-FLV-EXT-DATA, OS-SCH-HNT, OS-SRV-USG"
    DEFAULT_COMPUTE_EXT+=", os-admin-actions, os-agents, os-aggregates, os-assisted-volume-snapshots"
    DEFAULT_COMPUTE_EXT+=", os-attach-interfaces, os-availability-zone, os-baremetal-ext-status, os-baremetal-nodes"
    DEFAULT_COMPUTE_EXT+=", os-block-device-mapping-v2-boot, os-cell-capacities, os-cells, os-certificates"
    DEFAULT_COMPUTE_EXT+=", os-cloudpipe, os-cloudpipe-update, os-config-drive, os-console-auth-tokens"
    DEFAULT_COMPUTE_EXT+=", os-console-output, os-consoles, os-create-server-ext, os-deferred-delete, os-evacuate"
    DEFAULT_COMPUTE_EXT+=", os-extended-evacuate-find-host, os-extended-floating-ips, os-extended-hypervisors"
    DEFAULT_COMPUTE_EXT+=", os-extended-networks, os-extended-quotas, os-extended-rescue-with-image"
    DEFAULT_COMPUTE_EXT+=", os-extended-services, os-extended-services-delete, os-extended-volumes, os-fixed-ips"
    DEFAULT_COMPUTE_EXT+=", os-flavor-access, os-flavor-extra-specs, os-flavor-manage, os-flavor-rxtx"
    DEFAULT_COMPUTE_EXT+=", os-flavor-swap, os-floating-ip-dns, os-floating-ip-pools, os-floating-ips"
    DEFAULT_COMPUTE_EXT+=", os-floating-ips-bulk, os-fping, os-hide-server-addresses, os-hosts, os-hypervisor-status"
    DEFAULT_COMPUTE_EXT+=", os-hypervisors, os-instance-actions, os-instance_usage_audit_log, os-keypairs"
    DEFAULT_COMPUTE_EXT+=", os-migrations, os-multiple-create, os-networks, os-networks-associate"
    DEFAULT_COMPUTE_EXT+=", os-preserve-ephemeral-rebuild, os-quota-class-sets, os-quota-sets, os-rescue"
    DEFAULT_COMPUTE_EXT+=", os-security-group-default-rules, os-security-groups, os-server-diagnostics"
    DEFAULT_COMPUTE_EXT+=", os-server-external-events, os-server-group-quotas, os-server-groups"
    DEFAULT_COMPUTE_EXT+=", os-server-list-multi-status, os-server-password, os-server-start-stop, os-services"
    DEFAULT_COMPUTE_EXT+=", os-shelve, os-simple-tenant-usage, os-tenant-networks, os-used-limits"
    DEFAULT_COMPUTE_EXT+=", os-used-limits-for-admin, os-user-data, os-user-quotas, os-virtual-interfaces"
    DEFAULT_COMPUTE_EXT+=", os-volume-attachment-update, os-volumes"

    iniset $TEMPEST_CONFIG compute-feature-enabled api_extensions "${COMPUTE_API_EXTENSIONS:-$DEFAULT_COMPUTE_EXT}"
    iniset $TEMPEST_CONFIG compute-feature-enabled xml_api_v2 ${COMPUTE_XML_API_V2:-True}
    iniset $TEMPEST_CONFIG compute-feature-disabled api_extensions "${DISABLE_COMPUTE_API_EXTENSIONS}"

    # Compute admin
    iniset $TEMPEST_CONFIG "compute-admin" username $ADMIN_USERNAME
    iniset $TEMPEST_CONFIG "compute-admin" password "$password"
    iniset $TEMPEST_CONFIG "compute-admin" tenant_name $ADMIN_TENANT_NAME

    # Network
    iniset $TEMPEST_CONFIG network api_version 2.0
    iniset $TEMPEST_CONFIG network tenant_networks_reachable "$tenant_networks_reachable"
    iniset $TEMPEST_CONFIG network public_network_id "$public_network_id"
    iniset $TEMPEST_CONFIG network public_router_id "$public_router_id"
    iniset $TEMPEST_CONFIG network default_network "$FIXED_RANGE"
    iniset $TEMPEST_CONFIG network-feature-enabled ipv6 "$IPV6_ENABLED"
    iniset $TEMPEST_CONFIG network-feature-enabled ipv6_subnet_attributes "$IPV6_SUBNET_ATTRIBUTES_ENABLED"
    DEFAULT_NET_EXT="agent, allowed-address-pairs, binding, dhcp_agent_scheduler, dvr, ext-gw-mode, external-net, extra_dhcp_opt"
    DEFAULT_NET_EXT+=", extraroute, fwaas, l3-ha, l3_agent_scheduler, lbaas, lbaas_agent_scheduler, metering"
    DEFAULT_NET_EXT+=", multi-provider, provider, quotas, router, security-group, service-type, vpnaas"
    iniset $TEMPEST_CONFIG network-feature-enabled api_extensions "${NETWORK_API_EXTENSIONS:-$DEFAULT_NET_EXT}"
    iniset $TEMPEST_CONFIG network-feature-disabled api_extensions "${DISABLE_NETWORK_API_EXTENSIONS}"
    iniset $TEMPEST_CONFIG network-feature-enabled xml_api True

    # boto - disabled
    #
    # because of compat issues boto in icehouse is not testable
    # against tempest. Set FORCE_BOTO=1 in local.conf to enable.
    iniset $TEMPEST_CONFIG compute-feature-enabled ec2_api False
    if [[ -n "$FORCE_BOTO" ]]; then
        iniset $TEMPEST_CONFIG boto ec2_url "$EC2_SERVICE_PROTOCOL://$SERVICE_HOST:8773/services/Cloud"
        iniset $TEMPEST_CONFIG boto s3_url "http://$SERVICE_HOST:${S3_SERVICE_PORT:-3333}"
        iniset $TEMPEST_CONFIG boto s3_materials_path "$BOTO_MATERIALS_PATH"
        iniset $TEMPEST_CONFIG boto ari_manifest cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-initrd.manifest.xml
        iniset $TEMPEST_CONFIG boto ami_manifest cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-blank.img.manifest.xml
        iniset $TEMPEST_CONFIG boto aki_manifest cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-vmlinuz.manifest.xml
        iniset $TEMPEST_CONFIG boto instance_type "$boto_instance_type"
        iniset $TEMPEST_CONFIG boto http_socket_timeout 30
        iniset $TEMPEST_CONFIG boto ssh_user ${DEFAULT_INSTANCE_USER:-cirros}
        iniset $TEMPEST_CONFIG compute-feature-enabled ec2_api True
    fi

    # Orchestration Tests
    if is_service_enabled heat; then
        if [[ ! -z "$HEAT_CFN_IMAGE_URL" ]]; then
            iniset $TEMPEST_CONFIG orchestration image_ref $(basename "$HEAT_CFN_IMAGE_URL" ".qcow2")
        fi
        # build a specialized heat flavor
        available_flavors=$(nova flavor-list)
        if [[ ! ( $available_flavors =~ 'm1.heat' ) ]]; then
            nova flavor-create m1.heat 451 512 0 1
        fi
        iniset $TEMPEST_CONFIG orchestration instance_type "m1.heat"
        iniset $TEMPEST_CONFIG orchestration build_timeout 900
    fi

    # Scenario
    iniset $TEMPEST_CONFIG scenario img_dir "$FILES/images/cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-uec"
    iniset $TEMPEST_CONFIG scenario ami_img_file "cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-blank.img"
    iniset $TEMPEST_CONFIG scenario ari_img_file "cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-initrd"
    iniset $TEMPEST_CONFIG scenario aki_img_file "cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-vmlinuz"

    # Large Ops Number
    iniset $TEMPEST_CONFIG scenario large_ops_number ${TEMPEST_LARGE_OPS_NUMBER:-0}

    # Telemetry
    # Ceilometer API optimization happened in juno that allows to run more tests in tempest.
    # Once Tempest retires support for icehouse this flag can be removed.
    iniset $TEMPEST_CONFIG telemetry too_slow_to_test "False"

    # Object storage
    DEFAULT_SWIFT_OPT="account_quotas, bulk_delete, bulk_upload, container_quotas, container_sync, crossdomain, formpost"
    DEFAULT_SWIFT_OPT+=", keystoneauth, ratelimit, slo, staticweb, tempauth, tempurl"
    iniset $TEMPEST_CONFIG object-storage-feature-enabled discoverable_apis "${OBJECT_STORAGE_API_EXTENSIONS:-$DEFAULT_SWIFT_OPT}"
    iniset $TEMPEST_CONFIG object-storage-feature-disabled discoverable_apis "${OBJECT_STORAGE_DISABLE_API_EXTENSIONS}"

    # Volume
    DEFAULT_VOL_EXT="OS-SCH-HNT, backups, cgsnapshots, consistencygroups, encryption, os-admin-actions, os-availability-zone"
    DEFAULT_VOL_EXT+=", os-extended-services, os-extended-snapshot-attributes, os-hosts, os-image-create"
    DEFAULT_VOL_EXT+=", os-quota-class-sets, os-quota-sets, os-services, os-snapshot-actions, os-types-extra-specs"
    DEFAULT_VOL_EXT+=", os-types-manage, os-used-limits, os-vol-host-attr, os-vol-image-meta"
    DEFAULT_VOL_EXT+=", os-vol-mig-status-attr, os-vol-tenant-attr, os-volume-actions, os-volume-encryption-metadata"
    DEFAULT_VOL_EXT+=", os-volume-manage, os-volume-replication, os-volume-transfer, os-volume-unmanage, qos-specs"
    DEFAULT_VOL_EXT+=", scheduler-stats"
    iniset $TEMPEST_CONFIG volume-feature-enabled api_extensions "${VOLUME_API_EXTENSIONS:-$DEFAULT_VOL_EXT}"
    iniset $TEMPEST_CONFIG volume-feature-disabled api_extensions "${DISABLE_VOLUME_API_EXTENSIONS}"
    if ! is_service_enabled c-bak; then
        iniset $TEMPEST_CONFIG volume-feature-enabled backup False
    fi
    CINDER_MULTI_LVM_BACKEND=$(trueorfalse False $CINDER_MULTI_LVM_BACKEND)
    if [ $CINDER_MULTI_LVM_BACKEND == "True" ]; then
        iniset $TEMPEST_CONFIG volume-feature-enabled multi_backend "True"
        iniset $TEMPEST_CONFIG volume backend1_name "LVM_iSCSI"
        iniset $TEMPEST_CONFIG volume backend2_name "LVM_iSCSI_2"
    fi

    if [ $TEMPEST_VOLUME_DRIVER != "default" ]; then
        iniset $TEMPEST_CONFIG volume vendor_name "$TEMPEST_VOLUME_VENDOR"
        iniset $TEMPEST_CONFIG volume storage_protocol $TEMPEST_STORAGE_PROTOCOL
    fi

    # Dashboard
    iniset $TEMPEST_CONFIG dashboard dashboard_url "http://$SERVICE_HOST/"
    iniset $TEMPEST_CONFIG dashboard login_url "http://$SERVICE_HOST/auth/login/"

    # cli
    iniset $TEMPEST_CONFIG cli cli_dir $NOVA_BIN_DIR

    # Baremetal
    if [ "$VIRT_DRIVER" = "ironic" ] ; then
        iniset $TEMPEST_CONFIG baremetal driver_enabled True
        iniset $TEMPEST_CONFIG compute-feature-enabled change_password False
        iniset $TEMPEST_CONFIG compute-feature-enabled console_output False
        iniset $TEMPEST_CONFIG compute-feature-enabled interface_attach False
        iniset $TEMPEST_CONFIG compute-feature-enabled live_migration False
        iniset $TEMPEST_CONFIG compute-feature-enabled pause False
        iniset $TEMPEST_CONFIG compute-feature-enabled rescue False
        iniset $TEMPEST_CONFIG compute-feature-enabled resize False
        iniset $TEMPEST_CONFIG compute-feature-enabled shelve False
        iniset $TEMPEST_CONFIG compute-feature-enabled snapshot False
        iniset $TEMPEST_CONFIG compute-feature-enabled suspend False
    fi

    # service_available
    for service in ${TEMPEST_SERVICES//,/ }; do
        if is_service_enabled $service ; then
            iniset $TEMPEST_CONFIG service_available $service "True"
        else
            iniset $TEMPEST_CONFIG service_available $service "False"
        fi
    done

    # Restore IFS
    IFS=$ifs
}

# create_tempest_accounts() - Set up common required tempest accounts

# Project              User         Roles
# ------------------------------------------------------------------
# alt_demo             alt_demo     Member

# Migrated from keystone_data.sh
function create_tempest_accounts {
    if is_service_enabled tempest; then
        # Tempest has some tests that validate various authorization checks
        # between two regular users in separate tenants
        get_or_create_project alt_demo
        get_or_create_user alt_demo "$ADMIN_PASSWORD" alt_demo "alt_demo@example.com"
        get_or_add_user_role Member alt_demo alt_demo
    fi
}

# install_tempest_lib() - Collect source, prepare, and install tempest-lib
function install_tempest_lib {
    if use_library_from_git "tempest-lib"; then
        git_clone_by_name "tempest-lib"
        setup_dev_lib "tempest-lib"
    fi
}

# install_tempest() - Collect source and prepare
function install_tempest {
    install_tempest_lib
    git_clone $TEMPEST_REPO $TEMPEST_DIR $TEMPEST_BRANCH
    pip_install tox
}

# init_tempest() - Initialize ec2 images
function init_tempest {
    local base_image_name=cirros-${CIRROS_VERSION}-${CIRROS_ARCH}
    # /opt/stack/devstack/files/images/cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-uec
    local image_dir="$FILES/images/${base_image_name}-uec"
    local kernel="$image_dir/${base_image_name}-vmlinuz"
    local ramdisk="$image_dir/${base_image_name}-initrd"
    local disk_image="$image_dir/${base_image_name}-blank.img"
    if is_service_enabled nova; then
        # if the cirros uec downloaded and the system is uec capable
        if [ -f "$kernel" -a -f "$ramdisk" -a -f "$disk_image" -a  "$VIRT_DRIVER" != "openvz" \
            -a \( "$LIBVIRT_TYPE" != "lxc" -o "$VIRT_DRIVER" != "libvirt" \) ]; then
            echo "Prepare aki/ari/ami Images"
            mkdir -p $BOTO_MATERIALS_PATH
            ( #new namespace
                # tenant:demo ; user: demo
                source $TOP_DIR/accrc/demo/demo
                euca-bundle-image -r ${CIRROS_ARCH} -i "$kernel" --kernel true -d "$BOTO_MATERIALS_PATH"
                euca-bundle-image -r ${CIRROS_ARCH} -i "$ramdisk" --ramdisk true -d "$BOTO_MATERIALS_PATH"
                euca-bundle-image -r ${CIRROS_ARCH} -i "$disk_image" -d "$BOTO_MATERIALS_PATH"
            ) 2>&1 </dev/null | cat
        else
            echo "Boto materials are not prepared"
        fi
    fi
}

# Restore xtrace
$XTRACE

# Tell emacs to use shell-script-mode
## Local variables:
## mode: shell-script
## End: