#!/bin/bash
#
# lib/glance
# Functions to control the configuration and operation of the **Glance** service

# Dependencies:
#
# - ``functions`` file
# - ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined
# - ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined
# - ``SERVICE_HOST``
# - ``KEYSTONE_TOKEN_FORMAT`` must be defined

# ``stack.sh`` calls the entry points in this order:
#
# - install_glance
# - configure_glance
# - init_glance
# - start_glance
# - stop_glance
# - cleanup_glance

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


# Defaults
# --------

# Set up default directories
GITDIR["python-glanceclient"]=$DEST/python-glanceclient
GITDIR["glance_store"]=$DEST/glance_store
GLANCE_DIR=$DEST/glance

# Glance virtual environment
if [[ ${USE_VENV} = True ]]; then
    PROJECT_VENV["glance"]=${GLANCE_DIR}.venv
    GLANCE_BIN_DIR=${PROJECT_VENV["glance"]}/bin
else
    GLANCE_BIN_DIR=$(get_python_exec_prefix)
fi

GLANCE_CACHE_DIR=${GLANCE_CACHE_DIR:=$DATA_DIR/glance/cache}
GLANCE_IMAGE_DIR=${GLANCE_IMAGE_DIR:=$DATA_DIR/glance/images}
GLANCE_AUTH_CACHE_DIR=${GLANCE_AUTH_CACHE_DIR:-/var/cache/glance}

GLANCE_CONF_DIR=${GLANCE_CONF_DIR:-/etc/glance}
GLANCE_METADEF_DIR=$GLANCE_CONF_DIR/metadefs
GLANCE_REGISTRY_CONF=$GLANCE_CONF_DIR/glance-registry.conf
GLANCE_API_CONF=$GLANCE_CONF_DIR/glance-api.conf
GLANCE_SEARCH_CONF=$GLANCE_CONF_DIR/glance-search.conf
GLANCE_REGISTRY_PASTE_INI=$GLANCE_CONF_DIR/glance-registry-paste.ini
GLANCE_API_PASTE_INI=$GLANCE_CONF_DIR/glance-api-paste.ini
GLANCE_SEARCH_PASTE_INI=$GLANCE_CONF_DIR/glance-search-paste.ini
GLANCE_CACHE_CONF=$GLANCE_CONF_DIR/glance-cache.conf
GLANCE_POLICY_JSON=$GLANCE_CONF_DIR/policy.json
GLANCE_SCHEMA_JSON=$GLANCE_CONF_DIR/schema-image.json

if is_ssl_enabled_service "glance" || is_service_enabled tls-proxy; then
    GLANCE_SERVICE_PROTOCOL="https"
fi

# Glance connection info.  Note the port must be specified.
GLANCE_SERVICE_HOST=${GLANCE_SERVICE_HOST:-$SERVICE_HOST}
GLANCE_SERVICE_PORT=${GLANCE_SERVICE_PORT:-9292}
GLANCE_SERVICE_PORT_INT=${GLANCE_SERVICE_PORT_INT:-19292}
GLANCE_HOSTPORT=${GLANCE_HOSTPORT:-$GLANCE_SERVICE_HOST:$GLANCE_SERVICE_PORT}
GLANCE_SERVICE_PROTOCOL=${GLANCE_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL}
GLANCE_REGISTRY_PORT=${GLANCE_REGISTRY_PORT:-9191}
GLANCE_REGISTRY_PORT_INT=${GLANCE_REGISTRY_PORT_INT:-19191}
GLANCE_SEARCH_PORT=${GLANCE_SEARCH_PORT:-9393}
GLANCE_SEARCH_PORT_INT=${GLANCE_SEARCH_PORT_INT:-19393}
GLANCE_SEARCH_HOSTPORT=${GLANCE_SEARCH_HOSTPORT:-$GLANCE_SERVICE_HOST:$GLANCE_SEARCH_PORT}

# Tell Tempest this project is present
TEMPEST_SERVICES+=,glance

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

# Test if any Glance services are enabled
# is_glance_enabled
function is_glance_enabled {
    [[ ,${ENABLED_SERVICES} =~ ,"g-" ]] && return 0
    return 1
}

# cleanup_glance() - Remove residual data files, anything left over from previous
# runs that a clean run would need to clean up
function cleanup_glance {
    # kill instances (nova)
    # delete image files (glance)
    sudo rm -rf $GLANCE_CACHE_DIR $GLANCE_IMAGE_DIR $GLANCE_AUTH_CACHE_DIR

    if is_service_enabled g-search; then
        ${TOP_DIR}/pkg/elasticsearch.sh stop
    fi
}

# configure_glance() - Set config files, create data dirs, etc
function configure_glance {
    sudo install -d -o $STACK_USER $GLANCE_CONF_DIR $GLANCE_METADEF_DIR

    # Copy over our glance configurations and update them
    cp $GLANCE_DIR/etc/glance-registry.conf $GLANCE_REGISTRY_CONF
    iniset $GLANCE_REGISTRY_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
    inicomment $GLANCE_REGISTRY_CONF DEFAULT log_file
    local dburl=`database_connection_url glance`
    iniset $GLANCE_REGISTRY_CONF DEFAULT sql_connection $dburl
    iniset $GLANCE_REGISTRY_CONF DEFAULT use_syslog $SYSLOG
    iniset $GLANCE_REGISTRY_CONF DEFAULT workers "$API_WORKERS"
    iniset $GLANCE_REGISTRY_CONF paste_deploy flavor keystone
    configure_auth_token_middleware $GLANCE_REGISTRY_CONF glance $GLANCE_AUTH_CACHE_DIR/registry
    if is_service_enabled qpid || [ -n "$RABBIT_HOST" ] && [ -n "$RABBIT_PASSWORD" ]; then
        iniset $GLANCE_REGISTRY_CONF DEFAULT notification_driver messaging
    fi
    iniset_rpc_backend glance $GLANCE_REGISTRY_CONF

    cp $GLANCE_DIR/etc/glance-api.conf $GLANCE_API_CONF
    iniset $GLANCE_API_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
    inicomment $GLANCE_API_CONF DEFAULT log_file
    iniset $GLANCE_API_CONF DEFAULT sql_connection $dburl
    iniset $GLANCE_API_CONF DEFAULT use_syslog $SYSLOG
    iniset $GLANCE_API_CONF DEFAULT image_cache_dir $GLANCE_CACHE_DIR/
    iniset $GLANCE_API_CONF paste_deploy flavor keystone+cachemanagement
    configure_auth_token_middleware $GLANCE_API_CONF glance $GLANCE_AUTH_CACHE_DIR/api
    if is_service_enabled qpid || [ -n "$RABBIT_HOST" ] && [ -n "$RABBIT_PASSWORD" ]; then
        iniset $GLANCE_API_CONF DEFAULT notification_driver messaging
    fi
    iniset_rpc_backend glance $GLANCE_API_CONF
    if [ "$VIRT_DRIVER" = 'xenserver' ]; then
        iniset $GLANCE_API_CONF DEFAULT container_formats "ami,ari,aki,bare,ovf,tgz"
        iniset $GLANCE_API_CONF DEFAULT disk_formats "ami,ari,aki,vhd,raw,iso"
    fi
    if [ "$VIRT_DRIVER" = 'libvirt' ] && [ "$LIBVIRT_TYPE" = 'parallels' ]; then
        iniset $GLANCE_API_CONF DEFAULT disk_formats "ami,ari,aki,vhd,vmdk,raw,qcow2,vdi,iso,ploop"
    fi

    # Store specific configs
    iniset $GLANCE_API_CONF glance_store filesystem_store_datadir $GLANCE_IMAGE_DIR/

    iniset $GLANCE_API_CONF DEFAULT workers "$API_WORKERS"

    # Store the images in swift if enabled.
    if is_service_enabled s-proxy; then
        iniset $GLANCE_API_CONF glance_store default_store swift
        iniset $GLANCE_API_CONF glance_store swift_store_auth_address $KEYSTONE_SERVICE_URI/v2.0/
        iniset $GLANCE_API_CONF glance_store swift_store_user $SERVICE_TENANT_NAME:glance-swift
        iniset $GLANCE_API_CONF glance_store swift_store_key $SERVICE_PASSWORD
        iniset $GLANCE_API_CONF glance_store swift_store_create_container_on_put True
        iniset $GLANCE_API_CONF glance_store stores "file, http, swift"
    fi

    if is_service_enabled tls-proxy; then
        iniset $GLANCE_API_CONF DEFAULT bind_port $GLANCE_SERVICE_PORT_INT
        iniset $GLANCE_REGISTRY_CONF DEFAULT bind_port $GLANCE_REGISTRY_PORT_INT
    fi

    # Register SSL certificates if provided
    if is_ssl_enabled_service glance; then
        ensure_certificates GLANCE

        iniset $GLANCE_API_CONF DEFAULT cert_file "$GLANCE_SSL_CERT"
        iniset $GLANCE_API_CONF DEFAULT key_file "$GLANCE_SSL_KEY"

        iniset $GLANCE_REGISTRY_CONF DEFAULT cert_file "$GLANCE_SSL_CERT"
        iniset $GLANCE_REGISTRY_CONF DEFAULT key_file "$GLANCE_SSL_KEY"
    fi

    if is_ssl_enabled_service glance || is_service_enabled tls-proxy; then
        iniset $GLANCE_API_CONF DEFAULT registry_client_protocol https
    fi

    # Format logging
    if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then
        setup_colorized_logging $GLANCE_API_CONF DEFAULT tenant user
        setup_colorized_logging $GLANCE_REGISTRY_CONF DEFAULT tenant user
    fi

    cp -p $GLANCE_DIR/etc/glance-registry-paste.ini $GLANCE_REGISTRY_PASTE_INI

    cp -p $GLANCE_DIR/etc/glance-api-paste.ini $GLANCE_API_PASTE_INI

    cp $GLANCE_DIR/etc/glance-cache.conf $GLANCE_CACHE_CONF
    iniset $GLANCE_CACHE_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
    inicomment $GLANCE_CACHE_CONF DEFAULT log_file
    iniset $GLANCE_CACHE_CONF DEFAULT use_syslog $SYSLOG
    iniset $GLANCE_CACHE_CONF DEFAULT image_cache_dir $GLANCE_CACHE_DIR/
    iniuncomment $GLANCE_CACHE_CONF DEFAULT auth_url
    iniset $GLANCE_CACHE_CONF DEFAULT auth_url $KEYSTONE_AUTH_URI/v2.0
    iniuncomment $GLANCE_CACHE_CONF DEFAULT auth_tenant_name
    iniset $GLANCE_CACHE_CONF DEFAULT admin_tenant_name $SERVICE_TENANT_NAME
    iniuncomment $GLANCE_CACHE_CONF DEFAULT auth_user
    iniset $GLANCE_CACHE_CONF DEFAULT admin_user glance
    iniuncomment $GLANCE_CACHE_CONF DEFAULT auth_password
    iniset $GLANCE_CACHE_CONF DEFAULT admin_password $SERVICE_PASSWORD

    # Store specific confs
    iniset $GLANCE_CACHE_CONF glance_store filesystem_store_datadir $GLANCE_IMAGE_DIR/

    cp -p $GLANCE_DIR/etc/policy.json $GLANCE_POLICY_JSON
    cp -p $GLANCE_DIR/etc/schema-image.json $GLANCE_SCHEMA_JSON

    cp -p $GLANCE_DIR/etc/metadefs/*.json $GLANCE_METADEF_DIR

    if is_ssl_enabled_service "cinder" || is_service_enabled tls-proxy; then
        CINDER_SERVICE_HOST=${CINDER_SERVICE_HOST:-$SERVICE_HOST}
        CINDER_SERVICE_PORT=${CINDER_SERVICE_PORT:-8776}

        iniset $GLANCE_API_CONF DEFAULT cinder_endpoint_template "https://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v1/%(project_id)s"
        iniset $GLANCE_CACHE_CONF DEFAULT cinder_endpoint_template "https://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v1/%(project_id)s"
    fi

    # Configure search
    if is_service_enabled g-search; then
        cp $GLANCE_DIR/etc/glance-search.conf $GLANCE_SEARCH_CONF
        iniset $GLANCE_SEARCH_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
        inicomment $GLANCE_SEARCH_CONF DEFAULT log_file
        iniset $GLANCE_SEARCH_CONF DEFAULT use_syslog $SYSLOG
        iniset $GLANCE_SEARCH_CONF DEFAULT sql_connection $dburl
        iniset $GLANCE_SEARCH_CONF paste_deploy flavor keystone
        configure_auth_token_middleware $GLANCE_SEARCH_CONF glance $GLANCE_AUTH_CACHE_DIR/search

        if is_service_enabled tls-proxy; then
            iniset $GLANCE_SEARCH_CONF DEFAULT bind_port $GLANCE_SEARCH_PORT_INT
        fi
        # Register SSL certificates if provided
        if is_ssl_enabled_service glance; then
            ensure_certificates GLANCE
            iniset $GLANCE_SEARCH_CONF DEFAULT cert_file "$GLANCE_SSL_CERT"
            iniset $GLANCE_SEARCH_CONF DEFAULT key_file "$GLANCE_SSL_KEY"
        fi

        cp $GLANCE_DIR/etc/glance-search-paste.ini $GLANCE_SEARCH_PASTE_INI
    fi
}

# create_glance_accounts() - Set up common required glance accounts

# Project              User            Roles
# ---------------------------------------------------------------------
# SERVICE_TENANT_NAME  glance          service
# SERVICE_TENANT_NAME  glance-swift    ResellerAdmin (if Swift is enabled)
# SERVICE_TENANT_NAME  glance-search   search (if Search is enabled)

function create_glance_accounts {
    if is_service_enabled g-api; then

        create_service_user "glance"

        # required for swift access
        if is_service_enabled s-proxy; then

            local glance_swift_user=$(get_or_create_user "glance-swift" \
                "$SERVICE_PASSWORD" "glance-swift@example.com")
            get_or_add_user_project_role "ResellerAdmin" $glance_swift_user $SERVICE_TENANT_NAME
        fi

        if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then

            local glance_service=$(get_or_create_service "glance" \
                "image" "Glance Image Service")
            get_or_create_endpoint $glance_service \
                "$REGION_NAME" \
                "$GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT" \
                "$GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT" \
                "$GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT"
        fi
    fi

    # Add glance-search service and endpoints
    if is_service_enabled g-search; then
        if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then
            local glance_search_service=$(get_or_create_service "glance-search" \
                "search" "EXPERIMENTAL - Glance Graffiti Search Service")

            get_or_create_endpoint $glance_search_service \
                "$REGION_NAME" \
                "$GLANCE_SERVICE_PROTOCOL://$GLANCE_SEARCH_HOSTPORT" \
                "$GLANCE_SERVICE_PROTOCOL://$GLANCE_SEARCH_HOSTPORT" \
                "$GLANCE_SERVICE_PROTOCOL://$GLANCE_SEARCH_HOSTPORT"
        fi
    fi
}

# create_glance_cache_dir() - Part of the init_glance() process
function create_glance_cache_dir {
    # Create cache dir
    sudo install -d -o $STACK_USER $GLANCE_AUTH_CACHE_DIR/api $GLANCE_AUTH_CACHE_DIR/registry $GLANCE_AUTH_CACHE_DIR/search
    rm -f $GLANCE_AUTH_CACHE_DIR/api/* $GLANCE_AUTH_CACHE_DIR/registry/* $GLANCE_AUTH_CACHE_DIR/search/*
}

# init_glance() - Initialize databases, etc.
function init_glance {
    # Delete existing images
    rm -rf $GLANCE_IMAGE_DIR
    mkdir -p $GLANCE_IMAGE_DIR

    # Delete existing cache
    rm -rf $GLANCE_CACHE_DIR
    mkdir -p $GLANCE_CACHE_DIR

    # (Re)create glance database
    recreate_database glance

    # Migrate glance database
    $GLANCE_BIN_DIR/glance-manage db_sync

    # Load metadata definitions
    $GLANCE_BIN_DIR/glance-manage db_load_metadefs

    create_glance_cache_dir

    # Init glance search by exporting found metadefs/images to elasticsearch
    if is_service_enabled g-search; then
        ${TOP_DIR}/pkg/elasticsearch.sh start
        $GLANCE_BIN_DIR/glance-index
    fi
}

# install_glanceclient() - Collect source and prepare
function install_glanceclient {
    if use_library_from_git "python-glanceclient"; then
        git_clone_by_name "python-glanceclient"
        setup_dev_lib "python-glanceclient"
        sudo install -D -m 0644 -o $STACK_USER {${GITDIR["python-glanceclient"]}/tools/,/etc/bash_completion.d/}glance.bash_completion
    fi
}

# install_glance() - Collect source and prepare
function install_glance {
    # Install glance_store from git so we make sure we're testing
    # the latest code.
    if use_library_from_git "glance_store"; then
        git_clone_by_name "glance_store"
        setup_dev_lib "glance_store"
    fi

    git_clone $GLANCE_REPO $GLANCE_DIR $GLANCE_BRANCH

    if is_service_enabled g-search; then
        ${TOP_DIR}/pkg/elasticsearch.sh download
        ${TOP_DIR}/pkg/elasticsearch.sh install
    fi

    setup_develop $GLANCE_DIR
}

# start_glance() - Start running processes, including screen
function start_glance {
    local service_protocol=$GLANCE_SERVICE_PROTOCOL
    if is_service_enabled tls-proxy; then
        start_tls_proxy '*' $GLANCE_SERVICE_PORT $GLANCE_SERVICE_HOST $GLANCE_SERVICE_PORT_INT &
        start_tls_proxy '*' $GLANCE_REGISTRY_PORT $GLANCE_SERVICE_HOST $GLANCE_REGISTRY_PORT_INT &

        # Handle g-search
        if is_service_enabled g-search; then
            start_tls_proxy '*' $GLANCE_SEARCH_PORT $GLANCE_SERVICE_HOST $GLANCE_SEARCH_PORT_INT &
        fi
    fi

    run_process g-reg "$GLANCE_BIN_DIR/glance-registry --config-file=$GLANCE_CONF_DIR/glance-registry.conf"
    run_process g-api "$GLANCE_BIN_DIR/glance-api --config-file=$GLANCE_CONF_DIR/glance-api.conf"

    echo "Waiting for g-api ($GLANCE_HOSTPORT) to start..."
    if ! wait_for_service $SERVICE_TIMEOUT $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT; then
        die $LINENO "g-api did not start"
    fi

    # Start g-search after g-reg/g-api
    if is_service_enabled g-search; then
        run_process g-search "$GLANCE_BIN_DIR/glance-search --config-file=$GLANCE_CONF_DIR/glance-search.conf"
        echo "Waiting for g-search ($GLANCE_SEARCH_HOSTPORT) to start..."
        if ! wait_for_service $SERVICE_TIMEOUT $GLANCE_SERVICE_PROTOCOL://$GLANCE_SEARCH_HOSTPORT; then
            die $LINENO "g-search did not start"
        fi
    fi
}

# stop_glance() - Stop running processes
function stop_glance {
    # Kill the Glance screen windows
    stop_process g-api
    stop_process g-reg

    if is_service_enabled g-search; then
        stop_process g-search
    fi
}

# Restore xtrace
$XTRACE

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