Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
#!/usr/bin/python
# -*- coding: utf-8 -*-

import json
import traceback
import requests
import ssl
import urllib.parse

from ansible.module_utils.basic import AnsibleModule

from keystoneauth1.identity.generic import password as keystone_password
from keystoneauth1 import session
from keystoneclient import client


DOCUMENTATION = '''
---
module: keystone_endpoints
short_description: Returns keystone service endpoints
options:
  insecure:
    description:
        - allow use of self-signed SSL certificates
    required: no
    choices: [ "yes", "no" ]
    default: no
  endpoint_type:
    description:
        - probe these endpoint types for version
    required: no
    choices: [ "admin", "internal", "public" ]
    default: public
  region:
    description:
        - region of service
    required: no
    default: RegionOne
  auth_url:
    description:
        - keystone endpoint
    required: yes
  username:
    description:
        - keystone user name
    required: yes
  password:
    description:
        - keystone user password
    required: yes
  tenant_name:
    description:
        - keystone tenant name
    required: yes
  domain_name:
    description:
        - keystone domain that user belongs to
    required: no
    default: default
  identity_api_version:
    description:
        - identity api version
    required: no
    default: "3"
  ignore_other_regions
    description:
        - ignore other regions other than what is asked for
    required: no
    default: true
requirements: [ python-keystoneclient ]
author: Murali Balcha
'''

EXAMPLES = '''
examples:
keystone_endpoints: >
    username=admin
    password=sosecure
    tenant_name=admin
    auth_url=http://192.168.206.130:5000/v2.0
    endpoint_type=internal
'''


def _validate_keystone_client_and_version(auth_url, username, password,
                                          tenant_name, domain_id, endpoint_type,
                                          insecure, cacert,
                                          identity_api_version):

    if identity_api_version == "3":
        auth = keystone_password.Password(auth_url=auth_url,
                                          username=username,
                                          password=password,
                                          user_domain_id=domain_id,
                                          domain_id=domain_id)
    else:
        auth = keystone_password.Password(auth_url=auth_url,
                                          username=username,
                                          password=password,
                                          project_name=tenant_name)

    sess = session.Session(auth=auth, verify=cacert)
    keystone = client.Client(session=sess,
                             auth_url=auth_url,
                             interface=endpoint_type,
                             insecure=insecure,
                             cacert=cacert)
    if keystone.version == 'v3':
        tenants = keystone.projects.list()
    elif keystone.version == 'v2.0':
        tenants = keystone.tenants.list()

    return (keystone, tenants)


def authenticate(keystone_auth_url, username, password,
                 tenant_name, domain_id,
                 endpoint_type, insecure, cacert, identity_api_version):
    """Return a keystone client object"""

    keystone, tenants = _validate_keystone_client_and_version(
        keystone_auth_url, username, password,
        tenant_name, domain_id, endpoint_type,
        insecure, cacert, identity_api_version)

    return keystone


def get_endpoints(keystone, region, endpoint_type,
                  ignore_other_regions=True):
    """ Retrieve a service endpoints """
    services = {}
    for x in keystone.services.list():
        services[x.id] = x

    endpoints = {}
    if keystone.version == 'v3':
        for x in keystone.endpoints.list():
            if x.region == region and x.enabled:
                stype = services[x.service_id].type
                url_parsed_obj = urllib.parse.urlparse(x.url)
                host = url_parsed_obj.hostname
                port = url_parsed_obj.port
                api_version = 1
                if stype not in endpoints:
                    endpoints[stype] = {
                        'region': x.region,
                        'enabled': x.enabled,
                        'service_id': x.service_id,
                        'type': services[x.service_id].type,
                        'name': services[x.service_id].name,
                        'api_version': api_version,
                        'host': host,
                        'port': port
                    }
                try:
                    if endpoint_type.lower() in x.interface.lower():
                        comps = x.url.split("/")
                        tmpurl = "%s//%s" % (comps[0], comps[2])
                        try:
                            versions = json.loads(
                                requests.get(tmpurl,
                                             allow_redirects=False,
                                             verify=False, timeout=10).content)

                        except requests.exceptions.ConnectTimeout:
                            continue

                        except:
                            versions = json.loads(
                                requests.get(x.url,
                                             allow_redirects=False,
                                             verify=False, timeout=10).content)
                        versions = versions.pop('versions')
                        if not type(versions) is list:
                            versions = versions.pop('values')
                        current_version = [x for x in versions if x['status'].lower() in ('supported', 'current', 'stable')]

                        if 'min_version' in current_version[0] and current_version[0]['min_version']:
                            api_version = \
                                 int(float(current_version[0]['min_version']))
                        else:
                            api_version = int(float(current_version[0]['id'][1:]))

                        endpoints[stype]['api_version'] = api_version
                except Exception as ex:
                    #print traceback.format_exc()
                    pass

                endpoints[stype][x.interface+'url'] = x.url
    else:
        for x in keystone.endpoints.list():
            if x.region == region:
                host = x.publicurl.split('/')[2].split(':')[0]
                port = ''
                if len(x.publicurl.split('/')[2].split(':')) == 2:
                    port = x.publicurl.split('/')[2].split(':')[1]
                endpoints[services[x.service_id].type] = {
                    'adminurl': x.adminurl,
                    'publicurl': x.publicurl,
                    'internalurl': x.internalurl,
                    'region': x.region,
                    'enabled': x.enabled,
                    'service_id': x.service_id,
                    'type': services[x.service_id].type,
                    'name': services[x.service_id].name,
                    'host': host,
                    'port': port
                }

    if 'object-store' in endpoints:
        endpoints['objectstore'] = endpoints['object-store']
    return {'all_endpoints': endpoints}


def get_admin_role(keystone):
    roles = {'other_roles': []}
    all_roles = keystone.roles.list()
    for role in all_roles:
        if role.name.lower() in ['admin', 'administrator']:
            roles['admin_role'] = role.name
        roles['other_roles'].append(role.name)
    return roles


def dispatch(keystone, region, endpoint_type, ignore_other_regions=True):
    endpoint_info = get_endpoints(keystone, region, endpoint_type)
    facts = {'openstack_endpoints': endpoint_info['all_endpoints'],
             'openstack_roles': get_admin_role(keystone)}

    return dict(changed=False,
                ansible_facts=facts)


def main():

    module = AnsibleModule(
        argument_spec=dict(
            region=dict(required=False, default='RegionOne'),
            endpoint_type=dict(required=False, default='public',
                               aliases=['interface']),
            ignore_other_regions=dict(required=False,
                                      default=False, type='bool'),
            auth_url=dict(required=False,
                          default="http://127.0.0.1:5000/v2.0",
                          aliases=['auth_url']),
            insecure=dict(required=False, default=False, type='bool'),
            cacert=dict(required=False, default='/etc/workloadmgr/ca-chain.pem'),

            username=dict(required=False),
            password=dict(required=False, no_log=True),
            tenant_name=dict(required=False, aliases=['tenant']),
            domain_id=dict(required=False, default='default'),
            identity_api_version=dict(required=False, default='3')
        ),
    )

    auth_url = module.params['auth_url']
    username = module.params['username']
    password = module.params['password']
    tenant_name = module.params['tenant_name']
    insecure = module.boolean(module.params['insecure'])
    cacert = module.params['cacert']
    region = module.params['region']
    endpoint_type = module.params['endpoint_type']
    ignore_other_regions = module.boolean(
        module.params['ignore_other_regions'])
    domain_id = module.params['domain_id']
    identity_api_version = module.params['identity_api_version']

    keystone = authenticate(auth_url, username, password,
                            tenant_name, domain_id, endpoint_type,
                            insecure, cacert, identity_api_version)

    try:
        d = dispatch(keystone, region, endpoint_type,
                     ignore_other_regions=ignore_other_regions)
    except Exception:
        module.fail_json(msg=traceback.format_exc())
    else:
        module.exit_json(**d)


# this is magic, see lib/ansible/module_common.py
# <<INCLUDE_ANSIBLE_MODULE_COMMON>>
if __name__ == '__main__':
    main()