#!/usr/bin/env python
#
# Plugin to monitor used size of a tenant in glance
#
# To monitor the used size of a tenant in glance do:
# E.g.
#    ln -s /usr/share/munin/plugins/glance_size_ /etc/munin/plugins/glance_size_<tenant_uuid>
#
# Needs following minimal configuration in plugin-conf.d/glance:
#   [glance_*]
#   user glance
#
# To show tenant name plugin must run as root
#
# Magic markers
#  #%# capabilities=autoconf suggest
#  #%# family=auto

import sys
import os

try:
    from sqlalchemy.orm import joinedload
    import sqlalchemy.exc

    from glance.common.cfg import CommonConfigOpts
    from glance.registry.db import models
    from glance.registry.db.api import get_session, configure_db

    from keystone.common import utils
    from keystone import config, exception, identity

except ImportError:
    successful_import = False
else:
    successful_import = True


def get_name_from_tenant(tenant):
    try:
        config.CONF(config_files=[utils.find_config('keystone.conf')])
    except:
        # keystone configuration can not be loaded, use id as name"
        return tenant

    identity_api = identity.Manager()

    try:
        tenant_info = identity_api.get_tenant(None, tenant)
    except sqlalchemy.exc.OperationalError:
        # keystone database can not be connected, use id as name"
        return tenant

    if not tenant_info:
        return tenant
    else:
        return tenant_info["name"]


def load_conf():
    loaded_config = CommonConfigOpts(project="glance", prog="glance-registry")
    loaded_config()

    # Hide missing logger warning message
    sys.stderr = open(os.devnull, 'w')
    configure_db(loaded_config)
    sys.stderr = sys.__stderr__


def print_config(tenant):
    if tenant == "Global":
        print('graph_title Glance used size for all tenants')
        print('graph_info This graph shows the used size in glance for all tenants')
    else:
        print('graph_title Glance used size for tenant %s' % get_name_from_tenant(tenant))
        print('graph_info This graph shows the used size in glance for tenant %s' % tenant)
    print('graph_vlabel Bytes')
    print('graph_args --base 1024 --lower-limit 0')
    print('graph_category cloud')
    print('%s.label %s' % (tenant, get_name_from_tenant(tenant)))
    print('%s.draw LINE2' % tenant)
    print('%s.info %s MBytes' % (tenant, tenant))


def request(**kwargs):

    session = get_session()
    try:
        query = session.query(models.Image).options(joinedload(models.Image.properties)).options(
            joinedload(models.Image.members))
        if kwargs:
            query = query.filter_by(**kwargs)

        images = query.all()

    except exception.NoResultFound:
        return []
    return images


def print_suggest():
    print("Global")
    print("\n".join(set(image["owner"] for image in request(deleted=False))))


def print_values(tenant):

    if tenant != "Global":
        images = request(deleted=False, owner=tenant)
    else:
        images = request(deleted=False)

    total_size = sum([image["size"] for image in images])
    print('%s.value %s' % (tenant, total_size))


if __name__ == '__main__':
    argv = sys.argv[:]
    tenant = argv[0].split('glance_size_').pop() or 'Global'

    if len(argv) > 1:
        if argv[1] == 'config':
            print_config(tenant)
        elif argv[1] == 'suggest' and successful_import:
            load_conf()
            print_suggest()
        elif argv[1] == 'autoconf':
            if not successful_import:
                print('no (failed import glance and/or sqlachemy module)')
                sys.exit(0)
            try:
                load_conf()
                get_session()
            except:
                print('no (failed to connect glance backend, check user)')
                sys.exit(0)
            print('yes')

    elif successful_import:
        load_conf()
        print_values(tenant)
