Beispiel #1
0
def allocation_managers(csv=False, filename=None, sslwarnings=False):
    """Get the allocation manager emails for all projects.
    """
    ssl_warnings(enabled=sslwarnings)
    keystone = hm_keystone.client_session(version=3)
    all_users = map(lambda x: x.to_dict(), keystone.users.list())
    email_dict = {x['id']: x['email'] for x in all_users
                  if 'email' in x and x['email'] is not None}
    projects = keystone.projects.list()
    managers = collections.defaultdict(list)
    for user_role in keystone.role_assignments.list(role=14):
        if 'project' in user_role.scope:
            managers[user_role.scope['project']['id']].append(
                user_role.user['id'])
    headings = ["Tenant ID", "Manager email(s)"]
    records = []
    for proj in projects:
        if len(managers[proj.id]) == 0:
            continue
        emails = set()
        for tm in managers[proj.id]:
            if tm in email_dict:
                emails.add(email_dict[tm])
        records.append([proj.id, ",".join(emails)])
    if csv:
        csv_output(headings, records, filename=filename)
    else:
        pretty_output(headings, records, filename=filename)
Beispiel #2
0
def allocation_homes(csv=False, filename=None, sslwarnings=False):
    """Get the allocation_homes for all projects. If this
metadata field is not set in keystone (see keystone hivemind
commands), the value reported is the email domains for all
tenant managers belonging to this project.
    """
    ssl_warnings(enabled=sslwarnings)
    keystone = hm_keystone.client_session(version=3)
    all_users = map(lambda x: x.to_dict(), keystone.users.list())
    email_dict = {x['id']: x['email'].split("@")[-1] for x in all_users
                  if 'email' in x and x['email'] is not None}
    projects = keystone.projects.list()
    managers = collections.defaultdict(list)
    for user_role in keystone.role_assignments.list(role=14):
        if 'project' in user_role.scope:
            managers[user_role.scope['project']['id']].append(
                user_role.user['id'])
    headings = ["Tenant ID", "Allocation Home(s)"]
    records = []
    for proj in projects:
        if "allocation_home" in proj.to_dict():
            records.append([proj.id, proj.allocation_home])
        else:
            if len(managers[proj.id]) == 0:
                continue
            institutions = set()
            for tm in managers[proj.id]:
                if tm in email_dict:
                    institutions.add(email_dict[tm])
            records.append([proj.id, ",".join(institutions)])
    if csv:
        csv_output(headings, records, filename=filename)
    else:
        pretty_output(headings, records, filename=filename)
Beispiel #3
0
def get_project_usage_csv(start_date=None, end_date=None,
                          filename=None, sslwarnings=False):
    """Get accumulated instance usage statistics for all projects.
    Date strings should be ISO 8601 to minute precision
    without timezone information.
    """
    ssl_warnings(enabled=sslwarnings)
    assert start_date and end_date
    start = datetime.datetime.strptime(start_date, "%Y-%m-%dT%H:%M")
    end = datetime.datetime.strptime(end_date, "%Y-%m-%dT%H:%M")
    keystone = hm_keystone.client_session(version=3)
    nova = hm_nova.client()

    tenants = {x.id: x for x in keystone.projects.list()}
    headings = ["Tenant ID", "Tenant Name", "Instance count",
                "Instance hours", "vCPU hours", "Memory Hours (MB)",
                "Disk hours (GB)"]
    usage = map(lambda u: [
                u.tenant_id,
                tenants[u.tenant_id].name if u.tenant_id in tenants else None,
                len(u.server_usages),
                u.total_hours,
                u.total_vcpus_usage,
                u.total_memory_mb_usage,
                u.total_local_gb_usage],
                nova.usage.list(start, end, detailed=True))
    csv_output(headings, usage, filename=filename)
Beispiel #4
0
def get_instance_usage_csv(start_date=None, end_date=None,
                           filename=None, sslwarnings=False):
    """Get individual instance usage for all projects, including tenant and
    availability zones.  Date strings should be ISO 8601 to minute precision
    without timezone information.
    """
    ssl_warnings(enabled=sslwarnings)
    assert start_date and end_date
    start = datetime.datetime.strptime(start_date, "%Y-%m-%dT%H:%M")
    end = datetime.datetime.strptime(end_date, "%Y-%m-%dT%H:%M")
    keystone = hm_keystone.client_session(version=3)
    nova = hm_nova.client()

    tenants = {x.id: x for x in keystone.projects.list()}
    usage = []
    for u in nova.usage.list(start, end, detailed=True):
        tenant_id = u.tenant_id
        tenant_name = tenants[tenant_id].name if tenant_id in tenants else None

        # The Nova API doesn't allow "show" on deleted instances, but
        # we can get the info using "list --deleted".  The problem is
        # figuring out how to avoid retrieving irrelevant instances,
        # and at the same time how to avoid too many requests.
        #
        # Attempt #1 - use the tenant_id and the instance's name to
        # focus queries.
        # Attempt #2 - as #1, but after N lookups by name for a tenant,
        # just fetch all of the deleted instances.
        cache = {}
        try:
            for iu in u.server_usages:
                name = iu['name']
                instance_id = iu['instance_id']
                instance = None
                if iu['state'] == 'terminated' or iu['state'] == 'deleted':
                    instance = _get_deleted_instance(cache, nova, u.tenant_id,
                                                     name, instance_id)
                else:
                    try:
                        instance = nova.servers.get(instance_id).to_dict()
                    except:
                        print 'Cannot find instance {0} in {1}' \
                            .format(instance_id, u.tenant_id)
                if instance is None:
                    instance = {'OS-EXT-AZ:availability_zone': 'unknown'}

                usage.append([tenant_id, tenant_name, instance_id, name,
                              iu['state'], iu['flavor'], iu['hours'],
                              iu['vcpus'], iu['memory_mb'], iu['local_gb'],
                              instance['OS-EXT-AZ:availability_zone']])
        except:
            traceback.print_exc(file=sys.stdout)

    headings = ["Tenant ID", "Tenant Name", "Instance id", "Instance name",
                "Instance state", "Flavour",
                "Instance hours", "vCPUs", "Memory (MB)", "Disk (GB)", "AZ"]
    csv_output(headings, usage, filename=filename)
def compare_quotas(name_or_id=None):
    """Compare the allocation and quota information for a tenant
    """
    if name_or_id == None:
        print 'A tenant name or id is required'
        return
        
    keystone_api = hm_keystone.client_session(version=3)
    try:
        tenant = hm_keystone.get_tenant(keystone_api, name_or_id)
    except:
        print 'Tenant {0} not found in keystone'.format(name_or_id)
        return
        
    nova_api = hm_nova.client()
    quotas = nova_api.quotas.get(tenant.id)
    print 'nova quotas: instances {0}, cores {1}, ram {2}'.format(
        quotas.instances, quotas.cores, quotas.ram / 1024)
    usage = _get_usage(nova_api, _get_flavor_map(nova_api), tenant.id)
    print 'nova usage: instances {0}, cores {1}, ram {2}'.format(
        usage['instances'], usage['vcpus'], usage['ram'] / 1024)

    allocations_api = NectarApiSession()
    allocations = allocations_api.get_allocations(); 
    tenant_allocations = filter(lambda x: x['tenant_uuid'] == tenant.id and \
                                (x['status'] == 'A' or x['status'] == 'X'),
                                allocations)
    if len(tenant_allocations) == 0:
        print 'No approved allocation records for tenant {0} / {1}'.format(
            tenant.id, tenant.name)
        return

    tenant_allocations.sort(key=lambda alloc: alloc['modified_time'])
    current_allocation = tenant_allocations[-1]
    
    format = '{0} mismatch: allocated {1}, nova {2}, used {3}'
    if current_allocation['instance_quota'] != quotas.instances:
        print format.format('Instance quota',
                            current_allocation['instance_quota'], 
                            quotas.instances,
                            usage['instances'])
    if current_allocation['core_quota'] != quotas.cores:
        print format.format('VCPU quota',
                            current_allocation['core_quota'], 
                            quotas.cores,
                            usage['vcpus'])
    if current_allocation['ram_quota'] * 1024 != quotas.ram:
        print format.format('RAM quota',
                            current_allocation['ram_quota'] * 1024, 
                            quotas.ram,
                            usage['ram'])