diff options
Diffstat (limited to 'openstack/usr/share/openstack/modules/keystone_service')
-rw-r--r-- | openstack/usr/share/openstack/modules/keystone_service | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/openstack/usr/share/openstack/modules/keystone_service b/openstack/usr/share/openstack/modules/keystone_service new file mode 100644 index 00000000..aa4302d1 --- /dev/null +++ b/openstack/usr/share/openstack/modules/keystone_service @@ -0,0 +1,309 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +DOCUMENTATION = ''' +--- +module: keystone_service +short_description: Manage OpenStack Identity (keystone) service endpoints +options: + name: + description: + - name of service (e.g., keystone) + required: yes + type: + description: + - type of service (e.g., identity) + required: yes + description: + description: + - description of service (e.g., Identity Service) + required: yes + public_url: + description: + - public url of service. + - 'Alias: I(url)' + - 'Alias: I(publicurl)' + required: yes + internal_url: + description: + - internal url of service. + - 'Alias: I(internalurl)' + required: no + default: value of public_url + admin_url: + description: + - admin url of service. + - 'Alias: I(adminurl)' + required: no + default: value of public_url + insecure: + description: + - allow use of self-signed SSL certificates + required: no + choices: [ "yes", "no" ] + region: + description: + - region of service + required: yes + state: + description: + - Indicate desired state of the resource + choices: ['present', 'absent'] + default: present + + + +requirements: [ python-keystoneclient ] +author: Lorin Hochstein +''' + +EXAMPLES = ''' +examples: +keystone_service: > + name=keystone + type=identity + description="Keystone Identity Service" + publicurl=http://192.168.206.130:5000/v2.0 + internalurl=http://192.168.206.130:5000/v2.0 + adminurl=http://192.168.206.130:35357/v2.0 + +keystone_service: > + name=glance + type=image + description="Glance Identity Service" + url=http://192.168.206.130:9292 + +''' + +try: + from keystoneclient.v2_0 import client +except ImportError: + keystoneclient_found = False +else: + keystoneclient_found = True + +import traceback + + +def authenticate(endpoint, token, login_user, login_password, tenant_name, + insecure): + """Return a keystone client object""" + + if token: + return client.Client(endpoint=endpoint, token=token, insecure=insecure) + else: + return client.Client(auth_url=endpoint, username=login_user, + password=login_password, tenant_name=tenant_name, + insecure=insecure) + +def get_service(keystone, name): + """ Retrieve a service by name """ + services = [x for x in keystone.services.list() if x.name == name] + count = len(services) + if count == 0: + raise KeyError("No keystone services with name %s" % name) + elif count > 1: + raise ValueError("%d services with name %s" % (count, name)) + else: + return services[0] + + +def get_endpoint(keystone, name): + """ Retrieve a service endpoint by name """ + service = get_service(keystone, name) + endpoints = [x for x in keystone.endpoints.list() + if x.service_id == service.id] + count = len(endpoints) + if count == 0: + raise KeyError("No keystone endpoints with service name %s" % name) + elif count > 1: + raise ValueError("%d endpoints with service name %s" % (count, name)) + else: + return endpoints[0] + + +def ensure_service_present(keystone, name, service_type, description, + check_mode): + """ Ensure the service is present and has the right values + + Returns a pair, where the first element is a boolean that indicates + a state change, and the second element is the service uuid, or None + if running in check mode""" + service = None + try: + service = get_service(keystone, name) + except: + # Service doesn't exist yet, we'll need to create one + pass + else: + # See if it matches exactly + if service.name == name and \ + service.type == service_type and \ + service.description == description: + + # Same, no changes needed + return (False, service.id) + + # At this point, we know we will need to make a change + if check_mode: + return (True, None) + + if service is None: + service = keystone.services.create(name=name, + service_type=service_type, + description=description) + return (True, service.id) + else: + msg = "keystone v2 API doesn't support updating services" + raise ValueError(msg) + + +def ensure_endpoint_present(keystone, name, public_url, internal_url, + admin_url, region, check_mode): + """ Ensure the service endpoint is present and have the right values + + Assumes the service object has already been created at this point""" + + service = get_service(keystone, name) + endpoint = None + try: + endpoint = get_endpoint(keystone, name) + except: + # Endpoint doesn't exist yet, we'll need to create one + pass + else: + # See if it matches + if endpoint.publicurl == public_url and \ + endpoint.adminurl == admin_url and \ + endpoint.internalurl == internal_url and \ + endpoint.region == region: + + # Same, no changes needed + return (False, endpoint.id) + + # At this point, we know we will need to make a change + if check_mode: + return (True, None) + + if endpoint is None: + endpoint = keystone.endpoints.create(region=region, + service_id=service.id, + publicurl=public_url, + adminurl=admin_url, + internalurl=internal_url) + return (True, endpoint.id) + else: + msg = "keystone v2 API doesn't support updating endpoints" + raise ValueError(msg) + + +def ensure_service_absent(keystone, name, check_mode): + """ Ensure the service is absent""" + + raise NotImplementedError() + +def ensure_endpoint_absent(keystone, name, check_mode): + """ Ensure the service endpoint """ + raise NotImplementedError() + + +def dispatch(keystone, name, service_type, description, public_url, + internal_url, admin_url, region, state, check_mode): + + if state == 'present': + (service_changed, service_id) = ensure_service_present(keystone, + name, + service_type, + description, + check_mode) + + (endpoint_changed, endpoint_id) = ensure_endpoint_present( + keystone, + name, + public_url, + internal_url, + admin_url, + region, + check_mode) + return dict(changed=service_changed or endpoint_changed, + service_id=service_id, + endpoint_id=endpoint_id) + elif state == 'absent': + endpoint_changed = ensure_endpoint_absent(keystone, name, check_mode) + service_changed = ensure_service_absent(keystone, name, check_mode) + return dict(changed=service_changed or endpoint_changed) + else: + raise ValueError("Code should never reach here") + + + +def main(): + + module = AnsibleModule( + argument_spec=dict( + name=dict(required=True), + type=dict(required=True), + description=dict(required=False), + public_url=dict(required=True, aliases=['url', 'publicurl']), + internal_url=dict(required=False, aliases=['internalurl']), + admin_url=dict(required=False, aliases=['adminurl']), + region=dict(required=True), + state=dict(default='present', choices=['present', 'absent']), + endpoint=dict(required=False, + default="http://127.0.0.1:35357/v2.0", + aliases=['auth_url']), + token=dict(required=False), + insecure=dict(required=False, default=False, choices=BOOLEANS), + + login_user=dict(required=False), + login_password=dict(required=False), + tenant_name=dict(required=False, aliases=['tenant']) + ), + supports_check_mode=True, + mutually_exclusive=[['token', 'login_user'], + ['token', 'login_password'], + ['token', 'tenant_name']] + ) + + endpoint = module.params['endpoint'] + token = module.params['token'] + login_user = module.params['login_user'] + login_password = module.params['login_password'] + tenant_name = module.params['tenant_name'] + insecure = module.boolean(module.params['insecure']) + name = module.params['name'] + service_type = module.params['type'] + description = module.params['description'] + public_url = module.params['public_url'] + internal_url = module.params['internal_url'] + if internal_url is None: + internal_url = public_url + admin_url = module.params['admin_url'] + if admin_url is None: + admin_url = public_url + region = module.params['region'] + state = module.params['state'] + + keystone = authenticate(endpoint, token, login_user, login_password, + tenant_name, insecure) + check_mode = module.check_mode + + try: + d = dispatch(keystone, name, service_type, description, + public_url, internal_url, admin_url, region, state, + check_mode) + except Exception: + if check_mode: + # If we have a failure in check mode + module.exit_json(changed=True, + msg="exception: %s" % traceback.format_exc()) + else: + 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() |