#!/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
    from keystone import exception
    from keystone import identity

except ImportError:
    successful_import = False
else:
    successful_import = True


def get_name_from_tenant(tenant):
    try:
        KEYSTONE_CONF = 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():
    CONF = CommonConfigOpts(project="glance", prog="glance-registry")
    CONF()

    # Hide missing logger warning message
    sys.stderr = open(os.devnull, 'w')
    configure_db(CONF)
    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 glance'
    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 exc.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)

