diff --git a/contrib/inventory/openstack.py b/contrib/inventory/openstack_inventory.py similarity index 93% rename from contrib/inventory/openstack.py rename to contrib/inventory/openstack_inventory.py index 30007e408c..cb581ad85d 100755 --- a/contrib/inventory/openstack.py +++ b/contrib/inventory/openstack_inventory.py @@ -63,9 +63,9 @@ try: except: import simplejson as json -import os_client_config -import shade -import shade.inventory +import openstack as sdk +from openstack.cloud import inventory as sdk_inventory +from openstack.config import loader as cloud_config CONFIG_FILES = ['/etc/ansible/openstack.yaml', '/etc/ansible/openstack.yml'] @@ -148,7 +148,7 @@ def get_host_groups_from_cloud(inventory): if hasattr(inventory, 'extra_config'): use_hostnames = inventory.extra_config['use_hostnames'] list_args['expand'] = inventory.extra_config['expand_hostvars'] - if StrictVersion(shade.__version__) >= StrictVersion("1.6.0"): + if StrictVersion(sdk.version.__version__) >= StrictVersion("0.13.0"): list_args['fail_on_cloud_config'] = \ inventory.extra_config['fail_on_errors'] else: @@ -191,8 +191,8 @@ def is_cache_stale(cache_file, cache_expiration_time, refresh=False): def get_cache_settings(cloud=None): - config = os_client_config.config.OpenStackConfig( - config_files=os_client_config.config.CONFIG_FILES + CONFIG_FILES) + config = cloud_config.OpenStackConfig( + config_files=cloud_config.CONFIG_FILES + CONFIG_FILES).get_one() # For inventory-wide caching cache_expiration_time = config.get_cache_expiration_time() cache_path = config.get_cache_path() @@ -230,15 +230,15 @@ def parse_args(): def main(): args = parse_args() try: - config_files = os_client_config.config.CONFIG_FILES + CONFIG_FILES - shade.simple_logging(debug=args.debug) + config_files = cloud_config.CONFIG_FILES + CONFIG_FILES + sdk.enable_logging(debug=args.debug) inventory_args = dict( refresh=args.refresh, config_files=config_files, private=args.private, cloud=args.cloud, ) - if hasattr(shade.inventory.OpenStackInventory, 'extra_config'): + if hasattr(sdk_inventory.OpenStackInventory, 'extra_config'): inventory_args.update(dict( config_key='ansible', config_defaults={ @@ -248,14 +248,14 @@ def main(): } )) - inventory = shade.inventory.OpenStackInventory(**inventory_args) + inventory = sdk_inventory.OpenStackInventory(**inventory_args) if args.list: output = get_host_groups(inventory, refresh=args.refresh, cloud=args.cloud) elif args.host: output = to_json(inventory.get_host(args.host)) print(output) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: sys.stderr.write('%s\n' % e.message) sys.exit(1) sys.exit(0) diff --git a/lib/ansible/module_utils/openstack.py b/lib/ansible/module_utils/openstack.py index 434a6561ef..8485db7233 100644 --- a/lib/ansible/module_utils/openstack.py +++ b/lib/ansible/module_utils/openstack.py @@ -108,44 +108,50 @@ def openstack_module_kwargs(**kwargs): return ret -def openstack_cloud_from_module(module, min_version=None): +def openstack_cloud_from_module(module, min_version='0.12.0'): from distutils.version import StrictVersion try: - import shade + # Due to the name shadowing we should import other way + import importlib + sdk = importlib.import_module('openstack') except ImportError: - module.fail_json(msg='shade is required for this module') + module.fail_json(msg='openstacksdk is required for this module') if min_version: - if StrictVersion(shade.__version__) < StrictVersion(min_version): + if StrictVersion(sdk.version.__version__) < StrictVersion(min_version): module.fail_json( msg="To utilize this module, the installed version of" - "the shade library MUST be >={min_version}".format( + "the openstacksdk library MUST be >={min_version}".format( min_version=min_version)) cloud_config = module.params.pop('cloud', None) - if isinstance(cloud_config, dict): - fail_message = ( - "A cloud config dict was provided to the cloud parameter" - " but also a value was provided for {param}. If a cloud" - " config dict is provided, {param} should be" - " excluded.") - for param in ( - 'auth', 'region_name', 'verify', - 'cacert', 'key', 'api_timeout', 'interface'): - if module.params[param] is not None: - module.fail_json(fail_message.format(param=param)) - if module.params['auth_type'] != 'password': - module.fail_json(fail_message.format(param='auth_type')) - return shade, shade.operator_cloud(**cloud_config) - else: - return shade, shade.operator_cloud( - cloud=cloud_config, - auth_type=module.params['auth_type'], - auth=module.params['auth'], - region_name=module.params['region_name'], - verify=module.params['verify'], - cacert=module.params['cacert'], - key=module.params['key'], - api_timeout=module.params['api_timeout'], - interface=module.params['interface'], - ) + try: + if isinstance(cloud_config, dict): + fail_message = ( + "A cloud config dict was provided to the cloud parameter" + " but also a value was provided for {param}. If a cloud" + " config dict is provided, {param} should be" + " excluded.") + for param in ( + 'auth', 'region_name', 'verify', + 'cacert', 'key', 'api_timeout', 'interface'): + if module.params[param] is not None: + module.fail_json(fail_message.format(param=param)) + if module.params['auth_type'] != 'password': + module.fail_json(fail_message.format(param='auth_type')) + return sdk, sdk.connect(**cloud_config) + else: + return sdk, sdk.connect( + cloud=cloud_config, + auth_type=module.params['auth_type'], + auth=module.params['auth'], + region_name=module.params['region_name'], + verify=module.params['verify'], + cacert=module.params['cacert'], + key=module.params['key'], + api_timeout=module.params['api_timeout'], + interface=module.params['interface'], + ) + except sdk.exceptions.SDKException as e: + # Probably a cloud configuration/login error + module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/README.md b/lib/ansible/modules/cloud/openstack/README.md index 1caced591a..075bb73fcc 100644 --- a/lib/ansible/modules/cloud/openstack/README.md +++ b/lib/ansible/modules/cloud/openstack/README.md @@ -48,7 +48,8 @@ Libraries * All modules should extends\_documentation\_fragment: openstack to go along with openstack\_full\_argument\_spec. * All complex cloud interaction or interoperability code should be housed in - the [shade](http://git.openstack.org/cgit/openstack-infra/shade) library. + the [openstacksdk](http://git.openstack.org/cgit/openstack/openstacksdk) + library. * All OpenStack API interactions should happen via shade and not via OpenStack Client libraries. The OpenStack Client libraries do no have end users as a primary audience, they are for intra-server communication. The diff --git a/lib/ansible/modules/cloud/openstack/os_auth.py b/lib/ansible/modules/cloud/openstack/os_auth.py index f88759f084..3d9f4b6524 100644 --- a/lib/ansible/modules/cloud/openstack/os_auth.py +++ b/lib/ansible/modules/cloud/openstack/os_auth.py @@ -22,7 +22,7 @@ description: - Retrieve an auth token from an OpenStack Cloud requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" options: availability_zone: description: @@ -53,7 +53,7 @@ def main(): module_kwargs = openstack_module_kwargs() module = AnsibleModule(argument_spec, **module_kwargs) - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: module.exit_json( changed=False, diff --git a/lib/ansible/modules/cloud/openstack/os_flavor_facts.py b/lib/ansible/modules/cloud/openstack/os_flavor_facts.py index 2c5a0ed9c0..8f10b4f35a 100644 --- a/lib/ansible/modules/cloud/openstack/os_flavor_facts.py +++ b/lib/ansible/modules/cloud/openstack/os_flavor_facts.py @@ -30,7 +30,7 @@ notes: contains a list of unsorted flavors. requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" options: name: description: @@ -201,13 +201,7 @@ def main(): if ephemeral: filters['ephemeral'] = ephemeral - if filters: - # Range search added in 1.5.0 - min_version = '1.5.0' - else: - min_version = None - - shade, cloud = openstack_cloud_from_module(module, min_version=min_version) + sdk, cloud = openstack_cloud_from_module(module) try: if name: flavors = cloud.search_flavors(filters={'name': name}) @@ -223,7 +217,7 @@ def main(): module.exit_json(changed=False, ansible_facts=dict(openstack_flavors=flavors)) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_floating_ip.py b/lib/ansible/modules/cloud/openstack/os_floating_ip.py index 1dd6b91449..60158891d1 100644 --- a/lib/ansible/modules/cloud/openstack/os_floating_ip.py +++ b/lib/ansible/modules/cloud/openstack/os_floating_ip.py @@ -78,7 +78,7 @@ options: availability_zone: description: - Ignored. Present for backwards compatibility -requirements: ["shade"] +requirements: ["openstacksdk"] ''' EXAMPLES = ''' @@ -152,11 +152,6 @@ def main(): module_kwargs = openstack_module_kwargs() module = AnsibleModule(argument_spec, **module_kwargs) - if module.params['nat_destination']: - min_version = '1.8.0' - else: - min_version = None - server_name_or_id = module.params['server'] state = module.params['state'] network = module.params['network'] @@ -168,9 +163,9 @@ def main(): timeout = module.params['timeout'] purge = module.params['purge'] - shade, cloud = openstack_cloud_from_module(module, min_version=min_version) - + sdk, cloud = openstack_cloud_from_module(module) try: + server = cloud.get_server(server_name_or_id) if server is None: module.fail_json( @@ -251,7 +246,7 @@ def main(): module.exit_json(changed=True) module.exit_json(changed=changed, floating_ip=f_ip) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e), extra_data=e.extra_data) diff --git a/lib/ansible/modules/cloud/openstack/os_group.py b/lib/ansible/modules/cloud/openstack/os_group.py index b5a3594bae..93478a7297 100644 --- a/lib/ansible/modules/cloud/openstack/os_group.py +++ b/lib/ansible/modules/cloud/openstack/os_group.py @@ -43,7 +43,7 @@ options: - Ignored. Present for backwards compatibility requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' @@ -127,7 +127,7 @@ def main(): domain_id = module.params.pop('domain_id') - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: if domain_id: group = cloud.get_group(name, filters={'domain_id': domain_id}) @@ -159,7 +159,7 @@ def main(): changed = True module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_image.py b/lib/ansible/modules/cloud/openstack/os_image.py index 48a2532191..cc43e47d65 100644 --- a/lib/ansible/modules/cloud/openstack/os_image.py +++ b/lib/ansible/modules/cloud/openstack/os_image.py @@ -80,7 +80,7 @@ options: availability_zone: description: - Ignored. Present for backwards compatibility -requirements: ["shade"] +requirements: ["openstacksdk"] ''' EXAMPLES = ''' @@ -128,7 +128,7 @@ def main(): module_kwargs = openstack_module_kwargs() module = AnsibleModule(argument_spec, **module_kwargs) - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: changed = False @@ -177,7 +177,7 @@ def main(): changed = True module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e), extra_data=e.extra_data) diff --git a/lib/ansible/modules/cloud/openstack/os_image_facts.py b/lib/ansible/modules/cloud/openstack/os_image_facts.py index 6a55669f28..a8c5f45808 100644 --- a/lib/ansible/modules/cloud/openstack/os_image_facts.py +++ b/lib/ansible/modules/cloud/openstack/os_image_facts.py @@ -23,7 +23,7 @@ notes: - Facts are placed in the C(openstack) variable. requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" options: image: description: @@ -139,13 +139,13 @@ def main(): module_kwargs = openstack_module_kwargs() module = AnsibleModule(argument_spec, **module_kwargs) - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: image = cloud.get_image(module.params['image']) module.exit_json(changed=False, ansible_facts=dict( openstack_image=image)) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_ironic.py b/lib/ansible/modules/cloud/openstack/os_ironic.py index 0911c5b40b..6b251235ee 100644 --- a/lib/ansible/modules/cloud/openstack/os_ironic.py +++ b/lib/ansible/modules/cloud/openstack/os_ironic.py @@ -106,7 +106,7 @@ options: description: - Ignored. Present for backwards compatibility -requirements: ["shade", "jsonpatch"] +requirements: ["openstacksdk", "jsonpatch"] ''' EXAMPLES = ''' @@ -153,11 +153,11 @@ def _parse_properties(module): return props -def _parse_driver_info(shade, module): +def _parse_driver_info(sdk, module): p = module.params['driver_info'] info = p.get('power') if not info: - raise shade.OpenStackCloudException( + raise sdk.exceptions.OpenStackCloudException( "driver_info['power'] is required") if p.get('console'): info.update(p.get('console')) @@ -225,7 +225,7 @@ def main(): node_id = _choose_id_value(module) - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: server = cloud.get_machine(node_id) if module.params['state'] == 'present': @@ -234,7 +234,7 @@ def main(): "to set a node to present.") properties = _parse_properties(module) - driver_info = _parse_driver_info(shade, module) + driver_info = _parse_driver_info(sdk, module) kwargs = dict( driver=module.params['driver'], properties=properties, @@ -328,7 +328,7 @@ def main(): else: module.exit_json(changed=False, result="Server not found") - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_ironic_inspect.py b/lib/ansible/modules/cloud/openstack/os_ironic_inspect.py index 07543e88a4..6ad2964b9f 100644 --- a/lib/ansible/modules/cloud/openstack/os_ironic_inspect.py +++ b/lib/ansible/modules/cloud/openstack/os_ironic_inspect.py @@ -46,7 +46,7 @@ options: description: - Ignored. Present for backwards compatibility -requirements: ["shade"] +requirements: ["openstacksdk"] ''' RETURN = ''' @@ -114,10 +114,8 @@ def main(): endpoint=module.params['ironic_url'] ) - shade, cloud = openstack_cloud_from_module( - module, min_version='1.0.0') + sdk, cloud = openstack_cloud_from_module(module) try: - if module.params['name'] or module.params['uuid']: server = cloud.get_machine(_choose_id_value(module)) elif module.params['mac']: @@ -138,7 +136,7 @@ def main(): else: module.fail_json(msg="node not found.") - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_ironic_node.py b/lib/ansible/modules/cloud/openstack/os_ironic_node.py index 00613ebaac..6ae50652ab 100644 --- a/lib/ansible/modules/cloud/openstack/os_ironic_node.py +++ b/lib/ansible/modules/cloud/openstack/os_ironic_node.py @@ -229,11 +229,6 @@ def main(): module_kwargs = openstack_module_kwargs() module = AnsibleModule(argument_spec, **module_kwargs) - if module.params['wait']: - min_version = '1.4.0' - else: - min_version = None - if (module.params['auth_type'] in [None, 'None'] and module.params['ironic_url'] is None): module.fail_json(msg="Authentication appears disabled, Please " @@ -250,8 +245,7 @@ def main(): if not node_id: module.fail_json(msg="A uuid or name value must be defined " "to use this module.") - shade, cloud = openstack_cloud_from_module( - module, min_version=min_version) + sdk, cloud = openstack_cloud_from_module(module) try: node = cloud.get_machine(node_id) @@ -344,7 +338,7 @@ def main(): module.fail_json(msg="State must be present, absent, " "maintenance, off") - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_keypair.py b/lib/ansible/modules/cloud/openstack/os_keypair.py index 24a1bf1f0f..eebb72182d 100644 --- a/lib/ansible/modules/cloud/openstack/os_keypair.py +++ b/lib/ansible/modules/cloud/openstack/os_keypair.py @@ -118,7 +118,7 @@ def main(): public_key = open(module.params['public_key_file']).read() public_key = public_key.rstrip() - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: keypair = cloud.get_keypair(name) @@ -148,7 +148,7 @@ def main(): module.exit_json(changed=True) module.exit_json(changed=False) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_keystone_domain.py b/lib/ansible/modules/cloud/openstack/os_keystone_domain.py index 6edc52d78e..d890e14f56 100644 --- a/lib/ansible/modules/cloud/openstack/os_keystone_domain.py +++ b/lib/ansible/modules/cloud/openstack/os_keystone_domain.py @@ -47,7 +47,7 @@ options: - Ignored. Present for backwards compatibility requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' @@ -139,7 +139,7 @@ def main(): enabled = module.params['enabled'] state = module.params['state'] - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: domains = cloud.search_domains(filters=dict(name=name)) @@ -177,7 +177,7 @@ def main(): changed = True module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_keystone_domain_facts.py b/lib/ansible/modules/cloud/openstack/os_keystone_domain_facts.py index 2f57431acb..473b52c340 100644 --- a/lib/ansible/modules/cloud/openstack/os_keystone_domain_facts.py +++ b/lib/ansible/modules/cloud/openstack/os_keystone_domain_facts.py @@ -22,7 +22,7 @@ description: - Retrieve facts about a one or more OpenStack domains requirements: - "python >= 2.6" - - "shade" + - "sdk" options: name: description: @@ -102,7 +102,7 @@ def main(): ) module = AnsibleModule(argument_spec, **module_kwargs) - shade, opcloud = openstack_cloud_from_module(module) + sdk, opcloud = openstack_cloud_from_module(module) try: name = module.params['name'] filters = module.params['filters'] @@ -120,7 +120,7 @@ def main(): module.exit_json(changed=False, ansible_facts=dict( openstack_domains=domains)) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_keystone_endpoint.py b/lib/ansible/modules/cloud/openstack/os_keystone_endpoint.py index b87a8b405f..c3d82eda2f 100644 --- a/lib/ansible/modules/cloud/openstack/os_keystone_endpoint.py +++ b/lib/ansible/modules/cloud/openstack/os_keystone_endpoint.py @@ -51,7 +51,7 @@ options: choices: [present, absent] default: present requirements: - - shade >= 1.11.0 + - openstacksdk >= 0.13.0 ''' EXAMPLES = ''' @@ -105,8 +105,6 @@ endpoint: sample: True ''' -from distutils.version import StrictVersion - from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module @@ -147,8 +145,6 @@ def main(): supports_check_mode=True, **module_kwargs) - shade, cloud = openstack_cloud_from_module(module, min_version='1.11.0') - service_name_or_id = module.params['service'] interface = module.params['endpoint_interface'] url = module.params['url'] @@ -156,8 +152,8 @@ def main(): enabled = module.params['enabled'] state = module.params['state'] + sdk, cloud = openstack_cloud_from_module(module) try: - cloud = shade.operator_cloud(**module.params) service = cloud.get_service(service_name_or_id) if service is None: @@ -204,7 +200,7 @@ def main(): changed = True module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_keystone_role.py b/lib/ansible/modules/cloud/openstack/os_keystone_role.py index 369971a99a..3340db7d30 100644 --- a/lib/ansible/modules/cloud/openstack/os_keystone_role.py +++ b/lib/ansible/modules/cloud/openstack/os_keystone_role.py @@ -36,7 +36,7 @@ options: required: false requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' @@ -95,9 +95,8 @@ def main(): name = module.params.get('name') state = module.params.get('state') - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: - role = cloud.get_role(name) if module.check_mode: @@ -118,7 +117,7 @@ def main(): changed = True module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_keystone_service.py b/lib/ansible/modules/cloud/openstack/os_keystone_service.py index 371b497483..0328559109 100644 --- a/lib/ansible/modules/cloud/openstack/os_keystone_service.py +++ b/lib/ansible/modules/cloud/openstack/os_keystone_service.py @@ -49,7 +49,7 @@ options: - Ignored. Present for backwards compatibility requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' @@ -147,7 +147,7 @@ def main(): state = module.params['state'] service_type = module.params['service_type'] - shade, cloud = openstack_cloud_from_module(module, min_version='1.6.0') + sdk, cloud = openstack_cloud_from_module(module) try: services = cloud.search_services(name_or_id=name, filters=dict(type=service_type)) @@ -186,7 +186,7 @@ def main(): changed = True module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_network.py b/lib/ansible/modules/cloud/openstack/os_network.py index 4479e4cd2f..4196dabfd7 100644 --- a/lib/ansible/modules/cloud/openstack/os_network.py +++ b/lib/ansible/modules/cloud/openstack/os_network.py @@ -69,7 +69,7 @@ options: availability_zone: description: - Ignored. Present for backwards compatibility -requirements: ["shade"] +requirements: ["openstacksdk"] ''' EXAMPLES = ''' @@ -171,7 +171,7 @@ def main(): provider_segmentation_id = module.params['provider_segmentation_id'] project = module.params.get('project') - shade, cloud = openstack_cloud_from_module(module, min_version='1.6.0') + sdk, cloud = openstack_cloud_from_module(module) try: if project is not None: proj = cloud.get_project(project) @@ -212,7 +212,7 @@ def main(): cloud.delete_network(name) module.exit_json(changed=True) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_networks_facts.py b/lib/ansible/modules/cloud/openstack/os_networks_facts.py index 9795e38c23..3e76f320a9 100644 --- a/lib/ansible/modules/cloud/openstack/os_networks_facts.py +++ b/lib/ansible/modules/cloud/openstack/os_networks_facts.py @@ -22,7 +22,7 @@ description: - Retrieve facts about one or more networks from OpenStack. requirements: - "python >= 2.6" - - "shade" + - "sdk" options: name: description: @@ -129,14 +129,14 @@ def main(): ) module = AnsibleModule(argument_spec) - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: networks = cloud.search_networks(module.params['name'], module.params['filters']) module.exit_json(changed=False, ansible_facts=dict( openstack_networks=networks)) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_nova_flavor.py b/lib/ansible/modules/cloud/openstack/os_nova_flavor.py index be40409508..e06717f2a0 100644 --- a/lib/ansible/modules/cloud/openstack/os_nova_flavor.py +++ b/lib/ansible/modules/cloud/openstack/os_nova_flavor.py @@ -71,7 +71,7 @@ options: description: - Metadata dictionary version_added: "2.3" -requirements: ["shade"] +requirements: ["openstacksdk"] ''' EXAMPLES = ''' @@ -204,7 +204,7 @@ def main(): name = module.params['name'] extra_specs = module.params['extra_specs'] or {} - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: flavor = cloud.get_flavor(name) @@ -250,7 +250,7 @@ def main(): module.exit_json(changed=True) module.exit_json(changed=False) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_nova_host_aggregate.py b/lib/ansible/modules/cloud/openstack/os_nova_host_aggregate.py index 70113af96f..9a3c2aacb5 100644 --- a/lib/ansible/modules/cloud/openstack/os_nova_host_aggregate.py +++ b/lib/ansible/modules/cloud/openstack/os_nova_host_aggregate.py @@ -38,7 +38,7 @@ options: default: present requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' @@ -118,7 +118,7 @@ def main(): if metadata is not None: metadata.pop('availability_zone', None) - shade, cloud = openstack_cloud_from_module(module, min_version='1.9.0') + sdk, cloud = openstack_cloud_from_module(module) try: aggregates = cloud.search_aggregates(name_or_id=name) @@ -171,7 +171,7 @@ def main(): changed = True module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_object.py b/lib/ansible/modules/cloud/openstack/os_object.py index 38e867b965..51d6ae3243 100644 --- a/lib/ansible/modules/cloud/openstack/os_object.py +++ b/lib/ansible/modules/cloud/openstack/os_object.py @@ -112,12 +112,12 @@ def main(): module_kwargs = openstack_module_kwargs() module = AnsibleModule(argument_spec, **module_kwargs) - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: changed = process_object(cloud, **module.params) module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_port.py b/lib/ansible/modules/cloud/openstack/os_port.py index 06cab9b1a2..83b7d5bd91 100644 --- a/lib/ansible/modules/cloud/openstack/os_port.py +++ b/lib/ansible/modules/cloud/openstack/os_port.py @@ -306,7 +306,7 @@ def main(): name = module.params['name'] state = module.params['state'] - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: if module.params['security_groups']: # translate security_groups to UUID's if names where provided @@ -356,7 +356,7 @@ def main(): changed = True module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_port_facts.py b/lib/ansible/modules/cloud/openstack/os_port_facts.py index a4dcb0e92a..a3d33bdd1b 100644 --- a/lib/ansible/modules/cloud/openstack/os_port_facts.py +++ b/lib/ansible/modules/cloud/openstack/os_port_facts.py @@ -23,7 +23,7 @@ notes: - Facts are placed in the C(openstack_ports) variable. requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" options: port: description: @@ -199,13 +199,13 @@ def main(): port = module.params.get('port') filters = module.params.get('filters') - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: ports = cloud.search_ports(port, filters) module.exit_json(changed=False, ansible_facts=dict( openstack_ports=ports)) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_project.py b/lib/ansible/modules/cloud/openstack/os_project.py index 2e7ac108e3..fab4c41f2d 100644 --- a/lib/ansible/modules/cloud/openstack/os_project.py +++ b/lib/ansible/modules/cloud/openstack/os_project.py @@ -35,7 +35,6 @@ options: domain_id: description: - Domain id to create the project in if the cloud supports domains. - The domain_id parameter requires shade >= 1.8.0 aliases: ['domain'] enabled: description: @@ -52,7 +51,7 @@ options: - Ignored. Present for backwards compatibility requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' @@ -152,13 +151,7 @@ def main(): enabled = module.params['enabled'] state = module.params['state'] - if domain: - min_version = '1.8.0' - else: - min_version = None - - shade, cloud = openstack_cloud_from_module( - module, min_version=min_version) + sdk, cloud = openstack_cloud_from_module(module) try: if domain: try: @@ -208,7 +201,7 @@ def main(): changed = True module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=e.message, extra_data=e.extra_data) diff --git a/lib/ansible/modules/cloud/openstack/os_project_access.py b/lib/ansible/modules/cloud/openstack/os_project_access.py index 9d44146c29..43ee8fd47d 100644 --- a/lib/ansible/modules/cloud/openstack/os_project_access.py +++ b/lib/ansible/modules/cloud/openstack/os_project_access.py @@ -51,13 +51,13 @@ options: description: - The availability zone of the resource. requirements: - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' - name: "Enable access to tiny flavor to your tenant." - os_project_access: + os_project_Access: cloud: mycloud state: present target_project_id: f0f1f2f3f4f5f67f8f9e0e1 @@ -66,7 +66,7 @@ EXAMPLES = ''' - name: "Disable access to the given flavor to project" - os_project_access: + os_project_Access: cloud: mycloud state: absent target_project_id: f0f1f2f3f4f5f67f8f9e0e1 @@ -93,15 +93,8 @@ flavor: ''' -try: - import shade - HAS_SHADE = True -except ImportError: - HAS_SHADE = False - - from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs +from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module def main(): @@ -123,8 +116,7 @@ def main(): ], **module_kwargs) - if not HAS_SHADE: - module.fail_json(msg='shade is required for this module') + sdk, cloud = openstack_cloud_from_module(module) changed = False state = module.params['state'] @@ -133,8 +125,6 @@ def main(): target_project_id = module.params['target_project_id'] try: - cloud = shade.operator_cloud(**module.params) - if resource_type == 'nova_flavor': # returns Munch({'NAME_ATTR': 'name', # 'tenant_id': u'37e55da59ec842649d84230f3a24eed5', @@ -201,7 +191,7 @@ def main(): resource=resource, id=resource_id) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e), **module.params) diff --git a/lib/ansible/modules/cloud/openstack/os_project_facts.py b/lib/ansible/modules/cloud/openstack/os_project_facts.py index 496d2dfea9..20fbe5d74e 100644 --- a/lib/ansible/modules/cloud/openstack/os_project_facts.py +++ b/lib/ansible/modules/cloud/openstack/os_project_facts.py @@ -22,7 +22,7 @@ description: - Retrieve facts about a one or more OpenStack projects requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" options: name: description: @@ -116,7 +116,7 @@ def main(): module = AnsibleModule(argument_spec) - shade, opcloud = openstack_cloud_from_module(module) + sdk, opcloud = openstack_cloud_from_module(module) try: name = module.params['name'] domain = module.params['domain'] @@ -145,7 +145,7 @@ def main(): module.exit_json(changed=False, ansible_facts=dict( openstack_projects=projects)) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_quota.py b/lib/ansible/modules/cloud/openstack/os_quota.py index d305120a27..fb196ee8ad 100644 --- a/lib/ansible/modules/cloud/openstack/os_quota.py +++ b/lib/ansible/modules/cloud/openstack/os_quota.py @@ -106,7 +106,7 @@ options: requirements: - "python >= 2.6" - - "shade > 1.9.0" + - "openstacksdk >= 0.13.0" ''' EXAMPLES = ''' @@ -244,17 +244,17 @@ def _get_compute_quotas(cloud, project): return cloud.get_compute_quotas(project) -def _get_quotas(shade, module, cloud, project): +def _get_quotas(sdk, module, cloud, project): quota = {} try: quota['volume'] = _get_volume_quotas(cloud, project) - except shade.OpenStackCloudURINotFound: + except sdk.exceptions.OpenStackCloudURINotFound: module.warn("No public endpoint for volumev2 service was found. Ignoring volume quotas.") try: quota['network'] = _get_network_quotas(cloud, project) - except shade.OpenStackCloudURINotFound: + except sdk.exceptions.OpenStackCloudURINotFound: module.warn("No public endpoint for network service was found. Ignoring network quotas.") quota['compute'] = _get_compute_quotas(cloud, project) @@ -364,7 +364,7 @@ def main(): supports_check_mode=True ) - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: cloud_params = dict(module.params) @@ -381,7 +381,7 @@ def main(): # Get current quota values project_quota_output = _get_quotas( - shade, module, cloud, cloud_params['name']) + sdk, module, cloud, cloud_params['name']) changes_required = False if module.params['state'] == "absent": @@ -392,7 +392,7 @@ def main(): module.exit_json(changed=True) # Calling delete_network_quotas when a quota has not been set results - # in an error, according to the shade docs it should return the + # in an error, according to the sdk docs it should return the # current quota. # The following error string is returned: # network client call failed: Quota for tenant 69dd91d217e949f1a0b35a4b901741dc could not be found. @@ -403,7 +403,7 @@ def main(): quota_call = getattr(cloud, 'delete_%s_quotas' % (quota_type)) try: quota_call(cloud_params['name']) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: error_msg = str(e) if error_msg.find(neutron_msg1) > -1 and error_msg.find(neutron_msg2) > -1: pass @@ -411,7 +411,7 @@ def main(): module.fail_json(msg=str(e), extra_data=e.extra_data) project_quota_output = _get_quotas( - shade, module, cloud, cloud_params['name']) + sdk, module, cloud, cloud_params['name']) changes_required = True elif module.params['state'] == "present": @@ -430,7 +430,7 @@ def main(): # Get quota state post changes for validation project_quota_update = _get_quotas( - shade, module, cloud, cloud_params['name']) + sdk, module, cloud, cloud_params['name']) if project_quota_output == project_quota_update: module.fail_json(msg='Could not apply quota update') @@ -441,7 +441,7 @@ def main(): openstack_quotas=project_quota_output ) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e), extra_data=e.extra_data) diff --git a/lib/ansible/modules/cloud/openstack/os_recordset.py b/lib/ansible/modules/cloud/openstack/os_recordset.py index 0ad794c96c..4afcda742f 100644 --- a/lib/ansible/modules/cloud/openstack/os_recordset.py +++ b/lib/ansible/modules/cloud/openstack/os_recordset.py @@ -55,7 +55,7 @@ options: - Ignored. Present for backwards compatibility requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' @@ -164,7 +164,7 @@ def main(): name = module.params.get('name') state = module.params.get('state') - shade, cloud = openstack_cloud_from_module(module, min_version='1.9.0') + sdk, cloud = openstack_cloud_from_module(module) try: recordset_type = module.params.get('recordset_type') recordset_filter = {'type': recordset_type} @@ -228,7 +228,7 @@ def main(): changed = True module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_router.py b/lib/ansible/modules/cloud/openstack/os_router.py index ce983b320c..d59982c137 100644 --- a/lib/ansible/modules/cloud/openstack/os_router.py +++ b/lib/ansible/modules/cloud/openstack/os_router.py @@ -72,7 +72,7 @@ options: availability_zone: description: - Ignored. Present for backwards compatibility -requirements: ["shade"] +requirements: ["openstacksdk"] ''' EXAMPLES = ''' @@ -383,11 +383,6 @@ def main(): supports_check_mode=True, **module_kwargs) - if module.params['project']: - min_version = '1.10.0' - else: - min_version = None - state = module.params['state'] name = module.params['name'] network = module.params['network'] @@ -396,7 +391,7 @@ def main(): if module.params['external_fixed_ips'] and not network: module.fail_json(msg='network is required when supplying external_fixed_ips') - shade, cloud = openstack_cloud_from_module(module, min_version=min_version) + sdk, cloud = openstack_cloud_from_module(module) try: if project is not None: proj = cloud.get_project(project) @@ -482,7 +477,7 @@ def main(): cloud.delete_router(router_id) module.exit_json(changed=True) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_security_group.py b/lib/ansible/modules/cloud/openstack/os_security_group.py index 40758ebbb4..d44961b929 100644 --- a/lib/ansible/modules/cloud/openstack/os_security_group.py +++ b/lib/ansible/modules/cloud/openstack/os_security_group.py @@ -98,7 +98,7 @@ def main(): state = module.params['state'] description = module.params['description'] - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: secgroup = cloud.get_security_group(name) @@ -124,7 +124,7 @@ def main(): changed = True module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_security_group_rule.py b/lib/ansible/modules/cloud/openstack/os_security_group_rule.py index 17e8e0cc40..e4c84a7285 100644 --- a/lib/ansible/modules/cloud/openstack/os_security_group_rule.py +++ b/lib/ansible/modules/cloud/openstack/os_security_group_rule.py @@ -64,7 +64,7 @@ options: availability_zone: description: - Ignored. Present for backwards compatibility -requirements: ["shade"] +requirements: ["openstacksdk"] ''' EXAMPLES = ''' @@ -168,15 +168,15 @@ def _ports_match(protocol, module_min, module_max, rule_min, rule_max): Capture the complex port matching logic. The port values coming in for the module might be -1 (for ICMP), - which will work only for Nova, but this is handled by shade. Likewise, + which will work only for Nova, but this is handled by sdk. Likewise, they might be None, which works for Neutron, but not Nova. This too is - handled by shade. Since shade will consistently return these port + handled by sdk. Since sdk will consistently return these port values as None, we need to convert any -1 values input to the module to None here for comparison. For TCP and UDP protocols, None values for both min and max are represented as the range 1-65535 for Nova, but remain None for - Neutron. Shade returns the full range when Nova is the backend (since + Neutron. sdk returns the full range when Nova is the backend (since that is how Nova stores them), and None values for Neutron. If None values are input to the module for both values, then we need to adjust for comparison. @@ -288,7 +288,7 @@ def main(): remote_group = module.params['remote_group'] changed = False - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: secgroup = cloud.get_security_group(security_group) @@ -328,7 +328,7 @@ def main(): module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_server.py b/lib/ansible/modules/cloud/openstack/os_server.py index ad7b545b4d..667e4acbc2 100644 --- a/lib/ansible/modules/cloud/openstack/os_server.py +++ b/lib/ansible/modules/cloud/openstack/os_server.py @@ -167,7 +167,7 @@ options: - Availability zone in which to create the server. requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' @@ -717,7 +717,7 @@ def main(): "if state == 'present'" ) - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: if state == 'present': _get_server_state(module, cloud) @@ -725,7 +725,7 @@ def main(): elif state == 'absent': _get_server_state(module, cloud) _delete_server(module, cloud) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e), extra_data=e.extra_data) diff --git a/lib/ansible/modules/cloud/openstack/os_server_action.py b/lib/ansible/modules/cloud/openstack/os_server_action.py index cd6433ceaa..a39474485a 100644 --- a/lib/ansible/modules/cloud/openstack/os_server_action.py +++ b/lib/ansible/modules/cloud/openstack/os_server_action.py @@ -55,7 +55,7 @@ options: - Ignored. Present for backwards compatibility requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' @@ -87,10 +87,14 @@ _action_map = {'stop': 'SHUTOFF', _admin_actions = ['pause', 'unpause', 'suspend', 'resume', 'lock', 'unlock'] -def _wait(timeout, cloud, server, action, module, shade): +def _action_url(server_id): + return '/servers/{server_id}/action'.format(server_id=server_id) + + +def _wait(timeout, cloud, server, action, module, sdk): """Wait for the server to reach the desired state for the given action.""" - for count in shade._utils._iterate_timeout( + for count in sdk.utils._iterate_timeout( timeout, "Timeout waiting for server to complete %s" % action): try: @@ -134,10 +138,7 @@ def main(): timeout = module.params['timeout'] image = module.params['image'] - if action in _admin_actions: - shade, cloud = openstack_cloud_from_module(module) - else: - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: server = cloud.get_server(module.params['server']) if not server: @@ -151,64 +152,80 @@ def main(): if not _system_state_change(action, status): module.exit_json(changed=False) - cloud.nova_client.servers.stop(server=server.id) + cloud.compute.post( + _action_url(server.id), + json={'os-stop': None}) if wait: - _wait(timeout, cloud, server, action, module, shade) + _wait(timeout, cloud, server, action, module, sdk) module.exit_json(changed=True) if action == 'start': if not _system_state_change(action, status): module.exit_json(changed=False) - cloud.nova_client.servers.start(server=server.id) + cloud.compute.post( + _action_url(server.id), + json={'os-start': None}) if wait: - _wait(timeout, cloud, server, action, module, shade) + _wait(timeout, cloud, server, action, module, sdk) module.exit_json(changed=True) if action == 'pause': if not _system_state_change(action, status): module.exit_json(changed=False) - cloud.nova_client.servers.pause(server=server.id) + cloud.compute.post( + _action_url(server.id), + json={'pause': None}) if wait: - _wait(timeout, cloud, server, action, module, shade) + _wait(timeout, cloud, server, action, module, sdk) module.exit_json(changed=True) elif action == 'unpause': if not _system_state_change(action, status): module.exit_json(changed=False) - cloud.nova_client.servers.unpause(server=server.id) + cloud.compute.post( + _action_url(server.id), + json={'unpause': None}) if wait: - _wait(timeout, cloud, server, action, module, shade) + _wait(timeout, cloud, server, action, module, sdk) module.exit_json(changed=True) elif action == 'lock': # lock doesn't set a state, just do it - cloud.nova_client.servers.lock(server=server.id) + cloud.compute.post( + _action_url(server.id), + json={'lock': None}) module.exit_json(changed=True) elif action == 'unlock': # unlock doesn't set a state, just do it - cloud.nova_client.servers.unlock(server=server.id) + cloud.compute.post( + _action_url(server.id), + json={'unlock': None}) module.exit_json(changed=True) elif action == 'suspend': if not _system_state_change(action, status): module.exit_json(changed=False) - cloud.nova_client.servers.suspend(server=server.id) + cloud.compute.post( + _action_url(server.id), + json={'suspend': None}) if wait: - _wait(timeout, cloud, server, action, module, shade) + _wait(timeout, cloud, server, action, module, sdk) module.exit_json(changed=True) elif action == 'resume': if not _system_state_change(action, status): module.exit_json(changed=False) - cloud.nova_client.servers.resume(server=server.id) + cloud.compute.post( + _action_url(server.id), + json={'resume': None}) if wait: - _wait(timeout, cloud, server, action, module, shade) + _wait(timeout, cloud, server, action, module, sdk) module.exit_json(changed=True) elif action == 'rebuild': @@ -218,12 +235,14 @@ def main(): module.fail_json(msg="Image does not exist") # rebuild doesn't set a state, just do it - cloud.nova_client.servers.rebuild(server=server.id, image=image.id) + cloud.compute.post( + _action_url(server.id), + json={'rebuild': None}) if wait: - _wait(timeout, cloud, server, action, module, shade) + _wait(timeout, cloud, server, action, module, sdk) module.exit_json(changed=True) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e), extra_data=e.extra_data) diff --git a/lib/ansible/modules/cloud/openstack/os_server_facts.py b/lib/ansible/modules/cloud/openstack/os_server_facts.py index 0b6ae4934b..84d0d12424 100644 --- a/lib/ansible/modules/cloud/openstack/os_server_facts.py +++ b/lib/ansible/modules/cloud/openstack/os_server_facts.py @@ -25,7 +25,7 @@ notes: contains a list of servers. requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" options: server: description: @@ -67,7 +67,7 @@ def main(): module_kwargs = openstack_module_kwargs() module = AnsibleModule(argument_spec, **module_kwargs) - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: openstack_servers = cloud.list_servers( detailed=module.params['detailed']) @@ -75,13 +75,13 @@ def main(): if module.params['server']: # filter servers by name pattern = module.params['server'] - # TODO(mordred) This is handled by shade now + # TODO(mordred) This is handled by sdk now openstack_servers = [server for server in openstack_servers if fnmatch.fnmatch(server['name'], pattern) or fnmatch.fnmatch(server['id'], pattern)] module.exit_json(changed=False, ansible_facts=dict( openstack_servers=openstack_servers)) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_server_group.py b/lib/ansible/modules/cloud/openstack/os_server_group.py index d6a29490ac..7b27a6dce7 100644 --- a/lib/ansible/modules/cloud/openstack/os_server_group.py +++ b/lib/ansible/modules/cloud/openstack/os_server_group.py @@ -46,7 +46,7 @@ options: required: false requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' @@ -134,7 +134,7 @@ def main(): policies = module.params['policies'] state = module.params['state'] - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: server_group = cloud.get_server_group(name) @@ -164,7 +164,7 @@ def main(): cloud.delete_server_group(server_group['id']) changed = True module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e), extra_data=e.extra_data) diff --git a/lib/ansible/modules/cloud/openstack/os_server_metadata.py b/lib/ansible/modules/cloud/openstack/os_server_metadata.py index 12d242ce3a..f3b6ee0a86 100644 --- a/lib/ansible/modules/cloud/openstack/os_server_metadata.py +++ b/lib/ansible/modules/cloud/openstack/os_server_metadata.py @@ -96,15 +96,10 @@ metadata: sample: {'key1': 'value1', 'key2': 'value2'} ''' -try: - import shade - HAS_SHADE = True -except ImportError: - HAS_SHADE = False - from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.openstack import (openstack_full_argument_spec, - openstack_module_kwargs) + openstack_module_kwargs, + openstack_cloud_from_module) def _needs_update(server_metadata=None, metadata=None): @@ -134,17 +129,13 @@ def main(): supports_check_mode=True, **module_kwargs) - if not HAS_SHADE: - module.fail_json(msg='shade is required for this module') - state = module.params['state'] server_param = module.params['server'] meta_param = module.params['meta'] changed = False + sdk, cloud = openstack_cloud_from_module(module) try: - cloud = shade.openstack_cloud(**module.params) - server = cloud.get_server(server_param) if not server: module.fail_json( @@ -172,7 +163,7 @@ def main(): module.exit_json( changed=changed, server_id=server.id, metadata=server.metadata) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=e.message, extra_data=e.extra_data) diff --git a/lib/ansible/modules/cloud/openstack/os_server_volume.py b/lib/ansible/modules/cloud/openstack/os_server_volume.py index 6b39d1dc55..5191115538 100644 --- a/lib/ansible/modules/cloud/openstack/os_server_volume.py +++ b/lib/ansible/modules/cloud/openstack/os_server_volume.py @@ -45,7 +45,7 @@ options: - Ignored. Present for backwards compatibility requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' @@ -96,7 +96,7 @@ def main(): wait = module.params['wait'] timeout = module.params['timeout'] - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: server = cloud.get_server(module.params['server']) volume = cloud.get_volume(module.params['volume']) @@ -135,7 +135,7 @@ def main(): result='Detached volume from server' ) - except (shade.OpenStackCloudException, shade.OpenStackCloudTimeout) as e: + except (sdk.exceptions.OpenStackCloudException, sdk.exceptions.OpenStackCloudTimeout) as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_stack.py b/lib/ansible/modules/cloud/openstack/os_stack.py index af4fc7908f..521eb72e97 100644 --- a/lib/ansible/modules/cloud/openstack/os_stack.py +++ b/lib/ansible/modules/cloud/openstack/os_stack.py @@ -60,7 +60,7 @@ options: - Ignored. Present for backwards compatibility requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' --- @@ -152,7 +152,7 @@ from ansible.module_utils.openstack import openstack_full_argument_spec, opensta from ansible.module_utils._text import to_native -def _create_stack(module, stack, cloud, shade): +def _create_stack(module, stack, cloud, sdk): try: stack = cloud.create_stack(module.params['name'], tags=module.params['tag'], @@ -168,14 +168,14 @@ def _create_stack(module, stack, cloud, shade): return stack else: module.fail_json(msg="Failure in creating stack: {0}".format(stack)) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: if hasattr(e, 'response'): module.fail_json(msg=to_native(e), response=e.response.json()) else: module.fail_json(msg=to_native(e)) -def _update_stack(module, stack, cloud, shade): +def _update_stack(module, stack, cloud, sdk): try: stack = cloud.update_stack( module.params['name'], @@ -191,7 +191,7 @@ def _update_stack(module, stack, cloud, shade): else: module.fail_json(msg="Failure in updating stack: %s" % stack['stack_status_reason']) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: if hasattr(e, 'response'): module.fail_json(msg=to_native(e), response=e.response.json()) else: @@ -226,13 +226,6 @@ def main(): supports_check_mode=True, **module_kwargs) - # stack API introduced in 1.8.0 - min_version = '1.8.0' - tag = module.params['tag'] - if tag is not None: - # stack tag API was introduced in 1.26.0 - min_version = '1.26.0' - state = module.params['state'] name = module.params['name'] # Check for required parameters when state == 'present' @@ -241,7 +234,7 @@ def main(): if not module.params[p]: module.fail_json(msg='%s required with present state' % p) - shade, cloud = openstack_cloud_from_module(module, min_version='1.26.0') + sdk, cloud = openstack_cloud_from_module(module) try: stack = cloud.get_stack(name) @@ -251,9 +244,9 @@ def main(): if state == 'present': if not stack: - stack = _create_stack(module, stack, cloud, shade) + stack = _create_stack(module, stack, cloud, sdk) else: - stack = _update_stack(module, stack, cloud, shade) + stack = _update_stack(module, stack, cloud, sdk) changed = True module.exit_json(changed=changed, stack=stack, @@ -266,7 +259,7 @@ def main(): if not cloud.delete_stack(name, wait=module.params['wait']): module.fail_json(msg='delete stack failed for stack: %s' % name) module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=to_native(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_subnet.py b/lib/ansible/modules/cloud/openstack/os_subnet.py index 4ccbfbf826..d3f805fba2 100644 --- a/lib/ansible/modules/cloud/openstack/os_subnet.py +++ b/lib/ansible/modules/cloud/openstack/os_subnet.py @@ -97,7 +97,7 @@ options: - Ignored. Present for backwards compatibility requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' @@ -257,10 +257,6 @@ def main(): use_default_subnetpool = module.params['use_default_subnetpool'] project = module.params.pop('project') - min_version = None - if use_default_subnetpool: - min_version = '1.16.0' - # Check for required parameters when state == 'present' if state == 'present': if not module.params['network_name']: @@ -279,7 +275,7 @@ def main(): if no_gateway_ip and gateway_ip: module.fail_json(msg='no_gateway_ip is not allowed with gateway_ip') - shade, cloud = openstack_cloud_from_module(module, min_version=min_version) + sdk, cloud = openstack_cloud_from_module(module) try: if project is not None: proj = cloud.get_project(project) @@ -340,7 +336,7 @@ def main(): cloud.delete_subnet(subnet_name) module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_subnets_facts.py b/lib/ansible/modules/cloud/openstack/os_subnets_facts.py index 8a6382f4d0..8b0326742c 100644 --- a/lib/ansible/modules/cloud/openstack/os_subnets_facts.py +++ b/lib/ansible/modules/cloud/openstack/os_subnets_facts.py @@ -22,7 +22,7 @@ description: - Retrieve facts about one or more subnets from OpenStack. requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" options: subnet: description: @@ -142,14 +142,14 @@ def main(): ) module = AnsibleModule(argument_spec) - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: subnets = cloud.search_subnets(module.params['name'], module.params['filters']) module.exit_json(changed=False, ansible_facts=dict( openstack_subnets=subnets)) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_user.py b/lib/ansible/modules/cloud/openstack/os_user.py index aebd34d131..6900cbe8b6 100644 --- a/lib/ansible/modules/cloud/openstack/os_user.py +++ b/lib/ansible/modules/cloud/openstack/os_user.py @@ -67,7 +67,7 @@ options: - Ignored. Present for backwards compatibility requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' @@ -199,10 +199,7 @@ def main(): update_password = module.params['update_password'] description = module.params['description'] - if description and StrictVersion(shade.__version__) < StrictVersion('1.13.0'): - module.fail_json(msg="To utilize description, the installed version of the shade library MUST be >=1.13.0") - - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: user = cloud.get_user(name) @@ -278,7 +275,7 @@ def main(): changed = True module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e), extra_data=e.extra_data) diff --git a/lib/ansible/modules/cloud/openstack/os_user_facts.py b/lib/ansible/modules/cloud/openstack/os_user_facts.py index ae32858b81..fded761d87 100644 --- a/lib/ansible/modules/cloud/openstack/os_user_facts.py +++ b/lib/ansible/modules/cloud/openstack/os_user_facts.py @@ -22,7 +22,7 @@ description: - Retrieve facts about a one or more OpenStack users requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" options: name: description: @@ -124,7 +124,7 @@ def main(): module = AnsibleModule(argument_spec) - shade, opcloud = openstack_cloud_from_module(module) + sdk, opcloud = openstack_cloud_from_module(module) try: name = module.params['name'] domain = module.params['domain'] @@ -153,7 +153,7 @@ def main(): module.exit_json(changed=False, ansible_facts=dict( openstack_users=users)) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_user_group.py b/lib/ansible/modules/cloud/openstack/os_user_group.py index ab357fd484..1d9ebb55f8 100644 --- a/lib/ansible/modules/cloud/openstack/os_user_group.py +++ b/lib/ansible/modules/cloud/openstack/os_user_group.py @@ -40,7 +40,7 @@ options: required: false requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' @@ -79,7 +79,7 @@ def main(): group = module.params['group'] state = module.params['state'] - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: in_group = cloud.is_user_in_group(user, group) @@ -99,7 +99,7 @@ def main(): module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e), extra_data=e.extra_data) diff --git a/lib/ansible/modules/cloud/openstack/os_user_role.py b/lib/ansible/modules/cloud/openstack/os_user_role.py index fceafa7f51..58c8962361 100644 --- a/lib/ansible/modules/cloud/openstack/os_user_role.py +++ b/lib/ansible/modules/cloud/openstack/os_user_role.py @@ -53,7 +53,7 @@ options: - Ignored. Present for backwards compatibility requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' @@ -127,9 +127,7 @@ def main(): domain = module.params.get('domain') state = module.params.get('state') - # role grant/revoke API introduced in 1.5.0 - shade, cloud = openstack_cloud_from_module( - module, min_version='1.5.0') + sdk, cloud = openstack_cloud_from_module(module) try: filters = {} @@ -184,7 +182,7 @@ def main(): module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_volume.py b/lib/ansible/modules/cloud/openstack/os_volume.py index 3ef290e0c9..743a4b5fd6 100644 --- a/lib/ansible/modules/cloud/openstack/os_volume.py +++ b/lib/ansible/modules/cloud/openstack/os_volume.py @@ -60,7 +60,7 @@ options: version_added: "2.4" requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' @@ -117,14 +117,14 @@ def _present_volume(module, cloud): module.exit_json(changed=True, id=volume['id'], volume=volume) -def _absent_volume(module, cloud, shade): +def _absent_volume(module, cloud, sdk): changed = False if cloud.volume_exists(module.params['display_name']): try: changed = cloud.delete_volume(name_or_id=module.params['display_name'], wait=module.params['wait'], timeout=module.params['timeout']) - except shade.OpenStackCloudTimeout: + except sdk.exceptions.OpenStackCloudTimeout: module.exit_json(changed=changed) module.exit_json(changed=changed) @@ -149,23 +149,18 @@ def main(): ) module = AnsibleModule(argument_spec=argument_spec, **module_kwargs) - if (module.params['scheduler_hints'] and - StrictVersion(shade.__version__) < StrictVersion('1.22')): - module.fail_json(msg="To utilize scheduler_hints, the installed version of" - "the shade library MUST be >= 1.22") - state = module.params['state'] if state == 'present' and not module.params['size']: module.fail_json(msg="Size is required when state is 'present'") - shade, cloud = openstack_cloud_from_module(module) + sdk, cloud = openstack_cloud_from_module(module) try: if state == 'present': _present_volume(module, cloud) if state == 'absent': - _absent_volume(module, cloud, shade) - except shade.OpenStackCloudException as e: + _absent_volume(module, cloud, sdk) + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/modules/cloud/openstack/os_volume_snapshot.py b/lib/ansible/modules/cloud/openstack/os_volume_snapshot.py index 66a51b5d81..f03ce14657 100644 --- a/lib/ansible/modules/cloud/openstack/os_volume_snapshot.py +++ b/lib/ansible/modules/cloud/openstack/os_volume_snapshot.py @@ -67,7 +67,7 @@ options: required: false requirements: - "python >= 2.7" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' @@ -105,15 +105,10 @@ snapshot: display_name: test_snapshot ''' -try: - import shade - HAS_SHADE = True -except ImportError: - HAS_SHADE = False - from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.openstack import (openstack_full_argument_spec, - openstack_module_kwargs) + openstack_module_kwargs, + openstack_cloud_from_module) def _present_volume_snapshot(module, cloud): @@ -175,13 +170,11 @@ def main(): supports_check_mode=True, **module_kwargs) - if not HAS_SHADE: - module.fail_json(msg='shade is required for this module') + sdk, cloud = openstack_cloud_from_module(module) state = module.params['state'] try: - cloud = shade.openstack_cloud(**module.params) if cloud.volume_exists(module.params['volume']): if module.check_mode: module.exit_json(changed=_system_state_change(module, cloud)) @@ -193,7 +186,7 @@ def main(): module.fail_json( msg="No volume with name or id '{0}' was found.".format( module.params['volume'])) - except (shade.OpenStackCloudException, shade.OpenStackCloudTimeout) as e: + except (sdk.exceptions.OpenStackCloudException, sdk.exceptions.OpenStackCloudTimeout) as e: module.fail_json(msg=e.message) diff --git a/lib/ansible/modules/cloud/openstack/os_zone.py b/lib/ansible/modules/cloud/openstack/os_zone.py index be4f583fe1..d19ebaa202 100644 --- a/lib/ansible/modules/cloud/openstack/os_zone.py +++ b/lib/ansible/modules/cloud/openstack/os_zone.py @@ -53,7 +53,7 @@ options: - Ignored. Present for backwards compatibility requirements: - "python >= 2.6" - - "shade" + - "openstacksdk" ''' EXAMPLES = ''' @@ -157,7 +157,7 @@ def main(): name = module.params.get('name') state = module.params.get('state') - shade, cloud = openstack_cloud_from_module(module, min_version='1.8.0') + sdk, cloud = openstack_cloud_from_module(module) try: zone = cloud.get_zone(name) @@ -206,7 +206,7 @@ def main(): changed = True module.exit_json(changed=changed) - except shade.OpenStackCloudException as e: + except sdk.exceptions.OpenStackCloudException as e: module.fail_json(msg=str(e)) diff --git a/lib/ansible/plugins/inventory/openstack.py b/lib/ansible/plugins/inventory/openstack.py index 333b0e9c0e..3a85a43f54 100644 --- a/lib/ansible/plugins/inventory/openstack.py +++ b/lib/ansible/plugins/inventory/openstack.py @@ -106,12 +106,14 @@ from ansible.errors import AnsibleParserError from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable try: - import os_client_config - import shade - import shade.inventory - HAS_SHADE = True + # Due to the name shadowing we should import other way + import importlib + sdk = importlib.import_module('openstack') + sdk_inventory = importlib.import_module('openstack.cloud.inventory') + client_config = importlib.import_module('openstack.config.loader') + HAS_SDK = True except ImportError: - HAS_SHADE = False + HAS_SDK = False class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable): @@ -135,8 +137,8 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable): msg = 'plugin config file, but not for us: %s' % self._config_data['plugin'] elif 'plugin' not in self._config_data and 'clouds' not in self._config_data: msg = "it's not a plugin configuration nor a clouds.yaml file" - elif not HAS_SHADE: - msg = "shade is required for the OpenStack inventory plugin. OpenStack inventory sources will be skipped." + elif not HAS_SDK: + msg = "openstacksdk is required for the OpenStack inventory plugin. OpenStack inventory sources will be skipped." if msg: raise AnsibleParserError(msg) @@ -157,14 +159,14 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable): clouds_yaml_path = self._config_data.get('clouds_yaml_path') if clouds_yaml_path: config_files = (clouds_yaml_path + - os_client_config.config.CONFIG_FILES) + client_config.CONFIG_FILES) else: config_files = None # TODO(mordred) Integrate shade's logging with ansible's logging - shade.simple_logging() + sdk.enable_logging() - cloud_inventory = shade.inventory.OpenStackInventory( + cloud_inventory = sdk_inventory.OpenStackInventory( config_files=config_files, private=self._config_data.get('private', False)) only_clouds = self._config_data.get('only_clouds', []) diff --git a/lib/ansible/utils/module_docs_fragments/openstack.py b/lib/ansible/utils/module_docs_fragments/openstack.py index 87eb0ca46d..869955c2f6 100644 --- a/lib/ansible/utils/module_docs_fragments/openstack.py +++ b/lib/ansible/utils/module_docs_fragments/openstack.py @@ -96,7 +96,7 @@ options: version_added: "2.3" requirements: - python >= 2.7 - - shade + - openstacksdk notes: - The standard OpenStack environment variables, such as C(OS_USERNAME) may be used instead of providing explicit values.