summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnsible Core Team <info@ansible.com>2020-03-09 09:40:35 +0000
committerAnsible Core Team <info@ansible.com>2020-03-09 09:40:35 +0000
commit618745158a000818c4793da5e4cd524022adf342 (patch)
treef83de0dd309ae4bd65cf867af0c8924b5cee7c32
parent37e8b907bcfdd5bfd3e4c8c5af8de23641874e32 (diff)
downloadansible-618745158a000818c4793da5e4cd524022adf342.tar.gz
Migrated to openstack.cloud
-rw-r--r--lib/ansible/module_utils/openstack.py163
-rw-r--r--lib/ansible/modules/cloud/openstack/os_auth.py79
-rw-r--r--lib/ansible/modules/cloud/openstack/os_client_config.py82
-rw-r--r--lib/ansible/modules/cloud/openstack/os_coe_cluster.py282
-rw-r--r--lib/ansible/modules/cloud/openstack/os_coe_cluster_template.py373
-rw-r--r--lib/ansible/modules/cloud/openstack/os_flavor_info.py238
-rw-r--r--lib/ansible/modules/cloud/openstack/os_floating_ip.py255
-rw-r--r--lib/ansible/modules/cloud/openstack/os_group.py167
-rw-r--r--lib/ansible/modules/cloud/openstack/os_group_info.py171
-rw-r--r--lib/ansible/modules/cloud/openstack/os_image.py235
-rw-r--r--lib/ansible/modules/cloud/openstack/os_image_info.py196
-rw-r--r--lib/ansible/modules/cloud/openstack/os_ironic.py355
-rw-r--r--lib/ansible/modules/cloud/openstack/os_ironic_inspect.py144
-rw-r--r--lib/ansible/modules/cloud/openstack/os_ironic_node.py333
-rw-r--r--lib/ansible/modules/cloud/openstack/os_keypair.py163
-rw-r--r--lib/ansible/modules/cloud/openstack/os_keystone_domain.py185
-rw-r--r--lib/ansible/modules/cloud/openstack/os_keystone_domain_info.py140
-rw-r--r--lib/ansible/modules/cloud/openstack/os_keystone_endpoint.py209
-rw-r--r--lib/ansible/modules/cloud/openstack/os_keystone_role.py127
-rw-r--r--lib/ansible/modules/cloud/openstack/os_keystone_service.py194
-rw-r--r--lib/ansible/modules/cloud/openstack/os_listener.py256
-rw-r--r--lib/ansible/modules/cloud/openstack/os_loadbalancer.py605
-rw-r--r--lib/ansible/modules/cloud/openstack/os_member.py227
-rw-r--r--lib/ansible/modules/cloud/openstack/os_network.py255
-rw-r--r--lib/ansible/modules/cloud/openstack/os_networks_info.py157
-rw-r--r--lib/ansible/modules/cloud/openstack/os_nova_flavor.py273
-rw-r--r--lib/ansible/modules/cloud/openstack/os_nova_host_aggregate.py182
-rw-r--r--lib/ansible/modules/cloud/openstack/os_object.py125
-rw-r--r--lib/ansible/modules/cloud/openstack/os_pool.py267
-rw-r--r--lib/ansible/modules/cloud/openstack/os_port.py441
-rw-r--r--lib/ansible/modules/cloud/openstack/os_port_info.py224
-rw-r--r--lib/ansible/modules/cloud/openstack/os_project.py211
-rw-r--r--lib/ansible/modules/cloud/openstack/os_project_access.py199
-rw-r--r--lib/ansible/modules/cloud/openstack/os_project_info.py166
-rw-r--r--lib/ansible/modules/cloud/openstack/os_quota.py463
-rw-r--r--lib/ansible/modules/cloud/openstack/os_recordset.py236
-rw-r--r--lib/ansible/modules/cloud/openstack/os_router.py487
-rw-r--r--lib/ansible/modules/cloud/openstack/os_security_group.py163
-rw-r--r--lib/ansible/modules/cloud/openstack/os_security_group_rule.py385
-rw-r--r--lib/ansible/modules/cloud/openstack/os_server.py852
-rw-r--r--lib/ansible/modules/cloud/openstack/os_server_action.py247
-rw-r--r--lib/ansible/modules/cloud/openstack/os_server_group.py172
-rw-r--r--lib/ansible/modules/cloud/openstack/os_server_info.py115
-rw-r--r--lib/ansible/modules/cloud/openstack/os_server_metadata.py171
-rw-r--r--lib/ansible/modules/cloud/openstack/os_server_volume.py146
-rw-r--r--lib/ansible/modules/cloud/openstack/os_stack.py278
-rw-r--r--lib/ansible/modules/cloud/openstack/os_subnet.py360
-rw-r--r--lib/ansible/modules/cloud/openstack/os_subnets_info.py173
-rw-r--r--lib/ansible/modules/cloud/openstack/os_user.py296
-rw-r--r--lib/ansible/modules/cloud/openstack/os_user_group.py107
-rw-r--r--lib/ansible/modules/cloud/openstack/os_user_info.py174
-rw-r--r--lib/ansible/modules/cloud/openstack/os_user_role.py200
-rw-r--r--lib/ansible/modules/cloud/openstack/os_volume.py264
-rw-r--r--lib/ansible/modules/cloud/openstack/os_volume_snapshot.py178
-rw-r--r--lib/ansible/modules/cloud/openstack/os_zone.py243
-rw-r--r--lib/ansible/plugins/doc_fragments/openstack.py101
-rw-r--r--lib/ansible/plugins/inventory/openstack.py344
-rw-r--r--test/sanity/ignore.txt138
-rw-r--r--test/units/modules/cloud/openstack/test_os_server.py228
-rw-r--r--test/units/plugins/inventory/test_openstack.py90
60 files changed, 0 insertions, 14290 deletions
diff --git a/lib/ansible/module_utils/openstack.py b/lib/ansible/module_utils/openstack.py
deleted file mode 100644
index 87570c6b71..0000000000
--- a/lib/ansible/module_utils/openstack.py
+++ /dev/null
@@ -1,163 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-import os
-
-from ansible.module_utils.six import iteritems
-
-
-def openstack_argument_spec():
- # DEPRECATED: This argument spec is only used for the deprecated old
- # OpenStack modules. It turns out that modern OpenStack auth is WAY
- # more complex than this.
- # Consume standard OpenStack environment variables.
- # This is mainly only useful for ad-hoc command line operation as
- # in playbooks one would assume variables would be used appropriately
- OS_AUTH_URL = os.environ.get('OS_AUTH_URL', 'http://127.0.0.1:35357/v2.0/')
- OS_PASSWORD = os.environ.get('OS_PASSWORD', None)
- OS_REGION_NAME = os.environ.get('OS_REGION_NAME', None)
- OS_USERNAME = os.environ.get('OS_USERNAME', 'admin')
- OS_TENANT_NAME = os.environ.get('OS_TENANT_NAME', OS_USERNAME)
-
- spec = dict(
- login_username=dict(default=OS_USERNAME),
- auth_url=dict(default=OS_AUTH_URL),
- region_name=dict(default=OS_REGION_NAME),
- availability_zone=dict(),
- )
- if OS_PASSWORD:
- spec['login_password'] = dict(default=OS_PASSWORD)
- else:
- spec['login_password'] = dict(required=True)
- if OS_TENANT_NAME:
- spec['login_tenant_name'] = dict(default=OS_TENANT_NAME)
- else:
- spec['login_tenant_name'] = dict(required=True)
- return spec
-
-
-def openstack_find_nova_addresses(addresses, ext_tag, key_name=None):
-
- ret = []
- for (k, v) in iteritems(addresses):
- if key_name and k == key_name:
- ret.extend([addrs['addr'] for addrs in v])
- else:
- for interface_spec in v:
- if 'OS-EXT-IPS:type' in interface_spec and interface_spec['OS-EXT-IPS:type'] == ext_tag:
- ret.append(interface_spec['addr'])
- return ret
-
-
-def openstack_full_argument_spec(**kwargs):
- spec = dict(
- cloud=dict(default=None, type='raw'),
- auth_type=dict(default=None),
- auth=dict(default=None, type='dict', no_log=True),
- region_name=dict(default=None),
- availability_zone=dict(default=None),
- validate_certs=dict(default=None, type='bool', aliases=['verify']),
- ca_cert=dict(default=None, aliases=['cacert']),
- client_cert=dict(default=None, aliases=['cert']),
- client_key=dict(default=None, no_log=True, aliases=['key']),
- wait=dict(default=True, type='bool'),
- timeout=dict(default=180, type='int'),
- api_timeout=dict(default=None, type='int'),
- interface=dict(
- default='public', choices=['public', 'internal', 'admin'],
- aliases=['endpoint_type']),
- )
- spec.update(kwargs)
- return spec
-
-
-def openstack_module_kwargs(**kwargs):
- ret = {}
- for key in ('mutually_exclusive', 'required_together', 'required_one_of'):
- if key in kwargs:
- if key in ret:
- ret[key].extend(kwargs[key])
- else:
- ret[key] = kwargs[key]
-
- return ret
-
-
-def openstack_cloud_from_module(module, min_version='0.12.0'):
- from distutils.version import StrictVersion
- try:
- # Due to the name shadowing we should import other way
- import importlib
- sdk = importlib.import_module('openstack')
- sdk_version = importlib.import_module('openstack.version')
- except ImportError:
- module.fail_json(msg='openstacksdk is required for this module')
-
- if min_version:
- min_version = max(StrictVersion('0.12.0'), StrictVersion(min_version))
- else:
- min_version = StrictVersion('0.12.0')
-
- if StrictVersion(sdk_version.__version__) < min_version:
- module.fail_json(
- msg="To utilize this module, the installed version of "
- "the openstacksdk library MUST be >={min_version}.".format(
- min_version=min_version))
-
- cloud_config = module.params.pop('cloud', None)
- 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', 'validate_certs',
- 'ca_cert', 'client_key', 'api_timeout', 'auth_type'):
- if module.params[param] is not None:
- module.fail_json(msg=fail_message.format(param=param))
- # For 'interface' parameter, fail if we receive a non-default value
- if module.params['interface'] != 'public':
- module.fail_json(msg=fail_message.format(param='interface'))
- 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['validate_certs'],
- cacert=module.params['ca_cert'],
- key=module.params['client_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/os_auth.py b/lib/ansible/modules/cloud/openstack/os_auth.py
deleted file mode 100644
index 0f86ab103e..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_auth.py
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_auth
-short_description: Retrieve an auth token
-version_added: "2.0"
-author: "Monty Taylor (@emonty)"
-description:
- - Retrieve an auth token from an OpenStack Cloud
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-options:
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
- required: false
-extends_documentation_fragment: openstack
-'''
-
-EXAMPLES = '''
-- name: Authenticate to the cloud and retrieve the service catalog
- os_auth:
- cloud: rax-dfw
-
-- name: Show service catalog
- debug:
- var: service_catalog
-'''
-
-RETURN = '''
-auth_token:
- description: Openstack API Auth Token
- returned: success
- type: str
-service_catalog:
- description: A dictionary of available API endpoints
- returned: success
- type: dict
-'''
-
-import traceback
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def main():
-
- argument_spec = openstack_full_argument_spec()
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec, **module_kwargs)
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- module.exit_json(
- changed=False,
- ansible_facts=dict(
- auth_token=cloud.auth_token,
- service_catalog=cloud.service_catalog))
- except Exception as e:
- module.fail_json(msg=str(e), exception=traceback.format_exc())
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_client_config.py b/lib/ansible/modules/cloud/openstack/os_client_config.py
deleted file mode 100644
index a8f8f69e5f..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_client_config.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_client_config
-short_description: Get OpenStack Client config
-description:
- - Get I(openstack) client config data from clouds.yaml or environment
-version_added: "2.0"
-notes:
- - Facts are placed in the C(openstack.clouds) variable.
-options:
- clouds:
- description:
- - List of clouds to limit the return list to. No value means return
- information on all configured clouds
- required: false
- default: []
-requirements: [ os-client-config ]
-author: "Monty Taylor (@emonty)"
-'''
-
-EXAMPLES = '''
-- name: Get list of clouds that do not support security groups
- os_client_config:
-
-- debug:
- var: "{{ item }}"
- with_items: "{{ openstack.clouds | rejectattr('secgroup_source', 'none') | list }}"
-
-- name: Get the information back just about the mordred cloud
- os_client_config:
- clouds:
- - mordred
-'''
-
-try:
- import os_client_config
- from os_client_config import exceptions
- HAS_OS_CLIENT_CONFIG = True
-except ImportError:
- HAS_OS_CLIENT_CONFIG = False
-
-from ansible.module_utils.basic import AnsibleModule
-
-
-def main():
- module = AnsibleModule(argument_spec=dict(
- clouds=dict(required=False, type='list', default=[]),
- ))
-
- if not HAS_OS_CLIENT_CONFIG:
- module.fail_json(msg='os-client-config is required for this module')
-
- p = module.params
-
- try:
- config = os_client_config.OpenStackConfig()
- clouds = []
- for cloud in config.get_all_clouds():
- if not p['clouds'] or cloud.name in p['clouds']:
- cloud.config['name'] = cloud.name
- clouds.append(cloud.config)
- module.exit_json(ansible_facts=dict(openstack=dict(clouds=clouds)))
- except exceptions.OpenStackConfigException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == "__main__":
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_coe_cluster.py b/lib/ansible/modules/cloud/openstack/os_coe_cluster.py
deleted file mode 100644
index 26e3a18aeb..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_coe_cluster.py
+++ /dev/null
@@ -1,282 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2018 Catalyst IT Ltd.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_coe_cluster
-short_description: Add/Remove COE cluster from OpenStack Cloud
-extends_documentation_fragment: openstack
-version_added: "2.8"
-author: "Feilong Wang (@flwang)"
-description:
- - Add or Remove COE cluster from the OpenStack Container Infra service.
-options:
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
- cluster_template_id:
- description:
- - The template ID of cluster template.
- required: true
- discovery_url:
- description:
- - Url used for cluster node discovery
- docker_volume_size:
- description:
- - The size in GB of the docker volume
- flavor_id:
- description:
- - The flavor of the minion node for this ClusterTemplate
- keypair:
- description:
- - Name of the keypair to use.
- labels:
- description:
- - One or more key/value pairs
- master_flavor_id:
- description:
- - The flavor of the master node for this ClusterTemplate
- master_count:
- description:
- - The number of master nodes for this cluster
- default: 1
- name:
- description:
- - Name that has to be given to the cluster template
- required: true
- node_count:
- description:
- - The number of nodes for this cluster
- default: 1
- state:
- description:
- - Indicate desired state of the resource.
- choices: [present, absent]
- default: present
- timeout:
- description:
- - Timeout for creating the cluster in minutes. Default to 60 mins
- if not set
- default: 60
-requirements: ["openstacksdk"]
-'''
-
-RETURN = '''
-id:
- description: The cluster UUID.
- returned: On success when I(state) is 'present'
- type: str
- sample: "39007a7e-ee4f-4d13-8283-b4da2e037c69"
-cluster:
- description: Dictionary describing the cluster.
- returned: On success when I(state) is 'present'
- type: complex
- contains:
- api_address:
- description:
- - Api address of cluster master node
- type: str
- sample: https://172.24.4.30:6443
- cluster_template_id:
- description: The cluster_template UUID
- type: str
- sample: '7b1418c8-cea8-48fc-995d-52b66af9a9aa'
- coe_version:
- description:
- - Version of the COE software currently running in this cluster
- type: str
- sample: v1.11.1
- container_version:
- description:
- - "Version of the container software. Example: docker version."
- type: str
- sample: 1.12.6
- created_at:
- description:
- - The time in UTC at which the cluster is created
- type: str
- sample: "2018-08-16T10:29:45+00:00"
- create_timeout:
- description:
- - Timeout for creating the cluster in minutes. Default to 60 if
- not set.
- type: int
- sample: 60
- discovery_url:
- description:
- - Url used for cluster node discovery
- type: str
- sample: https://discovery.etcd.io/a42ee38e7113f31f4d6324f24367aae5
- faults:
- description:
- - Fault info collected from the Heat resources of this cluster
- type: dict
- sample: {'0': 'ResourceInError: resources[0].resources...'}
- flavor_id:
- description:
- - The flavor of the minion node for this cluster
- type: str
- sample: c1.c1r1
- keypair:
- description:
- - Name of the keypair to use.
- type: str
- sample: mykey
- labels:
- description: One or more key/value pairs
- type: dict
- sample: {'key1': 'value1', 'key2': 'value2'}
- master_addresses:
- description:
- - IP addresses of cluster master nodes
- type: list
- sample: ['172.24.4.5']
- master_count:
- description:
- - The number of master nodes for this cluster.
- type: int
- sample: 1
- master_flavor_id:
- description:
- - The flavor of the master node for this cluster
- type: str
- sample: c1.c1r1
- name:
- description:
- - Name that has to be given to the cluster
- type: str
- sample: k8scluster
- node_addresses:
- description:
- - IP addresses of cluster slave nodes
- type: list
- sample: ['172.24.4.8']
- node_count:
- description:
- - The number of master nodes for this cluster.
- type: int
- sample: 1
- stack_id:
- description:
- - Stack id of the Heat stack
- type: str
- sample: '07767ec6-85f5-44cb-bd63-242a8e7f0d9d'
- status:
- description: Status of the cluster from the heat stack
- type: str
- sample: 'CREATE_COMLETE'
- status_reason:
- description:
- - Status reason of the cluster from the heat stack
- type: str
- sample: 'Stack CREATE completed successfully'
- updated_at:
- description:
- - The time in UTC at which the cluster is updated
- type: str
- sample: '2018-08-16T10:39:25+00:00'
- uuid:
- description:
- - Unique UUID for this cluster
- type: str
- sample: '86246a4d-a16c-4a58-9e96ad7719fe0f9d'
-'''
-
-EXAMPLES = '''
-# Create a new Kubernetes cluster
-- os_coe_cluster:
- name: k8s
- cluster_template_id: k8s-ha
- keypair: mykey
- master_count: 3
- node_count: 5
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _parse_labels(labels):
- if isinstance(labels, str):
- labels_dict = {}
- for kv_str in labels.split(","):
- k, v = kv_str.split("=")
- labels_dict[k] = v
- return labels_dict
- if not labels:
- return {}
- return labels
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- cluster_template_id=dict(required=True),
- discovery_url=dict(default=None),
- docker_volume_size=dict(type='int'),
- flavor_id=dict(default=None),
- keypair=dict(default=None),
- labels=dict(default=None, type='raw'),
- master_count=dict(type='int', default=1),
- master_flavor_id=dict(default=None),
- name=dict(required=True),
- node_count=dict(type='int', default=1),
- state=dict(default='present', choices=['absent', 'present']),
- timeout=dict(type='int', default=60),
- )
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec, **module_kwargs)
-
- params = module.params.copy()
-
- state = module.params['state']
- name = module.params['name']
- cluster_template_id = module.params['cluster_template_id']
-
- kwargs = dict(
- discovery_url=module.params['discovery_url'],
- docker_volume_size=module.params['docker_volume_size'],
- flavor_id=module.params['flavor_id'],
- keypair=module.params['keypair'],
- labels=_parse_labels(params['labels']),
- master_count=module.params['master_count'],
- master_flavor_id=module.params['master_flavor_id'],
- node_count=module.params['node_count'],
- create_timeout=module.params['timeout'],
- )
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- changed = False
- cluster = cloud.get_coe_cluster(name_or_id=name, filters={'cluster_template_id': cluster_template_id})
-
- if state == 'present':
- if not cluster:
- cluster = cloud.create_coe_cluster(name, cluster_template_id=cluster_template_id, **kwargs)
- changed = True
- else:
- changed = False
-
- module.exit_json(changed=changed, cluster=cluster, id=cluster['uuid'])
- elif state == 'absent':
- if not cluster:
- module.exit_json(changed=False)
- else:
- cloud.delete_coe_cluster(name)
- module.exit_json(changed=True)
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e), extra_data=e.extra_data)
-
-
-if __name__ == "__main__":
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_coe_cluster_template.py b/lib/ansible/modules/cloud/openstack/os_coe_cluster_template.py
deleted file mode 100644
index 75121f0afa..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_coe_cluster_template.py
+++ /dev/null
@@ -1,373 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2018 Catalyst IT Ltd.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_coe_cluster_template
-short_description: Add/Remove COE cluster template from OpenStack Cloud
-extends_documentation_fragment: openstack
-version_added: "2.7"
-author: "Feilong Wang (@flwang)"
-description:
- - Add or Remove COE cluster template from the OpenStack Container Infra
- service.
-options:
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
- coe:
- description:
- - The Container Orchestration Engine for this clustertemplate
- choices: [kubernetes, swarm, mesos]
- dns_nameserver:
- description:
- - The DNS nameserver address
- default: '8.8.8.8'
- docker_storage_driver:
- description:
- - Docker storage driver
- choices: [devicemapper, overlay, overlay2]
- docker_volume_size:
- description:
- - The size in GB of the docker volume
- external_network_id:
- description:
- - The external network to attach to the Cluster
- fixed_network:
- description:
- - The fixed network name to attach to the Cluster
- fixed_subnet:
- description:
- - The fixed subnet name to attach to the Cluster
- flavor_id:
- description:
- - The flavor of the minion node for this ClusterTemplate
- floating_ip_enabled:
- description:
- - Indicates whether created clusters should have a floating ip or not
- type: bool
- default: 'yes'
- keypair_id:
- description:
- - Name or ID of the keypair to use.
- image_id:
- description:
- - Image id the cluster will be based on
- labels:
- description:
- - One or more key/value pairs wrapped in string
- http_proxy:
- description:
- - Address of a proxy that will receive all HTTP requests and relay them
- The format is a URL including a port number
- https_proxy:
- description:
- - Address of a proxy that will receive all HTTPS requests and relay
- them. The format is a URL including a port number
- master_flavor_id:
- description:
- - The flavor of the master node for this ClusterTemplate
- master_lb_enabled:
- description:
- - Indicates whether created clusters should have a load balancer
- for master nodes or not
- type: bool
- default: 'no'
- name:
- description:
- - Name that has to be given to the cluster template
- required: true
- network_driver:
- description:
- - The name of the driver used for instantiating container networks
- choices: [flannel, calico, docker]
- no_proxy:
- description:
- - A comma separated list of IPs for which proxies should not be
- used in the cluster
- public:
- description:
- - Indicates whether the ClusterTemplate is public or not
- type: bool
- default: 'no'
- registry_enabled:
- description:
- - Indicates whether the docker registry is enabled
- type: bool
- default: 'no'
- server_type:
- description:
- - Server type for this ClusterTemplate
- choices: [vm, bm]
- default: vm
- state:
- description:
- - Indicate desired state of the resource.
- choices: [present, absent]
- default: present
- tls_disabled:
- description:
- - Indicates whether the TLS should be disabled
- type: bool
- default: 'no'
- volume_driver:
- description:
- - The name of the driver used for instantiating container volumes
- choices: [cinder, rexray]
-requirements: ["openstacksdk"]
-'''
-
-RETURN = '''
-id:
- description: The cluster UUID.
- returned: On success when I(state) is 'present'
- type: str
- sample: "39007a7e-ee4f-4d13-8283-b4da2e037c69"
-cluster_template:
- description: Dictionary describing the template.
- returned: On success when I(state) is 'present'
- type: complex
- contains:
- coe:
- description: The Container Orchestration Engine for this clustertemplate
- type: str
- sample: kubernetes
- dns_nameserver:
- description: The DNS nameserver address
- type: str
- sample: '8.8.8.8'
- docker_storage_driver:
- description: Docker storage driver
- type: str
- sample: devicemapper
- docker_volume_size:
- description: The size in GB of the docker volume
- type: int
- sample: 5
- external_network_id:
- description: The external network to attach to the Cluster
- type: str
- sample: public
- fixed_network:
- description: The fixed network name to attach to the Cluster
- type: str
- sample: 07767ec6-85f5-44cb-bd63-242a8e7f0d9d
- fixed_subnet:
- description:
- - The fixed subnet name to attach to the Cluster
- type: str
- sample: 05567ec6-85f5-44cb-bd63-242a8e7f0d9d
- flavor_id:
- description:
- - The flavor of the minion node for this ClusterTemplate
- type: str
- sample: c1.c1r1
- floating_ip_enabled:
- description:
- - Indicates whether created clusters should have a floating ip or not
- type: bool
- sample: true
- keypair_id:
- description:
- - Name or ID of the keypair to use.
- type: str
- sample: mykey
- image_id:
- description:
- - Image id the cluster will be based on
- type: str
- sample: 05567ec6-85f5-44cb-bd63-242a8e7f0e9d
- labels:
- description: One or more key/value pairs wrapped in string
- type: str
- sample: 'key1=value1, key2=value2'
- http_proxy:
- description:
- - Address of a proxy that will receive all HTTP requests and relay them
- The format is a URL including a port number
- type: str
- sample: http://10.0.0.11:9090
- https_proxy:
- description:
- - Address of a proxy that will receive all HTTPS requests and relay
- them. The format is a URL including a port number
- type: str
- sample: https://10.0.0.10:8443
- master_flavor_id:
- description:
- - The flavor of the master node for this ClusterTemplate
- type: str
- sample: c1.c1r1
- master_lb_enabled:
- description:
- - Indicates whether created clusters should have a load balancer
- for master nodes or not
- type: bool
- sample: true
- name:
- description:
- - Name that has to be given to the cluster template
- type: str
- sample: k8scluster
- network_driver:
- description:
- - The name of the driver used for instantiating container networks
- type: str
- sample: calico
- no_proxy:
- description:
- - A comma separated list of IPs for which proxies should not be
- used in the cluster
- type: str
- sample: 10.0.0.4,10.0.0.5
- public:
- description:
- - Indicates whether the ClusterTemplate is public or not
- type: bool
- sample: false
- registry_enabled:
- description:
- - Indicates whether the docker registry is enabled
- type: bool
- sample: false
- server_type:
- description:
- - Server type for this ClusterTemplate
- type: str
- sample: vm
- tls_disabled:
- description:
- - Indicates whether the TLS should be disabled
- type: bool
- sample: false
- volume_driver:
- description:
- - The name of the driver used for instantiating container volumes
- type: str
- sample: cinder
-'''
-
-EXAMPLES = '''
-# Create a new Kubernetes cluster template
-- os_coe_cluster_template:
- name: k8s
- coe: kubernetes
- keypair_id: mykey
- image_id: 2a8c9888-9054-4b06-a1ca-2bb61f9adb72
- public: no
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _parse_labels(labels):
- if isinstance(labels, str):
- labels_dict = {}
- for kv_str in labels.split(","):
- k, v = kv_str.split("=")
- labels_dict[k.strip()] = v.strip()
- return labels_dict
- if not labels:
- return {}
- return labels
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- coe=dict(required=True, choices=['kubernetes', 'swarm', 'mesos']),
- dns_nameserver=dict(default='8.8.8.8'),
- docker_storage_driver=dict(choices=['devicemapper', 'overlay', 'overlay2']),
- docker_volume_size=dict(type='int'),
- external_network_id=dict(default=None),
- fixed_network=dict(default=None),
- fixed_subnet=dict(default=None),
- flavor_id=dict(default=None),
- floating_ip_enabled=dict(type='bool', default=True),
- keypair_id=dict(default=None),
- image_id=dict(required=True),
- labels=dict(default=None, type='raw'),
- http_proxy=dict(default=None),
- https_proxy=dict(default=None),
- master_lb_enabled=dict(type='bool', default=False),
- master_flavor_id=dict(default=None),
- name=dict(required=True),
- network_driver=dict(choices=['flannel', 'calico', 'docker']),
- no_proxy=dict(default=None),
- public=dict(type='bool', default=False),
- registry_enabled=dict(type='bool', default=False),
- server_type=dict(default="vm", choices=['vm', 'bm']),
- state=dict(default='present', choices=['absent', 'present']),
- tls_disabled=dict(type='bool', default=False),
- volume_driver=dict(choices=['cinder', 'rexray']),
- )
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec, **module_kwargs)
-
- params = module.params.copy()
-
- state = module.params['state']
- name = module.params['name']
- coe = module.params['coe']
- image_id = module.params['image_id']
-
- kwargs = dict(
- dns_nameserver=module.params['dns_nameserver'],
- docker_storage_driver=module.params['docker_storage_driver'],
- docker_volume_size=module.params['docker_volume_size'],
- external_network_id=module.params['external_network_id'],
- fixed_network=module.params['fixed_network'],
- fixed_subnet=module.params['fixed_subnet'],
- flavor_id=module.params['flavor_id'],
- floating_ip_enabled=module.params['floating_ip_enabled'],
- keypair_id=module.params['keypair_id'],
- labels=_parse_labels(params['labels']),
- http_proxy=module.params['http_proxy'],
- https_proxy=module.params['https_proxy'],
- master_lb_enabled=module.params['master_lb_enabled'],
- master_flavor_id=module.params['master_flavor_id'],
- network_driver=module.params['network_driver'],
- no_proxy=module.params['no_proxy'],
- public=module.params['public'],
- registry_enabled=module.params['registry_enabled'],
- server_type=module.params['server_type'],
- tls_disabled=module.params['tls_disabled'],
- volume_driver=module.params['volume_driver'],
- )
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- changed = False
- template = cloud.get_coe_cluster_template(name_or_id=name, filters={'coe': coe, 'image_id': image_id})
-
- if state == 'present':
- if not template:
- template = cloud.create_coe_cluster_template(name, coe=coe, image_id=image_id, **kwargs)
- changed = True
- else:
- changed = False
-
- module.exit_json(changed=changed, cluster_template=template, id=template['uuid'])
- elif state == 'absent':
- if not template:
- module.exit_json(changed=False)
- else:
- cloud.delete_coe_cluster_template(name)
- module.exit_json(changed=True)
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e), extra_data=e.extra_data)
-
-
-if __name__ == "__main__":
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_flavor_info.py b/lib/ansible/modules/cloud/openstack/os_flavor_info.py
deleted file mode 100644
index 3919cde8b0..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_flavor_info.py
+++ /dev/null
@@ -1,238 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2015 IBM
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: os_flavor_info
-short_description: Retrieve information about one or more flavors
-author: "David Shrewsbury (@Shrews)"
-version_added: "2.1"
-description:
- - Retrieve information about available OpenStack instance flavors. By default,
- information about ALL flavors are retrieved. Filters can be applied to get
- information for only matching flavors. For example, you can filter on the
- amount of RAM available to the flavor, or the number of virtual CPUs
- available to the flavor, or both. When specifying multiple filters,
- *ALL* filters must match on a flavor before that flavor is returned as
- a fact.
- - This module was called C(os_flavor_facts) before Ansible 2.9, returning C(ansible_facts).
- Note that the M(os_flavor_info) module no longer returns C(ansible_facts)!
-notes:
- - The result contains a list of unsorted flavors.
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-options:
- name:
- description:
- - A flavor name. Cannot be used with I(ram) or I(vcpus) or I(ephemeral).
- ram:
- description:
- - "A string used for filtering flavors based on the amount of RAM
- (in MB) desired. This string accepts the following special values:
- 'MIN' (return flavors with the minimum amount of RAM), and 'MAX'
- (return flavors with the maximum amount of RAM)."
-
- - "A specific amount of RAM may also be specified. Any flavors with this
- exact amount of RAM will be returned."
-
- - "A range of acceptable RAM may be given using a special syntax. Simply
- prefix the amount of RAM with one of these acceptable range values:
- '<', '>', '<=', '>='. These values represent less than, greater than,
- less than or equal to, and greater than or equal to, respectively."
- type: bool
- default: 'no'
- vcpus:
- description:
- - A string used for filtering flavors based on the number of virtual
- CPUs desired. Format is the same as the I(ram) parameter.
- type: bool
- default: 'no'
- limit:
- description:
- - Limits the number of flavors returned. All matching flavors are
- returned by default.
- ephemeral:
- description:
- - A string used for filtering flavors based on the amount of ephemeral
- storage. Format is the same as the I(ram) parameter
- type: bool
- default: 'no'
- version_added: "2.3"
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-extends_documentation_fragment: openstack
-'''
-
-EXAMPLES = '''
-# Gather information about all available flavors
-- os_flavor_info:
- cloud: mycloud
- register: result
-
-- debug:
- msg: "{{ result.openstack_flavors }}"
-
-# Gather information for the flavor named "xlarge-flavor"
-- os_flavor_info:
- cloud: mycloud
- name: "xlarge-flavor"
-
-# Get all flavors that have exactly 512 MB of RAM.
-- os_flavor_info:
- cloud: mycloud
- ram: "512"
-
-# Get all flavors that have 1024 MB or more of RAM.
-- os_flavor_info:
- cloud: mycloud
- ram: ">=1024"
-
-# Get a single flavor that has the minimum amount of RAM. Using the 'limit'
-# option will guarantee only a single flavor is returned.
-- os_flavor_info:
- cloud: mycloud
- ram: "MIN"
- limit: 1
-
-# Get all flavors with 1024 MB of RAM or more, AND exactly 2 virtual CPUs.
-- os_flavor_info:
- cloud: mycloud
- ram: ">=1024"
- vcpus: "2"
-
-# Get all flavors with 1024 MB of RAM or more, exactly 2 virtual CPUs, and
-# less than 30gb of ephemeral storage.
-- os_flavor_info:
- cloud: mycloud
- ram: ">=1024"
- vcpus: "2"
- ephemeral: "<30"
-'''
-
-
-RETURN = '''
-openstack_flavors:
- description: Dictionary describing the flavors.
- returned: On success.
- type: complex
- contains:
- id:
- description: Flavor ID.
- returned: success
- type: str
- sample: "515256b8-7027-4d73-aa54-4e30a4a4a339"
- name:
- description: Flavor name.
- returned: success
- type: str
- sample: "tiny"
- disk:
- description: Size of local disk, in GB.
- returned: success
- type: int
- sample: 10
- ephemeral:
- description: Ephemeral space size, in GB.
- returned: success
- type: int
- sample: 10
- ram:
- description: Amount of memory, in MB.
- returned: success
- type: int
- sample: 1024
- swap:
- description: Swap space size, in MB.
- returned: success
- type: int
- sample: 100
- vcpus:
- description: Number of virtual CPUs.
- returned: success
- type: int
- sample: 2
- is_public:
- description: Make flavor accessible to the public.
- returned: success
- type: bool
- sample: true
-'''
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- name=dict(required=False, default=None),
- ram=dict(required=False, default=None),
- vcpus=dict(required=False, default=None),
- limit=dict(required=False, default=None, type='int'),
- ephemeral=dict(required=False, default=None),
- )
- module_kwargs = openstack_module_kwargs(
- mutually_exclusive=[
- ['name', 'ram'],
- ['name', 'vcpus'],
- ['name', 'ephemeral']
- ]
- )
- module = AnsibleModule(argument_spec, **module_kwargs)
- is_old_facts = module._name == 'os_flavor_facts'
- if is_old_facts:
- module.deprecate("The 'os_flavor_facts' module has been renamed to 'os_flavor_info', "
- "and the renamed one no longer returns ansible_facts", version='2.13')
-
- name = module.params['name']
- vcpus = module.params['vcpus']
- ram = module.params['ram']
- ephemeral = module.params['ephemeral']
- limit = module.params['limit']
-
- filters = {}
- if vcpus:
- filters['vcpus'] = vcpus
- if ram:
- filters['ram'] = ram
- if ephemeral:
- filters['ephemeral'] = ephemeral
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- if name:
- flavors = cloud.search_flavors(filters={'name': name})
-
- else:
- flavors = cloud.list_flavors()
- if filters:
- flavors = cloud.range_search(flavors, filters)
-
- if limit is not None:
- flavors = flavors[:limit]
-
- if is_old_facts:
- module.exit_json(changed=False,
- ansible_facts=dict(openstack_flavors=flavors))
- else:
- module.exit_json(changed=False,
- openstack_flavors=flavors)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_floating_ip.py b/lib/ansible/modules/cloud/openstack/os_floating_ip.py
deleted file mode 100644
index b11048599e..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_floating_ip.py
+++ /dev/null
@@ -1,255 +0,0 @@
-#!/usr/bin/python
-
-# Copyright: (c) 2015, Hewlett-Packard Development Company, L.P.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_floating_ip
-version_added: "2.0"
-author: Davide Guerri (@dguerri) <davide.guerri@hp.com>
-short_description: Add/Remove floating IP from an instance
-extends_documentation_fragment: openstack
-description:
- - Add or Remove a floating IP to an instance.
- - Returns the floating IP when attaching only if I(wait=true).
-options:
- server:
- description:
- - The name or ID of the instance to which the IP address
- should be assigned.
- required: true
- network:
- description:
- - The name or ID of a neutron external network or a nova pool name.
- floating_ip_address:
- description:
- - A floating IP address to attach or to detach. Required only if I(state)
- is absent. When I(state) is present can be used to specify a IP address
- to attach.
- reuse:
- description:
- - When I(state) is present, and I(floating_ip_address) is not present,
- this parameter can be used to specify whether we should try to reuse
- a floating IP address already allocated to the project.
- type: bool
- default: 'no'
- fixed_address:
- description:
- - To which fixed IP of server the floating IP address should be
- attached to.
- nat_destination:
- description:
- - The name or id of a neutron private network that the fixed IP to
- attach floating IP is on
- aliases: ["fixed_network", "internal_network"]
- version_added: "2.3"
- wait:
- description:
- - When attaching a floating IP address, specify whether to wait for it to appear as attached.
- - Must be set to C(yes) for the module to return the value of the floating IP.
- type: bool
- default: 'no'
- timeout:
- description:
- - Time to wait for an IP address to appear as attached. See wait.
- required: false
- default: 60
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- purge:
- description:
- - When I(state) is absent, indicates whether or not to delete the floating
- IP completely, or only detach it from the server. Default is to detach only.
- type: bool
- default: 'no'
- version_added: "2.1"
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-requirements: ["openstacksdk"]
-'''
-
-EXAMPLES = '''
-# Assign a floating IP to the fist interface of `cattle001` from an exiting
-# external network or nova pool. A new floating IP from the first available
-# external network is allocated to the project.
-- os_floating_ip:
- cloud: dguerri
- server: cattle001
-
-# Assign a new floating IP to the instance fixed ip `192.0.2.3` of
-# `cattle001`. If a free floating IP is already allocated to the project, it is
-# reused; if not, a new one is created.
-- os_floating_ip:
- cloud: dguerri
- state: present
- reuse: yes
- server: cattle001
- network: ext_net
- fixed_address: 192.0.2.3
- wait: true
- timeout: 180
-
-# Assign a new floating IP from the network `ext_net` to the instance fixed
-# ip in network `private_net` of `cattle001`.
-- os_floating_ip:
- cloud: dguerri
- state: present
- server: cattle001
- network: ext_net
- nat_destination: private_net
- wait: true
- timeout: 180
-
-# Detach a floating IP address from a server
-- os_floating_ip:
- cloud: dguerri
- state: absent
- floating_ip_address: 203.0.113.2
- server: cattle001
-'''
-
-from ansible.module_utils.basic import AnsibleModule, remove_values
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _get_floating_ip(cloud, floating_ip_address):
- f_ips = cloud.search_floating_ips(
- filters={'floating_ip_address': floating_ip_address})
- if not f_ips:
- return None
-
- return f_ips[0]
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- server=dict(required=True),
- state=dict(default='present', choices=['absent', 'present']),
- network=dict(required=False, default=None),
- floating_ip_address=dict(required=False, default=None),
- reuse=dict(required=False, type='bool', default=False),
- fixed_address=dict(required=False, default=None),
- nat_destination=dict(required=False, default=None,
- aliases=['fixed_network', 'internal_network']),
- wait=dict(required=False, type='bool', default=False),
- timeout=dict(required=False, type='int', default=60),
- purge=dict(required=False, type='bool', default=False),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec, **module_kwargs)
-
- server_name_or_id = module.params['server']
- state = module.params['state']
- network = module.params['network']
- floating_ip_address = module.params['floating_ip_address']
- reuse = module.params['reuse']
- fixed_address = module.params['fixed_address']
- nat_destination = module.params['nat_destination']
- wait = module.params['wait']
- timeout = module.params['timeout']
- purge = module.params['purge']
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
-
- server = cloud.get_server(server_name_or_id)
- if server is None:
- module.fail_json(
- msg="server {0} not found".format(server_name_or_id))
-
- if state == 'present':
- # If f_ip already assigned to server, check that it matches
- # requirements.
- public_ip = cloud.get_server_public_ip(server)
- f_ip = _get_floating_ip(cloud, public_ip) if public_ip else public_ip
- if f_ip:
- if network:
- network_id = cloud.get_network(name_or_id=network)["id"]
- else:
- network_id = None
- # check if we have floating ip on given nat_destination network
- if nat_destination:
- nat_floating_addrs = [addr for addr in server.addresses.get(
- cloud.get_network(nat_destination)['name'], [])
- if addr['addr'] == public_ip and
- addr['OS-EXT-IPS:type'] == 'floating']
-
- if len(nat_floating_addrs) == 0:
- module.fail_json(msg="server {server} already has a "
- "floating-ip on a different "
- "nat-destination than '{nat_destination}'"
- .format(server=server_name_or_id,
- nat_destination=nat_destination))
-
- if all([fixed_address, f_ip.fixed_ip_address == fixed_address,
- network, f_ip.network != network_id]):
- # Current state definitely conflicts with requirements
- module.fail_json(msg="server {server} already has a "
- "floating-ip on requested "
- "interface but it doesn't match "
- "requested network {network}: {fip}"
- .format(server=server_name_or_id,
- network=network,
- fip=remove_values(f_ip,
- module.no_log_values)))
- if not network or f_ip.network == network_id:
- # Requirements are met
- module.exit_json(changed=False, floating_ip=f_ip)
-
- # Requirements are vague enough to ignore existing f_ip and try
- # to create a new f_ip to the server.
-
- server = cloud.add_ips_to_server(
- server=server, ips=floating_ip_address, ip_pool=network,
- reuse=reuse, fixed_address=fixed_address, wait=wait,
- timeout=timeout, nat_destination=nat_destination)
- fip_address = cloud.get_server_public_ip(server)
- # Update the floating IP status
- f_ip = _get_floating_ip(cloud, fip_address)
- module.exit_json(changed=True, floating_ip=f_ip)
-
- elif state == 'absent':
- if floating_ip_address is None:
- if not server_name_or_id:
- module.fail_json(msg="either server or floating_ip_address are required")
- server = cloud.get_server(server_name_or_id)
- floating_ip_address = cloud.get_server_public_ip(server)
-
- f_ip = _get_floating_ip(cloud, floating_ip_address)
-
- if not f_ip:
- # Nothing to detach
- module.exit_json(changed=False)
- changed = False
- if f_ip["fixed_ip_address"]:
- cloud.detach_ip_from_server(
- server_id=server['id'], floating_ip_id=f_ip['id'])
- # Update the floating IP status
- f_ip = cloud.get_floating_ip(id=f_ip['id'])
- changed = True
- if purge:
- cloud.delete_floating_ip(f_ip['id'])
- module.exit_json(changed=True)
- module.exit_json(changed=changed, floating_ip=f_ip)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e), extra_data=e.extra_data)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_group.py b/lib/ansible/modules/cloud/openstack/os_group.py
deleted file mode 100644
index 3f7e291c1c..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_group.py
+++ /dev/null
@@ -1,167 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2016 IBM
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_group
-short_description: Manage OpenStack Identity Groups
-extends_documentation_fragment: openstack
-version_added: "2.1"
-author: "Monty Taylor (@emonty), David Shrewsbury (@Shrews)"
-description:
- - Manage OpenStack Identity Groups. Groups can be created, deleted or
- updated. Only the I(description) value can be updated.
-options:
- name:
- description:
- - Group name
- required: true
- description:
- description:
- - Group description
- domain_id:
- description:
- - Domain id to create the group in if the cloud supports domains.
- version_added: "2.3"
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-# Create a group named "demo"
-- os_group:
- cloud: mycloud
- state: present
- name: demo
- description: "Demo Group"
- domain_id: demoid
-
-# Update the description on existing "demo" group
-- os_group:
- cloud: mycloud
- state: present
- name: demo
- description: "Something else"
- domain_id: demoid
-
-# Delete group named "demo"
-- os_group:
- cloud: mycloud
- state: absent
- name: demo
-'''
-
-RETURN = '''
-group:
- description: Dictionary describing the group.
- returned: On success when I(state) is 'present'.
- type: complex
- contains:
- id:
- description: Unique group ID
- type: str
- sample: "ee6156ff04c645f481a6738311aea0b0"
- name:
- description: Group name
- type: str
- sample: "demo"
- description:
- description: Group description
- type: str
- sample: "Demo Group"
- domain_id:
- description: Domain for the group
- type: str
- sample: "default"
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _system_state_change(state, description, group):
- if state == 'present' and not group:
- return True
- if state == 'present' and description is not None and group.description != description:
- return True
- if state == 'absent' and group:
- return True
- return False
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- description=dict(required=False, default=None),
- domain_id=dict(required=False, default=None),
- state=dict(default='present', choices=['absent', 'present']),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- name = module.params.get('name')
- description = module.params.get('description')
- state = module.params.get('state')
-
- domain_id = module.params.pop('domain_id')
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- if domain_id:
- group = cloud.get_group(name, filters={'domain_id': domain_id})
- else:
- group = cloud.get_group(name)
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(state, description, group))
-
- if state == 'present':
- if group is None:
- group = cloud.create_group(
- name=name, description=description, domain=domain_id)
- changed = True
- else:
- if description is not None and group.description != description:
- group = cloud.update_group(
- group.id, description=description)
- changed = True
- else:
- changed = False
- module.exit_json(changed=changed, group=group)
-
- elif state == 'absent':
- if group is None:
- changed = False
- else:
- cloud.delete_group(group.id)
- changed = True
- module.exit_json(changed=changed)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_group_info.py b/lib/ansible/modules/cloud/openstack/os_group_info.py
deleted file mode 100644
index 0630516d71..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_group_info.py
+++ /dev/null
@@ -1,171 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2019, Phillipe Smith <phillipelnx@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_group_info
-short_description: Retrieve info about one or more OpenStack groups
-extends_documentation_fragment: openstack
-version_added: "2.9"
-author: "Phillipe Smith (@phsmith)"
-description:
- - Retrieve info about a one or more OpenStack groups.
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-options:
- name:
- description:
- - Name or ID of the group.
- required: true
- type: str
- domain:
- description:
- - Name or ID of the domain containing the group if the cloud supports domains
- type: str
- filters:
- description:
- - A dictionary of meta data to use for further filtering. Elements of
- this dictionary may be additional dictionaries.
- type: dict
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
- type: str
-'''
-
-EXAMPLES = '''
-# Gather info about previously created groups
-- name: gather info
- hosts: localhost
- tasks:
- - name: Gather info about previously created groups
- os_group_info:
- cloud: awesomecloud
- register: openstack_groups
- - debug:
- var: openstack_groups
-
-# Gather info about a previously created group by name
-- name: gather info
- hosts: localhost
- tasks:
- - name: Gather info about a previously created group by name
- os_group_info:
- cloud: awesomecloud
- name: demogroup
- register: openstack_groups
- - debug:
- var: openstack_groups
-
-# Gather info about a previously created group in a specific domain
-- name: gather info
- hosts: localhost
- tasks:
- - name: Gather info about a previously created group in a specific domain
- os_group_info:
- cloud: awesomecloud
- name: demogroup
- domain: admindomain
- register: openstack_groups
- - debug:
- var: openstack_groups
-
-# Gather info about a previously created group in a specific domain with filter
-- name: gather info
- hosts: localhost
- tasks:
- - name: Gather info about a previously created group in a specific domain with filter
- os_group_info:
- cloud: awesomecloud
- name: demogroup
- domain: admindomain
- filters:
- enabled: False
- register: openstack_groups
- - debug:
- var: openstack_groups
-'''
-
-
-RETURN = '''
-openstack_groups:
- description: Dictionary describing all the matching groups.
- returned: always, but can be null
- type: complex
- contains:
- name:
- description: Name given to the group.
- returned: success
- type: str
- description:
- description: Description of the group.
- returned: success
- type: str
- id:
- description: Unique UUID.
- returned: success
- type: str
- domain_id:
- description: Domain ID containing the group (keystone v3 clouds only)
- returned: success
- type: bool
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_cloud_from_module
-
-
-def main():
-
- argument_spec = openstack_full_argument_spec(
- name=dict(required=False, default=None),
- domain=dict(required=False, default=None),
- filters=dict(required=False, type='dict', default=None),
- )
-
- module = AnsibleModule(argument_spec)
-
- sdk, opcloud = openstack_cloud_from_module(module)
- try:
- name = module.params['name']
- domain = module.params['domain']
- filters = module.params['filters']
-
- if domain:
- try:
- # We assume admin is passing domain id
- dom = opcloud.get_domain(domain)['id']
- domain = dom
- except Exception:
- # If we fail, maybe admin is passing a domain name.
- # Note that domains have unique names, just like id.
- dom = opcloud.search_domains(filters={'name': domain})
- if dom:
- domain = dom[0]['id']
- else:
- module.fail_json(msg='Domain name or ID does not exist')
-
- if not filters:
- filters = {}
-
- groups = opcloud.search_groups(name, filters, domain_id=domain)
- module.exit_json(changed=False, groups=groups)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_image.py b/lib/ansible/modules/cloud/openstack/os_image.py
deleted file mode 100644
index fc272a9fdf..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_image.py
+++ /dev/null
@@ -1,235 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
-# Copyright (c) 2013, Benno Joy <benno@ansible.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-# TODO(mordred): we need to support "location"(v1) and "locations"(v2)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_image
-short_description: Add/Delete images from OpenStack Cloud
-extends_documentation_fragment: openstack
-version_added: "2.0"
-author: "Monty Taylor (@emonty)"
-description:
- - Add or Remove images from the OpenStack Image Repository
-options:
- name:
- description:
- - The name of the image when uploading - or the name/ID of the image if deleting
- required: true
- id:
- version_added: "2.4"
- description:
- - The ID of the image when uploading an image
- checksum:
- version_added: "2.5"
- description:
- - The checksum of the image
- disk_format:
- description:
- - The format of the disk that is getting uploaded
- default: qcow2
- container_format:
- description:
- - The format of the container
- default: bare
- owner:
- description:
- - The owner of the image
- min_disk:
- description:
- - The minimum disk space (in GB) required to boot this image
- min_ram:
- description:
- - The minimum ram (in MB) required to boot this image
- is_public:
- description:
- - Whether the image can be accessed publicly. Note that publicizing an image requires admin role by default.
- type: bool
- default: 'yes'
- protected:
- version_added: "2.9"
- description:
- - Prevent image from being deleted
- type: bool
- default: 'no'
- filename:
- description:
- - The path to the file which has to be uploaded
- ramdisk:
- description:
- - The name of an existing ramdisk image that will be associated with this image
- kernel:
- description:
- - The name of an existing kernel image that will be associated with this image
- properties:
- description:
- - Additional properties to be associated with this image
- default: {}
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
- volume:
- version_added: "2.10"
- description:
- - ID of a volume to create an image from.
- - The volume must be in AVAILABLE state.
-requirements: ["openstacksdk"]
-'''
-
-EXAMPLES = '''
-# Upload an image from a local file named cirros-0.3.0-x86_64-disk.img
-- os_image:
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: passme
- project_name: admin
- os_user_domain_name: Default
- os_project_domain_name: Default
- name: cirros
- container_format: bare
- disk_format: qcow2
- state: present
- filename: cirros-0.3.0-x86_64-disk.img
- kernel: cirros-vmlinuz
- ramdisk: cirros-initrd
- properties:
- cpu_arch: x86_64
- distro: ubuntu
-
-# Create image from volume attached to an instance
-- name: create volume snapshot
- os_volume_snapshot:
- auth:
- "{{ auth }}"
- display_name: myvol_snapshot
- volume: myvol
- force: yes
- register: myvol_snapshot
-
-- name: create volume from snapshot
- os_volume:
- auth:
- "{{ auth }}"
- size: "{{ myvol_snapshot.snapshot.size }}"
- snapshot_id: "{{ myvol_snapshot.snapshot.id }}"
- display_name: myvol_snapshot_volume
- wait: yes
- register: myvol_snapshot_volume
-
-- name: create image from volume snapshot
- os_image:
- auth:
- "{{ auth }}"
- volume: "{{ myvol_snapshot_volume.volume.id }}"
- name: myvol_image
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def main():
-
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- id=dict(default=None),
- checksum=dict(default=None),
- disk_format=dict(default='qcow2', choices=['ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2', 'vdi', 'iso', 'vhdx', 'ploop']),
- container_format=dict(default='bare', choices=['ami', 'aki', 'ari', 'bare', 'ovf', 'ova', 'docker']),
- owner=dict(default=None),
- min_disk=dict(type='int', default=0),
- min_ram=dict(type='int', default=0),
- is_public=dict(type='bool', default=False),
- protected=dict(type='bool', default=False),
- filename=dict(default=None),
- ramdisk=dict(default=None),
- kernel=dict(default=None),
- properties=dict(type='dict', default={}),
- volume=dict(default=None),
- state=dict(default='present', choices=['absent', 'present']),
- )
-
- module_kwargs = openstack_module_kwargs(
- mutually_exclusive=[['filename', 'volume']],
- )
- module = AnsibleModule(argument_spec, **module_kwargs)
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
-
- changed = False
- if module.params['id']:
- image = cloud.get_image(name_or_id=module.params['id'])
- elif module.params['checksum']:
- image = cloud.get_image(name_or_id=module.params['name'], filters={'checksum': module.params['checksum']})
- else:
- image = cloud.get_image(name_or_id=module.params['name'])
-
- if module.params['state'] == 'present':
- if not image:
- kwargs = {}
- if module.params['id'] is not None:
- kwargs['id'] = module.params['id']
- image = cloud.create_image(
- name=module.params['name'],
- filename=module.params['filename'],
- disk_format=module.params['disk_format'],
- container_format=module.params['container_format'],
- wait=module.params['wait'],
- timeout=module.params['timeout'],
- is_public=module.params['is_public'],
- protected=module.params['protected'],
- min_disk=module.params['min_disk'],
- min_ram=module.params['min_ram'],
- volume=module.params['volume'],
- **kwargs
- )
- changed = True
- if not module.params['wait']:
- module.exit_json(changed=changed, image=image, id=image.id)
-
- cloud.update_image_properties(
- image=image,
- kernel=module.params['kernel'],
- ramdisk=module.params['ramdisk'],
- protected=module.params['protected'],
- **module.params['properties'])
- image = cloud.get_image(name_or_id=image.id)
- module.exit_json(changed=changed, image=image, id=image.id)
-
- elif module.params['state'] == 'absent':
- if not image:
- changed = False
- else:
- cloud.delete_image(
- name_or_id=module.params['name'],
- wait=module.params['wait'],
- timeout=module.params['timeout'])
- changed = True
- module.exit_json(changed=changed)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e), extra_data=e.extra_data)
-
-
-if __name__ == "__main__":
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_image_info.py b/lib/ansible/modules/cloud/openstack/os_image_info.py
deleted file mode 100644
index 7ae55dd15e..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_image_info.py
+++ /dev/null
@@ -1,196 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
-module: os_image_info
-short_description: Retrieve information about an image within OpenStack.
-version_added: "2.0"
-author: "Davide Agnello (@dagnello)"
-description:
- - Retrieve information about a image image from OpenStack.
- - This module was called C(os_image_facts) before Ansible 2.9, returning C(ansible_facts).
- Note that the M(os_image_info) module no longer returns C(ansible_facts)!
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-options:
- image:
- description:
- - Name or ID of the image
- required: false
- properties:
- description:
- - Dict of properties of the images used for query
- type: dict
- required: false
- version_added: '2.9'
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
- required: false
-extends_documentation_fragment: openstack
-'''
-
-EXAMPLES = '''
-- name: Gather information about a previously created image named image1
- os_image_info:
- auth:
- auth_url: https://identity.example.com
- username: user
- password: password
- project_name: someproject
- image: image1
- register: result
-
-- name: Show openstack information
- debug:
- msg: "{{ result.openstack_image }}"
-
-# Show all available Openstack images
-- name: Retrieve all available Openstack images
- os_image_info:
- register: result
-
-- name: Show images
- debug:
- msg: "{{ result.openstack_image }}"
-
-# Show images matching requested properties
-- name: Retrieve images having properties with desired values
- os_image_facts:
- properties:
- some_property: some_value
- OtherProp: OtherVal
-
-- name: Show images
- debug:
- msg: "{{ result.openstack_image }}"
-'''
-
-RETURN = '''
-openstack_image:
- description: has all the openstack information about the image
- returned: always, but can be null
- type: complex
- contains:
- id:
- description: Unique UUID.
- returned: success
- type: str
- name:
- description: Name given to the image.
- returned: success
- type: str
- status:
- description: Image status.
- returned: success
- type: str
- created_at:
- description: Image created at timestamp.
- returned: success
- type: str
- deleted:
- description: Image deleted flag.
- returned: success
- type: bool
- container_format:
- description: Container format of the image.
- returned: success
- type: str
- min_ram:
- description: Min amount of RAM required for this image.
- returned: success
- type: int
- disk_format:
- description: Disk format of the image.
- returned: success
- type: str
- updated_at:
- description: Image updated at timestamp.
- returned: success
- type: str
- properties:
- description: Additional properties associated with the image.
- returned: success
- type: dict
- min_disk:
- description: Min amount of disk space required for this image.
- returned: success
- type: int
- protected:
- description: Image protected flag.
- returned: success
- type: bool
- checksum:
- description: Checksum for the image.
- returned: success
- type: str
- owner:
- description: Owner for the image.
- returned: success
- type: str
- is_public:
- description: Is public flag of the image.
- returned: success
- type: bool
- deleted_at:
- description: Image deleted at timestamp.
- returned: success
- type: str
- size:
- description: Size of the image.
- returned: success
- type: int
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def main():
-
- argument_spec = openstack_full_argument_spec(
- image=dict(required=False),
- properties=dict(default=None, type='dict'),
- )
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec, **module_kwargs)
- is_old_facts = module._name == 'os_image_facts'
- if is_old_facts:
- module.deprecate("The 'os_image_facts' module has been renamed to 'os_image_info', "
- "and the renamed one no longer returns ansible_facts", version='2.13')
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- if module.params['image']:
- image = cloud.get_image(module.params['image'])
- if is_old_facts:
- module.exit_json(changed=False, ansible_facts=dict(
- openstack_image=image))
- else:
- module.exit_json(changed=False, openstack_image=image)
- else:
- images = cloud.search_images(filters=module.params['properties'])
- if is_old_facts:
- module.exit_json(changed=False, ansible_facts=dict(
- openstack_image=images))
- else:
- module.exit_json(changed=False, openstack_image=images)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_ironic.py b/lib/ansible/modules/cloud/openstack/os_ironic.py
deleted file mode 100644
index 6a09afe2fa..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_ironic.py
+++ /dev/null
@@ -1,355 +0,0 @@
-#!/usr/bin/python
-# coding: utf-8 -*-
-
-# (c) 2014, Hewlett-Packard Development Company, L.P.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_ironic
-short_description: Create/Delete Bare Metal Resources from OpenStack
-extends_documentation_fragment: openstack
-author: "Monty Taylor (@emonty)"
-version_added: "2.0"
-description:
- - Create or Remove Ironic nodes from OpenStack.
-options:
- state:
- description:
- - Indicates desired state of the resource
- choices: ['present', 'absent']
- default: present
- uuid:
- description:
- - globally unique identifier (UUID) to be given to the resource. Will
- be auto-generated if not specified, and name is specified.
- - Definition of a UUID will always take precedence to a name value.
- name:
- description:
- - unique name identifier to be given to the resource.
- driver:
- description:
- - The name of the Ironic Driver to use with this node.
- required: true
- chassis_uuid:
- description:
- - Associate the node with a pre-defined chassis.
- ironic_url:
- description:
- - If noauth mode is utilized, this is required to be set to the
- endpoint URL for the Ironic API. Use with "auth" and "auth_type"
- settings set to None.
- driver_info:
- description:
- - Information for this server's driver. Will vary based on which
- driver is in use. Any sub-field which is populated will be validated
- during creation.
- suboptions:
- power:
- description:
- - Information necessary to turn this server on / off.
- This often includes such things as IPMI username, password, and IP address.
- required: true
- deploy:
- description:
- - Information necessary to deploy this server directly, without using Nova. THIS IS NOT RECOMMENDED.
- console:
- description:
- - Information necessary to connect to this server's serial console. Not all drivers support this.
- management:
- description:
- - Information necessary to interact with this server's management interface. May be shared by power_info in some cases.
- required: true
- nics:
- description:
- - 'A list of network interface cards, eg, " - mac: aa:bb:cc:aa:bb:cc"'
- required: true
- properties:
- description:
- - Definition of the physical characteristics of this server, used for scheduling purposes
- suboptions:
- cpu_arch:
- description:
- - CPU architecture (x86_64, i686, ...)
- default: x86_64
- cpus:
- description:
- - Number of CPU cores this machine has
- default: 1
- ram:
- description:
- - amount of RAM this machine has, in MB
- default: 1
- disk_size:
- description:
- - size of first storage device in this machine (typically /dev/sda), in GB
- default: 1
- capabilities:
- description:
- - special capabilities for the node, such as boot_option, node_role etc
- (see U(https://docs.openstack.org/ironic/latest/install/advanced.html)
- for more information)
- default: ""
- version_added: "2.8"
- root_device:
- description:
- - Root disk device hints for deployment.
- (see U(https://docs.openstack.org/ironic/latest/install/include/root-device-hints.html)
- for allowed hints)
- default: ""
- version_added: "2.8"
- skip_update_of_driver_password:
- description:
- - Allows the code that would assert changes to nodes to skip the
- update if the change is a single line consisting of the password
- field. As of Kilo, by default, passwords are always masked to API
- requests, which means the logic as a result always attempts to
- re-assert the password field.
- type: bool
- default: 'no'
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-
-requirements: ["openstacksdk", "jsonpatch"]
-'''
-
-EXAMPLES = '''
-# Enroll a node with some basic properties and driver info
-- os_ironic:
- cloud: "devstack"
- driver: "pxe_ipmitool"
- uuid: "00000000-0000-0000-0000-000000000002"
- properties:
- cpus: 2
- cpu_arch: "x86_64"
- ram: 8192
- disk_size: 64
- capabilities: "boot_option:local"
- root_device:
- wwn: "0x4000cca77fc4dba1"
- nics:
- - mac: "aa:bb:cc:aa:bb:cc"
- - mac: "dd:ee:ff:dd:ee:ff"
- driver_info:
- power:
- ipmi_address: "1.2.3.4"
- ipmi_username: "admin"
- ipmi_password: "adminpass"
- chassis_uuid: "00000000-0000-0000-0000-000000000001"
-
-'''
-
-try:
- import jsonpatch
- HAS_JSONPATCH = True
-except ImportError:
- HAS_JSONPATCH = False
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _parse_properties(module):
- p = module.params['properties']
- props = dict(
- cpu_arch=p.get('cpu_arch') if p.get('cpu_arch') else 'x86_64',
- cpus=p.get('cpus') if p.get('cpus') else 1,
- memory_mb=p.get('ram') if p.get('ram') else 1,
- local_gb=p.get('disk_size') if p.get('disk_size') else 1,
- capabilities=p.get('capabilities') if p.get('capabilities') else '',
- root_device=p.get('root_device') if p.get('root_device') else '',
- )
- return props
-
-
-def _parse_driver_info(sdk, module):
- p = module.params['driver_info']
- info = p.get('power')
- if not info:
- raise sdk.exceptions.OpenStackCloudException(
- "driver_info['power'] is required")
- if p.get('console'):
- info.update(p.get('console'))
- if p.get('management'):
- info.update(p.get('management'))
- if p.get('deploy'):
- info.update(p.get('deploy'))
- return info
-
-
-def _choose_id_value(module):
- if module.params['uuid']:
- return module.params['uuid']
- if module.params['name']:
- return module.params['name']
- return None
-
-
-def _choose_if_password_only(module, patch):
- if len(patch) == 1:
- if 'password' in patch[0]['path'] and module.params['skip_update_of_masked_password']:
- # Return false to abort update as the password appears
- # to be the only element in the patch.
- return False
- return True
-
-
-def _exit_node_not_updated(module, server):
- module.exit_json(
- changed=False,
- result="Node not updated",
- uuid=server['uuid'],
- provision_state=server['provision_state']
- )
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- uuid=dict(required=False),
- name=dict(required=False),
- driver=dict(required=False),
- driver_info=dict(type='dict', required=True),
- nics=dict(type='list', required=True),
- properties=dict(type='dict', default={}),
- ironic_url=dict(required=False),
- chassis_uuid=dict(required=False),
- skip_update_of_masked_password=dict(required=False, type='bool'),
- state=dict(required=False, default='present')
- )
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec, **module_kwargs)
-
- if not HAS_JSONPATCH:
- module.fail_json(msg='jsonpatch is required for this module')
- if (module.params['auth_type'] in [None, 'None'] and
- module.params['ironic_url'] is None):
- module.fail_json(msg="Authentication appears to be disabled, "
- "Please define an ironic_url parameter")
-
- if (module.params['ironic_url'] and
- module.params['auth_type'] in [None, 'None']):
- module.params['auth'] = dict(
- endpoint=module.params['ironic_url']
- )
-
- node_id = _choose_id_value(module)
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- server = cloud.get_machine(node_id)
- if module.params['state'] == 'present':
- if module.params['driver'] is None:
- module.fail_json(msg="A driver must be defined in order "
- "to set a node to present.")
-
- properties = _parse_properties(module)
- driver_info = _parse_driver_info(sdk, module)
- kwargs = dict(
- driver=module.params['driver'],
- properties=properties,
- driver_info=driver_info,
- name=module.params['name'],
- )
-
- if module.params['chassis_uuid']:
- kwargs['chassis_uuid'] = module.params['chassis_uuid']
-
- if server is None:
- # Note(TheJulia): Add a specific UUID to the request if
- # present in order to be able to re-use kwargs for if
- # the node already exists logic, since uuid cannot be
- # updated.
- if module.params['uuid']:
- kwargs['uuid'] = module.params['uuid']
-
- server = cloud.register_machine(module.params['nics'],
- **kwargs)
- module.exit_json(changed=True, uuid=server['uuid'],
- provision_state=server['provision_state'])
- else:
- # TODO(TheJulia): Presently this does not support updating
- # nics. Support needs to be added.
- #
- # Note(TheJulia): This message should never get logged
- # however we cannot realistically proceed if neither a
- # name or uuid was supplied to begin with.
- if not node_id:
- module.fail_json(msg="A uuid or name value "
- "must be defined")
-
- # Note(TheJulia): Constructing the configuration to compare
- # against. The items listed in the server_config block can
- # be updated via the API.
-
- server_config = dict(
- driver=server['driver'],
- properties=server['properties'],
- driver_info=server['driver_info'],
- name=server['name'],
- )
-
- # Add the pre-existing chassis_uuid only if
- # it is present in the server configuration.
- if hasattr(server, 'chassis_uuid'):
- server_config['chassis_uuid'] = server['chassis_uuid']
-
- # Note(TheJulia): If a password is defined and concealed, a
- # patch will always be generated and re-asserted.
- patch = jsonpatch.JsonPatch.from_diff(server_config, kwargs)
-
- if not patch:
- _exit_node_not_updated(module, server)
- elif _choose_if_password_only(module, list(patch)):
- # Note(TheJulia): Normally we would allow the general
- # exception catch below, however this allows a specific
- # message.
- try:
- server = cloud.patch_machine(
- server['uuid'],
- list(patch))
- except Exception as e:
- module.fail_json(msg="Failed to update node, "
- "Error: %s" % e.message)
-
- # Enumerate out a list of changed paths.
- change_list = []
- for change in list(patch):
- change_list.append(change['path'])
- module.exit_json(changed=True,
- result="Node Updated",
- changes=change_list,
- uuid=server['uuid'],
- provision_state=server['provision_state'])
-
- # Return not updated by default as the conditions were not met
- # to update.
- _exit_node_not_updated(module, server)
-
- if module.params['state'] == 'absent':
- if not node_id:
- module.fail_json(msg="A uuid or name value must be defined "
- "in order to remove a node.")
-
- if server is not None:
- cloud.unregister_machine(module.params['nics'],
- server['uuid'])
- module.exit_json(changed=True, result="deleted")
- else:
- module.exit_json(changed=False, result="Server not found")
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == "__main__":
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_ironic_inspect.py b/lib/ansible/modules/cloud/openstack/os_ironic_inspect.py
deleted file mode 100644
index 2ebb8eebbd..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_ironic_inspect.py
+++ /dev/null
@@ -1,144 +0,0 @@
-#!/usr/bin/python
-# coding: utf-8 -*-
-
-# (c) 2015-2016, Hewlett Packard Enterprise Development Company LP
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_ironic_inspect
-short_description: Explicitly triggers baremetal node introspection in ironic.
-extends_documentation_fragment: openstack
-author: "Julia Kreger (@juliakreger)"
-version_added: "2.1"
-description:
- - Requests Ironic to set a node into inspect state in order to collect metadata regarding the node.
- This command may be out of band or in-band depending on the ironic driver configuration.
- This is only possible on nodes in 'manageable' and 'available' state.
-options:
- mac:
- description:
- - unique mac address that is used to attempt to identify the host.
- uuid:
- description:
- - globally unique identifier (UUID) to identify the host.
- name:
- description:
- - unique name identifier to identify the host in Ironic.
- ironic_url:
- description:
- - If noauth mode is utilized, this is required to be set to the endpoint URL for the Ironic API.
- Use with "auth" and "auth_type" settings set to None.
- timeout:
- description:
- - A timeout in seconds to tell the role to wait for the node to complete introspection if wait is set to True.
- default: 1200
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-
-requirements: ["openstacksdk"]
-'''
-
-RETURN = '''
-ansible_facts:
- description: Dictionary of new facts representing discovered properties of the node..
- returned: changed
- type: complex
- contains:
- memory_mb:
- description: Amount of node memory as updated in the node properties
- type: str
- sample: "1024"
- cpu_arch:
- description: Detected CPU architecture type
- type: str
- sample: "x86_64"
- local_gb:
- description: Total size of local disk storage as updated in node properties.
- type: str
- sample: "10"
- cpus:
- description: Count of cpu cores defined in the updated node properties.
- type: str
- sample: "1"
-'''
-
-EXAMPLES = '''
-# Invoke node inspection
-- os_ironic_inspect:
- name: "testnode1"
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _choose_id_value(module):
- if module.params['uuid']:
- return module.params['uuid']
- if module.params['name']:
- return module.params['name']
- return None
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- auth_type=dict(required=False),
- uuid=dict(required=False),
- name=dict(required=False),
- mac=dict(required=False),
- ironic_url=dict(required=False),
- timeout=dict(default=1200, type='int', required=False),
- )
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec, **module_kwargs)
-
- if (module.params['auth_type'] in [None, 'None'] and
- module.params['ironic_url'] is None):
- module.fail_json(msg="Authentication appears to be disabled, "
- "Please define an ironic_url parameter")
-
- if (module.params['ironic_url'] and
- module.params['auth_type'] in [None, 'None']):
- module.params['auth'] = dict(
- endpoint=module.params['ironic_url']
- )
-
- 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']:
- server = cloud.get_machine_by_mac(module.params['mac'])
- else:
- module.fail_json(msg="The worlds did not align, "
- "the host was not found as "
- "no name, uuid, or mac was "
- "defined.")
- if server:
- cloud.inspect_machine(server['uuid'], module.params['wait'])
- # TODO(TheJulia): diff properties, ?and ports? and determine
- # if a change occurred. In theory, the node is always changed
- # if introspection is able to update the record.
- module.exit_json(changed=True,
- ansible_facts=server['properties'])
-
- else:
- module.fail_json(msg="node not found.")
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == "__main__":
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_ironic_node.py b/lib/ansible/modules/cloud/openstack/os_ironic_node.py
deleted file mode 100644
index 78abb0592d..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_ironic_node.py
+++ /dev/null
@@ -1,333 +0,0 @@
-#!/usr/bin/python
-# coding: utf-8 -*-
-
-# (c) 2015, Hewlett-Packard Development Company, L.P.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_ironic_node
-short_description: Activate/Deactivate Bare Metal Resources from OpenStack
-author: "Monty Taylor (@emonty)"
-extends_documentation_fragment: openstack
-version_added: "2.0"
-description:
- - Deploy to nodes controlled by Ironic.
-options:
- state:
- description:
- - Indicates desired state of the resource
- choices: ['present', 'absent']
- default: present
- deploy:
- description:
- - Indicates if the resource should be deployed. Allows for deployment
- logic to be disengaged and control of the node power or maintenance
- state to be changed.
- type: bool
- default: 'yes'
- uuid:
- description:
- - globally unique identifier (UUID) to be given to the resource.
- ironic_url:
- description:
- - If noauth mode is utilized, this is required to be set to the
- endpoint URL for the Ironic API. Use with "auth" and "auth_type"
- settings set to None.
- config_drive:
- description:
- - A configdrive file or HTTP(S) URL that will be passed along to the
- node.
- instance_info:
- description:
- - Definition of the instance information which is used to deploy
- the node. This information is only required when an instance is
- set to present.
- suboptions:
- image_source:
- description:
- - An HTTP(S) URL where the image can be retrieved from.
- image_checksum:
- description:
- - The checksum of image_source.
- image_disk_format:
- description:
- - The type of image that has been requested to be deployed.
- power:
- description:
- - A setting to allow power state to be asserted allowing nodes
- that are not yet deployed to be powered on, and nodes that
- are deployed to be powered off.
- choices: ['present', 'absent']
- default: present
- maintenance:
- description:
- - A setting to allow the direct control if a node is in
- maintenance mode.
- type: bool
- default: 'no'
- maintenance_reason:
- description:
- - A string expression regarding the reason a node is in a
- maintenance mode.
- wait:
- description:
- - A boolean value instructing the module to wait for node
- activation or deactivation to complete before returning.
- type: bool
- default: 'no'
- version_added: "2.1"
- timeout:
- description:
- - An integer value representing the number of seconds to
- wait for the node activation or deactivation to complete.
- version_added: "2.1"
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-'''
-
-EXAMPLES = '''
-# Activate a node by booting an image with a configdrive attached
-os_ironic_node:
- cloud: "openstack"
- uuid: "d44666e1-35b3-4f6b-acb0-88ab7052da69"
- state: present
- power: present
- deploy: True
- maintenance: False
- config_drive: "http://192.168.1.1/host-configdrive.iso"
- instance_info:
- image_source: "http://192.168.1.1/deploy_image.img"
- image_checksum: "356a6b55ecc511a20c33c946c4e678af"
- image_disk_format: "qcow"
- delegate_to: localhost
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _choose_id_value(module):
- if module.params['uuid']:
- return module.params['uuid']
- if module.params['name']:
- return module.params['name']
- return None
-
-
-def _is_true(value):
- true_values = [True, 'yes', 'Yes', 'True', 'true', 'present', 'on']
- if value in true_values:
- return True
- return False
-
-
-def _is_false(value):
- false_values = [False, None, 'no', 'No', 'False', 'false', 'absent', 'off']
- if value in false_values:
- return True
- return False
-
-
-def _check_set_maintenance(module, cloud, node):
- if _is_true(module.params['maintenance']):
- if _is_false(node['maintenance']):
- cloud.set_machine_maintenance_state(
- node['uuid'],
- True,
- reason=module.params['maintenance_reason'])
- module.exit_json(changed=True, msg="Node has been set into "
- "maintenance mode")
- else:
- # User has requested maintenance state, node is already in the
- # desired state, checking to see if the reason has changed.
- if (str(node['maintenance_reason']) not in
- str(module.params['maintenance_reason'])):
- cloud.set_machine_maintenance_state(
- node['uuid'],
- True,
- reason=module.params['maintenance_reason'])
- module.exit_json(changed=True, msg="Node maintenance reason "
- "updated, cannot take any "
- "additional action.")
- elif _is_false(module.params['maintenance']):
- if node['maintenance'] is True:
- cloud.remove_machine_from_maintenance(node['uuid'])
- return True
- else:
- module.fail_json(msg="maintenance parameter was set but a valid "
- "the value was not recognized.")
- return False
-
-
-def _check_set_power_state(module, cloud, node):
- if 'power on' in str(node['power_state']):
- if _is_false(module.params['power']):
- # User has requested the node be powered off.
- cloud.set_machine_power_off(node['uuid'])
- module.exit_json(changed=True, msg="Power requested off")
- if 'power off' in str(node['power_state']):
- if (_is_false(module.params['power']) and
- _is_false(module.params['state'])):
- return False
- if (_is_false(module.params['power']) and
- _is_false(module.params['state'])):
- module.exit_json(
- changed=False,
- msg="Power for node is %s, node must be reactivated "
- "OR set to state absent"
- )
- # In the event the power has been toggled on and
- # deployment has been requested, we need to skip this
- # step.
- if (_is_true(module.params['power']) and
- _is_false(module.params['deploy'])):
- # Node is powered down when it is not awaiting to be provisioned
- cloud.set_machine_power_on(node['uuid'])
- return True
- # Default False if no action has been taken.
- return False
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- uuid=dict(required=False),
- name=dict(required=False),
- instance_info=dict(type='dict', required=False),
- config_drive=dict(required=False),
- ironic_url=dict(required=False),
- state=dict(required=False, default='present'),
- maintenance=dict(required=False),
- maintenance_reason=dict(required=False),
- power=dict(required=False, default='present'),
- deploy=dict(required=False, default=True),
- wait=dict(type='bool', required=False, default=False),
- timeout=dict(required=False, type='int', default=1800),
- )
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec, **module_kwargs)
-
- if (module.params['auth_type'] in [None, 'None'] and
- module.params['ironic_url'] is None):
- module.fail_json(msg="Authentication appears disabled, Please "
- "define an ironic_url parameter")
-
- if (module.params['ironic_url'] and
- module.params['auth_type'] in [None, 'None']):
- module.params['auth'] = dict(
- endpoint=module.params['ironic_url']
- )
-
- node_id = _choose_id_value(module)
-
- if not node_id:
- module.fail_json(msg="A uuid or name value must be defined "
- "to use this module.")
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- node = cloud.get_machine(node_id)
-
- if node is None:
- module.fail_json(msg="node not found")
-
- uuid = node['uuid']
- instance_info = module.params['instance_info']
- changed = False
- wait = module.params['wait']
- timeout = module.params['timeout']
-
- # User has requested desired state to be in maintenance state.
- if module.params['state'] == 'maintenance':
- module.params['maintenance'] = True
-
- if node['provision_state'] in [
- 'cleaning',
- 'deleting',
- 'wait call-back']:
- module.fail_json(msg="Node is in %s state, cannot act upon the "
- "request as the node is in a transition "
- "state" % node['provision_state'])
- # TODO(TheJulia) This is in-development code, that requires
- # code in the shade library that is still in development.
- if _check_set_maintenance(module, cloud, node):
- if node['provision_state'] in 'active':
- module.exit_json(changed=True,
- result="Maintenance state changed")
- changed = True
- node = cloud.get_machine(node_id)
-
- if _check_set_power_state(module, cloud, node):
- changed = True
- node = cloud.get_machine(node_id)
-
- if _is_true(module.params['state']):
- if _is_false(module.params['deploy']):
- module.exit_json(
- changed=changed,
- result="User request has explicitly disabled "
- "deployment logic"
- )
-
- if 'active' in node['provision_state']:
- module.exit_json(
- changed=changed,
- result="Node already in an active state."
- )
-
- if instance_info is None:
- module.fail_json(
- changed=changed,
- msg="When setting an instance to present, "
- "instance_info is a required variable.")
-
- # TODO(TheJulia): Update instance info, however info is
- # deployment specific. Perhaps consider adding rebuild
- # support, although there is a known desire to remove
- # rebuild support from Ironic at some point in the future.
- cloud.update_machine(uuid, instance_info=instance_info)
- cloud.validate_node(uuid)
- if not wait:
- cloud.activate_node(uuid, module.params['config_drive'])
- else:
- cloud.activate_node(
- uuid,
- configdrive=module.params['config_drive'],
- wait=wait,
- timeout=timeout)
- # TODO(TheJulia): Add more error checking..
- module.exit_json(changed=changed, result="node activated")
-
- elif _is_false(module.params['state']):
- if node['provision_state'] not in "deleted":
- cloud.update_machine(uuid, instance_info={})
- if not wait:
- cloud.deactivate_node(uuid)
- else:
- cloud.deactivate_node(
- uuid,
- wait=wait,
- timeout=timeout)
-
- module.exit_json(changed=True, result="deleted")
- else:
- module.exit_json(changed=False, result="node not found")
- else:
- module.fail_json(msg="State must be present, absent, "
- "maintenance, off")
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == "__main__":
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_keypair.py b/lib/ansible/modules/cloud/openstack/os_keypair.py
deleted file mode 100644
index 85a0fdf0a0..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_keypair.py
+++ /dev/null
@@ -1,163 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
-# Copyright (c) 2013, Benno Joy <benno@ansible.com>
-# Copyright (c) 2013, John Dewey <john@dewey.ws>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_keypair
-short_description: Add/Delete a keypair from OpenStack
-author: "Benno Joy (@bennojoy)"
-extends_documentation_fragment: openstack
-version_added: "2.0"
-description:
- - Add or Remove key pair from OpenStack
-options:
- name:
- description:
- - Name that has to be given to the key pair
- required: true
- public_key:
- description:
- - The public key that would be uploaded to nova and injected into VMs
- upon creation.
- public_key_file:
- description:
- - Path to local file containing ssh public key. Mutually exclusive
- with public_key.
- state:
- description:
- - Should the resource be present or absent. If state is replace and
- the key exists but has different content, delete it and recreate it
- with the new content.
- choices: [present, absent, replace]
- default: present
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-'''
-
-EXAMPLES = '''
-# Creates a key pair with the running users public key
-- os_keypair:
- cloud: mordred
- state: present
- name: ansible_key
- public_key_file: /home/me/.ssh/id_rsa.pub
-
-# Creates a new key pair and the private key returned after the run.
-- os_keypair:
- cloud: rax-dfw
- state: present
- name: ansible_key
-'''
-
-RETURN = '''
-id:
- description: Unique UUID.
- returned: success
- type: str
-name:
- description: Name given to the keypair.
- returned: success
- type: str
-public_key:
- description: The public key value for the keypair.
- returned: success
- type: str
-private_key:
- description: The private key value for the keypair.
- returned: Only when a keypair is generated for the user (e.g., when creating one
- and a public key is not specified).
- type: str
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _system_state_change(module, keypair):
- state = module.params['state']
- if state == 'present' and not keypair:
- return True
- if state == 'absent' and keypair:
- return True
- return False
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- public_key=dict(default=None),
- public_key_file=dict(default=None),
- state=dict(default='present',
- choices=['absent', 'present', 'replace']),
- )
-
- module_kwargs = openstack_module_kwargs(
- mutually_exclusive=[['public_key', 'public_key_file']])
-
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- state = module.params['state']
- name = module.params['name']
- public_key = module.params['public_key']
-
- if module.params['public_key_file']:
- with open(module.params['public_key_file']) as public_key_fh:
- public_key = public_key_fh.read().rstrip()
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- keypair = cloud.get_keypair(name)
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(module, keypair))
-
- if state in ('present', 'replace'):
- if keypair and keypair['name'] == name:
- if public_key and (public_key != keypair['public_key']):
- if state == 'present':
- module.fail_json(
- msg="Key name %s present but key hash not the same"
- " as offered. Delete key first." % name
- )
- else:
- cloud.delete_keypair(name)
- keypair = cloud.create_keypair(name, public_key)
- changed = True
- else:
- changed = False
- else:
- keypair = cloud.create_keypair(name, public_key)
- changed = True
-
- module.exit_json(changed=changed,
- key=keypair,
- id=keypair['id'])
-
- elif state == 'absent':
- if keypair:
- cloud.delete_keypair(name)
- module.exit_json(changed=True)
- module.exit_json(changed=False)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_keystone_domain.py b/lib/ansible/modules/cloud/openstack/os_keystone_domain.py
deleted file mode 100644
index 2cf4920100..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_keystone_domain.py
+++ /dev/null
@@ -1,185 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_keystone_domain
-short_description: Manage OpenStack Identity Domains
-author:
- - Monty Taylor (@emonty)
- - Haneef Ali (@haneefs)
-extends_documentation_fragment: openstack
-version_added: "2.1"
-description:
- - Create, update, or delete OpenStack Identity domains. If a domain
- with the supplied name already exists, it will be updated with the
- new description and enabled attributes.
-options:
- name:
- description:
- - Name that has to be given to the instance
- required: true
- description:
- description:
- - Description of the domain
- enabled:
- description:
- - Is the domain enabled
- type: bool
- default: 'yes'
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-# Create a domain
-- os_keystone_domain:
- cloud: mycloud
- state: present
- name: demo
- description: Demo Domain
-
-# Delete a domain
-- os_keystone_domain:
- cloud: mycloud
- state: absent
- name: demo
-'''
-
-RETURN = '''
-domain:
- description: Dictionary describing the domain.
- returned: On success when I(state) is 'present'
- type: complex
- contains:
- id:
- description: Domain ID.
- type: str
- sample: "474acfe5-be34-494c-b339-50f06aa143e4"
- name:
- description: Domain name.
- type: str
- sample: "demo"
- description:
- description: Domain description.
- type: str
- sample: "Demo Domain"
- enabled:
- description: Domain description.
- type: bool
- sample: True
-
-id:
- description: The domain ID.
- returned: On success when I(state) is 'present'
- type: str
- sample: "474acfe5-be34-494c-b339-50f06aa143e4"
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _needs_update(module, domain):
- if module.params['description'] is not None and \
- domain.description != module.params['description']:
- return True
- if domain.enabled != module.params['enabled']:
- return True
- return False
-
-
-def _system_state_change(module, domain):
- state = module.params['state']
- if state == 'absent' and domain:
- return True
-
- if state == 'present':
- if domain is None:
- return True
- return _needs_update(module, domain)
-
- return False
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- description=dict(default=None),
- enabled=dict(default=True, type='bool'),
- state=dict(default='present', choices=['absent', 'present']),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- name = module.params['name']
- description = module.params['description']
- enabled = module.params['enabled']
- state = module.params['state']
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
-
- domains = cloud.search_domains(filters=dict(name=name))
-
- if len(domains) > 1:
- module.fail_json(msg='Domain name %s is not unique' % name)
- elif len(domains) == 1:
- domain = domains[0]
- else:
- domain = None
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(module, domain))
-
- if state == 'present':
- if domain is None:
- domain = cloud.create_domain(
- name=name, description=description, enabled=enabled)
- changed = True
- else:
- if _needs_update(module, domain):
- domain = cloud.update_domain(
- domain.id, name=name, description=description,
- enabled=enabled)
- changed = True
- else:
- changed = False
- module.exit_json(changed=changed, domain=domain, id=domain.id)
-
- elif state == 'absent':
- if domain is None:
- changed = False
- else:
- cloud.delete_domain(domain.id)
- changed = True
- module.exit_json(changed=changed)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_keystone_domain_info.py b/lib/ansible/modules/cloud/openstack/os_keystone_domain_info.py
deleted file mode 100644
index 919b301ab5..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_keystone_domain_info.py
+++ /dev/null
@@ -1,140 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2016 Hewlett-Packard Enterprise Corporation
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_keystone_domain_info
-short_description: Retrieve information about one or more OpenStack domains
-extends_documentation_fragment: openstack
-version_added: "2.1"
-author: "Ricardo Carrillo Cruz (@rcarrillocruz)"
-description:
- - Retrieve information about a one or more OpenStack domains
- - This module was called C(os_keystone_domain_facts) before Ansible 2.9, returning C(ansible_facts).
- Note that the M(os_keystone_domain_info) module no longer returns C(ansible_facts)!
-requirements:
- - "python >= 2.7"
- - "sdk"
-options:
- name:
- description:
- - Name or ID of the domain
- filters:
- description:
- - A dictionary of meta data to use for further filtering. Elements of
- this dictionary may be additional dictionaries.
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-'''
-
-EXAMPLES = '''
-# Gather information about previously created domain
-- os_keystone_domain_info:
- cloud: awesomecloud
- register: result
-- debug:
- msg: "{{ result.openstack_domains }}"
-
-# Gather information about a previously created domain by name
-- os_keystone_domain_info:
- cloud: awesomecloud
- name: demodomain
- register: result
-- debug:
- msg: "{{ result.openstack_domains }}"
-
-# Gather information about a previously created domain with filter
-- os_keystone_domain_info:
- cloud: awesomecloud
- name: demodomain
- filters:
- enabled: false
- register: result
-- debug:
- msg: "{{ result.openstack_domains }}"
-'''
-
-
-RETURN = '''
-openstack_domains:
- description: has all the OpenStack information about domains
- returned: always, but can be null
- type: complex
- contains:
- id:
- description: Unique UUID.
- returned: success
- type: str
- name:
- description: Name given to the domain.
- returned: success
- type: str
- description:
- description: Description of the domain.
- returned: success
- type: str
- enabled:
- description: Flag to indicate if the domain is enabled.
- returned: success
- type: bool
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def main():
-
- argument_spec = openstack_full_argument_spec(
- name=dict(required=False, default=None),
- filters=dict(required=False, type='dict', default=None),
- )
- module_kwargs = openstack_module_kwargs(
- mutually_exclusive=[
- ['name', 'filters'],
- ]
- )
- module = AnsibleModule(argument_spec, **module_kwargs)
- is_old_facts = module._name == 'os_keystone_domain_facts'
- if is_old_facts:
- module.deprecate("The 'os_keystone_domain_facts' module has been renamed to 'os_keystone_domain_info', "
- "and the renamed one no longer returns ansible_facts", version='2.13')
-
- sdk, opcloud = openstack_cloud_from_module(module)
- try:
- name = module.params['name']
- filters = module.params['filters']
-
- if name:
- # Let's suppose user is passing domain ID
- try:
- domains = opcloud.get_domain(name)
- except Exception:
- domains = opcloud.search_domains(filters={'name': name})
-
- else:
- domains = opcloud.search_domains(filters)
-
- if is_old_facts:
- module.exit_json(changed=False, ansible_facts=dict(
- openstack_domains=domains))
- else:
- module.exit_json(changed=False, openstack_domains=domains)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_keystone_endpoint.py b/lib/ansible/modules/cloud/openstack/os_keystone_endpoint.py
deleted file mode 100644
index 9705990838..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_keystone_endpoint.py
+++ /dev/null
@@ -1,209 +0,0 @@
-#!/usr/bin/python
-
-# Copyright: (c) 2017, VEXXHOST, Inc.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: os_keystone_endpoint
-short_description: Manage OpenStack Identity service endpoints
-extends_documentation_fragment: openstack
-author:
- - Mohammed Naser (@mnaser)
- - Alberto Murillo (@albertomurillo)
-version_added: "2.5"
-description:
- - Create, update, or delete OpenStack Identity service endpoints. If a
- service with the same combination of I(service), I(interface) and I(region)
- exist, the I(url) and I(state) (C(present) or C(absent)) will be updated.
-options:
- service:
- description:
- - Name or id of the service.
- required: true
- endpoint_interface:
- description:
- - Interface of the service.
- choices: [admin, public, internal]
- required: true
- url:
- description:
- - URL of the service.
- required: true
- region:
- description:
- - Region that the service belongs to. Note that I(region_name) is used for authentication.
- enabled:
- description:
- - Is the service enabled.
- default: True
- type: bool
- state:
- description:
- - Should the resource be C(present) or C(absent).
- choices: [present, absent]
- default: present
-requirements:
- - openstacksdk >= 0.13.0
-'''
-
-EXAMPLES = '''
-- name: Create a service for glance
- os_keystone_endpoint:
- cloud: mycloud
- service: glance
- endpoint_interface: public
- url: http://controller:9292
- region: RegionOne
- state: present
-
-- name: Delete a service for nova
- os_keystone_endpoint:
- cloud: mycloud
- service: nova
- endpoint_interface: public
- region: RegionOne
- state: absent
-'''
-
-RETURN = '''
-endpoint:
- description: Dictionary describing the endpoint.
- returned: On success when I(state) is C(present)
- type: complex
- contains:
- id:
- description: Endpoint ID.
- type: str
- sample: 3292f020780b4d5baf27ff7e1d224c44
- region:
- description: Region Name.
- type: str
- sample: RegionOne
- service_id:
- description: Service ID.
- type: str
- sample: b91f1318f735494a825a55388ee118f3
- interface:
- description: Endpoint Interface.
- type: str
- sample: public
- url:
- description: Service URL.
- type: str
- sample: http://controller:9292
- enabled:
- description: Service status.
- type: bool
- sample: True
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _needs_update(module, endpoint):
- if endpoint.enabled != module.params['enabled']:
- return True
- if endpoint.url != module.params['url']:
- return True
- return False
-
-
-def _system_state_change(module, endpoint):
- state = module.params['state']
- if state == 'absent' and endpoint:
- return True
-
- if state == 'present':
- if endpoint is None:
- return True
- return _needs_update(module, endpoint)
-
- return False
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- service=dict(type='str', required=True),
- endpoint_interface=dict(type='str', required=True, choices=['admin', 'public', 'internal']),
- url=dict(type='str', required=True),
- region=dict(type='str'),
- enabled=dict(type='bool', default=True),
- state=dict(type='str', default='present', choices=['absent', 'present']),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- service_name_or_id = module.params['service']
- interface = module.params['endpoint_interface']
- url = module.params['url']
- region = module.params['region']
- enabled = module.params['enabled']
- state = module.params['state']
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
-
- service = cloud.get_service(service_name_or_id)
- if service is None:
- module.fail_json(msg='Service %s does not exist' % service_name_or_id)
-
- filters = dict(service_id=service.id, interface=interface)
- if region is not None:
- filters['region'] = region
- endpoints = cloud.search_endpoints(filters=filters)
-
- if len(endpoints) > 1:
- module.fail_json(msg='Service %s, interface %s and region %s are '
- 'not unique' %
- (service_name_or_id, interface, region))
- elif len(endpoints) == 1:
- endpoint = endpoints[0]
- else:
- endpoint = None
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(module, endpoint))
-
- if state == 'present':
- if endpoint is None:
- result = cloud.create_endpoint(service_name_or_id=service,
- url=url, interface=interface,
- region=region, enabled=enabled)
- endpoint = result[0]
- changed = True
- else:
- if _needs_update(module, endpoint):
- endpoint = cloud.update_endpoint(
- endpoint.id, url=url, enabled=enabled)
- changed = True
- else:
- changed = False
- module.exit_json(changed=changed, endpoint=endpoint)
-
- elif state == 'absent':
- if endpoint is None:
- changed = False
- else:
- cloud.delete_endpoint(endpoint.id)
- changed = True
- module.exit_json(changed=changed)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_keystone_role.py b/lib/ansible/modules/cloud/openstack/os_keystone_role.py
deleted file mode 100644
index e3a752706e..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_keystone_role.py
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2016 IBM
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_keystone_role
-short_description: Manage OpenStack Identity Roles
-extends_documentation_fragment: openstack
-version_added: "2.1"
-author:
- - Monty Taylor (@emonty)
- - David Shrewsbury (@Shrews)
-description:
- - Manage OpenStack Identity Roles.
-options:
- name:
- description:
- - Role Name
- required: true
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
- required: false
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-# Create a role named "demo"
-- os_keystone_role:
- cloud: mycloud
- state: present
- name: demo
-
-# Delete the role named "demo"
-- os_keystone_role:
- cloud: mycloud
- state: absent
- name: demo
-'''
-
-RETURN = '''
-role:
- description: Dictionary describing the role.
- returned: On success when I(state) is 'present'.
- type: complex
- contains:
- id:
- description: Unique role ID.
- type: str
- sample: "677bfab34c844a01b88a217aa12ec4c2"
- name:
- description: Role name.
- type: str
- sample: "demo"
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _system_state_change(state, role):
- if state == 'present' and not role:
- return True
- if state == 'absent' and role:
- return True
- return False
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- state=dict(default='present', choices=['absent', 'present']),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- name = module.params.get('name')
- state = module.params.get('state')
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- role = cloud.get_role(name)
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(state, role))
-
- if state == 'present':
- if role is None:
- role = cloud.create_role(name)
- changed = True
- else:
- changed = False
- module.exit_json(changed=changed, role=role)
- elif state == 'absent':
- if role is None:
- changed = False
- else:
- cloud.delete_role(name)
- changed = True
- module.exit_json(changed=changed)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_keystone_service.py b/lib/ansible/modules/cloud/openstack/os_keystone_service.py
deleted file mode 100644
index cd11e4ceca..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_keystone_service.py
+++ /dev/null
@@ -1,194 +0,0 @@
-#!/usr/bin/python
-# Copyright 2016 Sam Yaple
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_keystone_service
-short_description: Manage OpenStack Identity services
-extends_documentation_fragment: openstack
-author: "Sam Yaple (@SamYaple)"
-version_added: "2.2"
-description:
- - Create, update, or delete OpenStack Identity service. If a service
- with the supplied name already exists, it will be updated with the
- new description and enabled attributes.
-options:
- name:
- description:
- - Name of the service
- required: true
- description:
- description:
- - Description of the service
- enabled:
- description:
- - Is the service enabled
- type: bool
- default: 'yes'
- service_type:
- description:
- - The type of service
- required: true
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-# Create a service for glance
-- os_keystone_service:
- cloud: mycloud
- state: present
- name: glance
- service_type: image
- description: OpenStack Image Service
-# Delete a service
-- os_keystone_service:
- cloud: mycloud
- state: absent
- name: glance
- service_type: image
-'''
-
-RETURN = '''
-service:
- description: Dictionary describing the service.
- returned: On success when I(state) is 'present'
- type: complex
- contains:
- id:
- description: Service ID.
- type: str
- sample: "3292f020780b4d5baf27ff7e1d224c44"
- name:
- description: Service name.
- type: str
- sample: "glance"
- service_type:
- description: Service type.
- type: str
- sample: "image"
- description:
- description: Service description.
- type: str
- sample: "OpenStack Image Service"
- enabled:
- description: Service status.
- type: bool
- sample: True
-id:
- description: The service ID.
- returned: On success when I(state) is 'present'
- type: str
- sample: "3292f020780b4d5baf27ff7e1d224c44"
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _needs_update(module, service):
- if service.enabled != module.params['enabled']:
- return True
- if service.description is not None and \
- service.description != module.params['description']:
- return True
- return False
-
-
-def _system_state_change(module, service):
- state = module.params['state']
- if state == 'absent' and service:
- return True
-
- if state == 'present':
- if service is None:
- return True
- return _needs_update(module, service)
-
- return False
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- description=dict(default=None),
- enabled=dict(default=True, type='bool'),
- name=dict(required=True),
- service_type=dict(required=True),
- state=dict(default='present', choices=['absent', 'present']),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- description = module.params['description']
- enabled = module.params['enabled']
- name = module.params['name']
- state = module.params['state']
- service_type = module.params['service_type']
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- services = cloud.search_services(name_or_id=name,
- filters=dict(type=service_type))
-
- if len(services) > 1:
- module.fail_json(msg='Service name %s and type %s are not unique' %
- (name, service_type))
- elif len(services) == 1:
- service = services[0]
- else:
- service = None
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(module, service))
-
- if state == 'present':
- if service is None:
- service = cloud.create_service(name=name, description=description,
- type=service_type, enabled=True)
- changed = True
- else:
- if _needs_update(module, service):
- service = cloud.update_service(
- service.id, name=name, type=service_type, enabled=enabled,
- description=description)
- changed = True
- else:
- changed = False
- module.exit_json(changed=changed, service=service, id=service.id)
-
- elif state == 'absent':
- if service is None:
- changed = False
- else:
- cloud.delete_service(service.id)
- changed = True
- module.exit_json(changed=changed)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_listener.py b/lib/ansible/modules/cloud/openstack/os_listener.py
deleted file mode 100644
index 6d29f55e9f..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_listener.py
+++ /dev/null
@@ -1,256 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2018 Catalyst Cloud Ltd.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: os_listener
-short_description: Add/Delete a listener for a load balancer from OpenStack Cloud
-extends_documentation_fragment: openstack
-version_added: "2.7"
-author: "Lingxian Kong (@lingxiankong)"
-description:
- - Add or Remove a listener for a load balancer from the OpenStack load-balancer service.
-options:
- name:
- description:
- - Name that has to be given to the listener
- required: true
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- loadbalancer:
- description:
- - The name or id of the load balancer that this listener belongs to.
- required: true
- protocol:
- description:
- - The protocol for the listener.
- choices: [HTTP, HTTPS, TCP, TERMINATED_HTTPS]
- default: HTTP
- protocol_port:
- description:
- - The protocol port number for the listener.
- default: 80
- wait:
- description:
- - If the module should wait for the load balancer to be ACTIVE.
- type: bool
- default: 'yes'
- timeout:
- description:
- - The amount of time the module should wait for the load balancer to get
- into ACTIVE state.
- default: 180
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-requirements: ["openstacksdk"]
-'''
-
-RETURN = '''
-id:
- description: The listener UUID.
- returned: On success when I(state) is 'present'
- type: str
- sample: "39007a7e-ee4f-4d13-8283-b4da2e037c69"
-listener:
- description: Dictionary describing the listener.
- returned: On success when I(state) is 'present'
- type: complex
- contains:
- id:
- description: Unique UUID.
- type: str
- sample: "39007a7e-ee4f-4d13-8283-b4da2e037c69"
- name:
- description: Name given to the listener.
- type: str
- sample: "test"
- description:
- description: The listener description.
- type: str
- sample: "description"
- load_balancer_id:
- description: The load balancer UUID this listener belongs to.
- type: str
- sample: "b32eef7e-d2a6-4ea4-a301-60a873f89b3b"
- loadbalancers:
- description: A list of load balancer IDs..
- type: list
- sample: [{"id": "b32eef7e-d2a6-4ea4-a301-60a873f89b3b"}]
- provisioning_status:
- description: The provisioning status of the listener.
- type: str
- sample: "ACTIVE"
- operating_status:
- description: The operating status of the listener.
- type: str
- sample: "ONLINE"
- is_admin_state_up:
- description: The administrative state of the listener.
- type: bool
- sample: true
- protocol:
- description: The protocol for the listener.
- type: str
- sample: "HTTP"
- protocol_port:
- description: The protocol port number for the listener.
- type: int
- sample: 80
-'''
-
-EXAMPLES = '''
-# Create a listener, wait for the loadbalancer to be active.
-- os_listener:
- cloud: mycloud
- endpoint_type: admin
- state: present
- name: test-listener
- loadbalancer: test-loadbalancer
- protocol: HTTP
- protocol_port: 8080
-
-# Create a listener, do not wait for the loadbalancer to be active.
-- os_listener:
- cloud: mycloud
- endpoint_type: admin
- state: present
- name: test-listener
- loadbalancer: test-loadbalancer
- protocol: HTTP
- protocol_port: 8080
- wait: no
-
-# Delete a listener
-- os_listener:
- cloud: mycloud
- endpoint_type: admin
- state: absent
- name: test-listener
- loadbalancer: test-loadbalancer
-'''
-
-import time
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, \
- openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _lb_wait_for_status(module, cloud, lb, status, failures, interval=5):
- """Wait for load balancer to be in a particular provisioning status."""
- timeout = module.params['timeout']
-
- total_sleep = 0
- if failures is None:
- failures = []
-
- while total_sleep < timeout:
- lb = cloud.load_balancer.get_load_balancer(lb.id)
- if lb.provisioning_status == status:
- return None
- if lb.provisioning_status in failures:
- module.fail_json(
- msg="Load Balancer %s transitioned to failure state %s" %
- (lb.id, lb.provisioning_status)
- )
-
- time.sleep(interval)
- total_sleep += interval
-
- module.fail_json(
- msg="Timeout waiting for Load Balancer %s to transition to %s" %
- (lb.id, status)
- )
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- state=dict(default='present', choices=['absent', 'present']),
- loadbalancer=dict(required=True),
- protocol=dict(default='HTTP',
- choices=['HTTP', 'HTTPS', 'TCP', 'TERMINATED_HTTPS']),
- protocol_port=dict(default=80, type='int', required=False),
- )
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec, **module_kwargs)
- sdk, cloud = openstack_cloud_from_module(module)
- loadbalancer = module.params['loadbalancer']
- loadbalancer_id = None
-
- try:
- changed = False
- listener = cloud.load_balancer.find_listener(
- name_or_id=module.params['name'])
-
- if module.params['state'] == 'present':
- if not listener:
- lb = cloud.load_balancer.find_load_balancer(loadbalancer)
- if not lb:
- module.fail_json(
- msg='load balancer %s is not found' % loadbalancer
- )
- loadbalancer_id = lb.id
-
- listener = cloud.load_balancer.create_listener(
- name=module.params['name'],
- loadbalancer_id=loadbalancer_id,
- protocol=module.params['protocol'],
- protocol_port=module.params['protocol_port'],
- )
- changed = True
-
- if not module.params['wait']:
- module.exit_json(changed=changed,
- listener=listener.to_dict(),
- id=listener.id)
-
- if module.params['wait']:
- # Check in case the listener already exists.
- lb = cloud.load_balancer.find_load_balancer(loadbalancer)
- if not lb:
- module.fail_json(
- msg='load balancer %s is not found' % loadbalancer
- )
- _lb_wait_for_status(module, cloud, lb, "ACTIVE", ["ERROR"])
-
- module.exit_json(changed=changed, listener=listener.to_dict(),
- id=listener.id)
- elif module.params['state'] == 'absent':
- if not listener:
- changed = False
- else:
- cloud.load_balancer.delete_listener(listener)
- changed = True
-
- if module.params['wait']:
- # Wait for the load balancer to be active after deleting
- # the listener.
- lb = cloud.load_balancer.find_load_balancer(loadbalancer)
- if not lb:
- module.fail_json(
- msg='load balancer %s is not found' % loadbalancer
- )
- _lb_wait_for_status(module, cloud, lb, "ACTIVE", ["ERROR"])
-
- module.exit_json(changed=changed)
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e), extra_data=e.extra_data)
-
-
-if __name__ == "__main__":
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_loadbalancer.py b/lib/ansible/modules/cloud/openstack/os_loadbalancer.py
deleted file mode 100644
index f1ff83eea7..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_loadbalancer.py
+++ /dev/null
@@ -1,605 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2018 Catalyst Cloud Ltd.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: os_loadbalancer
-short_description: Add/Delete load balancer from OpenStack Cloud
-extends_documentation_fragment: openstack
-version_added: "2.7"
-author: "Lingxian Kong (@lingxiankong)"
-description:
- - Add or Remove load balancer from the OpenStack load-balancer
- service(Octavia). Load balancer update is not supported for now.
-options:
- name:
- description:
- - Name that has to be given to the load balancer
- required: true
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- vip_network:
- description:
- - The name or id of the network for the virtual IP of the load balancer.
- One of I(vip_network), I(vip_subnet), or I(vip_port) must be specified
- for creation.
- vip_subnet:
- description:
- - The name or id of the subnet for the virtual IP of the load balancer.
- One of I(vip_network), I(vip_subnet), or I(vip_port) must be specified
- for creation.
- vip_port:
- description:
- - The name or id of the load balancer virtual IP port. One of
- I(vip_network), I(vip_subnet), or I(vip_port) must be specified for
- creation.
- vip_address:
- description:
- - IP address of the load balancer virtual IP.
- public_ip_address:
- description:
- - Public IP address associated with the VIP.
- auto_public_ip:
- description:
- - Allocate a public IP address and associate with the VIP automatically.
- type: bool
- default: 'no'
- public_network:
- description:
- - The name or ID of a Neutron external network.
- delete_public_ip:
- description:
- - When C(state=absent) and this option is true, any public IP address
- associated with the VIP will be deleted along with the load balancer.
- type: bool
- default: 'no'
- listeners:
- description:
- - A list of listeners that attached to the load balancer.
- suboptions:
- name:
- description:
- - The listener name or ID.
- protocol:
- description:
- - The protocol for the listener.
- default: HTTP
- protocol_port:
- description:
- - The protocol port number for the listener.
- default: 80
- pool:
- description:
- - The pool attached to the listener.
- suboptions:
- name:
- description:
- - The pool name or ID.
- protocol:
- description:
- - The protocol for the pool.
- default: HTTP
- lb_algorithm:
- description:
- - The load balancing algorithm for the pool.
- default: ROUND_ROBIN
- members:
- description:
- - A list of members that added to the pool.
- suboptions:
- name:
- description:
- - The member name or ID.
- address:
- description:
- - The IP address of the member.
- protocol_port:
- description:
- - The protocol port number for the member.
- default: 80
- subnet:
- description:
- - The name or ID of the subnet the member service is
- accessible from.
- wait:
- description:
- - If the module should wait for the load balancer to be created or
- deleted.
- type: bool
- default: 'yes'
- timeout:
- description:
- - The amount of time the module should wait.
- default: 180
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-requirements: ["openstacksdk"]
-'''
-
-RETURN = '''
-id:
- description: The load balancer UUID.
- returned: On success when C(state=present)
- type: str
- sample: "39007a7e-ee4f-4d13-8283-b4da2e037c69"
-loadbalancer:
- description: Dictionary describing the load balancer.
- returned: On success when C(state=present)
- type: complex
- contains:
- id:
- description: Unique UUID.
- type: str
- sample: "39007a7e-ee4f-4d13-8283-b4da2e037c69"
- name:
- description: Name given to the load balancer.
- type: str
- sample: "lingxian_test"
- vip_network_id:
- description: Network ID the load balancer virtual IP port belongs in.
- type: str
- sample: "f171db43-56fd-41cf-82d7-4e91d741762e"
- vip_subnet_id:
- description: Subnet ID the load balancer virtual IP port belongs in.
- type: str
- sample: "c53e3c70-9d62-409a-9f71-db148e7aa853"
- vip_port_id:
- description: The load balancer virtual IP port ID.
- type: str
- sample: "2061395c-1c01-47ab-b925-c91b93df9c1d"
- vip_address:
- description: The load balancer virtual IP address.
- type: str
- sample: "192.168.2.88"
- public_vip_address:
- description: The load balancer public VIP address.
- type: str
- sample: "10.17.8.254"
- provisioning_status:
- description: The provisioning status of the load balancer.
- type: str
- sample: "ACTIVE"
- operating_status:
- description: The operating status of the load balancer.
- type: str
- sample: "ONLINE"
- is_admin_state_up:
- description: The administrative state of the load balancer.
- type: bool
- sample: true
- listeners:
- description: The associated listener IDs, if any.
- type: list
- sample: [{"id": "7aa1b380-beec-459c-a8a7-3a4fb6d30645"}, {"id": "692d06b8-c4f8-4bdb-b2a3-5a263cc23ba6"}]
- pools:
- description: The associated pool IDs, if any.
- type: list
- sample: [{"id": "27b78d92-cee1-4646-b831-e3b90a7fa714"}, {"id": "befc1fb5-1992-4697-bdb9-eee330989344"}]
-'''
-
-EXAMPLES = '''
-# Create a load balancer by specifying the VIP subnet.
-- os_loadbalancer:
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: passme
- project_name: admin
- state: present
- name: my_lb
- vip_subnet: my_subnet
- timeout: 150
-
-# Create a load balancer by specifying the VIP network and the IP address.
-- os_loadbalancer:
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: passme
- project_name: admin
- state: present
- name: my_lb
- vip_network: my_network
- vip_address: 192.168.0.11
-
-# Create a load balancer together with its sub-resources in the 'all in one'
-# way. A public IP address is also allocated to the load balancer VIP.
-- os_loadbalancer:
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: passme
- project_name: admin
- name: lingxian_test
- state: present
- vip_subnet: kong_subnet
- auto_public_ip: yes
- public_network: public
- listeners:
- - name: lingxian_80
- protocol: TCP
- protocol_port: 80
- pool:
- name: lingxian_80_pool
- protocol: TCP
- members:
- - name: mywebserver1
- address: 192.168.2.81
- protocol_port: 80
- subnet: webserver_subnet
- - name: lingxian_8080
- protocol: TCP
- protocol_port: 8080
- pool:
- name: lingxian_8080-pool
- protocol: TCP
- members:
- - name: mywebserver2
- address: 192.168.2.82
- protocol_port: 8080
- wait: yes
- timeout: 600
-
-# Delete a load balancer(and all its related resources)
-- os_loadbalancer:
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: passme
- project_name: admin
- state: absent
- name: my_lb
-
-# Delete a load balancer(and all its related resources) together with the
-# public IP address(if any) attached to it.
-- os_loadbalancer:
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: passme
- project_name: admin
- state: absent
- name: my_lb
- delete_public_ip: yes
-'''
-
-import time
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, \
- openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _wait_for_lb(module, cloud, lb, status, failures, interval=5):
- """Wait for load balancer to be in a particular provisioning status."""
- timeout = module.params['timeout']
-
- total_sleep = 0
- if failures is None:
- failures = []
-
- while total_sleep < timeout:
- lb = cloud.load_balancer.find_load_balancer(lb.id)
-
- if lb:
- if lb.provisioning_status == status:
- return None
- if lb.provisioning_status in failures:
- module.fail_json(
- msg="Load Balancer %s transitioned to failure state %s" %
- (lb.id, lb.provisioning_status)
- )
- else:
- if status == "DELETED":
- return None
- else:
- module.fail_json(
- msg="Load Balancer %s transitioned to DELETED" % lb.id
- )
-
- time.sleep(interval)
- total_sleep += interval
-
- module.fail_json(
- msg="Timeout waiting for Load Balancer %s to transition to %s" %
- (lb.id, status)
- )
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- state=dict(default='present', choices=['absent', 'present']),
- vip_network=dict(required=False),
- vip_subnet=dict(required=False),
- vip_port=dict(required=False),
- vip_address=dict(required=False),
- listeners=dict(type='list', default=[]),
- public_ip_address=dict(required=False, default=None),
- auto_public_ip=dict(required=False, default=False, type='bool'),
- public_network=dict(required=False),
- delete_public_ip=dict(required=False, default=False, type='bool'),
- )
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec, **module_kwargs)
- sdk, cloud = openstack_cloud_from_module(module)
-
- vip_network = module.params['vip_network']
- vip_subnet = module.params['vip_subnet']
- vip_port = module.params['vip_port']
- listeners = module.params['listeners']
- public_vip_address = module.params['public_ip_address']
- allocate_fip = module.params['auto_public_ip']
- delete_fip = module.params['delete_public_ip']
- public_network = module.params['public_network']
-
- vip_network_id = None
- vip_subnet_id = None
- vip_port_id = None
-
- try:
- changed = False
- lb = cloud.load_balancer.find_load_balancer(
- name_or_id=module.params['name'])
-
- if module.params['state'] == 'present':
- if not lb:
- if not (vip_network or vip_subnet or vip_port):
- module.fail_json(
- msg="One of vip_network, vip_subnet, or vip_port must "
- "be specified for load balancer creation"
- )
-
- if vip_network:
- network = cloud.get_network(vip_network)
- if not network:
- module.fail_json(
- msg='network %s is not found' % vip_network
- )
- vip_network_id = network.id
- if vip_subnet:
- subnet = cloud.get_subnet(vip_subnet)
- if not subnet:
- module.fail_json(
- msg='subnet %s is not found' % vip_subnet
- )
- vip_subnet_id = subnet.id
- if vip_port:
- port = cloud.get_port(vip_port)
- if not port:
- module.fail_json(
- msg='port %s is not found' % vip_port
- )
- vip_port_id = port.id
-
- lb = cloud.load_balancer.create_load_balancer(
- name=module.params['name'],
- vip_network_id=vip_network_id,
- vip_subnet_id=vip_subnet_id,
- vip_port_id=vip_port_id,
- vip_address=module.params['vip_address'],
- )
- changed = True
-
- if not listeners and not module.params['wait']:
- module.exit_json(
- changed=changed,
- loadbalancer=lb.to_dict(),
- id=lb.id
- )
-
- _wait_for_lb(module, cloud, lb, "ACTIVE", ["ERROR"])
-
- for listener_def in listeners:
- listener_name = listener_def.get("name")
- pool_def = listener_def.get("pool")
-
- if not listener_name:
- module.fail_json(msg='listener name is required')
-
- listener = cloud.load_balancer.find_listener(
- name_or_id=listener_name
- )
-
- if not listener:
- _wait_for_lb(module, cloud, lb, "ACTIVE", ["ERROR"])
-
- protocol = listener_def.get("protocol", "HTTP")
- protocol_port = listener_def.get("protocol_port", 80)
-
- listener = cloud.load_balancer.create_listener(
- name=listener_name,
- loadbalancer_id=lb.id,
- protocol=protocol,
- protocol_port=protocol_port,
- )
- changed = True
-
- # Ensure pool in the listener.
- if pool_def:
- pool_name = pool_def.get("name")
- members = pool_def.get('members', [])
-
- if not pool_name:
- module.fail_json(msg='pool name is required')
-
- pool = cloud.load_balancer.find_pool(name_or_id=pool_name)
-
- if not pool:
- _wait_for_lb(module, cloud, lb, "ACTIVE", ["ERROR"])
-
- protocol = pool_def.get("protocol", "HTTP")
- lb_algorithm = pool_def.get("lb_algorithm",
- "ROUND_ROBIN")
-
- pool = cloud.load_balancer.create_pool(
- name=pool_name,
- listener_id=listener.id,
- protocol=protocol,
- lb_algorithm=lb_algorithm
- )
- changed = True
-
- # Ensure members in the pool
- for member_def in members:
- member_name = member_def.get("name")
- if not member_name:
- module.fail_json(msg='member name is required')
-
- member = cloud.load_balancer.find_member(member_name,
- pool.id)
-
- if not member:
- _wait_for_lb(module, cloud, lb, "ACTIVE",
- ["ERROR"])
-
- address = member_def.get("address")
- if not address:
- module.fail_json(
- msg='member address for member %s is '
- 'required' % member_name
- )
-
- subnet_id = member_def.get("subnet")
- if subnet_id:
- subnet = cloud.get_subnet(subnet_id)
- if not subnet:
- module.fail_json(
- msg='subnet %s for member %s is not '
- 'found' % (subnet_id, member_name)
- )
- subnet_id = subnet.id
-
- protocol_port = member_def.get("protocol_port", 80)
-
- member = cloud.load_balancer.create_member(
- pool,
- name=member_name,
- address=address,
- protocol_port=protocol_port,
- subnet_id=subnet_id
- )
- changed = True
-
- # Associate public ip to the load balancer VIP. If
- # public_vip_address is provided, use that IP, otherwise, either
- # find an available public ip or create a new one.
- fip = None
- orig_public_ip = None
- new_public_ip = None
- if public_vip_address or allocate_fip:
- ips = cloud.network.ips(
- port_id=lb.vip_port_id,
- fixed_ip_address=lb.vip_address
- )
- ips = list(ips)
- if ips:
- orig_public_ip = ips[0]
- new_public_ip = orig_public_ip.floating_ip_address
-
- if public_vip_address and public_vip_address != orig_public_ip:
- fip = cloud.network.find_ip(public_vip_address)
- if not fip:
- module.fail_json(
- msg='Public IP %s is unavailable' % public_vip_address
- )
-
- # Release origin public ip first
- cloud.network.update_ip(
- orig_public_ip,
- fixed_ip_address=None,
- port_id=None
- )
-
- # Associate new public ip
- cloud.network.update_ip(
- fip,
- fixed_ip_address=lb.vip_address,
- port_id=lb.vip_port_id
- )
-
- new_public_ip = public_vip_address
- changed = True
- elif allocate_fip and not orig_public_ip:
- fip = cloud.network.find_available_ip()
- if not fip:
- if not public_network:
- module.fail_json(msg="Public network is not provided")
-
- pub_net = cloud.network.find_network(public_network)
- if not pub_net:
- module.fail_json(
- msg='Public network %s not found' %
- public_network
- )
- fip = cloud.network.create_ip(
- floating_network_id=pub_net.id
- )
-
- cloud.network.update_ip(
- fip,
- fixed_ip_address=lb.vip_address,
- port_id=lb.vip_port_id
- )
-
- new_public_ip = fip.floating_ip_address
- changed = True
-
- # Include public_vip_address in the result.
- lb = cloud.load_balancer.find_load_balancer(name_or_id=lb.id)
- lb_dict = lb.to_dict()
- lb_dict.update({"public_vip_address": new_public_ip})
-
- module.exit_json(
- changed=changed,
- loadbalancer=lb_dict,
- id=lb.id
- )
- elif module.params['state'] == 'absent':
- changed = False
- public_vip_address = None
-
- if lb:
- if delete_fip:
- ips = cloud.network.ips(
- port_id=lb.vip_port_id,
- fixed_ip_address=lb.vip_address
- )
- ips = list(ips)
- if ips:
- public_vip_address = ips[0]
-
- # Deleting load balancer with `cascade=False` does not make
- # sense because the deletion will always fail if there are
- # sub-resources.
- cloud.load_balancer.delete_load_balancer(lb, cascade=True)
- changed = True
-
- if module.params['wait']:
- _wait_for_lb(module, cloud, lb, "DELETED", ["ERROR"])
-
- if delete_fip and public_vip_address:
- cloud.network.delete_ip(public_vip_address)
- changed = True
-
- module.exit_json(changed=changed)
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e), extra_data=e.extra_data)
-
-
-if __name__ == "__main__":
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_member.py b/lib/ansible/modules/cloud/openstack/os_member.py
deleted file mode 100644
index 7b5632ec6d..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_member.py
+++ /dev/null
@@ -1,227 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2018 Catalyst Cloud Ltd.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: os_member
-short_description: Add/Delete a member for a pool in load balancer from OpenStack Cloud
-extends_documentation_fragment: openstack
-version_added: "2.7"
-author: "Lingxian Kong (@lingxiankong)"
-description:
- - Add or Remove a member for a pool from the OpenStack load-balancer service.
-options:
- name:
- description:
- - Name that has to be given to the member
- required: true
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- pool:
- description:
- - The name or id of the pool that this member belongs to.
- required: true
- protocol_port:
- description:
- - The protocol port number for the member.
- default: 80
- address:
- description:
- - The IP address of the member.
- subnet_id:
- description:
- - The subnet ID the member service is accessible from.
- wait:
- description:
- - If the module should wait for the load balancer to be ACTIVE.
- type: bool
- default: 'yes'
- timeout:
- description:
- - The amount of time the module should wait for the load balancer to get
- into ACTIVE state.
- default: 180
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-requirements: ["openstacksdk"]
-'''
-
-RETURN = '''
-id:
- description: The member UUID.
- returned: On success when I(state) is 'present'
- type: str
- sample: "39007a7e-ee4f-4d13-8283-b4da2e037c69"
-member:
- description: Dictionary describing the member.
- returned: On success when I(state) is 'present'
- type: complex
- contains:
- id:
- description: Unique UUID.
- type: str
- sample: "39007a7e-ee4f-4d13-8283-b4da2e037c69"
- name:
- description: Name given to the member.
- type: str
- sample: "test"
- description:
- description: The member description.
- type: str
- sample: "description"
- provisioning_status:
- description: The provisioning status of the member.
- type: str
- sample: "ACTIVE"
- operating_status:
- description: The operating status of the member.
- type: str
- sample: "ONLINE"
- is_admin_state_up:
- description: The administrative state of the member.
- type: bool
- sample: true
- protocol_port:
- description: The protocol port number for the member.
- type: int
- sample: 80
- subnet_id:
- description: The subnet ID the member service is accessible from.
- type: str
- sample: "489247fa-9c25-11e8-9679-00224d6b7bc1"
- address:
- description: The IP address of the backend member server.
- type: str
- sample: "192.168.2.10"
-'''
-
-EXAMPLES = '''
-# Create a member, wait for the member to be created.
-- os_member:
- cloud: mycloud
- endpoint_type: admin
- state: present
- name: test-member
- pool: test-pool
- address: 192.168.10.3
- protocol_port: 8080
-
-# Delete a listener
-- os_member:
- cloud: mycloud
- endpoint_type: admin
- state: absent
- name: test-member
- pool: test-pool
-'''
-
-import time
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, \
- openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _wait_for_member_status(module, cloud, pool_id, member_id, status,
- failures, interval=5):
- timeout = module.params['timeout']
-
- total_sleep = 0
- if failures is None:
- failures = []
-
- while total_sleep < timeout:
- member = cloud.load_balancer.get_member(member_id, pool_id)
- provisioning_status = member.provisioning_status
- if provisioning_status == status:
- return member
- if provisioning_status in failures:
- module.fail_json(
- msg="Member %s transitioned to failure state %s" %
- (member_id, provisioning_status)
- )
-
- time.sleep(interval)
- total_sleep += interval
-
- module.fail_json(
- msg="Timeout waiting for member %s to transition to %s" %
- (member_id, status)
- )
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- state=dict(default='present', choices=['absent', 'present']),
- pool=dict(required=True),
- address=dict(default=None),
- protocol_port=dict(default=80, type='int'),
- subnet_id=dict(default=None),
- )
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec, **module_kwargs)
- sdk, cloud = openstack_cloud_from_module(module)
- name = module.params['name']
- pool = module.params['pool']
-
- try:
- changed = False
-
- pool_ret = cloud.load_balancer.find_pool(name_or_id=pool)
- if not pool_ret:
- module.fail_json(msg='pool %s is not found' % pool)
-
- pool_id = pool_ret.id
- member = cloud.load_balancer.find_member(name, pool_id)
-
- if module.params['state'] == 'present':
- if not member:
- member = cloud.load_balancer.create_member(
- pool_ret,
- address=module.params['address'],
- name=name,
- protocol_port=module.params['protocol_port'],
- subnet_id=module.params['subnet_id']
- )
- changed = True
-
- if not module.params['wait']:
- module.exit_json(changed=changed,
- member=member.to_dict(),
- id=member.id)
-
- if module.params['wait']:
- member = _wait_for_member_status(module, cloud, pool_id,
- member.id, "ACTIVE",
- ["ERROR"])
-
- module.exit_json(changed=changed, member=member.to_dict(),
- id=member.id)
-
- elif module.params['state'] == 'absent':
- if member:
- cloud.load_balancer.delete_member(member, pool_ret)
- changed = True
-
- module.exit_json(changed=changed)
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e), extra_data=e.extra_data)
-
-
-if __name__ == "__main__":
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_network.py b/lib/ansible/modules/cloud/openstack/os_network.py
deleted file mode 100644
index 79f4b0f9e3..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_network.py
+++ /dev/null
@@ -1,255 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
-# Copyright (c) 2013, Benno Joy <benno@ansible.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_network
-short_description: Creates/removes networks from OpenStack
-extends_documentation_fragment: openstack
-version_added: "2.0"
-author: "Monty Taylor (@emonty)"
-description:
- - Add or remove network from OpenStack.
-options:
- name:
- description:
- - Name to be assigned to the network.
- required: true
- shared:
- description:
- - Whether this network is shared or not.
- type: bool
- default: 'no'
- admin_state_up:
- description:
- - Whether the state should be marked as up or down.
- type: bool
- default: 'yes'
- external:
- description:
- - Whether this network is externally accessible.
- type: bool
- default: 'no'
- state:
- description:
- - Indicate desired state of the resource.
- choices: ['present', 'absent']
- default: present
- provider_physical_network:
- description:
- - The physical network where this network object is implemented.
- version_added: "2.1"
- provider_network_type:
- description:
- - The type of physical network that maps to this network resource.
- version_added: "2.1"
- provider_segmentation_id:
- description:
- - An isolated segment on the physical network. The I(network_type)
- attribute defines the segmentation model. For example, if the
- I(network_type) value is vlan, this ID is a vlan identifier. If
- the I(network_type) value is gre, this ID is a gre key.
- version_added: "2.1"
- project:
- description:
- - Project name or ID containing the network (name admin-only)
- version_added: "2.1"
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
- port_security_enabled:
- description:
- - Whether port security is enabled on the network or not.
- Network will use OpenStack defaults if this option is
- not utilised.
- type: bool
- version_added: "2.8"
- mtu:
- description:
- - The maximum transmission unit (MTU) value to address fragmentation.
- Network will use OpenStack defaults if this option is
- not provided.
- type: int
- version_added: "2.9"
- dns_domain:
- description:
- - The DNS domain value to set.
- Network will use Openstack defaults if this option is
- not provided.
- version_added: "2.9"
-requirements:
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-# Create an externally accessible network named 'ext_network'.
-- os_network:
- cloud: mycloud
- state: present
- name: ext_network
- external: true
-'''
-
-RETURN = '''
-network:
- description: Dictionary describing the network.
- returned: On success when I(state) is 'present'.
- type: complex
- contains:
- id:
- description: Network ID.
- type: str
- sample: "4bb4f9a5-3bd2-4562-bf6a-d17a6341bb56"
- name:
- description: Network name.
- type: str
- sample: "ext_network"
- shared:
- description: Indicates whether this network is shared across all tenants.
- type: bool
- sample: false
- status:
- description: Network status.
- type: str
- sample: "ACTIVE"
- mtu:
- description: The MTU of a network resource.
- type: int
- sample: 0
- dns_domain:
- description: The DNS domain of a network resource.
- type: str
- sample: "sample.openstack.org."
- admin_state_up:
- description: The administrative state of the network.
- type: bool
- sample: true
- port_security_enabled:
- description: The port security status
- type: bool
- sample: true
- router:external:
- description: Indicates whether this network is externally accessible.
- type: bool
- sample: true
- tenant_id:
- description: The tenant ID.
- type: str
- sample: "06820f94b9f54b119636be2728d216fc"
- subnets:
- description: The associated subnets.
- type: list
- sample: []
- "provider:physical_network":
- description: The physical network where this network object is implemented.
- type: str
- sample: my_vlan_net
- "provider:network_type":
- description: The type of physical network that maps to this network resource.
- type: str
- sample: vlan
- "provider:segmentation_id":
- description: An isolated segment on the physical network.
- type: str
- sample: 101
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- shared=dict(default=False, type='bool'),
- admin_state_up=dict(default=True, type='bool'),
- external=dict(default=False, type='bool'),
- provider_physical_network=dict(required=False),
- provider_network_type=dict(required=False),
- provider_segmentation_id=dict(required=False, type='int'),
- state=dict(default='present', choices=['absent', 'present']),
- project=dict(default=None),
- port_security_enabled=dict(type='bool'),
- mtu=dict(required=False, type='int'),
- dns_domain=dict(required=False)
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec, **module_kwargs)
-
- state = module.params['state']
- name = module.params['name']
- shared = module.params['shared']
- admin_state_up = module.params['admin_state_up']
- external = module.params['external']
- provider_physical_network = module.params['provider_physical_network']
- provider_network_type = module.params['provider_network_type']
- provider_segmentation_id = module.params['provider_segmentation_id']
- project = module.params.get('project')
- port_security_enabled = module.params.get('port_security_enabled')
- mtu = module.params.get('mtu')
- dns_domain = module.params.get('dns_domain')
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- if project is not None:
- proj = cloud.get_project(project)
- if proj is None:
- module.fail_json(msg='Project %s could not be found' % project)
- project_id = proj['id']
- filters = {'tenant_id': project_id}
- else:
- project_id = None
- filters = None
- net = cloud.get_network(name, filters=filters)
-
- if state == 'present':
- if not net:
- provider = {}
- if provider_physical_network:
- provider['physical_network'] = provider_physical_network
- if provider_network_type:
- provider['network_type'] = provider_network_type
- if provider_segmentation_id:
- provider['segmentation_id'] = provider_segmentation_id
-
- if project_id is not None:
- net = cloud.create_network(name, shared, admin_state_up,
- external, provider, project_id,
- port_security_enabled=port_security_enabled,
- mtu_size=mtu, dns_domain=dns_domain)
- else:
- net = cloud.create_network(name, shared, admin_state_up,
- external, provider,
- port_security_enabled=port_security_enabled,
- mtu_size=mtu, dns_domain=dns_domain)
- changed = True
- else:
- changed = False
- module.exit_json(changed=changed, network=net, id=net['id'])
-
- elif state == 'absent':
- if not net:
- module.exit_json(changed=False)
- else:
- cloud.delete_network(name)
- module.exit_json(changed=True)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == "__main__":
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_networks_info.py b/lib/ansible/modules/cloud/openstack/os_networks_info.py
deleted file mode 100644
index d580f46728..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_networks_info.py
+++ /dev/null
@@ -1,157 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_networks_info
-short_description: Retrieve information about one or more OpenStack networks.
-version_added: "2.0"
-author: "Davide Agnello (@dagnello)"
-description:
- - Retrieve information about one or more networks from OpenStack.
- - This module was called C(os_networks_facts) before Ansible 2.9, returning C(ansible_facts).
- Note that the M(os_networks_info) module no longer returns C(ansible_facts)!
-requirements:
- - "python >= 2.7"
- - "sdk"
-options:
- name:
- description:
- - Name or ID of the Network
- required: false
- filters:
- description:
- - A dictionary of meta data to use for further filtering. Elements of
- this dictionary may be additional dictionaries.
- required: false
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
- required: false
-extends_documentation_fragment: openstack
-'''
-
-EXAMPLES = '''
-- name: Gather information about previously created networks
- os_networks_info:
- auth:
- auth_url: https://identity.example.com
- username: user
- password: password
- project_name: someproject
- register: result
-
-- name: Show openstack networks
- debug:
- msg: "{{ result.openstack_networks }}"
-
-- name: Gather information about a previously created network by name
- os_networks_info:
- auth:
- auth_url: https://identity.example.com
- username: user
- password: password
- project_name: someproject
- name: network1
- register: result
-
-- name: Show openstack networks
- debug:
- msg: "{{ result.openstack_networks }}"
-
-- name: Gather information about a previously created network with filter
- # Note: name and filters parameters are Not mutually exclusive
- os_networks_info:
- auth:
- auth_url: https://identity.example.com
- username: user
- password: password
- project_name: someproject
- filters:
- tenant_id: 55e2ce24b2a245b09f181bf025724cbe
- subnets:
- - 057d4bdf-6d4d-4728-bb0f-5ac45a6f7400
- - 443d4dc0-91d4-4998-b21c-357d10433483
- register: result
-
-- name: Show openstack networks
- debug:
- msg: "{{ result.openstack_networks }}"
-'''
-
-RETURN = '''
-openstack_networks:
- description: has all the openstack information about the networks
- returned: always, but can be null
- type: complex
- contains:
- id:
- description: Unique UUID.
- returned: success
- type: str
- name:
- description: Name given to the network.
- returned: success
- type: str
- status:
- description: Network status.
- returned: success
- type: str
- subnets:
- description: Subnet(s) included in this network.
- returned: success
- type: list
- elements: str
- tenant_id:
- description: Tenant id associated with this network.
- returned: success
- type: str
- shared:
- description: Network shared flag.
- returned: success
- type: bool
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_cloud_from_module
-
-
-def main():
-
- argument_spec = openstack_full_argument_spec(
- name=dict(required=False, default=None),
- filters=dict(required=False, type='dict', default=None)
- )
- module = AnsibleModule(argument_spec)
- is_old_facts = module._name == 'os_networks_facts'
- if is_old_facts:
- module.deprecate("The 'os_networks_facts' module has been renamed to 'os_networks_info', "
- "and the renamed one no longer returns ansible_facts", version='2.13')
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- networks = cloud.search_networks(module.params['name'],
- module.params['filters'])
- if is_old_facts:
- module.exit_json(changed=False, ansible_facts=dict(
- openstack_networks=networks))
- else:
- module.exit_json(changed=False, openstack_networks=networks)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_nova_flavor.py b/lib/ansible/modules/cloud/openstack/os_nova_flavor.py
deleted file mode 100644
index aa6ee1e750..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_nova_flavor.py
+++ /dev/null
@@ -1,273 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_nova_flavor
-short_description: Manage OpenStack compute flavors
-extends_documentation_fragment: openstack
-version_added: "2.0"
-author: "David Shrewsbury (@Shrews)"
-description:
- - Add or remove flavors from OpenStack.
-options:
- state:
- description:
- - Indicate desired state of the resource. When I(state) is 'present',
- then I(ram), I(vcpus), and I(disk) are all required. There are no
- default values for those parameters.
- choices: ['present', 'absent']
- default: present
- name:
- description:
- - Flavor name.
- required: true
- ram:
- description:
- - Amount of memory, in MB.
- vcpus:
- description:
- - Number of virtual CPUs.
- disk:
- description:
- - Size of local disk, in GB.
- default: 0
- type: int
- ephemeral:
- description:
- - Ephemeral space size, in GB.
- default: 0
- swap:
- description:
- - Swap space size, in MB.
- default: 0
- rxtx_factor:
- description:
- - RX/TX factor.
- default: 1.0
- is_public:
- description:
- - Make flavor accessible to the public.
- type: bool
- default: 'yes'
- flavorid:
- description:
- - ID for the flavor. This is optional as a unique UUID will be
- assigned if a value is not specified.
- default: "auto"
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
- extra_specs:
- description:
- - Metadata dictionary
- version_added: "2.3"
-requirements: ["openstacksdk"]
-'''
-
-EXAMPLES = '''
-- name: "Create 'tiny' flavor with 1024MB of RAM, 1 virtual CPU, and 10GB of local disk, and 10GB of ephemeral."
- os_nova_flavor:
- cloud: mycloud
- state: present
- name: tiny
- ram: 1024
- vcpus: 1
- disk: 10
- ephemeral: 10
-
-- name: "Delete 'tiny' flavor"
- os_nova_flavor:
- cloud: mycloud
- state: absent
- name: tiny
-
-- name: Create flavor with metadata
- os_nova_flavor:
- cloud: mycloud
- state: present
- name: tiny
- ram: 1024
- vcpus: 1
- disk: 10
- extra_specs:
- "quota:disk_read_iops_sec": 5000
- "aggregate_instance_extra_specs:pinned": false
-'''
-
-RETURN = '''
-flavor:
- description: Dictionary describing the flavor.
- returned: On success when I(state) is 'present'
- type: complex
- contains:
- id:
- description: Flavor ID.
- returned: success
- type: str
- sample: "515256b8-7027-4d73-aa54-4e30a4a4a339"
- name:
- description: Flavor name.
- returned: success
- type: str
- sample: "tiny"
- disk:
- description: Size of local disk, in GB.
- returned: success
- type: int
- sample: 10
- ephemeral:
- description: Ephemeral space size, in GB.
- returned: success
- type: int
- sample: 10
- ram:
- description: Amount of memory, in MB.
- returned: success
- type: int
- sample: 1024
- swap:
- description: Swap space size, in MB.
- returned: success
- type: int
- sample: 100
- vcpus:
- description: Number of virtual CPUs.
- returned: success
- type: int
- sample: 2
- is_public:
- description: Make flavor accessible to the public.
- returned: success
- type: bool
- sample: true
- extra_specs:
- description: Flavor metadata
- returned: success
- type: dict
- sample:
- "quota:disk_read_iops_sec": 5000
- "aggregate_instance_extra_specs:pinned": false
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _system_state_change(module, flavor):
- state = module.params['state']
- if state == 'present' and not flavor:
- return True
- if state == 'absent' and flavor:
- return True
- return False
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- state=dict(required=False, default='present',
- choices=['absent', 'present']),
- name=dict(required=False),
-
- # required when state is 'present'
- ram=dict(required=False, type='int'),
- vcpus=dict(required=False, type='int'),
-
- disk=dict(required=False, default=0, type='int'),
- ephemeral=dict(required=False, default=0, type='int'),
- swap=dict(required=False, default=0, type='int'),
- rxtx_factor=dict(required=False, default=1.0, type='float'),
- is_public=dict(required=False, default=True, type='bool'),
- flavorid=dict(required=False, default="auto"),
- extra_specs=dict(required=False, default=None, type='dict'),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(
- argument_spec,
- supports_check_mode=True,
- required_if=[
- ('state', 'present', ['ram', 'vcpus', 'disk'])
- ],
- **module_kwargs)
-
- state = module.params['state']
- name = module.params['name']
- extra_specs = module.params['extra_specs'] or {}
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- flavor = cloud.get_flavor(name)
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(module, flavor))
-
- if state == 'present':
- old_extra_specs = {}
- require_update = False
-
- if flavor:
- old_extra_specs = flavor['extra_specs']
- for param_key in ['ram', 'vcpus', 'disk', 'ephemeral', 'swap', 'rxtx_factor', 'is_public']:
- if module.params[param_key] != flavor[param_key]:
- require_update = True
- break
-
- if flavor and require_update:
- cloud.delete_flavor(name)
- flavor = None
-
- if not flavor:
- flavor = cloud.create_flavor(
- name=name,
- ram=module.params['ram'],
- vcpus=module.params['vcpus'],
- disk=module.params['disk'],
- flavorid=module.params['flavorid'],
- ephemeral=module.params['ephemeral'],
- swap=module.params['swap'],
- rxtx_factor=module.params['rxtx_factor'],
- is_public=module.params['is_public']
- )
- changed = True
- else:
- changed = False
-
- new_extra_specs = dict([(k, str(v)) for k, v in extra_specs.items()])
- unset_keys = set(old_extra_specs.keys()) - set(extra_specs.keys())
-
- if unset_keys and not require_update:
- cloud.unset_flavor_specs(flavor['id'], unset_keys)
-
- if old_extra_specs != new_extra_specs:
- cloud.set_flavor_specs(flavor['id'], extra_specs)
-
- changed = (changed or old_extra_specs != new_extra_specs)
-
- module.exit_json(changed=changed,
- flavor=flavor,
- id=flavor['id'])
-
- elif state == 'absent':
- if flavor:
- cloud.delete_flavor(name)
- module.exit_json(changed=True)
- module.exit_json(changed=False)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_nova_host_aggregate.py b/lib/ansible/modules/cloud/openstack/os_nova_host_aggregate.py
deleted file mode 100644
index 94bd628988..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_nova_host_aggregate.py
+++ /dev/null
@@ -1,182 +0,0 @@
-#!/usr/bin/python
-# Copyright 2016 Jakub Jursa <jakub.jursa1@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_nova_host_aggregate
-short_description: Manage OpenStack host aggregates
-extends_documentation_fragment: openstack
-author: "Jakub Jursa (@kuboj)"
-version_added: "2.3"
-description:
- - Create, update, or delete OpenStack host aggregates. If a aggregate
- with the supplied name already exists, it will be updated with the
- new name, new availability zone, new metadata and new list of hosts.
-options:
- name:
- description: Name of the aggregate.
- required: true
- metadata:
- description: Metadata dict.
- availability_zone:
- description: Availability zone to create aggregate into.
- hosts:
- description: List of hosts to set for an aggregate.
- state:
- description: Should the resource be present or absent.
- choices: [present, absent]
- default: present
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-# Create a host aggregate
-- os_nova_host_aggregate:
- cloud: mycloud
- state: present
- name: db_aggregate
- hosts:
- - host1
- - host2
- metadata:
- type: dbcluster
-# Delete an aggregate
-- os_nova_host_aggregate:
- cloud: mycloud
- state: absent
- name: db_aggregate
-'''
-
-RETURN = '''
-
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _needs_update(module, aggregate):
- new_metadata = (module.params['metadata'] or {})
-
- if module.params['availability_zone'] is not None:
- new_metadata['availability_zone'] = module.params['availability_zone']
-
- if ((module.params['name'] != aggregate.name) or
- (module.params['hosts'] is not None and set(module.params['hosts']) != set(aggregate.hosts)) or
- (module.params['availability_zone'] is not None and module.params['availability_zone'] != aggregate.availability_zone) or
- (module.params['metadata'] is not None and new_metadata != aggregate.metadata)):
- return True
-
- return False
-
-
-def _system_state_change(module, aggregate):
- state = module.params['state']
- if state == 'absent' and aggregate:
- return True
-
- if state == 'present':
- if aggregate is None:
- return True
- return _needs_update(module, aggregate)
-
- return False
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- metadata=dict(required=False, default=None, type='dict'),
- availability_zone=dict(required=False, default=None),
- hosts=dict(required=False, default=None, type='list'),
- state=dict(default='present', choices=['absent', 'present']),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- name = module.params['name']
- metadata = module.params['metadata']
- availability_zone = module.params['availability_zone']
- hosts = module.params['hosts']
- state = module.params['state']
-
- if metadata is not None:
- metadata.pop('availability_zone', None)
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- aggregates = cloud.search_aggregates(name_or_id=name)
-
- if len(aggregates) == 1:
- aggregate = aggregates[0]
- elif len(aggregates) == 0:
- aggregate = None
- else:
- raise Exception("Should not happen")
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(module, aggregate))
-
- if state == 'present':
- if aggregate is None:
- aggregate = cloud.create_aggregate(name=name,
- availability_zone=availability_zone)
- if hosts:
- for h in hosts:
- cloud.add_host_to_aggregate(aggregate.id, h)
- if metadata:
- cloud.set_aggregate_metadata(aggregate.id, metadata)
- changed = True
- else:
- if _needs_update(module, aggregate):
- if availability_zone is not None:
- aggregate = cloud.update_aggregate(aggregate.id, name=name,
- availability_zone=availability_zone)
- if metadata is not None:
- metas = metadata
- for i in (set(aggregate.metadata.keys()) - set(metadata.keys())):
- if i != 'availability_zone':
- metas[i] = None
- cloud.set_aggregate_metadata(aggregate.id, metas)
- if hosts is not None:
- for i in (set(aggregate.hosts) - set(hosts)):
- cloud.remove_host_from_aggregate(aggregate.id, i)
- for i in (set(hosts) - set(aggregate.hosts)):
- cloud.add_host_to_aggregate(aggregate.id, i)
- changed = True
- else:
- changed = False
- module.exit_json(changed=changed)
-
- elif state == 'absent':
- if aggregate is None:
- changed = False
- else:
- if hosts:
- for h in hosts:
- cloud.remove_host_from_aggregate(aggregate.id, h)
- cloud.delete_aggregate(aggregate.id)
- changed = True
- module.exit_json(changed=changed)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_object.py b/lib/ansible/modules/cloud/openstack/os_object.py
deleted file mode 100644
index 51d6ae3243..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_object.py
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
-# Copyright (c) 2013, Benno Joy <benno@ansible.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_object
-short_description: Create or Delete objects and containers from OpenStack
-version_added: "2.0"
-author: "Monty Taylor (@emonty)"
-extends_documentation_fragment: openstack
-description:
- - Create or Delete objects and containers from OpenStack
-options:
- container:
- description:
- - The name of the container in which to create the object
- required: true
- name:
- description:
- - Name to be give to the object. If omitted, operations will be on
- the entire container
- required: false
- filename:
- description:
- - Path to local file to be uploaded.
- required: false
- container_access:
- description:
- - desired container access level.
- required: false
- choices: ['private', 'public']
- default: private
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
- required: false
-'''
-
-EXAMPLES = '''
-- name: "Create a object named 'fstab' in the 'config' container"
- os_object:
- cloud: mordred
- state: present
- name: fstab
- container: config
- filename: /etc/fstab
-
-- name: Delete a container called config and all of its contents
- os_object:
- cloud: rax-iad
- state: absent
- container: config
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def process_object(
- cloud_obj, container, name, filename, container_access, **kwargs):
-
- changed = False
- container_obj = cloud_obj.get_container(container)
- if kwargs['state'] == 'present':
- if not container_obj:
- container_obj = cloud_obj.create_container(container)
- changed = True
- if cloud_obj.get_container_access(container) != container_access:
- cloud_obj.set_container_access(container, container_access)
- changed = True
- if name:
- if cloud_obj.is_object_stale(container, name, filename):
- cloud_obj.create_object(container, name, filename)
- changed = True
- else:
- if container_obj:
- if name:
- if cloud_obj.get_object_metadata(container, name):
- cloud_obj.delete_object(container, name)
- changed = True
- else:
- cloud_obj.delete_container(container)
- changed = True
- return changed
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- name=dict(required=False, default=None),
- container=dict(required=True),
- filename=dict(required=False, default=None),
- container_access=dict(default='private', choices=['private', 'public']),
- state=dict(default='present', choices=['absent', 'present']),
- )
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec, **module_kwargs)
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- changed = process_object(cloud, **module.params)
-
- module.exit_json(changed=changed)
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == "__main__":
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_pool.py b/lib/ansible/modules/cloud/openstack/os_pool.py
deleted file mode 100644
index 694305094e..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_pool.py
+++ /dev/null
@@ -1,267 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2018 Catalyst Cloud Ltd.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: os_pool
-short_description: Add/Delete a pool in the load balancing service from OpenStack Cloud
-extends_documentation_fragment: openstack
-version_added: "2.7"
-author: "Lingxian Kong (@lingxiankong)"
-description:
- - Add or Remove a pool from the OpenStack load-balancer service.
-options:
- name:
- description:
- - Name that has to be given to the pool
- required: true
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- loadbalancer:
- description:
- - The name or id of the load balancer that this pool belongs to.
- Either loadbalancer or listener must be specified for pool creation.
- listener:
- description:
- - The name or id of the listener that this pool belongs to.
- Either loadbalancer or listener must be specified for pool creation.
- protocol:
- description:
- - The protocol for the pool.
- choices: [HTTP, HTTPS, PROXY, TCP, UDP]
- default: HTTP
- lb_algorithm:
- description:
- - The load balancing algorithm for the pool.
- choices: [LEAST_CONNECTIONS, ROUND_ROBIN, SOURCE_IP]
- default: ROUND_ROBIN
- wait:
- description:
- - If the module should wait for the pool to be ACTIVE.
- type: bool
- default: 'yes'
- timeout:
- description:
- - The amount of time the module should wait for the pool to get
- into ACTIVE state.
- default: 180
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-requirements: ["openstacksdk"]
-'''
-
-RETURN = '''
-id:
- description: The pool UUID.
- returned: On success when I(state) is 'present'
- type: str
- sample: "39007a7e-ee4f-4d13-8283-b4da2e037c69"
-listener:
- description: Dictionary describing the pool.
- returned: On success when I(state) is 'present'
- type: complex
- contains:
- id:
- description: Unique UUID.
- type: str
- sample: "39007a7e-ee4f-4d13-8283-b4da2e037c69"
- name:
- description: Name given to the pool.
- type: str
- sample: "test"
- description:
- description: The pool description.
- type: str
- sample: "description"
- loadbalancers:
- description: A list of load balancer IDs.
- type: list
- sample: [{"id": "b32eef7e-d2a6-4ea4-a301-60a873f89b3b"}]
- listeners:
- description: A list of listener IDs.
- type: list
- sample: [{"id": "b32eef7e-d2a6-4ea4-a301-60a873f89b3b"}]
- members:
- description: A list of member IDs.
- type: list
- sample: [{"id": "b32eef7e-d2a6-4ea4-a301-60a873f89b3b"}]
- loadbalancer_id:
- description: The load balancer ID the pool belongs to. This field is set when the pool doesn't belong to any listener in the load balancer.
- type: str
- sample: "7c4be3f8-9c2f-11e8-83b3-44a8422643a4"
- listener_id:
- description: The listener ID the pool belongs to.
- type: str
- sample: "956aa716-9c2f-11e8-83b3-44a8422643a4"
- provisioning_status:
- description: The provisioning status of the pool.
- type: str
- sample: "ACTIVE"
- operating_status:
- description: The operating status of the pool.
- type: str
- sample: "ONLINE"
- is_admin_state_up:
- description: The administrative state of the pool.
- type: bool
- sample: true
- protocol:
- description: The protocol for the pool.
- type: str
- sample: "HTTP"
- lb_algorithm:
- description: The load balancing algorithm for the pool.
- type: str
- sample: "ROUND_ROBIN"
-'''
-
-EXAMPLES = '''
-# Create a pool, wait for the pool to be active.
-- os_pool:
- cloud: mycloud
- endpoint_type: admin
- state: present
- name: test-pool
- loadbalancer: test-loadbalancer
- protocol: HTTP
- lb_algorithm: ROUND_ROBIN
-
-# Delete a pool
-- os_pool:
- cloud: mycloud
- endpoint_type: admin
- state: absent
- name: test-pool
-'''
-
-import time
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, \
- openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _wait_for_pool_status(module, cloud, pool_id, status, failures,
- interval=5):
- timeout = module.params['timeout']
-
- total_sleep = 0
- if failures is None:
- failures = []
-
- while total_sleep < timeout:
- pool = cloud.load_balancer.get_pool(pool_id)
- provisioning_status = pool.provisioning_status
- if provisioning_status == status:
- return pool
- if provisioning_status in failures:
- module.fail_json(
- msg="pool %s transitioned to failure state %s" %
- (pool_id, provisioning_status)
- )
-
- time.sleep(interval)
- total_sleep += interval
-
- module.fail_json(
- msg="timeout waiting for pool %s to transition to %s" %
- (pool_id, status)
- )
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- state=dict(default='present', choices=['absent', 'present']),
- loadbalancer=dict(default=None),
- listener=dict(default=None),
- protocol=dict(default='HTTP',
- choices=['HTTP', 'HTTPS', 'TCP', 'UDP', 'PROXY']),
- lb_algorithm=dict(
- default='ROUND_ROBIN',
- choices=['ROUND_ROBIN', 'LEAST_CONNECTIONS', 'SOURCE_IP']
- )
- )
- module_kwargs = openstack_module_kwargs(
- mutually_exclusive=[['loadbalancer', 'listener']]
- )
- module = AnsibleModule(argument_spec, **module_kwargs)
- sdk, cloud = openstack_cloud_from_module(module)
-
- loadbalancer = module.params['loadbalancer']
- listener = module.params['listener']
-
- try:
- changed = False
- pool = cloud.load_balancer.find_pool(name_or_id=module.params['name'])
-
- if module.params['state'] == 'present':
- if not pool:
- loadbalancer_id = None
- if not (loadbalancer or listener):
- module.fail_json(
- msg="either loadbalancer or listener must be provided"
- )
-
- if loadbalancer:
- lb = cloud.load_balancer.find_load_balancer(loadbalancer)
- if not lb:
- module.fail_json(msg='load balancer %s is not '
- 'found' % loadbalancer)
- loadbalancer_id = lb.id
-
- listener_id = None
- if listener:
- listener_ret = cloud.load_balancer.find_listener(listener)
- if not listener_ret:
- module.fail_json(msg='listener %s is not found'
- % listener)
- listener_id = listener_ret.id
-
- pool = cloud.load_balancer.create_pool(
- name=module.params['name'],
- loadbalancer_id=loadbalancer_id,
- listener_id=listener_id,
- protocol=module.params['protocol'],
- lb_algorithm=module.params['lb_algorithm']
- )
- changed = True
-
- if not module.params['wait']:
- module.exit_json(changed=changed,
- pool=pool.to_dict(),
- id=pool.id)
-
- if module.params['wait']:
- pool = _wait_for_pool_status(module, cloud, pool.id, "ACTIVE",
- ["ERROR"])
-
- module.exit_json(changed=changed, pool=pool.to_dict(),
- id=pool.id)
-
- elif module.params['state'] == 'absent':
- if pool:
- cloud.load_balancer.delete_pool(pool)
- changed = True
-
- module.exit_json(changed=changed)
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e), extra_data=e.extra_data)
-
-
-if __name__ == "__main__":
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_port.py b/lib/ansible/modules/cloud/openstack/os_port.py
deleted file mode 100644
index 01b77b0c0a..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_port.py
+++ /dev/null
@@ -1,441 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_port
-short_description: Add/Update/Delete ports from an OpenStack cloud.
-extends_documentation_fragment: openstack
-author: "Davide Agnello (@dagnello)"
-version_added: "2.0"
-description:
- - Add, Update or Remove ports from an OpenStack cloud. A I(state) of
- 'present' will ensure the port is created or updated if required.
-requirements:
- - "ordereddict unless python >= 2.7"
- - "openstacksdk"
-options:
- network:
- description:
- - Network ID or name this port belongs to.
- required: true
- name:
- description:
- - Name that has to be given to the port.
- fixed_ips:
- description:
- - Desired IP and/or subnet for this port. Subnet is referenced by
- subnet_id and IP is referenced by ip_address.
- admin_state_up:
- description:
- - Sets admin state.
- type: bool
- mac_address:
- description:
- - MAC address of this port.
- security_groups:
- description:
- - Security group(s) ID(s) or name(s) associated with the port (comma
- separated string or YAML list)
- no_security_groups:
- description:
- - Do not associate a security group with this port.
- type: bool
- default: 'no'
- allowed_address_pairs:
- description:
- - "Allowed address pairs list. Allowed address pairs are supported with
- dictionary structure.
- e.g. allowed_address_pairs:
- - ip_address: 10.1.0.12
- mac_address: ab:cd:ef:12:34:56
- - ip_address: ..."
- extra_dhcp_opts:
- description:
- - "Extra dhcp options to be assigned to this port. Extra options are
- supported with dictionary structure. Note that options cannot be removed
- only updated.
- e.g. extra_dhcp_opts:
- - opt_name: opt name1
- opt_value: value1
- ip_version: 4
- - opt_name: ..."
- device_owner:
- description:
- - The ID of the entity that uses this port.
- device_id:
- description:
- - Device ID of device using this port.
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
- vnic_type:
- description:
- - The type of the port that should be created
- choices: [normal, direct, direct-physical, macvtap, baremetal, virtio-forwarder]
- version_added: "2.8"
- port_security_enabled:
- description:
- - Whether to enable or disable the port security on the network.
- type: bool
- version_added: "2.8"
-'''
-
-EXAMPLES = '''
-# Create a port
-- os_port:
- state: present
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: admin
- project_name: admin
- name: port1
- network: foo
-
-# Create a port with a static IP
-- os_port:
- state: present
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: admin
- project_name: admin
- name: port1
- network: foo
- fixed_ips:
- - ip_address: 10.1.0.21
-
-# Create a port with No security groups
-- os_port:
- state: present
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: admin
- project_name: admin
- name: port1
- network: foo
- no_security_groups: True
-
-# Update the existing 'port1' port with multiple security groups (version 1)
-- os_port:
- state: present
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: admin
- project_name: admin
- name: port1
- security_groups: 1496e8c7-4918-482a-9172-f4f00fc4a3a5,057d4bdf-6d4d-472...
-
-# Update the existing 'port1' port with multiple security groups (version 2)
-- os_port:
- state: present
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: admin
- project_name: admin
- name: port1
- security_groups:
- - 1496e8c7-4918-482a-9172-f4f00fc4a3a5
- - 057d4bdf-6d4d-472...
-
-# Create port of type 'direct'
-- os_port:
- state: present
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: admin
- project_name: admin
- name: port1
- network: foo
- vnic_type: direct
-'''
-
-RETURN = '''
-id:
- description: Unique UUID.
- returned: success
- type: str
-name:
- description: Name given to the port.
- returned: success
- type: str
-network_id:
- description: Network ID this port belongs in.
- returned: success
- type: str
-security_groups:
- description: Security group(s) associated with this port.
- returned: success
- type: list
-status:
- description: Port's status.
- returned: success
- type: str
-fixed_ips:
- description: Fixed ip(s) associated with this port.
- returned: success
- type: list
-tenant_id:
- description: Tenant id associated with this port.
- returned: success
- type: str
-allowed_address_pairs:
- description: Allowed address pairs with this port.
- returned: success
- type: list
-admin_state_up:
- description: Admin state up flag for this port.
- returned: success
- type: bool
-vnic_type:
- description: Type of the created port
- returned: success
- type: str
-port_security_enabled:
- description: Port security state on the network.
- returned: success
- type: bool
-'''
-
-from ansible.module_utils.basic import AnsibleModule, missing_required_lib
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-try:
- from collections import OrderedDict
- HAS_ORDEREDDICT = True
-except ImportError:
- try:
- from ordereddict import OrderedDict
- HAS_ORDEREDDICT = True
- except ImportError:
- HAS_ORDEREDDICT = False
-
-
-def _needs_update(module, port, cloud):
- """Check for differences in the updatable values.
-
- NOTE: We don't currently allow name updates.
- """
- compare_simple = ['admin_state_up',
- 'mac_address',
- 'device_owner',
- 'device_id',
- 'binding:vnic_type',
- 'port_security_enabled']
- compare_list_dict = ['allowed_address_pairs',
- 'extra_dhcp_opts']
- compare_list = ['security_groups']
-
- for key in compare_simple:
- if module.params[key] is not None and module.params[key] != port[key]:
- return True
- for key in compare_list:
- if module.params[key] is not None and (set(module.params[key]) !=
- set(port[key])):
- return True
-
- for key in compare_list_dict:
- if not module.params[key]:
- if not port[key]:
- return True
-
- # sort dicts in list
- port_ordered = [OrderedDict(sorted(d.items())) for d in port[key]]
- param_ordered = [OrderedDict(sorted(d.items())) for d in module.params[key]]
-
- for d in param_ordered:
- if d not in port_ordered:
- return True
-
- for d in port_ordered:
- if d not in param_ordered:
- return True
-
- # NOTE: if port was created or updated with 'no_security_groups=True',
- # subsequent updates without 'no_security_groups' flag or
- # 'no_security_groups=False' and no specified 'security_groups', will not
- # result in an update to the port where the default security group is
- # applied.
- if module.params['no_security_groups'] and port['security_groups'] != []:
- return True
-
- if module.params['fixed_ips'] is not None:
- for item in module.params['fixed_ips']:
- if 'ip_address' in item:
- # if ip_address in request does not match any in existing port,
- # update is required.
- if not any(match['ip_address'] == item['ip_address']
- for match in port['fixed_ips']):
- return True
- if 'subnet_id' in item:
- return True
- for item in port['fixed_ips']:
- # if ip_address in existing port does not match any in request,
- # update is required.
- if not any(match.get('ip_address') == item['ip_address']
- for match in module.params['fixed_ips']):
- return True
-
- return False
-
-
-def _system_state_change(module, port, cloud):
- state = module.params['state']
- if state == 'present':
- if not port:
- return True
- return _needs_update(module, port, cloud)
- if state == 'absent' and port:
- return True
- return False
-
-
-def _compose_port_args(module, cloud):
- port_kwargs = {}
- optional_parameters = ['name',
- 'fixed_ips',
- 'admin_state_up',
- 'mac_address',
- 'security_groups',
- 'allowed_address_pairs',
- 'extra_dhcp_opts',
- 'device_owner',
- 'device_id',
- 'binding:vnic_type',
- 'port_security_enabled']
- for optional_param in optional_parameters:
- if module.params[optional_param] is not None:
- port_kwargs[optional_param] = module.params[optional_param]
-
- if module.params['no_security_groups']:
- port_kwargs['security_groups'] = []
-
- return port_kwargs
-
-
-def get_security_group_id(module, cloud, security_group_name_or_id):
- security_group = cloud.get_security_group(security_group_name_or_id)
- if not security_group:
- module.fail_json(msg="Security group: %s, was not found"
- % security_group_name_or_id)
- return security_group['id']
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- network=dict(required=False),
- name=dict(required=False),
- fixed_ips=dict(type='list', default=None),
- admin_state_up=dict(type='bool', default=None),
- mac_address=dict(default=None),
- security_groups=dict(default=None, type='list'),
- no_security_groups=dict(default=False, type='bool'),
- allowed_address_pairs=dict(type='list', default=None),
- extra_dhcp_opts=dict(type='list', default=None),
- device_owner=dict(default=None),
- device_id=dict(default=None),
- state=dict(default='present', choices=['absent', 'present']),
- vnic_type=dict(default=None,
- choices=['normal', 'direct', 'direct-physical',
- 'macvtap', 'baremetal', 'virtio-forwarder']),
- port_security_enabled=dict(default=None, type='bool')
- )
-
- module_kwargs = openstack_module_kwargs(
- mutually_exclusive=[
- ['no_security_groups', 'security_groups'],
- ]
- )
-
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- if not HAS_ORDEREDDICT:
- module.fail_json(msg=missing_required_lib('ordereddict'))
-
- name = module.params['name']
- state = module.params['state']
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- if module.params['security_groups']:
- # translate security_groups to UUID's if names where provided
- module.params['security_groups'] = [
- get_security_group_id(module, cloud, v)
- for v in module.params['security_groups']
- ]
-
- # Neutron API accept 'binding:vnic_type' as an argument
- # for the port type.
- module.params['binding:vnic_type'] = module.params.pop('vnic_type')
-
- port = None
- network_id = None
- if name:
- port = cloud.get_port(name)
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(module, port, cloud))
-
- changed = False
- if state == 'present':
- if not port:
- network = module.params['network']
- if not network:
- module.fail_json(
- msg="Parameter 'network' is required in Port Create"
- )
- port_kwargs = _compose_port_args(module, cloud)
- network_object = cloud.get_network(network)
-
- if network_object:
- network_id = network_object['id']
- else:
- module.fail_json(
- msg="Specified network was not found."
- )
-
- port = cloud.create_port(network_id, **port_kwargs)
- changed = True
- else:
- if _needs_update(module, port, cloud):
- port_kwargs = _compose_port_args(module, cloud)
- port = cloud.update_port(port['id'], **port_kwargs)
- changed = True
- module.exit_json(changed=changed, id=port['id'], port=port)
-
- if state == 'absent':
- if port:
- cloud.delete_port(port['id'])
- changed = True
- module.exit_json(changed=changed)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_port_info.py b/lib/ansible/modules/cloud/openstack/os_port_info.py
deleted file mode 100644
index d59282b32f..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_port_info.py
+++ /dev/null
@@ -1,224 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2016 IBM
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
-module: os_port_info
-short_description: Retrieve information about ports within OpenStack.
-version_added: "2.1"
-author: "David Shrewsbury (@Shrews)"
-description:
- - Retrieve information about ports from OpenStack.
- - This module was called C(os_port_facts) before Ansible 2.9, returning C(ansible_facts).
- Note that the M(os_port_info) module no longer returns C(ansible_facts)!
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-options:
- port:
- description:
- - Unique name or ID of a port.
- filters:
- description:
- - A dictionary of meta data to use for further filtering. Elements
- of this dictionary will be matched against the returned port
- dictionaries. Matching is currently limited to strings within
- the port dictionary, or strings within nested dictionaries.
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-extends_documentation_fragment: openstack
-'''
-
-EXAMPLES = '''
-# Gather information about all ports
-- os_port_info:
- cloud: mycloud
- register: result
-
-- debug:
- msg: "{{ result.openstack_ports }}"
-
-# Gather information about a single port
-- os_port_info:
- cloud: mycloud
- port: 6140317d-e676-31e1-8a4a-b1913814a471
-
-# Gather information about all ports that have device_id set to a specific value
-# and with a status of ACTIVE.
-- os_port_info:
- cloud: mycloud
- filters:
- device_id: 1038a010-3a37-4a9d-82ea-652f1da36597
- status: ACTIVE
-'''
-
-RETURN = '''
-openstack_ports:
- description: List of port dictionaries. A subset of the dictionary keys
- listed below may be returned, depending on your cloud provider.
- returned: always, but can be null
- type: complex
- contains:
- admin_state_up:
- description: The administrative state of the router, which is
- up (true) or down (false).
- returned: success
- type: bool
- sample: true
- allowed_address_pairs:
- description: A set of zero or more allowed address pairs. An
- address pair consists of an IP address and MAC address.
- returned: success
- type: list
- sample: []
- "binding:host_id":
- description: The UUID of the host where the port is allocated.
- returned: success
- type: str
- sample: "b4bd682d-234a-4091-aa5b-4b025a6a7759"
- "binding:profile":
- description: A dictionary the enables the application running on
- the host to pass and receive VIF port-specific
- information to the plug-in.
- returned: success
- type: dict
- sample: {}
- "binding:vif_details":
- description: A dictionary that enables the application to pass
- information about functions that the Networking API
- provides.
- returned: success
- type: dict
- sample: {"port_filter": true}
- "binding:vif_type":
- description: The VIF type for the port.
- returned: success
- type: dict
- sample: "ovs"
- "binding:vnic_type":
- description: The virtual network interface card (vNIC) type that is
- bound to the neutron port.
- returned: success
- type: str
- sample: "normal"
- device_id:
- description: The UUID of the device that uses this port.
- returned: success
- type: str
- sample: "b4bd682d-234a-4091-aa5b-4b025a6a7759"
- device_owner:
- description: The UUID of the entity that uses this port.
- returned: success
- type: str
- sample: "network:router_interface"
- dns_assignment:
- description: DNS assignment information.
- returned: success
- type: list
- dns_name:
- description: DNS name
- returned: success
- type: str
- sample: ""
- extra_dhcp_opts:
- description: A set of zero or more extra DHCP option pairs.
- An option pair consists of an option value and name.
- returned: success
- type: list
- sample: []
- fixed_ips:
- description: The IP addresses for the port. Includes the IP address
- and UUID of the subnet.
- returned: success
- type: list
- id:
- description: The UUID of the port.
- returned: success
- type: str
- sample: "3ec25c97-7052-4ab8-a8ba-92faf84148de"
- ip_address:
- description: The IP address.
- returned: success
- type: str
- sample: "127.0.0.1"
- mac_address:
- description: The MAC address.
- returned: success
- type: str
- sample: "00:00:5E:00:53:42"
- name:
- description: The port name.
- returned: success
- type: str
- sample: "port_name"
- network_id:
- description: The UUID of the attached network.
- returned: success
- type: str
- sample: "dd1ede4f-3952-4131-aab6-3b8902268c7d"
- port_security_enabled:
- description: The port security status. The status is enabled (true) or disabled (false).
- returned: success
- type: bool
- sample: false
- security_groups:
- description: The UUIDs of any attached security groups.
- returned: success
- type: list
- status:
- description: The port status.
- returned: success
- type: str
- sample: "ACTIVE"
- tenant_id:
- description: The UUID of the tenant who owns the network.
- returned: success
- type: str
- sample: "51fce036d7984ba6af4f6c849f65ef00"
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- port=dict(required=False),
- filters=dict(type='dict', required=False),
- )
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec, **module_kwargs)
- is_old_facts = module._name == 'os_port_facts'
- if is_old_facts:
- module.deprecate("The 'os_port_facts' module has been renamed to 'os_port_info', "
- "and the renamed one no longer returns ansible_facts", version='2.13')
-
- port = module.params.get('port')
- filters = module.params.get('filters')
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- ports = cloud.search_ports(port, filters)
- if is_old_facts:
- module.exit_json(changed=False, ansible_facts=dict(
- openstack_ports=ports))
- else:
- module.exit_json(changed=False, openstack_ports=ports)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_project.py b/lib/ansible/modules/cloud/openstack/os_project.py
deleted file mode 100644
index 17922285e5..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_project.py
+++ /dev/null
@@ -1,211 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2015 IBM Corporation
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_project
-short_description: Manage OpenStack Projects
-extends_documentation_fragment: openstack
-version_added: "2.0"
-author: "Alberto Gireud (@agireud)"
-description:
- - Manage OpenStack Projects. Projects can be created,
- updated or deleted using this module. A project will be updated
- if I(name) matches an existing project and I(state) is present.
- The value for I(name) cannot be updated without deleting and
- re-creating the project.
-options:
- name:
- description:
- - Name for the project
- required: true
- description:
- description:
- - Description for the project
- domain_id:
- description:
- - Domain id to create the project in if the cloud supports domains.
- aliases: ['domain']
- enabled:
- description:
- - Is the project enabled
- type: bool
- default: 'yes'
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-# Create a project
-- os_project:
- cloud: mycloud
- endpoint_type: admin
- state: present
- name: demoproject
- description: demodescription
- domain_id: demoid
- enabled: True
-
-# Delete a project
-- os_project:
- cloud: mycloud
- endpoint_type: admin
- state: absent
- name: demoproject
-'''
-
-
-RETURN = '''
-project:
- description: Dictionary describing the project.
- returned: On success when I(state) is 'present'
- type: complex
- contains:
- id:
- description: Project ID
- type: str
- sample: "f59382db809c43139982ca4189404650"
- name:
- description: Project name
- type: str
- sample: "demoproject"
- description:
- description: Project description
- type: str
- sample: "demodescription"
- enabled:
- description: Boolean to indicate if project is enabled
- type: bool
- sample: True
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _needs_update(module, project):
- keys = ('description', 'enabled')
- for key in keys:
- if module.params[key] is not None and module.params[key] != project.get(key):
- return True
-
- return False
-
-
-def _system_state_change(module, project):
- state = module.params['state']
- if state == 'present':
- if project is None:
- changed = True
- else:
- if _needs_update(module, project):
- changed = True
- else:
- changed = False
-
- elif state == 'absent':
- if project is None:
- changed = False
- else:
- changed = True
-
- return changed
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- description=dict(required=False, default=None),
- domain_id=dict(required=False, default=None, aliases=['domain']),
- enabled=dict(default=True, type='bool'),
- state=dict(default='present', choices=['absent', 'present'])
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(
- argument_spec,
- supports_check_mode=True,
- **module_kwargs
- )
-
- name = module.params['name']
- description = module.params['description']
- domain = module.params.get('domain_id')
- enabled = module.params['enabled']
- state = module.params['state']
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- if domain:
- try:
- # We assume admin is passing domain id
- dom = cloud.get_domain(domain)['id']
- domain = dom
- except Exception:
- # If we fail, maybe admin is passing a domain name.
- # Note that domains have unique names, just like id.
- try:
- dom = cloud.search_domains(filters={'name': domain})[0]['id']
- domain = dom
- except Exception:
- # Ok, let's hope the user is non-admin and passing a sane id
- pass
-
- if domain:
- project = cloud.get_project(name, domain_id=domain)
- else:
- project = cloud.get_project(name)
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(module, project))
-
- if state == 'present':
- if project is None:
- project = cloud.create_project(
- name=name, description=description,
- domain_id=domain,
- enabled=enabled)
- changed = True
- else:
- if _needs_update(module, project):
- project = cloud.update_project(
- project['id'], description=description,
- enabled=enabled)
- changed = True
- else:
- changed = False
- module.exit_json(changed=changed, project=project)
-
- elif state == 'absent':
- if project is None:
- changed = False
- else:
- cloud.delete_project(project['id'])
- changed = True
- module.exit_json(changed=changed)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=e.message, extra_data=e.extra_data)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_project_access.py b/lib/ansible/modules/cloud/openstack/os_project_access.py
deleted file mode 100644
index 912936f1f6..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_project_access.py
+++ /dev/null
@@ -1,199 +0,0 @@
-#!/usr/bin/python
-
-# This module is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This software is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this software. If not, see <http://www.gnu.org/licenses/>.
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = '''
----
-module: os_project_access
-short_description: Manage OpenStack compute flavors access
-extends_documentation_fragment: openstack
-version_added: "2.5"
-author: "Roberto Polli (@ioggstream)"
-description:
- - Add or remove flavor, volume_type or other resources access
- from OpenStack.
-options:
- state:
- description:
- - Indicate desired state of the resource.
- choices: ['present', 'absent']
- required: false
- default: present
- target_project_id:
- description:
- - Project id.
- required: true
- resource_type:
- description:
- - The resource type (eg. nova_flavor, cinder_volume_type).
- resource_name:
- description:
- - The resource name (eg. tiny).
- availability_zone:
- description:
- - The availability zone of the resource.
-requirements:
- - "openstacksdk"
-
-'''
-
-EXAMPLES = '''
-- name: "Enable access to tiny flavor to your tenant."
- os_project_access:
- cloud: mycloud
- state: present
- target_project_id: f0f1f2f3f4f5f67f8f9e0e1
- resource_name: tiny
- resource_type: nova_flavor
-
-
-- name: "Disable access to the given flavor to project"
- os_project_access:
- cloud: mycloud
- state: absent
- target_project_id: f0f1f2f3f4f5f67f8f9e0e1
- resource_name: tiny
- resource_type: nova_flavor
-'''
-
-RETURN = '''
-flavor:
- description: Dictionary describing the flavor.
- returned: On success when I(state) is 'present'
- type: complex
- contains:
- id:
- description: Flavor ID.
- returned: success
- type: str
- sample: "515256b8-7027-4d73-aa54-4e30a4a4a339"
- name:
- description: Flavor name.
- returned: success
- type: str
- sample: "tiny"
-
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- state=dict(required=False, default='present',
- choices=['absent', 'present']),
-
- target_project_id=dict(required=True, type='str'),
- resource_type=dict(required=True, type='str'),
- resource_name=dict(required=True, type='str'),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(
- argument_spec,
- supports_check_mode=True,
- required_if=[
- ('state', 'present', ['target_project_id'])
- ],
- **module_kwargs)
-
- sdk, cloud = openstack_cloud_from_module(module)
-
- changed = False
- state = module.params['state']
- resource_name = module.params['resource_name']
- resource_type = module.params['resource_type']
- target_project_id = module.params['target_project_id']
-
- try:
- if resource_type == 'nova_flavor':
- # returns Munch({'NAME_ATTR': 'name',
- # 'tenant_id': u'37e55da59ec842649d84230f3a24eed5',
- # 'HUMAN_ID': False,
- # 'flavor_id': u'6d4d37b9-0480-4a8c-b8c9-f77deaad73f9',
- # 'request_ids': [], 'human_id': None}),
- _get_resource = cloud.get_flavor
- _list_resource_access = cloud.list_flavor_access
- _add_resource_access = cloud.add_flavor_access
- _remove_resource_access = cloud.remove_flavor_access
- elif resource_type == 'cinder_volume_type':
- # returns [Munch({
- # 'project_id': u'178cdb9955b047eea7afbe582038dc94',
- # 'properties': {'request_ids': [], 'NAME_ATTR': 'name',
- # 'human_id': None,
- # 'HUMAN_ID': False},
- # 'id': u'd5573023-b290-42c8-b232-7c5ca493667f'}),
- _get_resource = cloud.get_volume_type
- _list_resource_access = cloud.get_volume_type_access
- _add_resource_access = cloud.add_volume_type_access
- _remove_resource_access = cloud.remove_volume_type_access
- else:
- module.exit_json(changed=False,
- resource_name=resource_name,
- resource_type=resource_type,
- error="Not implemented.")
-
- resource = _get_resource(resource_name)
- if not resource:
- module.exit_json(changed=False,
- resource_name=resource_name,
- resource_type=resource_type,
- error="Not found.")
- resource_id = getattr(resource, 'id', resource['id'])
- # _list_resource_access returns a list of dicts containing 'project_id'
- acls = _list_resource_access(resource_id)
-
- if not all(acl.get('project_id') for acl in acls):
- module.exit_json(changed=False,
- resource_name=resource_name,
- resource_type=resource_type,
- error="Missing project_id in resource output.")
- allowed_tenants = [acl['project_id'] for acl in acls]
-
- changed_access = any((
- state == 'present' and target_project_id not in allowed_tenants,
- state == 'absent' and target_project_id in allowed_tenants
- ))
- if module.check_mode or not changed_access:
- module.exit_json(changed=changed_access,
- resource=resource,
- id=resource_id)
-
- if state == 'present':
- _add_resource_access(
- resource_id, target_project_id
- )
- elif state == 'absent':
- _remove_resource_access(
- resource_id, target_project_id
- )
-
- module.exit_json(changed=True,
- resource=resource,
- id=resource_id)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e), **module.params)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_project_info.py b/lib/ansible/modules/cloud/openstack/os_project_info.py
deleted file mode 100644
index 0ce12c7d3a..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_project_info.py
+++ /dev/null
@@ -1,166 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2016 Hewlett-Packard Enterprise Corporation
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_project_info
-short_description: Retrieve information about one or more OpenStack projects
-extends_documentation_fragment: openstack
-version_added: "2.1"
-author: "Ricardo Carrillo Cruz (@rcarrillocruz)"
-description:
- - Retrieve information about a one or more OpenStack projects
- - This module was called C(os_project_facts) before Ansible 2.9, returning C(ansible_facts).
- Note that the M(os_project_info) module no longer returns C(ansible_facts)!
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-options:
- name:
- description:
- - Name or ID of the project
- required: true
- domain:
- description:
- - Name or ID of the domain containing the project if the cloud supports domains
- filters:
- description:
- - A dictionary of meta data to use for further filtering. Elements of
- this dictionary may be additional dictionaries.
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-'''
-
-EXAMPLES = '''
-# Gather information about previously created projects
-- os_project_info:
- cloud: awesomecloud
- register: result
-- debug:
- msg: "{{ result.openstack_projects }}"
-
-# Gather information about a previously created project by name
-- os_project_info:
- cloud: awesomecloud
- name: demoproject
- register: result
-- debug:
- msg: "{{ result.openstack_projects }}"
-
-# Gather information about a previously created project in a specific domain
-- os_project_info:
- cloud: awesomecloud
- name: demoproject
- domain: admindomain
- register: result
-- debug:
- msg: "{{ result.openstack_projects }}"
-
-# Gather information about a previously created project in a specific domain with filter
-- os_project_info:
- cloud: awesomecloud
- name: demoproject
- domain: admindomain
- filters:
- enabled: False
- register: result
-- debug:
- msg: "{{ result.openstack_projects }}"
-'''
-
-
-RETURN = '''
-openstack_projects:
- description: has all the OpenStack information about projects
- returned: always, but can be null
- type: complex
- contains:
- id:
- description: Unique UUID.
- returned: success
- type: str
- name:
- description: Name given to the project.
- returned: success
- type: str
- description:
- description: Description of the project
- returned: success
- type: str
- enabled:
- description: Flag to indicate if the project is enabled
- returned: success
- type: bool
- domain_id:
- description: Domain ID containing the project (keystone v3 clouds only)
- returned: success
- type: bool
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_cloud_from_module
-
-
-def main():
-
- argument_spec = openstack_full_argument_spec(
- name=dict(required=False, default=None),
- domain=dict(required=False, default=None),
- filters=dict(required=False, type='dict', default=None),
- )
-
- module = AnsibleModule(argument_spec)
- is_old_facts = module._name == 'os_project_facts'
- if is_old_facts:
- module.deprecate("The 'os_project_facts' module has been renamed to 'os_project_info', "
- "and the renamed one no longer returns ansible_facts", version='2.13')
-
- sdk, opcloud = openstack_cloud_from_module(module)
- try:
- name = module.params['name']
- domain = module.params['domain']
- filters = module.params['filters']
-
- if domain:
- try:
- # We assume admin is passing domain id
- dom = opcloud.get_domain(domain)['id']
- domain = dom
- except Exception:
- # If we fail, maybe admin is passing a domain name.
- # Note that domains have unique names, just like id.
- dom = opcloud.search_domains(filters={'name': domain})
- if dom:
- domain = dom[0]['id']
- else:
- module.fail_json(msg='Domain name or ID does not exist')
-
- if not filters:
- filters = {}
-
- filters['domain_id'] = domain
-
- projects = opcloud.search_projects(name, filters)
- if is_old_facts:
- module.exit_json(changed=False, ansible_facts=dict(
- openstack_projects=projects))
- else:
- module.exit_json(changed=False, openstack_projects=projects)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_quota.py b/lib/ansible/modules/cloud/openstack/os_quota.py
deleted file mode 100644
index 5cf40040ec..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_quota.py
+++ /dev/null
@@ -1,463 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2016 Pason System Corporation
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_quota
-short_description: Manage OpenStack Quotas
-extends_documentation_fragment: openstack
-version_added: "2.3"
-author: "Michael Gale (@mgale) <gale.michael@gmail.com>"
-description:
- - Manage OpenStack Quotas. Quotas can be created,
- updated or deleted using this module. A quota will be updated
- if matches an existing project and is present.
-options:
- name:
- description:
- - Name of the OpenStack Project to manage.
- required: true
- state:
- description:
- - A value of present sets the quota and a value of absent resets the quota to system defaults.
- default: present
- backup_gigabytes:
- description: Maximum size of backups in GB's.
- backups:
- description: Maximum number of backups allowed.
- cores:
- description: Maximum number of CPU's per project.
- fixed_ips:
- description: Number of fixed IP's to allow.
- floating_ips:
- description: Number of floating IP's to allow in Compute.
- aliases: ['compute_floating_ips']
- floatingip:
- description: Number of floating IP's to allow in Network.
- aliases: ['network_floating_ips']
- gigabytes:
- description: Maximum volume storage allowed for project.
- gigabytes_lvm:
- description: Maximum size in GB's of individual lvm volumes.
- injected_file_size:
- description: Maximum file size in bytes.
- injected_files:
- description: Number of injected files to allow.
- injected_path_size:
- description: Maximum path size.
- instances:
- description: Maximum number of instances allowed.
- key_pairs:
- description: Number of key pairs to allow.
- loadbalancer:
- description: Number of load balancers to allow.
- version_added: "2.4"
- network:
- description: Number of networks to allow.
- per_volume_gigabytes:
- description: Maximum size in GB's of individual volumes.
- pool:
- description: Number of load balancer pools to allow.
- version_added: "2.4"
- port:
- description: Number of Network ports to allow, this needs to be greater than the instances limit.
- properties:
- description: Number of properties to allow.
- ram:
- description: Maximum amount of ram in MB to allow.
- rbac_policy:
- description: Number of policies to allow.
- router:
- description: Number of routers to allow.
- security_group_rule:
- description: Number of rules per security group to allow.
- security_group:
- description: Number of security groups to allow.
- server_group_members:
- description: Number of server group members to allow.
- server_groups:
- description: Number of server groups to allow.
- snapshots:
- description: Number of snapshots to allow.
- snapshots_lvm:
- description: Number of LVM snapshots to allow.
- subnet:
- description: Number of subnets to allow.
- subnetpool:
- description: Number of subnet pools to allow.
- volumes:
- description: Number of volumes to allow.
- volumes_lvm:
- description: Number of LVM volumes to allow.
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-
-
-requirements:
- - "python >= 2.7"
- - "openstacksdk >= 0.13.0"
- - "keystoneauth1 >= 3.4.0"
-'''
-
-EXAMPLES = '''
-# List a Project Quota
-- os_quota:
- cloud: mycloud
- name: demoproject
-
-# Set a Project back to the defaults
-- os_quota:
- cloud: mycloud
- name: demoproject
- state: absent
-
-# Update a Project Quota for cores
-- os_quota:
- cloud: mycloud
- name: demoproject
- cores: 100
-
-# Update a Project Quota
-- os_quota:
- name: demoproject
- cores: 1000
- volumes: 20
- volumes_type:
- - volume_lvm: 10
-
-# Complete example based on list of projects
-- name: Update quotas
- os_quota:
- name: "{{ item.name }}"
- backup_gigabytes: "{{ item.backup_gigabytes }}"
- backups: "{{ item.backups }}"
- cores: "{{ item.cores }}"
- fixed_ips: "{{ item.fixed_ips }}"
- floating_ips: "{{ item.floating_ips }}"
- floatingip: "{{ item.floatingip }}"
- gigabytes: "{{ item.gigabytes }}"
- injected_file_size: "{{ item.injected_file_size }}"
- injected_files: "{{ item.injected_files }}"
- injected_path_size: "{{ item.injected_path_size }}"
- instances: "{{ item.instances }}"
- key_pairs: "{{ item.key_pairs }}"
- loadbalancer: "{{ item.loadbalancer }}"
- per_volume_gigabytes: "{{ item.per_volume_gigabytes }}"
- pool: "{{ item.pool }}"
- port: "{{ item.port }}"
- properties: "{{ item.properties }}"
- ram: "{{ item.ram }}"
- security_group_rule: "{{ item.security_group_rule }}"
- security_group: "{{ item.security_group }}"
- server_group_members: "{{ item.server_group_members }}"
- server_groups: "{{ item.server_groups }}"
- snapshots: "{{ item.snapshots }}"
- volumes: "{{ item.volumes }}"
- volumes_types:
- volumes_lvm: "{{ item.volumes_lvm }}"
- snapshots_types:
- snapshots_lvm: "{{ item.snapshots_lvm }}"
- gigabytes_types:
- gigabytes_lvm: "{{ item.gigabytes_lvm }}"
- with_items:
- - "{{ projects }}"
- when: item.state == "present"
-'''
-
-RETURN = '''
-openstack_quotas:
- description: Dictionary describing the project quota.
- returned: Regardless if changes where made or not
- type: complex
- sample:
- openstack_quotas: {
- compute: {
- cores: 150,
- fixed_ips: -1,
- floating_ips: 10,
- injected_file_content_bytes: 10240,
- injected_file_path_bytes: 255,
- injected_files: 5,
- instances: 100,
- key_pairs: 100,
- metadata_items: 128,
- ram: 153600,
- security_group_rules: 20,
- security_groups: 10,
- server_group_members: 10,
- server_groups: 10
- },
- network: {
- floatingip: 50,
- loadbalancer: 10,
- network: 10,
- pool: 10,
- port: 160,
- rbac_policy: 10,
- router: 10,
- security_group: 10,
- security_group_rule: 100,
- subnet: 10,
- subnetpool: -1
- },
- volume: {
- backup_gigabytes: 1000,
- backups: 10,
- gigabytes: 1000,
- gigabytes_lvm: -1,
- per_volume_gigabytes: -1,
- snapshots: 10,
- snapshots_lvm: -1,
- volumes: 10,
- volumes_lvm: -1
- }
- }
-
-'''
-
-import traceback
-
-KEYSTONEAUTH1_IMP_ERR = None
-try:
- from keystoneauth1 import exceptions as ksa_exceptions
- HAS_KEYSTONEAUTH1 = True
-except ImportError:
- KEYSTONEAUTH1_IMP_ERR = traceback.format_exc()
- HAS_KEYSTONEAUTH1 = False
-
-from ansible.module_utils.basic import AnsibleModule, missing_required_lib
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _get_volume_quotas(cloud, project):
-
- return cloud.get_volume_quotas(project)
-
-
-def _get_network_quotas(cloud, project):
-
- return cloud.get_network_quotas(project)
-
-
-def _get_compute_quotas(cloud, project):
-
- return cloud.get_compute_quotas(project)
-
-
-def _get_quotas(sdk, module, cloud, project):
-
- quota = {}
- try:
- quota['volume'] = _get_volume_quotas(cloud, project)
- except ksa_exceptions.EndpointNotFound:
- module.warn("No public endpoint for volumev2 service was found. Ignoring volume quotas.")
-
- try:
- quota['network'] = _get_network_quotas(cloud, project)
- except ksa_exceptions.EndpointNotFound:
- module.warn("No public endpoint for network service was found. Ignoring network quotas.")
-
- quota['compute'] = _get_compute_quotas(cloud, project)
-
- for quota_type in quota.keys():
- quota[quota_type] = _scrub_results(quota[quota_type])
-
- return quota
-
-
-def _scrub_results(quota):
-
- filter_attr = [
- 'HUMAN_ID',
- 'NAME_ATTR',
- 'human_id',
- 'request_ids',
- 'x_openstack_request_ids',
- ]
-
- for attr in filter_attr:
- if attr in quota:
- del quota[attr]
-
- return quota
-
-
-def _system_state_change_details(module, project_quota_output):
-
- quota_change_request = {}
- changes_required = False
-
- for quota_type in project_quota_output.keys():
- for quota_option in project_quota_output[quota_type].keys():
- if quota_option in module.params and module.params[quota_option] is not None:
- if project_quota_output[quota_type][quota_option] != module.params[quota_option]:
- changes_required = True
-
- if quota_type not in quota_change_request:
- quota_change_request[quota_type] = {}
-
- quota_change_request[quota_type][quota_option] = module.params[quota_option]
-
- return (changes_required, quota_change_request)
-
-
-def _system_state_change(module, project_quota_output):
- """
- Determine if changes are required to the current project quota.
-
- This is done by comparing the current project_quota_output against
- the desired quota settings set on the module params.
- """
-
- changes_required, quota_change_request = _system_state_change_details(
- module,
- project_quota_output
- )
-
- if changes_required:
- return True
- else:
- return False
-
-
-def main():
-
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- state=dict(default='present', choices=['absent', 'present']),
- backup_gigabytes=dict(required=False, type='int', default=None),
- backups=dict(required=False, type='int', default=None),
- cores=dict(required=False, type='int', default=None),
- fixed_ips=dict(required=False, type='int', default=None),
- floating_ips=dict(required=False, type='int', default=None, aliases=['compute_floating_ips']),
- floatingip=dict(required=False, type='int', default=None, aliases=['network_floating_ips']),
- gigabytes=dict(required=False, type='int', default=None),
- gigabytes_types=dict(required=False, type='dict', default={}),
- injected_file_size=dict(required=False, type='int', default=None),
- injected_files=dict(required=False, type='int', default=None),
- injected_path_size=dict(required=False, type='int', default=None),
- instances=dict(required=False, type='int', default=None),
- key_pairs=dict(required=False, type='int', default=None),
- loadbalancer=dict(required=False, type='int', default=None),
- network=dict(required=False, type='int', default=None),
- per_volume_gigabytes=dict(required=False, type='int', default=None),
- pool=dict(required=False, type='int', default=None),
- port=dict(required=False, type='int', default=None),
- project=dict(required=False, type='int', default=None),
- properties=dict(required=False, type='int', default=None),
- ram=dict(required=False, type='int', default=None),
- rbac_policy=dict(required=False, type='int', default=None),
- router=dict(required=False, type='int', default=None),
- security_group_rule=dict(required=False, type='int', default=None),
- security_group=dict(required=False, type='int', default=None),
- server_group_members=dict(required=False, type='int', default=None),
- server_groups=dict(required=False, type='int', default=None),
- snapshots=dict(required=False, type='int', default=None),
- snapshots_types=dict(required=False, type='dict', default={}),
- subnet=dict(required=False, type='int', default=None),
- subnetpool=dict(required=False, type='int', default=None),
- volumes=dict(required=False, type='int', default=None),
- volumes_types=dict(required=False, type='dict', default={})
- )
-
- module = AnsibleModule(argument_spec,
- supports_check_mode=True
- )
-
- if not HAS_KEYSTONEAUTH1:
- module.fail_json(msg=missing_required_lib("keystoneauth1"), exception=KEYSTONEAUTH1_IMP_ERR)
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- cloud_params = dict(module.params)
-
- # In order to handle the different volume types we update module params after.
- dynamic_types = [
- 'gigabytes_types',
- 'snapshots_types',
- 'volumes_types',
- ]
-
- for dynamic_type in dynamic_types:
- for k, v in module.params[dynamic_type].items():
- module.params[k] = int(v)
-
- # Get current quota values
- project_quota_output = _get_quotas(
- sdk, module, cloud, cloud_params['name'])
- changes_required = False
-
- if module.params['state'] == "absent":
- # If a quota state is set to absent we should assume there will be changes.
- # The default quota values are not accessible so we can not determine if
- # no changes will occur or not.
- if module.check_mode:
- module.exit_json(changed=True)
-
- # Calling delete_network_quotas when a quota has not been set results
- # 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.
- neutron_msg1 = "network client call failed: Quota for tenant"
- neutron_msg2 = "could not be found"
-
- for quota_type in project_quota_output.keys():
- quota_call = getattr(cloud, 'delete_%s_quotas' % (quota_type))
- try:
- quota_call(cloud_params['name'])
- 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
- else:
- module.fail_json(msg=str(e), extra_data=e.extra_data)
-
- project_quota_output = _get_quotas(
- sdk, module, cloud, cloud_params['name'])
- changes_required = True
-
- elif module.params['state'] == "present":
- if module.check_mode:
- module.exit_json(changed=_system_state_change(module, project_quota_output))
-
- changes_required, quota_change_request = _system_state_change_details(
- module,
- project_quota_output
- )
-
- if changes_required:
- for quota_type in quota_change_request.keys():
- quota_call = getattr(cloud, 'set_%s_quotas' % (quota_type))
- quota_call(cloud_params['name'], **quota_change_request[quota_type])
-
- # Get quota state post changes for validation
- project_quota_update = _get_quotas(
- sdk, module, cloud, cloud_params['name'])
-
- if project_quota_output == project_quota_update:
- module.fail_json(msg='Could not apply quota update')
-
- project_quota_output = project_quota_update
-
- module.exit_json(changed=changes_required,
- openstack_quotas=project_quota_output
- )
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e), extra_data=e.extra_data)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_recordset.py b/lib/ansible/modules/cloud/openstack/os_recordset.py
deleted file mode 100644
index 3bd4b6f0a8..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_recordset.py
+++ /dev/null
@@ -1,236 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2016 Hewlett-Packard Enterprise
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_recordset
-short_description: Manage OpenStack DNS recordsets
-extends_documentation_fragment: openstack
-version_added: "2.2"
-author: "Ricardo Carrillo Cruz (@rcarrillocruz)"
-description:
- - Manage OpenStack DNS recordsets. Recordsets can be created, deleted or
- updated. Only the I(records), I(description), and I(ttl) values
- can be updated.
-options:
- zone:
- description:
- - Zone managing the recordset
- required: true
- name:
- description:
- - Name of the recordset
- required: true
- recordset_type:
- description:
- - Recordset type
- required: true
- records:
- description:
- - List of recordset definitions
- required: true
- description:
- description:
- - Description of the recordset
- ttl:
- description:
- - TTL (Time To Live) value in seconds
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-# Create a recordset named "www.example.net."
-- os_recordset:
- cloud: mycloud
- state: present
- zone: example.net.
- name: www
- recordset_type: primary
- records: ['10.1.1.1']
- description: test recordset
- ttl: 3600
-
-# Update the TTL on existing "www.example.net." recordset
-- os_recordset:
- cloud: mycloud
- state: present
- zone: example.net.
- name: www
- ttl: 7200
-
-# Delete recordset named "www.example.net."
-- os_recordset:
- cloud: mycloud
- state: absent
- zone: example.net.
- name: www
-'''
-
-RETURN = '''
-recordset:
- description: Dictionary describing the recordset.
- returned: On success when I(state) is 'present'.
- type: complex
- contains:
- id:
- description: Unique recordset ID
- type: str
- sample: "c1c530a3-3619-46f3-b0f6-236927b2618c"
- name:
- description: Recordset name
- type: str
- sample: "www.example.net."
- zone_id:
- description: Zone id
- type: str
- sample: 9508e177-41d8-434e-962c-6fe6ca880af7
- type:
- description: Recordset type
- type: str
- sample: "A"
- description:
- description: Recordset description
- type: str
- sample: "Test description"
- ttl:
- description: Zone TTL value
- type: int
- sample: 3600
- records:
- description: Recordset records
- type: list
- sample: ['10.0.0.1']
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _system_state_change(state, records, description, ttl, zone, recordset):
- if state == 'present':
- if recordset is None:
- return True
- if records is not None and recordset['records'] != records:
- return True
- if description is not None and recordset['description'] != description:
- return True
- if ttl is not None and recordset['ttl'] != ttl:
- return True
- if state == 'absent' and recordset:
- return True
- return False
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- zone=dict(required=True),
- name=dict(required=True),
- recordset_type=dict(required=False),
- records=dict(required=False, type='list'),
- description=dict(required=False, default=None),
- ttl=dict(required=False, default=None, type='int'),
- state=dict(default='present', choices=['absent', 'present']),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec,
- required_if=[
- ('state', 'present',
- ['recordset_type', 'records'])],
- supports_check_mode=True,
- **module_kwargs)
-
- zone = module.params.get('zone')
- name = module.params.get('name')
- state = module.params.get('state')
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- recordset_type = module.params.get('recordset_type')
- recordset_filter = {'type': recordset_type}
-
- recordsets = cloud.search_recordsets(zone, name_or_id=name, filters=recordset_filter)
-
- if len(recordsets) == 1:
- recordset = recordsets[0]
- try:
- recordset_id = recordset['id']
- except KeyError as e:
- module.fail_json(msg=str(e))
- else:
- # recordsets is filtered by type and should never be more than 1 return
- recordset = None
-
- if state == 'present':
- records = module.params.get('records')
- description = module.params.get('description')
- ttl = module.params.get('ttl')
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(state,
- records, description,
- ttl, zone,
- recordset))
-
- if recordset is None:
- recordset = cloud.create_recordset(
- zone=zone, name=name, recordset_type=recordset_type,
- records=records, description=description, ttl=ttl)
- changed = True
- else:
- if records is None:
- records = []
-
- pre_update_recordset = recordset
- changed = _system_state_change(state, records,
- description, ttl,
- zone, pre_update_recordset)
- if changed:
- zone = cloud.update_recordset(
- zone, recordset_id,
- records=records,
- description=description,
- ttl=ttl)
-
- module.exit_json(changed=changed, recordset=recordset)
-
- elif state == 'absent':
- if module.check_mode:
- module.exit_json(changed=_system_state_change(state,
- None, None,
- None,
- None, recordset))
-
- if recordset is None:
- changed = False
- else:
- cloud.delete_recordset(zone, recordset_id)
- changed = True
- module.exit_json(changed=changed)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_router.py b/lib/ansible/modules/cloud/openstack/os_router.py
deleted file mode 100644
index 56abc21493..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_router.py
+++ /dev/null
@@ -1,487 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright: Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_router
-short_description: Create or delete routers from OpenStack
-extends_documentation_fragment: openstack
-version_added: "2.0"
-author: "David Shrewsbury (@Shrews)"
-description:
- - Create or Delete routers from OpenStack. Although Neutron allows
- routers to share the same name, this module enforces name uniqueness
- to be more user friendly.
-options:
- state:
- description:
- - Indicate desired state of the resource
- choices: ['present', 'absent']
- default: present
- name:
- description:
- - Name to be give to the router
- required: true
- admin_state_up:
- description:
- - Desired admin state of the created or existing router.
- type: bool
- default: 'yes'
- enable_snat:
- description:
- - Enable Source NAT (SNAT) attribute.
- type: bool
- network:
- description:
- - Unique name or ID of the external gateway network.
- - required I(interfaces) or I(enable_snat) are provided.
- project:
- description:
- - Unique name or ID of the project.
- version_added: "2.2"
- external_fixed_ips:
- description:
- - The IP address parameters for the external gateway network. Each
- is a dictionary with the subnet name or ID (subnet) and the IP
- address to assign on the subnet (ip). If no IP is specified,
- one is automatically assigned from that subnet.
- interfaces:
- description:
- - List of subnets to attach to the router internal interface. Default
- gateway associated with the subnet will be automatically attached
- with the router's internal interface.
- In order to provide an ip address different from the default
- gateway,parameters are passed as dictionary with keys as network
- name or ID(net), subnet name or ID (subnet) and the IP of
- port (portip) from the network.
- User defined portip is often required when a multiple router need
- to be connected to a single subnet for which the default gateway has
- been already used.
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-requirements: ["openstacksdk"]
-'''
-
-EXAMPLES = '''
-# Create a simple router, not attached to a gateway or subnets.
-- os_router:
- cloud: mycloud
- state: present
- name: simple_router
-
-# Create a simple router, not attached to a gateway or subnets for a given project.
-- os_router:
- cloud: mycloud
- state: present
- name: simple_router
- project: myproj
-
-# Creates a router attached to ext_network1 on an IPv4 subnet and one
-# internal subnet interface.
-- os_router:
- cloud: mycloud
- state: present
- name: router1
- network: ext_network1
- external_fixed_ips:
- - subnet: public-subnet
- ip: 172.24.4.2
- interfaces:
- - private-subnet
-
-# Create another router with two internal subnet interfaces.One with user defined port
-# ip and another with default gateway.
-- os_router:
- cloud: mycloud
- state: present
- name: router2
- network: ext_network1
- interfaces:
- - net: private-net
- subnet: private-subnet
- portip: 10.1.1.10
- - project-subnet
-
-# Create another router with two internal subnet interface.One with user defined port
-# ip and and another with default gateway.
-- os_router:
- cloud: mycloud
- state: present
- name: router2
- network: ext_network1
- interfaces:
- - net: private-net
- subnet: private-subnet
- portip: 10.1.1.10
- - project-subnet
-
-# Create another router with two internal subnet interface. one with user defined port
-# ip and and another with default gateway.
-- os_router:
- cloud: mycloud
- state: present
- name: router2
- network: ext_network1
- interfaces:
- - net: private-net
- subnet: private-subnet
- portip: 10.1.1.10
- - project-subnet
-
-# Update existing router1 external gateway to include the IPv6 subnet.
-# Note that since 'interfaces' is not provided, any existing internal
-# interfaces on an existing router will be left intact.
-- os_router:
- cloud: mycloud
- state: present
- name: router1
- network: ext_network1
- external_fixed_ips:
- - subnet: public-subnet
- ip: 172.24.4.2
- - subnet: ipv6-public-subnet
- ip: 2001:db8::3
-
-# Delete router1
-- os_router:
- cloud: mycloud
- state: absent
- name: router1
-'''
-
-RETURN = '''
-router:
- description: Dictionary describing the router.
- returned: On success when I(state) is 'present'
- type: complex
- contains:
- id:
- description: Router ID.
- type: str
- sample: "474acfe5-be34-494c-b339-50f06aa143e4"
- name:
- description: Router name.
- type: str
- sample: "router1"
- admin_state_up:
- description: Administrative state of the router.
- type: bool
- sample: true
- status:
- description: The router status.
- type: str
- sample: "ACTIVE"
- tenant_id:
- description: The tenant ID.
- type: str
- sample: "861174b82b43463c9edc5202aadc60ef"
- external_gateway_info:
- description: The external gateway parameters.
- type: dict
- sample: {
- "enable_snat": true,
- "external_fixed_ips": [
- {
- "ip_address": "10.6.6.99",
- "subnet_id": "4272cb52-a456-4c20-8f3c-c26024ecfa81"
- }
- ]
- }
- routes:
- description: The extra routes configuration for L3 router.
- type: list
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-ROUTER_INTERFACE_OWNERS = set([
- 'network:router_interface',
- 'network:router_interface_distributed',
- 'network:ha_router_replicated_interface'
-])
-
-
-def _router_internal_interfaces(cloud, router):
- for port in cloud.list_router_interfaces(router, 'internal'):
- if port['device_owner'] in ROUTER_INTERFACE_OWNERS:
- yield port
-
-
-def _needs_update(cloud, module, router, network, internal_subnet_ids, internal_port_ids, filters=None):
- """Decide if the given router needs an update.
- """
- if router['admin_state_up'] != module.params['admin_state_up']:
- return True
- if router['external_gateway_info']:
- # check if enable_snat is set in module params
- if module.params['enable_snat'] is not None:
- if router['external_gateway_info'].get('enable_snat', True) != module.params['enable_snat']:
- return True
- if network:
- if not router['external_gateway_info']:
- return True
- elif router['external_gateway_info']['network_id'] != network['id']:
- return True
-
- # check external interfaces
- if module.params['external_fixed_ips']:
- for new_iface in module.params['external_fixed_ips']:
- subnet = cloud.get_subnet(new_iface['subnet'], filters)
- exists = False
-
- # compare the requested interface with existing, looking for an existing match
- for existing_iface in router['external_gateway_info']['external_fixed_ips']:
- if existing_iface['subnet_id'] == subnet['id']:
- if 'ip' in new_iface:
- if existing_iface['ip_address'] == new_iface['ip']:
- # both subnet id and ip address match
- exists = True
- break
- else:
- # only the subnet was given, so ip doesn't matter
- exists = True
- break
-
- # this interface isn't present on the existing router
- if not exists:
- return True
-
- # check internal interfaces
- if module.params['interfaces']:
- existing_subnet_ids = []
- for port in _router_internal_interfaces(cloud, router):
- if 'fixed_ips' in port:
- for fixed_ip in port['fixed_ips']:
- existing_subnet_ids.append(fixed_ip['subnet_id'])
-
- for iface in module.params['interfaces']:
- if isinstance(iface, dict):
- for p_id in internal_port_ids:
- p = cloud.get_port(name_or_id=p_id)
- if 'fixed_ips' in p:
- for fip in p['fixed_ips']:
- internal_subnet_ids.append(fip['subnet_id'])
-
- if set(internal_subnet_ids) != set(existing_subnet_ids):
- internal_subnet_ids = []
- return True
-
- return False
-
-
-def _system_state_change(cloud, module, router, network, internal_ids, internal_portids, filters=None):
- """Check if the system state would be changed."""
- state = module.params['state']
- if state == 'absent' and router:
- return True
- if state == 'present':
- if not router:
- return True
- return _needs_update(cloud, module, router, network, internal_ids, internal_portids, filters)
- return False
-
-
-def _build_kwargs(cloud, module, router, network):
- kwargs = {
- 'admin_state_up': module.params['admin_state_up'],
- }
-
- if router:
- kwargs['name_or_id'] = router['id']
- else:
- kwargs['name'] = module.params['name']
-
- if network:
- kwargs['ext_gateway_net_id'] = network['id']
- # can't send enable_snat unless we have a network
- if module.params.get('enable_snat') is not None:
- kwargs['enable_snat'] = module.params['enable_snat']
-
- if module.params['external_fixed_ips']:
- kwargs['ext_fixed_ips'] = []
- for iface in module.params['external_fixed_ips']:
- subnet = cloud.get_subnet(iface['subnet'])
- d = {'subnet_id': subnet['id']}
- if 'ip' in iface:
- d['ip_address'] = iface['ip']
- kwargs['ext_fixed_ips'].append(d)
-
- return kwargs
-
-
-def _validate_subnets(module, cloud, filters=None):
- external_subnet_ids = []
- internal_subnet_ids = []
- internal_port_ids = []
- existing_port_ips = []
- existing_port_ids = []
- if module.params['external_fixed_ips']:
- for iface in module.params['external_fixed_ips']:
- subnet = cloud.get_subnet(iface['subnet'])
- if not subnet:
- module.fail_json(msg='subnet %s not found' % iface['subnet'])
- external_subnet_ids.append(subnet['id'])
-
- if module.params['interfaces']:
- for iface in module.params['interfaces']:
- if isinstance(iface, str):
- subnet = cloud.get_subnet(iface, filters)
- if not subnet:
- module.fail_json(msg='subnet %s not found' % iface)
- internal_subnet_ids.append(subnet['id'])
- elif isinstance(iface, dict):
- subnet = cloud.get_subnet(iface['subnet'], filters)
- if not subnet:
- module.fail_json(msg='subnet %s not found' % iface['subnet'])
- net = cloud.get_network(iface['net'])
- if not net:
- module.fail_json(msg='net %s not found' % iface['net'])
- if "portip" not in iface:
- internal_subnet_ids.append(subnet['id'])
- elif not iface['portip']:
- module.fail_json(msg='put an ip in portip or remove it from list to assign default port to router')
- else:
- for existing_port in cloud.list_ports(filters={'network_id': net.id}):
- for fixed_ip in existing_port['fixed_ips']:
- if iface['portip'] == fixed_ip['ip_address']:
- internal_port_ids.append(existing_port.id)
- existing_port_ips.append(fixed_ip['ip_address'])
- if iface['portip'] not in existing_port_ips:
- p = cloud.create_port(network_id=net.id, fixed_ips=[{'ip_address': iface['portip'], 'subnet_id': subnet.id}])
- if p:
- internal_port_ids.append(p.id)
-
- return external_subnet_ids, internal_subnet_ids, internal_port_ids
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- state=dict(default='present', choices=['absent', 'present']),
- name=dict(required=True),
- admin_state_up=dict(type='bool', default=True),
- enable_snat=dict(type='bool'),
- network=dict(default=None),
- interfaces=dict(type='list', default=None),
- external_fixed_ips=dict(type='list', default=None),
- project=dict(default=None)
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- state = module.params['state']
- name = module.params['name']
- network = module.params['network']
- project = module.params['project']
-
- if module.params['external_fixed_ips'] and not network:
- module.fail_json(msg='network is required when supplying external_fixed_ips')
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- if project is not None:
- proj = cloud.get_project(project)
- if proj is None:
- module.fail_json(msg='Project %s could not be found' % project)
- project_id = proj['id']
- filters = {'tenant_id': project_id}
- else:
- project_id = None
- filters = None
-
- router = cloud.get_router(name, filters=filters)
- net = None
- if network:
- net = cloud.get_network(network)
- if not net:
- module.fail_json(msg='network %s not found' % network)
-
- # Validate and cache the subnet IDs so we can avoid duplicate checks
- # and expensive API calls.
- external_ids, subnet_internal_ids, internal_portids = _validate_subnets(module, cloud, filters)
- if module.check_mode:
- module.exit_json(
- changed=_system_state_change(cloud, module, router, net, subnet_internal_ids, internal_portids, filters)
- )
-
- if state == 'present':
- changed = False
-
- if not router:
- kwargs = _build_kwargs(cloud, module, router, net)
- if project_id:
- kwargs['project_id'] = project_id
- router = cloud.create_router(**kwargs)
- for int_s_id in subnet_internal_ids:
- cloud.add_router_interface(router, subnet_id=int_s_id)
- changed = True
- # add interface by port id as well
- for int_p_id in internal_portids:
- cloud.add_router_interface(router, port_id=int_p_id)
- changed = True
- else:
- if _needs_update(cloud, module, router, net, subnet_internal_ids, internal_portids, filters):
- kwargs = _build_kwargs(cloud, module, router, net)
- updated_router = cloud.update_router(**kwargs)
-
- # Protect against update_router() not actually
- # updating the router.
- if not updated_router:
- changed = False
-
- # On a router update, if any internal interfaces were supplied,
- # just detach all existing internal interfaces and attach the new.
- if internal_portids or subnet_internal_ids:
- router = updated_router
- ports = _router_internal_interfaces(cloud, router)
- for port in ports:
- cloud.remove_router_interface(router, port_id=port['id'])
- if internal_portids:
- external_ids, subnet_internal_ids, internal_portids = _validate_subnets(module, cloud, filters)
- for int_p_id in internal_portids:
- cloud.add_router_interface(router, port_id=int_p_id)
- changed = True
- if subnet_internal_ids:
- for s_id in subnet_internal_ids:
- cloud.add_router_interface(router, subnet_id=s_id)
- changed = True
-
- module.exit_json(changed=changed,
- router=router,
- id=router['id'])
-
- elif state == 'absent':
- if not router:
- module.exit_json(changed=False)
- else:
- # We need to detach all internal interfaces on a router before
- # we will be allowed to delete it.
- ports = _router_internal_interfaces(cloud, router)
- router_id = router['id']
- for port in ports:
- cloud.remove_router_interface(router, port_id=port['id'])
- cloud.delete_router(router_id)
- module.exit_json(changed=True)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_security_group.py b/lib/ansible/modules/cloud/openstack/os_security_group.py
deleted file mode 100644
index d05765bf1f..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_security_group.py
+++ /dev/null
@@ -1,163 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
-# Copyright (c) 2013, Benno Joy <benno@ansible.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_security_group
-short_description: Add/Delete security groups from an OpenStack cloud.
-extends_documentation_fragment: openstack
-author: "Monty Taylor (@emonty)"
-version_added: "2.0"
-description:
- - Add or Remove security groups from an OpenStack cloud.
-options:
- name:
- description:
- - Name that has to be given to the security group. This module
- requires that security group names be unique.
- required: true
- description:
- description:
- - Long description of the purpose of the security group
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- project:
- description:
- - Unique name or ID of the project.
- required: false
- version_added: "2.7"
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-'''
-
-EXAMPLES = '''
-# Create a security group
-- os_security_group:
- cloud: mordred
- state: present
- name: foo
- description: security group for foo servers
-
-# Update the existing 'foo' security group description
-- os_security_group:
- cloud: mordred
- state: present
- name: foo
- description: updated description for the foo security group
-
-# Create a security group for a given project
-- os_security_group:
- cloud: mordred
- state: present
- name: foo
- project: myproj
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _needs_update(module, secgroup):
- """Check for differences in the updatable values.
-
- NOTE: We don't currently allow name updates.
- """
- if secgroup['description'] != module.params['description']:
- return True
- return False
-
-
-def _system_state_change(module, secgroup):
- state = module.params['state']
- if state == 'present':
- if not secgroup:
- return True
- return _needs_update(module, secgroup)
- if state == 'absent' and secgroup:
- return True
- return False
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- description=dict(default=''),
- state=dict(default='present', choices=['absent', 'present']),
- project=dict(default=None),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- name = module.params['name']
- state = module.params['state']
- description = module.params['description']
- project = module.params['project']
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- if project is not None:
- proj = cloud.get_project(project)
- if proj is None:
- module.fail_json(msg='Project %s could not be found' % project)
- project_id = proj['id']
- else:
- project_id = cloud.current_project_id
-
- if project_id:
- filters = {'tenant_id': project_id}
- else:
- filters = None
-
- secgroup = cloud.get_security_group(name, filters=filters)
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(module, secgroup))
-
- changed = False
- if state == 'present':
- if not secgroup:
- kwargs = {}
- if project_id:
- kwargs['project_id'] = project_id
- secgroup = cloud.create_security_group(name, description,
- **kwargs)
- changed = True
- else:
- if _needs_update(module, secgroup):
- secgroup = cloud.update_security_group(
- secgroup['id'], description=description)
- changed = True
- module.exit_json(
- changed=changed, id=secgroup['id'], secgroup=secgroup)
-
- if state == 'absent':
- if secgroup:
- cloud.delete_security_group(secgroup['id'])
- changed = True
- module.exit_json(changed=changed)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == "__main__":
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_security_group_rule.py b/lib/ansible/modules/cloud/openstack/os_security_group_rule.py
deleted file mode 100644
index 0c84dfd6d3..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_security_group_rule.py
+++ /dev/null
@@ -1,385 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
-# Copyright (c) 2013, Benno Joy <benno@ansible.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_security_group_rule
-short_description: Add/Delete rule from an existing security group
-author:
- - "Benno Joy (@bennojoy)"
- - "Jeffrey van Pelt (@Thulium-Drake)"
-extends_documentation_fragment: openstack
-version_added: "2.0"
-description:
- - Add or Remove rule from an existing security group
-options:
- security_group:
- description:
- - Name or ID of the security group
- required: true
- protocol:
- description:
- - IP protocols ANY TCP UDP ICMP 112 (VRRP) 132 (SCTP)
- choices: ['any', 'tcp', 'udp', 'icmp', '112', '132', None]
- port_range_min:
- description:
- - Starting port
- port_range_max:
- description:
- - Ending port
- remote_ip_prefix:
- description:
- - Source IP address(es) in CIDR notation (exclusive with remote_group)
- remote_group:
- description:
- - Name or ID of the Security group to link (exclusive with
- remote_ip_prefix)
- ethertype:
- description:
- - Must be IPv4 or IPv6, and addresses represented in CIDR must
- match the ingress or egress rules. Not all providers support IPv6.
- choices: ['IPv4', 'IPv6']
- default: IPv4
- direction:
- description:
- - The direction in which the security group rule is applied. Not
- all providers support egress.
- choices: ['egress', 'ingress']
- default: ingress
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- project:
- description:
- - Unique name or ID of the project.
- required: false
- version_added: "2.7"
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-requirements: ["openstacksdk"]
-'''
-
-EXAMPLES = '''
-# Create a security group rule
-- os_security_group_rule:
- cloud: mordred
- security_group: foo
- protocol: tcp
- port_range_min: 80
- port_range_max: 80
- remote_ip_prefix: 0.0.0.0/0
-
-# Create a security group rule for ping
-- os_security_group_rule:
- cloud: mordred
- security_group: foo
- protocol: icmp
- remote_ip_prefix: 0.0.0.0/0
-
-# Another way to create the ping rule
-- os_security_group_rule:
- cloud: mordred
- security_group: foo
- protocol: icmp
- port_range_min: -1
- port_range_max: -1
- remote_ip_prefix: 0.0.0.0/0
-
-# Create a TCP rule covering all ports
-- os_security_group_rule:
- cloud: mordred
- security_group: foo
- protocol: tcp
- port_range_min: 1
- port_range_max: 65535
- remote_ip_prefix: 0.0.0.0/0
-
-# Another way to create the TCP rule above (defaults to all ports)
-- os_security_group_rule:
- cloud: mordred
- security_group: foo
- protocol: tcp
- remote_ip_prefix: 0.0.0.0/0
-
-# Create a rule for VRRP with numbered protocol 112
-- os_security_group_rule:
- security_group: loadbalancer_sg
- protocol: 112
- remote_group: loadbalancer-node_sg
-
-# Create a security group rule for a given project
-- os_security_group_rule:
- cloud: mordred
- security_group: foo
- protocol: icmp
- remote_ip_prefix: 0.0.0.0/0
- project: myproj
-
-# Remove the default created egress rule for IPv4
-- os_security_group_rule:
- cloud: mordred
- security_group: foo
- protocol: any
- remote_ip_prefix: 0.0.0.0/0
-'''
-
-RETURN = '''
-id:
- description: Unique rule UUID.
- type: str
- returned: state == present
-direction:
- description: The direction in which the security group rule is applied.
- type: str
- sample: 'egress'
- returned: state == present
-ethertype:
- description: One of IPv4 or IPv6.
- type: str
- sample: 'IPv4'
- returned: state == present
-port_range_min:
- description: The minimum port number in the range that is matched by
- the security group rule.
- type: int
- sample: 8000
- returned: state == present
-port_range_max:
- description: The maximum port number in the range that is matched by
- the security group rule.
- type: int
- sample: 8000
- returned: state == present
-protocol:
- description: The protocol that is matched by the security group rule.
- type: str
- sample: 'tcp'
- returned: state == present
-remote_ip_prefix:
- description: The remote IP prefix to be associated with this security group rule.
- type: str
- sample: '0.0.0.0/0'
- returned: state == present
-security_group_id:
- description: The security group ID to associate with this security group rule.
- type: str
- returned: state == present
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-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 sdk. Likewise,
- they might be None, which works for Neutron, but not Nova. This too is
- 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. 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.
- """
-
- # Check if the user is supplying -1 for ICMP.
- if protocol == 'icmp':
- if module_min and int(module_min) == -1:
- module_min = None
- if module_max and int(module_max) == -1:
- module_max = None
-
- # Rules with 'any' protocol do not match ports
- if protocol == 'any':
- return True
-
- # Check if the user is supplying -1 or None values for full TPC/UDP port range.
- if protocol in ['tcp', 'udp'] or protocol is None:
- if module_min and module_max and int(module_min) == int(module_max) == -1:
- module_min = None
- module_max = None
-
- if ((module_min is None and module_max is None) and
- (rule_min and int(rule_min) == 1 and
- rule_max and int(rule_max) == 65535)):
- # (None, None) == (1, 65535)
- return True
-
- # Sanity check to make sure we don't have type comparison issues.
- if module_min:
- module_min = int(module_min)
- if module_max:
- module_max = int(module_max)
- if rule_min:
- rule_min = int(rule_min)
- if rule_max:
- rule_max = int(rule_max)
-
- return module_min == rule_min and module_max == rule_max
-
-
-def _find_matching_rule(module, secgroup, remotegroup):
- """
- Find a rule in the group that matches the module parameters.
- :returns: The matching rule dict, or None if no matches.
- """
- protocol = module.params['protocol']
- remote_ip_prefix = module.params['remote_ip_prefix']
- ethertype = module.params['ethertype']
- direction = module.params['direction']
- remote_group_id = remotegroup['id']
-
- for rule in secgroup['security_group_rules']:
- if (protocol == rule['protocol'] and
- remote_ip_prefix == rule['remote_ip_prefix'] and
- ethertype == rule['ethertype'] and
- direction == rule['direction'] and
- remote_group_id == rule['remote_group_id'] and
- _ports_match(protocol,
- module.params['port_range_min'],
- module.params['port_range_max'],
- rule['port_range_min'],
- rule['port_range_max'])):
- return rule
- return None
-
-
-def _system_state_change(module, secgroup, remotegroup):
- state = module.params['state']
- if secgroup:
- rule_exists = _find_matching_rule(module, secgroup, remotegroup)
- else:
- return False
-
- if state == 'present' and not rule_exists:
- return True
- if state == 'absent' and rule_exists:
- return True
- return False
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- security_group=dict(required=True),
- # NOTE(Shrews): None is an acceptable protocol value for
- # Neutron, but Nova will balk at this.
- protocol=dict(default=None,
- choices=[None, 'any', 'tcp', 'udp', 'icmp', '112', '132']),
- port_range_min=dict(required=False, type='int'),
- port_range_max=dict(required=False, type='int'),
- remote_ip_prefix=dict(required=False, default=None),
- remote_group=dict(required=False, default=None),
- ethertype=dict(default='IPv4',
- choices=['IPv4', 'IPv6']),
- direction=dict(default='ingress',
- choices=['egress', 'ingress']),
- state=dict(default='present',
- choices=['absent', 'present']),
- project=dict(default=None),
- )
-
- module_kwargs = openstack_module_kwargs(
- mutually_exclusive=[
- ['remote_ip_prefix', 'remote_group'],
- ]
- )
-
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- state = module.params['state']
- security_group = module.params['security_group']
- remote_group = module.params['remote_group']
- project = module.params['project']
- changed = False
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- if project is not None:
- proj = cloud.get_project(project)
- if proj is None:
- module.fail_json(msg='Project %s could not be found' % project)
- project_id = proj['id']
- else:
- project_id = cloud.current_project_id
-
- if project_id:
- filters = {'tenant_id': project_id}
- else:
- filters = None
-
- secgroup = cloud.get_security_group(security_group, filters=filters)
-
- if remote_group:
- remotegroup = cloud.get_security_group(remote_group,
- filters=filters)
- else:
- remotegroup = {'id': None}
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(module, secgroup, remotegroup))
-
- if state == 'present':
- if module.params['protocol'] == 'any':
- module.params['protocol'] = None
-
- if not secgroup:
- module.fail_json(msg='Could not find security group %s' %
- security_group)
-
- rule = _find_matching_rule(module, secgroup, remotegroup)
- if not rule:
- kwargs = {}
- if project_id:
- kwargs['project_id'] = project_id
- rule = cloud.create_security_group_rule(
- secgroup['id'],
- port_range_min=module.params['port_range_min'],
- port_range_max=module.params['port_range_max'],
- protocol=module.params['protocol'],
- remote_ip_prefix=module.params['remote_ip_prefix'],
- remote_group_id=remotegroup['id'],
- direction=module.params['direction'],
- ethertype=module.params['ethertype'],
- **kwargs
- )
- changed = True
- module.exit_json(changed=changed, rule=rule, id=rule['id'])
-
- if state == 'absent' and secgroup:
- rule = _find_matching_rule(module, secgroup, remotegroup)
- if rule:
- cloud.delete_security_group_rule(rule['id'])
- changed = True
-
- module.exit_json(changed=changed)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_server.py b/lib/ansible/modules/cloud/openstack/os_server.py
deleted file mode 100644
index 02c57b1faf..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_server.py
+++ /dev/null
@@ -1,852 +0,0 @@
-#!/usr/bin/python
-# coding: utf-8 -*-
-
-# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
-# Copyright (c) 2013, Benno Joy <benno@ansible.com>
-# Copyright (c) 2013, John Dewey <john@dewey.ws>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_server
-short_description: Create/Delete Compute Instances from OpenStack
-extends_documentation_fragment: openstack
-version_added: "2.0"
-author: "Monty Taylor (@emonty)"
-description:
- - Create or Remove compute instances from OpenStack.
-options:
- name:
- description:
- - Name that has to be given to the instance. It is also possible to
- specify the ID of the instance instead of its name if I(state) is I(absent).
- required: true
- image:
- description:
- - The name or id of the base image to boot.
- required: true
- image_exclude:
- description:
- - Text to use to filter image names, for the case, such as HP, where
- there are multiple image names matching the common identifying
- portions. image_exclude is a negative match filter - it is text that
- may not exist in the image name. Defaults to "(deprecated)"
- flavor:
- description:
- - The name or id of the flavor in which the new instance has to be
- created. Mutually exclusive with flavor_ram
- default: 1
- flavor_ram:
- description:
- - The minimum amount of ram in MB that the flavor in which the new
- instance has to be created must have. Mutually exclusive with flavor.
- default: 1
- flavor_include:
- description:
- - Text to use to filter flavor names, for the case, such as Rackspace,
- where there are multiple flavors that have the same ram count.
- flavor_include is a positive match filter - it must exist in the
- flavor name.
- key_name:
- description:
- - The key pair name to be used when creating a instance
- security_groups:
- description:
- - Names of the security groups to which the instance should be
- added. This may be a YAML list or a comma separated string.
- network:
- description:
- - Name or ID of a network to attach this instance to. A simpler
- version of the nics parameter, only one of network or nics should
- be supplied.
- nics:
- description:
- - A list of networks to which the instance's interface should
- be attached. Networks may be referenced by net-id/net-name/port-id
- or port-name.
- - 'Also this accepts a string containing a list of (net/port)-(id/name)
- Eg: nics: "net-id=uuid-1,port-name=myport"
- Only one of network or nics should be supplied.'
- suboptions:
- tag:
- description:
- - 'A "tag" for the specific port to be passed via metadata.
- Eg: tag: test_tag'
- version_added: '2.10'
- auto_ip:
- description:
- - Ensure instance has public ip however the cloud wants to do that
- type: bool
- default: 'yes'
- aliases: ['auto_floating_ip', 'public_ip']
- floating_ips:
- description:
- - list of valid floating IPs that pre-exist to assign to this node
- floating_ip_pools:
- description:
- - Name of floating IP pool from which to choose a floating IP
- meta:
- description:
- - 'A list of key value pairs that should be provided as a metadata to
- the new instance or a string containing a list of key-value pairs.
- Eg: meta: "key1=value1,key2=value2"'
- wait:
- description:
- - If the module should wait for the instance to be created.
- type: bool
- default: 'yes'
- timeout:
- description:
- - The amount of time the module should wait for the instance to get
- into active state.
- default: 180
- config_drive:
- description:
- - Whether to boot the server with config drive enabled
- type: bool
- default: 'no'
- userdata:
- description:
- - Opaque blob of data which is made available to the instance
- boot_from_volume:
- description:
- - Should the instance boot from a persistent volume created based on
- the image given. Mutually exclusive with boot_volume.
- type: bool
- default: 'no'
- volume_size:
- description:
- - The size of the volume to create in GB if booting from volume based
- on an image.
- boot_volume:
- description:
- - Volume name or id to use as the volume to boot from. Implies
- boot_from_volume. Mutually exclusive with image and boot_from_volume.
- aliases: ['root_volume']
- terminate_volume:
- description:
- - If C(yes), delete volume when deleting instance (if booted from volume)
- type: bool
- default: 'no'
- volumes:
- description:
- - A list of preexisting volumes names or ids to attach to the instance
- default: []
- scheduler_hints:
- description:
- - Arbitrary key/value pairs to the scheduler for custom use
- version_added: "2.1"
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- delete_fip:
- description:
- - When I(state) is absent and this option is true, any floating IP
- associated with the instance will be deleted along with the instance.
- type: bool
- default: 'no'
- version_added: "2.2"
- reuse_ips:
- description:
- - When I(auto_ip) is true and this option is true, the I(auto_ip) code
- will attempt to re-use unassigned floating ips in the project before
- creating a new one. It is important to note that it is impossible
- to safely do this concurrently, so if your use case involves
- concurrent server creation, it is highly recommended to set this to
- false and to delete the floating ip associated with a server when
- the server is deleted using I(delete_fip).
- type: bool
- default: 'yes'
- version_added: "2.2"
- availability_zone:
- description:
- - Availability zone in which to create the server.
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-- name: Create a new instance and attaches to a network and passes metadata to the instance
- os_server:
- state: present
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: admin
- project_name: admin
- name: vm1
- image: 4f905f38-e52a-43d2-b6ec-754a13ffb529
- key_name: ansible_key
- timeout: 200
- flavor: 4
- nics:
- - net-id: 34605f38-e52a-25d2-b6ec-754a13ffb723
- - net-name: another_network
- meta:
- hostname: test1
- group: uge_master
-
-# Create a new instance in HP Cloud AE1 region availability zone az2 and
-# automatically assigns a floating IP
-- name: launch a compute instance
- hosts: localhost
- tasks:
- - name: launch an instance
- os_server:
- state: present
- auth:
- auth_url: https://identity.example.com
- username: username
- password: Equality7-2521
- project_name: username-project1
- name: vm1
- region_name: region-b.geo-1
- availability_zone: az2
- image: 9302692b-b787-4b52-a3a6-daebb79cb498
- key_name: test
- timeout: 200
- flavor: 101
- security_groups: default
- auto_ip: yes
-
-# Create a new instance in named cloud mordred availability zone az2
-# and assigns a pre-known floating IP
-- name: launch a compute instance
- hosts: localhost
- tasks:
- - name: launch an instance
- os_server:
- state: present
- cloud: mordred
- name: vm1
- availability_zone: az2
- image: 9302692b-b787-4b52-a3a6-daebb79cb498
- key_name: test
- timeout: 200
- flavor: 101
- floating_ips:
- - 12.34.56.79
-
-# Create a new instance with 4G of RAM on Ubuntu Trusty, ignoring
-# deprecated images
-- name: launch a compute instance
- hosts: localhost
- tasks:
- - name: launch an instance
- os_server:
- name: vm1
- state: present
- cloud: mordred
- region_name: region-b.geo-1
- image: Ubuntu Server 14.04
- image_exclude: deprecated
- flavor_ram: 4096
-
-# Create a new instance with 4G of RAM on Ubuntu Trusty on a Performance node
-- name: launch a compute instance
- hosts: localhost
- tasks:
- - name: launch an instance
- os_server:
- name: vm1
- cloud: rax-dfw
- state: present
- image: Ubuntu 14.04 LTS (Trusty Tahr) (PVHVM)
- flavor_ram: 4096
- flavor_include: Performance
-
-# Creates a new instance and attaches to multiple network
-- name: launch a compute instance
- hosts: localhost
- tasks:
- - name: launch an instance with a string
- os_server:
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: admin
- project_name: admin
- name: vm1
- image: 4f905f38-e52a-43d2-b6ec-754a13ffb529
- key_name: ansible_key
- timeout: 200
- flavor: 4
- nics: "net-id=4cb08b20-62fe-11e5-9d70-feff819cdc9f,net-id=542f0430-62fe-11e5-9d70-feff819cdc9f..."
-
-- name: Creates a new instance and attaches to a network and passes metadata to the instance
- os_server:
- state: present
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: admin
- project_name: admin
- name: vm1
- image: 4f905f38-e52a-43d2-b6ec-754a13ffb529
- key_name: ansible_key
- timeout: 200
- flavor: 4
- nics:
- - net-id: 34605f38-e52a-25d2-b6ec-754a13ffb723
- - net-name: another_network
- meta: "hostname=test1,group=uge_master"
-
-- name: Creates a new instance and attaches to a specific network
- os_server:
- state: present
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: admin
- project_name: admin
- name: vm1
- image: 4f905f38-e52a-43d2-b6ec-754a13ffb529
- key_name: ansible_key
- timeout: 200
- flavor: 4
- network: another_network
-
-# Create a new instance with 4G of RAM on a 75G Ubuntu Trusty volume
-- name: launch a compute instance
- hosts: localhost
- tasks:
- - name: launch an instance
- os_server:
- name: vm1
- state: present
- cloud: mordred
- region_name: ams01
- image: Ubuntu Server 14.04
- flavor_ram: 4096
- boot_from_volume: True
- volume_size: 75
-
-# Creates a new instance with 2 volumes attached
-- name: launch a compute instance
- hosts: localhost
- tasks:
- - name: launch an instance
- os_server:
- name: vm1
- state: present
- cloud: mordred
- region_name: ams01
- image: Ubuntu Server 14.04
- flavor_ram: 4096
- volumes:
- - photos
- - music
-
-# Creates a new instance with provisioning userdata using Cloud-Init
-- name: launch a compute instance
- hosts: localhost
- tasks:
- - name: launch an instance
- os_server:
- name: vm1
- state: present
- image: "Ubuntu Server 14.04"
- flavor: "P-1"
- network: "Production"
- userdata: |
- #cloud-config
- chpasswd:
- list: |
- ubuntu:{{ default_password }}
- expire: False
- packages:
- - ansible
- package_upgrade: true
-
-# Creates a new instance with provisioning userdata using Bash Scripts
-- name: launch a compute instance
- hosts: localhost
- tasks:
- - name: launch an instance
- os_server:
- name: vm1
- state: present
- image: "Ubuntu Server 14.04"
- flavor: "P-1"
- network: "Production"
- userdata: |
- {%- raw -%}#!/bin/bash
- echo " up ip route add 10.0.0.0/8 via {% endraw -%}{{ intra_router }}{%- raw -%}" >> /etc/network/interfaces.d/eth0.conf
- echo " down ip route del 10.0.0.0/8" >> /etc/network/interfaces.d/eth0.conf
- ifdown eth0 && ifup eth0
- {% endraw %}
-
-# Create a new instance with server group for (anti-)affinity
-# server group ID is returned from os_server_group module.
-- name: launch a compute instance
- hosts: localhost
- tasks:
- - name: launch an instance
- os_server:
- state: present
- name: vm1
- image: 4f905f38-e52a-43d2-b6ec-754a13ffb529
- flavor: 4
- scheduler_hints:
- group: f5c8c61a-9230-400a-8ed2-3b023c190a7f
-
-# Create an instance with "tags" for the nic
-- name: Create instance with nics "tags"
- os_server:
- state: present
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: admin
- project_name: admin
- name: vm1
- image: 4f905f38-e52a-43d2-b6ec-754a13ffb529
- key_name: ansible_key
- flavor: 4
- nics:
- - port-name: net1_port1
- tag: test_tag
- - net-name: another_network
-
-# Deletes an instance via its ID
-- name: remove an instance
- hosts: localhost
- tasks:
- - name: remove an instance
- os_server:
- name: abcdef01-2345-6789-0abc-def0123456789
- state: absent
-
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import (
- openstack_find_nova_addresses, openstack_cloud_from_module,
- openstack_full_argument_spec, openstack_module_kwargs)
-
-
-def _exit_hostvars(module, cloud, server, diff, changed=True):
- redact_keys = ['adminPass']
- for k in redact_keys:
- if k in diff['before']:
- diff['before'][k] = '***'
- if k in diff['after']:
- diff['after'][k] = '***'
- if k in server:
- server[k] = '***'
-
- if module.check_mode:
- hostvars = server
- else:
- hostvars = cloud.get_openstack_vars(server)
-
- module.exit_json(
- changed=changed, diff=diff, server=server, id=server.get('id', None), openstack=hostvars)
-
-
-def _parse_nics(nics):
- for net in nics:
- if isinstance(net, str):
- for nic in net.split(','):
- yield dict((nic.split('='),))
- else:
- yield net
-
-
-def _network_args(module, cloud):
- args = []
- nics = module.params['nics']
-
- if not isinstance(nics, list):
- module.fail_json(msg='The \'nics\' parameter must be a list.')
-
- for num, net in enumerate(_parse_nics(nics)):
- if not isinstance(net, dict):
- module.fail_json(
- msg='Each entry in the \'nics\' parameter must be a dict.')
-
- if net.get('net-id'):
- args.append(net)
- elif net.get('net-name'):
- by_name = cloud.get_network(net['net-name'])
- if not by_name:
- module.fail_json(
- msg='Could not find network by net-name: %s' %
- net['net-name'])
- resolved_net = net.copy()
- del resolved_net['net-name']
- resolved_net['net-id'] = by_name['id']
- args.append(resolved_net)
- elif net.get('port-id'):
- args.append(net)
- elif net.get('port-name'):
- by_name = cloud.get_port(net['port-name'])
- if not by_name:
- module.fail_json(
- msg='Could not find port by port-name: %s' %
- net['port-name'])
- resolved_net = net.copy()
- del resolved_net['port-name']
- resolved_net['port-id'] = by_name['id']
- args.append(resolved_net)
-
- if 'tag' in net:
- args[num]['tag'] = net['tag']
- return args
-
-
-def _parse_meta(meta):
- if isinstance(meta, str):
- metas = {}
- for kv_str in meta.split(','):
- k, v = kv_str.split('=')
- metas[k] = v
- return metas
- if not meta:
- return {}
- return meta
-
-
-def _delete_server(module, cloud):
- if module.check_mode:
- return True
-
- try:
- cloud.delete_server(
- module.params['name'], wait=module.params['wait'],
- timeout=module.params['timeout'],
- delete_ips=module.params['delete_fip'])
- except Exception as e:
- module.fail_json(msg='Error in deleting vm: %s' % e.message)
- return True
-
-
-def _create_server(module, cloud):
- flavor = module.params['flavor']
- flavor_ram = module.params['flavor_ram']
- flavor_include = module.params['flavor_include']
-
- image_id = None
- if not module.params['boot_volume']:
- image_id = cloud.get_image_id(
- module.params['image'], module.params['image_exclude'])
- if not image_id:
- module.fail_json(msg='Could not find image %s' %
- module.params['image'])
-
- if flavor:
- flavor_dict = cloud.get_flavor(flavor)
- if not flavor_dict:
- module.fail_json(msg='Could not find flavor %s' % flavor)
- else:
- flavor_dict = cloud.get_flavor_by_ram(flavor_ram, flavor_include)
- if not flavor_dict:
- module.fail_json(msg='Could not find any matching flavor')
-
- if module.check_mode:
- server = dict(
- name=module.params['name'],
- security_groups=module.params['security_groups']
- )
- return server
-
- nics = _network_args(module, cloud)
- module.params['meta'] = _parse_meta(module.params['meta'])
-
- bootkwargs = dict(
- name=module.params['name'],
- image=image_id,
- flavor=flavor_dict['id'],
- nics=nics,
- meta=module.params['meta'],
- security_groups=module.params['security_groups'],
- userdata=module.params['userdata'],
- config_drive=module.params['config_drive'],
- )
- for optional_param in (
- 'key_name', 'availability_zone', 'network',
- 'scheduler_hints', 'volume_size', 'volumes'):
- if module.params[optional_param]:
- bootkwargs[optional_param] = module.params[optional_param]
-
- server = cloud.create_server(
- ip_pool=module.params['floating_ip_pools'],
- ips=module.params['floating_ips'],
- auto_ip=module.params['auto_ip'],
- boot_volume=module.params['boot_volume'],
- boot_from_volume=module.params['boot_from_volume'],
- terminate_volume=module.params['terminate_volume'],
- reuse_ips=module.params['reuse_ips'],
- wait=module.params['wait'], timeout=module.params['timeout'],
- **bootkwargs
- )
-
- return server
-
-
-def _update_server(module, cloud, server):
- changed = False
- sg_changed = False
- ip_changed = False
-
- module.params['meta'] = _parse_meta(module.params['meta'])
-
- # cloud.set_server_metadata only updates the key=value pairs, it doesn't
- # touch existing ones
- update_meta = {}
- for (k, v) in module.params['meta'].items():
- if k not in server.metadata or server.metadata[k] != v:
- update_meta[k] = v
-
- if update_meta:
- if module.check_mode:
- server['metadata'].update(update_meta)
- else:
- cloud.set_server_metadata(server, update_meta)
- changed = True
-
- # these functions perform update checks themselves
- (sg_changed, server) = _update_security_groups(module, cloud, server)
- (ip_changed, server) = _update_ips(module, cloud, server)
-
- if sg_changed or ip_changed:
- changed = True
-
- if changed and not module.check_mode:
- # Refresh server vars
- server = cloud.get_server(module.params['name'])
-
- return (changed, server)
-
-
-def _detach_ip_list(cloud, server, extra_ips):
- for ip in extra_ips:
- ip_id = cloud.get_floating_ip(
- id=None, filters={'floating_ip_address': ip})
- cloud.detach_ip_from_server(
- server_id=server.id, floating_ip_id=ip_id)
-
-
-def _update_ips(module, cloud, server):
- changed = False
-
- auto_ip = module.params['auto_ip']
- floating_ips = module.params['floating_ips']
- floating_ip_pools = module.params['floating_ip_pools']
-
- if floating_ip_pools or floating_ips:
- ips = openstack_find_nova_addresses(server.addresses, 'floating')
- if not ips:
- # If we're configured to have a floating but we don't have one,
- # let's add one
- server = cloud.add_ips_to_server(
- server,
- auto_ip=auto_ip,
- ips=floating_ips,
- ip_pool=floating_ip_pools,
- wait=module.params['wait'],
- timeout=module.params['timeout'],
- )
- changed = True
- elif floating_ips:
- # we were configured to have specific ips, let's make sure we have
- # those
- missing_ips = []
- for ip in floating_ips:
- if ip not in ips:
- missing_ips.append(ip)
- if missing_ips:
- server = cloud.add_ip_list(server, missing_ips,
- wait=module.params['wait'],
- timeout=module.params['timeout'])
- changed = True
- extra_ips = []
- for ip in ips:
- if ip not in floating_ips:
- extra_ips.append(ip)
- if extra_ips:
- _detach_ip_list(cloud, server, extra_ips)
- changed = True
- elif auto_ip:
- if server['interface_ip']:
- changed = False
- else:
- # We're configured for auto_ip but we're not showing an
- # interface_ip. Maybe someone deleted an IP out from under us.
- server = cloud.add_ips_to_server(
- server,
- auto_ip=auto_ip,
- ips=floating_ips,
- ip_pool=floating_ip_pools,
- wait=module.params['wait'],
- timeout=module.params['timeout'],
- )
- changed = True
- return (changed, server)
-
-
-def _update_security_groups(module, cloud, server):
- changed = False
-
- # server security groups were added to shade in 1.19. Until then this
- # module simply ignored trying to update security groups and only set them
- # on newly created hosts.
- if not (hasattr(cloud, 'add_server_security_groups') and
- hasattr(cloud, 'remove_server_security_groups')):
- return changed, server
-
- module_security_groups = set(module.params['security_groups'])
- server_security_groups = set(sg['name'] for sg in server.security_groups)
-
- add_sgs = module_security_groups - server_security_groups
- remove_sgs = server_security_groups - module_security_groups
-
- if module.check_mode:
- if add_sgs:
- sg_list = [dict(name=sg) for sg in add_sgs]
- server['security_groups'].extend(sg_list)
- changed = True
-
- if remove_sgs:
- sg_list = [dict(name=sg) for sg in server_security_groups if sg not in remove_sgs]
- server['security_groups'] = sg_list
- changed = True
-
- return (changed, server)
-
- if add_sgs:
- cloud.add_server_security_groups(server, list(add_sgs))
- changed = True
-
- if remove_sgs:
- cloud.remove_server_security_groups(server, list(remove_sgs))
- changed = True
-
- return (changed, server)
-
-
-def _present_server(module, cloud):
- changed = False
- diff = {'before': '', 'after': ''}
- server = cloud.get_server(module.params['name'])
-
- if not server:
- server = _create_server(module, cloud)
- diff['after'] = server
- _exit_hostvars(module, cloud, server, diff, True)
-
- if server.status not in ('ACTIVE', 'SHUTOFF', 'PAUSED', 'SUSPENDED'):
- module.fail_json(
- msg='The instance is available but not Active state: %s' % server.status)
-
- if server:
- diff['before'] = cloud.get_openstack_vars(server)
- (changed, server) = _update_server(module, cloud, server)
- if module.check_mode:
- diff['after'] = server
- else:
- diff['after'] = cloud.get_openstack_vars(server)
-
- _exit_hostvars(module, cloud, server, diff, changed)
-
-
-def _absent_server(module, cloud):
- changed = False
- diff = {'before': '', 'after': ''}
- server = cloud.get_server(module.params['name'])
-
- if server:
- diff['before'] = cloud.get_openstack_vars(server)
- changed = _delete_server(module, cloud)
- module.exit_json(changed=changed, result='deleted', diff=diff)
-
- module.exit_json(changed=changed, diff=diff, result='not present')
-
-
-def main():
-
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- image=dict(default=None),
- image_exclude=dict(default='(deprecated)'),
- flavor=dict(default=None),
- flavor_ram=dict(default=None, type='int'),
- flavor_include=dict(default=None),
- key_name=dict(default=None),
- security_groups=dict(default=['default'], type='list'),
- network=dict(default=None),
- nics=dict(default=[], type='list'),
- meta=dict(default=None, type='raw'),
- userdata=dict(default=None, aliases=['user_data']),
- config_drive=dict(default=False, type='bool'),
- auto_ip=dict(default=True, type='bool', aliases=['auto_floating_ip', 'public_ip']),
- floating_ips=dict(default=None, type='list'),
- floating_ip_pools=dict(default=None, type='list'),
- volume_size=dict(default=False, type='int'),
- boot_from_volume=dict(default=False, type='bool'),
- boot_volume=dict(default=None, aliases=['root_volume']),
- terminate_volume=dict(default=False, type='bool'),
- volumes=dict(default=[], type='list'),
- scheduler_hints=dict(default=None, type='dict'),
- state=dict(default='present', choices=['absent', 'present']),
- delete_fip=dict(default=False, type='bool'),
- reuse_ips=dict(default=True, type='bool'),
- )
- module_kwargs = openstack_module_kwargs(
- mutually_exclusive=[
- ['auto_ip', 'floating_ips'],
- ['auto_ip', 'floating_ip_pools'],
- ['floating_ips', 'floating_ip_pools'],
- ['flavor', 'flavor_ram'],
- ['image', 'boot_volume'],
- ['boot_from_volume', 'boot_volume'],
- ['nics', 'network'],
- ],
- required_if=[
- ('boot_from_volume', True, ['volume_size', 'image']),
- ],
- )
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- state = module.params['state']
- image = module.params['image']
- boot_volume = module.params['boot_volume']
- flavor = module.params['flavor']
- flavor_ram = module.params['flavor_ram']
-
- if state == 'present':
- if not (image or boot_volume):
- module.fail_json(
- msg='Parameter image or boot_volume is required if state == present'
- )
- if not flavor and not flavor_ram:
- module.fail_json(
- msg='Parameter flavor or flavor_ram is required if state == present'
- )
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- if state == 'present':
- _present_server(module, cloud)
- if state == 'absent':
- _absent_server(module, cloud)
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e), extra_data=e.extra_data)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_server_action.py b/lib/ansible/modules/cloud/openstack/os_server_action.py
deleted file mode 100644
index ea352013e0..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_server_action.py
+++ /dev/null
@@ -1,247 +0,0 @@
-#!/usr/bin/python
-# coding: utf-8 -*-
-
-# Copyright (c) 2015, Jesse Keating <jlk@derpops.bike>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_server_action
-short_description: Perform actions on Compute Instances from OpenStack
-extends_documentation_fragment: openstack
-version_added: "2.0"
-author: "Jesse Keating (@omgjlk)"
-description:
- - Perform server actions on an existing compute instance from OpenStack.
- This module does not return any data other than changed true/false.
- When I(action) is 'rebuild', then I(image) parameter is required.
-options:
- server:
- description:
- - Name or ID of the instance
- required: true
- wait:
- description:
- - If the module should wait for the instance action to be performed.
- type: bool
- default: 'yes'
- timeout:
- description:
- - The amount of time the module should wait for the instance to perform
- the requested action.
- default: 180
- action:
- description:
- - Perform the given action. The lock and unlock actions always return
- changed as the servers API does not provide lock status.
- choices: [stop, start, pause, unpause, lock, unlock, suspend, resume,
- rebuild]
- default: present
- image:
- description:
- - Image the server should be rebuilt with
- version_added: "2.3"
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-# Pauses a compute instance
-- os_server_action:
- action: pause
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: admin
- project_name: admin
- server: vm1
- timeout: 200
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-_action_map = {'stop': 'SHUTOFF',
- 'start': 'ACTIVE',
- 'pause': 'PAUSED',
- 'unpause': 'ACTIVE',
- 'lock': 'ACTIVE', # API doesn't show lock/unlock status
- 'unlock': 'ACTIVE',
- 'suspend': 'SUSPENDED',
- 'resume': 'ACTIVE',
- 'rebuild': 'ACTIVE'}
-
-_admin_actions = ['pause', 'unpause', 'suspend', 'resume', 'lock', 'unlock']
-
-
-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 sdk.utils.iterate_timeout(
- timeout,
- "Timeout waiting for server to complete %s" % action):
- try:
- server = cloud.get_server(server.id)
- except Exception:
- continue
-
- if server.status == _action_map[action]:
- return
-
- if server.status == 'ERROR':
- module.fail_json(msg="Server reached ERROR state while attempting to %s" % action)
-
-
-def _system_state_change(action, status):
- """Check if system state would change."""
- if status == _action_map[action]:
- return False
- return True
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- server=dict(required=True),
- action=dict(required=True, choices=['stop', 'start', 'pause', 'unpause',
- 'lock', 'unlock', 'suspend', 'resume',
- 'rebuild']),
- image=dict(required=False),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec, supports_check_mode=True,
- required_if=[('action', 'rebuild', ['image'])],
- **module_kwargs)
-
- action = module.params['action']
- wait = module.params['wait']
- timeout = module.params['timeout']
- image = module.params['image']
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- server = cloud.get_server(module.params['server'])
- if not server:
- module.fail_json(msg='Could not find server %s' % server)
- status = server.status
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(action, status))
-
- if action == 'stop':
- if not _system_state_change(action, status):
- module.exit_json(changed=False)
-
- cloud.compute.post(
- _action_url(server.id),
- json={'os-stop': None})
- if wait:
- _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.compute.post(
- _action_url(server.id),
- json={'os-start': None})
- if wait:
- _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.compute.post(
- _action_url(server.id),
- json={'pause': None})
- if wait:
- _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.compute.post(
- _action_url(server.id),
- json={'unpause': None})
- if wait:
- _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.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.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.compute.post(
- _action_url(server.id),
- json={'suspend': None})
- if wait:
- _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.compute.post(
- _action_url(server.id),
- json={'resume': None})
- if wait:
- _wait(timeout, cloud, server, action, module, sdk)
- module.exit_json(changed=True)
-
- elif action == 'rebuild':
- image = cloud.get_image(image)
-
- if image is None:
- module.fail_json(msg="Image does not exist")
-
- # rebuild doesn't set a state, just do it
- cloud.compute.post(
- _action_url(server.id),
- json={'rebuild': None})
- if wait:
- _wait(timeout, cloud, server, action, module, sdk)
- module.exit_json(changed=True)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e), extra_data=e.extra_data)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_server_group.py b/lib/ansible/modules/cloud/openstack/os_server_group.py
deleted file mode 100644
index ef00b107f1..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_server_group.py
+++ /dev/null
@@ -1,172 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2016 Catalyst IT Limited
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_server_group
-short_description: Manage OpenStack server groups
-extends_documentation_fragment: openstack
-version_added: "2.2"
-author: "Lingxian Kong (@kong)"
-description:
- - Add or remove server groups from OpenStack.
-options:
- state:
- description:
- - Indicate desired state of the resource. When I(state) is 'present',
- then I(policies) is required.
- choices: ['present', 'absent']
- required: false
- default: present
- name:
- description:
- - Server group name.
- required: true
- policies:
- description:
- - A list of one or more policy names to associate with the server
- group. The list must contain at least one policy name. The current
- valid policy names are anti-affinity, affinity, soft-anti-affinity
- and soft-affinity.
- required: false
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
- required: false
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-# Create a server group with 'affinity' policy.
-- os_server_group:
- state: present
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: admin
- project_name: admin
- name: my_server_group
- policies:
- - affinity
-
-# Delete 'my_server_group' server group.
-- os_server_group:
- state: absent
- auth:
- auth_url: https://identity.example.com
- username: admin
- password: admin
- project_name: admin
- name: my_server_group
-'''
-
-RETURN = '''
-id:
- description: Unique UUID.
- returned: success
- type: str
-name:
- description: The name of the server group.
- returned: success
- type: str
-policies:
- description: A list of one or more policy names of the server group.
- returned: success
- type: list
-members:
- description: A list of members in the server group.
- returned: success
- type: list
-metadata:
- description: Metadata key and value pairs.
- returned: success
- type: dict
-project_id:
- description: The project ID who owns the server group.
- returned: success
- type: str
-user_id:
- description: The user ID who owns the server group.
- returned: success
- type: str
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _system_state_change(state, server_group):
- if state == 'present' and not server_group:
- return True
- if state == 'absent' and server_group:
- return True
-
- return False
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- policies=dict(required=False, type='list'),
- state=dict(default='present', choices=['absent', 'present']),
- )
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(
- argument_spec,
- supports_check_mode=True,
- **module_kwargs
- )
-
- name = module.params['name']
- policies = module.params['policies']
- state = module.params['state']
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- server_group = cloud.get_server_group(name)
-
- if module.check_mode:
- module.exit_json(
- changed=_system_state_change(state, server_group)
- )
-
- changed = False
- if state == 'present':
- if not server_group:
- if not policies:
- module.fail_json(
- msg="Parameter 'policies' is required in Server Group "
- "Create"
- )
- server_group = cloud.create_server_group(name, policies)
- changed = True
-
- module.exit_json(
- changed=changed,
- id=server_group['id'],
- server_group=server_group
- )
- if state == 'absent':
- if server_group:
- cloud.delete_server_group(server_group['id'])
- changed = True
- module.exit_json(changed=changed)
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e), extra_data=e.extra_data)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_server_info.py b/lib/ansible/modules/cloud/openstack/os_server_info.py
deleted file mode 100644
index 604f4f5ee0..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_server_info.py
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_server_info
-short_description: Retrieve information about one or more compute instances
-author: Monty (@emonty)
-version_added: "2.0"
-description:
- - Retrieve information about server instances from OpenStack.
- - This module was called C(os_server_facts) before Ansible 2.9, returning C(ansible_facts).
- Note that the M(os_server_info) module no longer returns C(ansible_facts)!
-notes:
- - The result contains a list of servers.
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-options:
- server:
- description:
- - restrict results to servers with names or UUID matching
- this glob expression (e.g., <web*>).
- detailed:
- description:
- - when true, return additional detail about servers at the expense
- of additional API calls.
- type: bool
- default: 'no'
- filters:
- description:
- - restrict results to servers matching a dictionary of
- filters
- version_added: "2.8"
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
- all_projects:
- description:
- - Whether to list servers from all projects or just the current auth
- scoped project.
- type: bool
- default: 'no'
- version_added: "2.8"
-extends_documentation_fragment: openstack
-'''
-
-EXAMPLES = '''
-# Gather information about all servers named <web*> that are in an active state:
-- os_server_info:
- cloud: rax-dfw
- server: web*
- filters:
- vm_state: active
- register: result
-- debug:
- msg: "{{ result.openstack_servers }}"
-'''
-
-import fnmatch
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def main():
-
- argument_spec = openstack_full_argument_spec(
- server=dict(required=False),
- detailed=dict(required=False, type='bool', default=False),
- filters=dict(required=False, type='dict', default=None),
- all_projects=dict(required=False, type='bool', default=False),
- )
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec, **module_kwargs)
- is_old_facts = module._name == 'os_server_facts'
- if is_old_facts:
- module.deprecate("The 'os_server_facts' module has been renamed to 'os_server_info', "
- "and the renamed one no longer returns ansible_facts", version='2.13')
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- openstack_servers = cloud.search_servers(
- detailed=module.params['detailed'], filters=module.params['filters'],
- all_projects=module.params['all_projects'])
-
- if module.params['server']:
- # filter servers by name
- pattern = module.params['server']
- # 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)]
- if is_old_facts:
- module.exit_json(changed=False, ansible_facts=dict(
- openstack_servers=openstack_servers))
- else:
- module.exit_json(changed=False, openstack_servers=openstack_servers)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_server_metadata.py b/lib/ansible/modules/cloud/openstack/os_server_metadata.py
deleted file mode 100644
index 5478354655..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_server_metadata.py
+++ /dev/null
@@ -1,171 +0,0 @@
-#!/usr/bin/python
-# coding: utf-8 -*-
-
-# Copyright (c) 2016, Mario Santos <mario.rf.santos@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: os_server_metadata
-short_description: Add/Update/Delete Metadata in Compute Instances from OpenStack
-extends_documentation_fragment: openstack
-version_added: "2.6"
-author: "Mario Santos (@ruizink)"
-description:
- - Add, Update or Remove metadata in compute instances from OpenStack.
-options:
- server:
- description:
- - Name of the instance to update the metadata
- required: true
- aliases: ['name']
- meta:
- description:
- - 'A list of key value pairs that should be provided as a metadata to
- the instance or a string containing a list of key-value pairs.
- Eg: meta: "key1=value1,key2=value2"'
- required: true
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- availability_zone:
- description:
- - Availability zone in which to create the snapshot.
- required: false
-requirements:
- - "python >= 2.7"
- - "openstack"
-'''
-
-EXAMPLES = '''
-# Creates or updates hostname=test1 as metadata of the server instance vm1
-- name: add metadata to compute instance
- hosts: localhost
- tasks:
- - name: add metadata to instance
- os_server_metadata:
- state: present
- auth:
- auth_url: https://openstack-api.example.com:35357/v2.0/
- username: admin
- password: admin
- project_name: admin
- name: vm1
- meta:
- hostname: test1
- group: group1
-
-# Removes the keys under meta from the instance named vm1
-- name: delete metadata from compute instance
- hosts: localhost
- tasks:
- - name: delete metadata from instance
- os_server_metadata:
- state: absent
- auth:
- auth_url: https://openstack-api.example.com:35357/v2.0/
- username: admin
- password: admin
- project_name: admin
- name: vm1
- meta:
- hostname:
- group:
-'''
-
-RETURN = '''
-server_id:
- description: The compute instance id where the change was made
- returned: success
- type: str
- sample: "324c4e91-3e03-4f62-9a4d-06119a8a8d16"
-metadata:
- description: The metadata of compute instance after the change
- returned: success
- type: dict
- sample: {'key1': 'value1', 'key2': 'value2'}
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import (openstack_full_argument_spec,
- openstack_module_kwargs,
- openstack_cloud_from_module)
-
-
-def _needs_update(server_metadata=None, metadata=None):
- if server_metadata is None:
- server_metadata = {}
- if metadata is None:
- metadata = {}
- return len(set(metadata.items()) - set(server_metadata.items())) != 0
-
-
-def _get_keys_to_delete(server_metadata_keys=None, metadata_keys=None):
- if server_metadata_keys is None:
- server_metadata_keys = []
- if metadata_keys is None:
- metadata_keys = []
- return set(server_metadata_keys) & set(metadata_keys)
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- server=dict(required=True, aliases=['name']),
- meta=dict(required=True, type='dict'),
- state=dict(default='present', choices=['absent', 'present']),
- )
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- state = module.params['state']
- server_param = module.params['server']
- meta_param = module.params['meta']
- changed = False
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- server = cloud.get_server(server_param)
- if not server:
- module.fail_json(
- msg='Could not find server {0}'.format(server_param))
-
- if state == 'present':
- # check if it needs update
- if _needs_update(server_metadata=server.metadata,
- metadata=meta_param):
- if not module.check_mode:
- cloud.set_server_metadata(server_param, meta_param)
- changed = True
- elif state == 'absent':
- # remove from params the keys that do not exist in the server
- keys_to_delete = _get_keys_to_delete(server.metadata.keys(),
- meta_param.keys())
- if len(keys_to_delete) > 0:
- if not module.check_mode:
- cloud.delete_server_metadata(server_param, keys_to_delete)
- changed = True
-
- if changed:
- server = cloud.get_server(server_param)
-
- module.exit_json(
- changed=changed, server_id=server.id, metadata=server.metadata)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=e.message, extra_data=e.extra_data)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_server_volume.py b/lib/ansible/modules/cloud/openstack/os_server_volume.py
deleted file mode 100644
index 2caec55777..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_server_volume.py
+++ /dev/null
@@ -1,146 +0,0 @@
-#!/usr/bin/python
-# coding: utf-8 -*-
-
-# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_server_volume
-short_description: Attach/Detach Volumes from OpenStack VM's
-extends_documentation_fragment: openstack
-version_added: "2.0"
-author: "Monty Taylor (@emonty)"
-description:
- - Attach or Detach volumes from OpenStack VM's
-options:
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- required: false
- server:
- description:
- - Name or ID of server you want to attach a volume to
- required: true
- volume:
- description:
- - Name or id of volume you want to attach to a server
- required: true
- device:
- description:
- - Device you want to attach. Defaults to auto finding a device name.
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-# Attaches a volume to a compute host
-- name: attach a volume
- hosts: localhost
- tasks:
- - name: attach volume to host
- os_server_volume:
- state: present
- cloud: mordred
- server: Mysql-server
- volume: mysql-data
- device: /dev/vdb
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _system_state_change(state, device):
- """Check if system state would change."""
- if state == 'present':
- if device:
- return False
- return True
- if state == 'absent':
- if device:
- return True
- return False
- return False
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- server=dict(required=True),
- volume=dict(required=True),
- device=dict(default=None), # None == auto choose device name
- state=dict(default='present', choices=['absent', 'present']),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- state = module.params['state']
- wait = module.params['wait']
- timeout = module.params['timeout']
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- server = cloud.get_server(module.params['server'])
- volume = cloud.get_volume(module.params['volume'])
-
- if not volume:
- module.fail_json(msg='volume %s is not found' % module.params['volume'])
-
- dev = cloud.get_volume_attach_device(volume, server.id)
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(state, dev))
-
- if state == 'present':
- changed = False
- if not dev:
- changed = True
- cloud.attach_volume(server, volume, module.params['device'],
- wait=wait, timeout=timeout)
-
- server = cloud.get_server(module.params['server']) # refresh
- volume = cloud.get_volume(module.params['volume']) # refresh
- hostvars = cloud.get_openstack_vars(server)
-
- module.exit_json(
- changed=changed,
- id=volume['id'],
- attachments=volume['attachments'],
- openstack=hostvars
- )
-
- elif state == 'absent':
- if not dev:
- # Volume is not attached to this server
- module.exit_json(changed=False)
-
- cloud.detach_volume(server, volume, wait=wait, timeout=timeout)
- module.exit_json(
- changed=True,
- result='Detached volume from server'
- )
-
- except (sdk.exceptions.OpenStackCloudException, sdk.exceptions.ResourceTimeout) as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_stack.py b/lib/ansible/modules/cloud/openstack/os_stack.py
deleted file mode 100644
index 617d5093c3..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_stack.py
+++ /dev/null
@@ -1,278 +0,0 @@
-#!/usr/bin/python
-# coding: utf-8 -*-
-
-# (c) 2016, Mathieu Bultel <mbultel@redhat.com>
-# (c) 2016, Steve Baker <sbaker@redhat.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_stack
-short_description: Add/Remove Heat Stack
-extends_documentation_fragment: openstack
-version_added: "2.2"
-author:
- - "Mathieu Bultel (@matbu)"
- - "Steve Baker (@steveb)"
-description:
- - Add or Remove a Stack to an OpenStack Heat
-options:
- state:
- description:
- - Indicate desired state of the resource
- choices: ['present', 'absent']
- default: present
- name:
- description:
- - Name of the stack that should be created, name could be char and digit, no space
- required: true
- tag:
- description:
- - Tag for the stack that should be created, name could be char and digit, no space
- version_added: "2.5"
- template:
- description:
- - Path of the template file to use for the stack creation
- environment:
- description:
- - List of environment files that should be used for the stack creation
- parameters:
- description:
- - Dictionary of parameters for the stack creation
- rollback:
- description:
- - Rollback stack creation
- type: bool
- default: 'yes'
- timeout:
- description:
- - Maximum number of seconds to wait for the stack creation
- default: 3600
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-EXAMPLES = '''
----
-- name: create stack
- ignore_errors: True
- register: stack_create
- os_stack:
- name: "{{ stack_name }}"
- tag: "{{ tag_name }}"
- state: present
- template: "/path/to/my_stack.yaml"
- environment:
- - /path/to/resource-registry.yaml
- - /path/to/environment.yaml
- parameters:
- bmc_flavor: m1.medium
- bmc_image: CentOS
- key_name: default
- private_net: "{{ private_net_param }}"
- node_count: 2
- name: undercloud
- image: CentOS
- my_flavor: m1.large
- external_net: "{{ external_net_param }}"
-'''
-
-RETURN = '''
-id:
- description: Stack ID.
- type: str
- sample: "97a3f543-8136-4570-920e-fd7605c989d6"
- returned: always
-
-stack:
- description: stack info
- type: complex
- returned: always
- contains:
- action:
- description: Action, could be Create or Update.
- type: str
- sample: "CREATE"
- creation_time:
- description: Time when the action has been made.
- type: str
- sample: "2016-07-05T17:38:12Z"
- description:
- description: Description of the Stack provided in the heat template.
- type: str
- sample: "HOT template to create a new instance and networks"
- id:
- description: Stack ID.
- type: str
- sample: "97a3f543-8136-4570-920e-fd7605c989d6"
- name:
- description: Name of the Stack
- type: str
- sample: "test-stack"
- identifier:
- description: Identifier of the current Stack action.
- type: str
- sample: "test-stack/97a3f543-8136-4570-920e-fd7605c989d6"
- links:
- description: Links to the current Stack.
- type: list
- elements: dict
- sample: "[{'href': 'http://foo:8004/v1/7f6a/stacks/test-stack/97a3f543-8136-4570-920e-fd7605c989d6']"
- outputs:
- description: Output returned by the Stack.
- type: list
- elements: dict
- sample: "{'description': 'IP address of server1 in private network',
- 'output_key': 'server1_private_ip',
- 'output_value': '10.1.10.103'}"
- parameters:
- description: Parameters of the current Stack
- type: dict
- sample: "{'OS::project_id': '7f6a3a3e01164a4eb4eecb2ab7742101',
- 'OS::stack_id': '97a3f543-8136-4570-920e-fd7605c989d6',
- 'OS::stack_name': 'test-stack',
- 'stack_status': 'CREATE_COMPLETE',
- 'stack_status_reason': 'Stack CREATE completed successfully',
- 'status': 'COMPLETE',
- 'template_description': 'HOT template to create a new instance and networks',
- 'timeout_mins': 60,
- 'updated_time': null}"
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-from ansible.module_utils._text import to_native
-
-
-def _create_stack(module, stack, cloud, sdk, parameters):
- try:
- stack = cloud.create_stack(module.params['name'],
- template_file=module.params['template'],
- environment_files=module.params['environment'],
- timeout=module.params['timeout'],
- wait=True,
- rollback=module.params['rollback'],
- **parameters)
-
- stack = cloud.get_stack(stack.id, None)
- if stack.stack_status == 'CREATE_COMPLETE':
- return stack
- else:
- module.fail_json(msg="Failure in creating stack: {0}".format(stack))
- 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, sdk, parameters):
- try:
- stack = cloud.update_stack(
- module.params['name'],
- template_file=module.params['template'],
- environment_files=module.params['environment'],
- timeout=module.params['timeout'],
- rollback=module.params['rollback'],
- wait=module.params['wait'],
- **parameters)
-
- if stack['stack_status'] == 'UPDATE_COMPLETE':
- return stack
- else:
- module.fail_json(msg="Failure in updating stack: %s" %
- stack['stack_status_reason'])
- 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 _system_state_change(module, stack, cloud):
- state = module.params['state']
- if state == 'present':
- if not stack:
- return True
- if state == 'absent' and stack:
- return True
- return False
-
-
-def main():
-
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- tag=dict(required=False, default=None),
- template=dict(default=None),
- environment=dict(default=None, type='list'),
- parameters=dict(default={}, type='dict'),
- rollback=dict(default=False, type='bool'),
- timeout=dict(default=3600, type='int'),
- state=dict(default='present', choices=['absent', 'present']),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- state = module.params['state']
- name = module.params['name']
- # Check for required parameters when state == 'present'
- if state == 'present':
- for p in ['template']:
- if not module.params[p]:
- module.fail_json(msg='%s required with present state' % p)
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- stack = cloud.get_stack(name)
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(module, stack, cloud))
-
- if state == 'present':
- parameters = module.params['parameters']
- if module.params['tag']:
- parameters['tags'] = module.params['tag']
- from distutils.version import StrictVersion
- min_version = '0.28.0'
- if StrictVersion(sdk.version.__version__) < StrictVersion(min_version) and stack:
- module.warn("To update tags using os_stack module, the"
- "installed version of the openstacksdk"
- "library MUST be >={min_version}"
- "".format(min_version=min_version))
- if not stack:
- stack = _create_stack(module, stack, cloud, sdk, parameters)
- else:
- stack = _update_stack(module, stack, cloud, sdk, parameters)
- module.exit_json(changed=True,
- stack=stack,
- id=stack.id)
- elif state == 'absent':
- if not stack:
- changed = False
- else:
- changed = True
- 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 sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=to_native(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_subnet.py b/lib/ansible/modules/cloud/openstack/os_subnet.py
deleted file mode 100644
index a4ac68047e..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_subnet.py
+++ /dev/null
@@ -1,360 +0,0 @@
-#!/usr/bin/python
-# coding: utf-8 -*-
-
-# (c) 2013, Benno Joy <benno@ansible.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_subnet
-short_description: Add/Remove subnet to an OpenStack network
-extends_documentation_fragment: openstack
-version_added: "2.0"
-author: "Monty Taylor (@emonty)"
-description:
- - Add or Remove a subnet to an OpenStack network
-options:
- state:
- description:
- - Indicate desired state of the resource
- choices: ['present', 'absent']
- default: present
- network_name:
- description:
- - Name of the network to which the subnet should be attached
- - Required when I(state) is 'present'
- name:
- description:
- - The name of the subnet that should be created. Although Neutron
- allows for non-unique subnet names, this module enforces subnet
- name uniqueness.
- required: true
- cidr:
- description:
- - The CIDR representation of the subnet that should be assigned to
- the subnet. Required when I(state) is 'present' and a subnetpool
- is not specified.
- ip_version:
- description:
- - The IP version of the subnet 4 or 6
- default: 4
- enable_dhcp:
- description:
- - Whether DHCP should be enabled for this subnet.
- type: bool
- default: 'yes'
- gateway_ip:
- description:
- - The ip that would be assigned to the gateway for this subnet
- no_gateway_ip:
- description:
- - The gateway IP would not be assigned for this subnet
- type: bool
- default: 'no'
- version_added: "2.2"
- dns_nameservers:
- description:
- - List of DNS nameservers for this subnet.
- allocation_pool_start:
- description:
- - From the subnet pool the starting address from which the IP should
- be allocated.
- allocation_pool_end:
- description:
- - From the subnet pool the last IP that should be assigned to the
- virtual machines.
- host_routes:
- description:
- - A list of host route dictionaries for the subnet.
- ipv6_ra_mode:
- description:
- - IPv6 router advertisement mode
- choices: ['dhcpv6-stateful', 'dhcpv6-stateless', 'slaac']
- ipv6_address_mode:
- description:
- - IPv6 address mode
- choices: ['dhcpv6-stateful', 'dhcpv6-stateless', 'slaac']
- use_default_subnetpool:
- description:
- - Use the default subnetpool for I(ip_version) to obtain a CIDR.
- type: bool
- default: 'no'
- project:
- description:
- - Project name or ID containing the subnet (name admin-only)
- version_added: "2.1"
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
- extra_specs:
- description:
- - Dictionary with extra key/value pairs passed to the API
- required: false
- default: {}
- version_added: "2.7"
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-# Create a new (or update an existing) subnet on the specified network
-- os_subnet:
- state: present
- network_name: network1
- name: net1subnet
- cidr: 192.168.0.0/24
- dns_nameservers:
- - 8.8.8.7
- - 8.8.8.8
- host_routes:
- - destination: 0.0.0.0/0
- nexthop: 12.34.56.78
- - destination: 192.168.0.0/24
- nexthop: 192.168.0.1
-
-# Delete a subnet
-- os_subnet:
- state: absent
- name: net1subnet
-
-# Create an ipv6 stateless subnet
-- os_subnet:
- state: present
- name: intv6
- network_name: internal
- ip_version: 6
- cidr: 2db8:1::/64
- dns_nameservers:
- - 2001:4860:4860::8888
- - 2001:4860:4860::8844
- ipv6_ra_mode: dhcpv6-stateless
- ipv6_address_mode: dhcpv6-stateless
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _can_update(subnet, module, cloud, filters=None):
- """Check for differences in non-updatable values"""
- network_name = module.params['network_name']
- ip_version = int(module.params['ip_version'])
- ipv6_ra_mode = module.params['ipv6_ra_mode']
- ipv6_a_mode = module.params['ipv6_address_mode']
-
- if network_name:
- network = cloud.get_network(network_name, filters)
- if network:
- netid = network['id']
- else:
- module.fail_json(msg='No network found for %s' % network_name)
- if netid != subnet['network_id']:
- module.fail_json(msg='Cannot update network_name in existing \
- subnet')
- if ip_version and subnet['ip_version'] != ip_version:
- module.fail_json(msg='Cannot update ip_version in existing subnet')
- if ipv6_ra_mode and subnet.get('ipv6_ra_mode', None) != ipv6_ra_mode:
- module.fail_json(msg='Cannot update ipv6_ra_mode in existing subnet')
- if ipv6_a_mode and subnet.get('ipv6_address_mode', None) != ipv6_a_mode:
- module.fail_json(msg='Cannot update ipv6_address_mode in existing \
- subnet')
-
-
-def _needs_update(subnet, module, cloud, filters=None):
- """Check for differences in the updatable values."""
-
- # First check if we are trying to update something we're not allowed to
- _can_update(subnet, module, cloud, filters)
-
- # now check for the things we are allowed to update
- enable_dhcp = module.params['enable_dhcp']
- subnet_name = module.params['name']
- pool_start = module.params['allocation_pool_start']
- pool_end = module.params['allocation_pool_end']
- gateway_ip = module.params['gateway_ip']
- no_gateway_ip = module.params['no_gateway_ip']
- dns = module.params['dns_nameservers']
- host_routes = module.params['host_routes']
- curr_pool = subnet['allocation_pools'][0]
-
- if subnet['enable_dhcp'] != enable_dhcp:
- return True
- if subnet_name and subnet['name'] != subnet_name:
- return True
- if pool_start and curr_pool['start'] != pool_start:
- return True
- if pool_end and curr_pool['end'] != pool_end:
- return True
- if gateway_ip and subnet['gateway_ip'] != gateway_ip:
- return True
- if dns and sorted(subnet['dns_nameservers']) != sorted(dns):
- return True
- if host_routes:
- curr_hr = sorted(subnet['host_routes'], key=lambda t: t.keys())
- new_hr = sorted(host_routes, key=lambda t: t.keys())
- if curr_hr != new_hr:
- return True
- if no_gateway_ip and subnet['gateway_ip']:
- return True
- return False
-
-
-def _system_state_change(module, subnet, cloud, filters=None):
- state = module.params['state']
- if state == 'present':
- if not subnet:
- return True
- return _needs_update(subnet, module, cloud, filters)
- if state == 'absent' and subnet:
- return True
- return False
-
-
-def main():
- ipv6_mode_choices = ['dhcpv6-stateful', 'dhcpv6-stateless', 'slaac']
- argument_spec = openstack_full_argument_spec(
- name=dict(type='str', required=True),
- network_name=dict(type='str'),
- cidr=dict(type='str'),
- ip_version=dict(type='str', default='4', choices=['4', '6']),
- enable_dhcp=dict(type='bool', default=True),
- gateway_ip=dict(type='str'),
- no_gateway_ip=dict(type='bool', default=False),
- dns_nameservers=dict(type='list', default=None),
- allocation_pool_start=dict(type='str'),
- allocation_pool_end=dict(type='str'),
- host_routes=dict(type='list', default=None),
- ipv6_ra_mode=dict(type='str', choices=ipv6_mode_choices),
- ipv6_address_mode=dict(type='str', choices=ipv6_mode_choices),
- use_default_subnetpool=dict(type='bool', default=False),
- extra_specs=dict(type='dict', default=dict()),
- state=dict(type='str', default='present', choices=['absent', 'present']),
- project=dict(type='str'),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- required_together=[
- ['allocation_pool_end', 'allocation_pool_start'],
- ],
- **module_kwargs)
-
- state = module.params['state']
- network_name = module.params['network_name']
- cidr = module.params['cidr']
- ip_version = module.params['ip_version']
- enable_dhcp = module.params['enable_dhcp']
- subnet_name = module.params['name']
- gateway_ip = module.params['gateway_ip']
- no_gateway_ip = module.params['no_gateway_ip']
- dns = module.params['dns_nameservers']
- pool_start = module.params['allocation_pool_start']
- pool_end = module.params['allocation_pool_end']
- host_routes = module.params['host_routes']
- ipv6_ra_mode = module.params['ipv6_ra_mode']
- ipv6_a_mode = module.params['ipv6_address_mode']
- use_default_subnetpool = module.params['use_default_subnetpool']
- project = module.params.pop('project')
- extra_specs = module.params['extra_specs']
-
- # Check for required parameters when state == 'present'
- if state == 'present':
- if not module.params['network_name']:
- module.fail_json(msg='network_name required with present state')
- if (not module.params['cidr'] and not use_default_subnetpool and
- not extra_specs.get('subnetpool_id', False)):
- module.fail_json(msg='cidr or use_default_subnetpool or '
- 'subnetpool_id required with present state')
-
- if pool_start and pool_end:
- pool = [dict(start=pool_start, end=pool_end)]
- else:
- pool = None
-
- if no_gateway_ip and gateway_ip:
- module.fail_json(msg='no_gateway_ip is not allowed with gateway_ip')
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- if project is not None:
- proj = cloud.get_project(project)
- if proj is None:
- module.fail_json(msg='Project %s could not be found' % project)
- project_id = proj['id']
- filters = {'tenant_id': project_id}
- else:
- project_id = None
- filters = None
-
- subnet = cloud.get_subnet(subnet_name, filters=filters)
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(module, subnet,
- cloud, filters))
-
- if state == 'present':
- if not subnet:
- kwargs = dict(
- cidr=cidr,
- ip_version=ip_version,
- enable_dhcp=enable_dhcp,
- subnet_name=subnet_name,
- gateway_ip=gateway_ip,
- disable_gateway_ip=no_gateway_ip,
- dns_nameservers=dns,
- allocation_pools=pool,
- host_routes=host_routes,
- ipv6_ra_mode=ipv6_ra_mode,
- ipv6_address_mode=ipv6_a_mode,
- tenant_id=project_id)
- dup_args = set(kwargs.keys()) & set(extra_specs.keys())
- if dup_args:
- raise ValueError('Duplicate key(s) {0} in extra_specs'
- .format(list(dup_args)))
- if use_default_subnetpool:
- kwargs['use_default_subnetpool'] = use_default_subnetpool
- kwargs = dict(kwargs, **extra_specs)
- subnet = cloud.create_subnet(network_name, **kwargs)
- changed = True
- else:
- if _needs_update(subnet, module, cloud, filters):
- cloud.update_subnet(subnet['id'],
- subnet_name=subnet_name,
- enable_dhcp=enable_dhcp,
- gateway_ip=gateway_ip,
- disable_gateway_ip=no_gateway_ip,
- dns_nameservers=dns,
- allocation_pools=pool,
- host_routes=host_routes)
- changed = True
- else:
- changed = False
- module.exit_json(changed=changed,
- subnet=subnet,
- id=subnet['id'])
-
- elif state == 'absent':
- if not subnet:
- changed = False
- else:
- changed = True
- cloud.delete_subnet(subnet_name)
- module.exit_json(changed=changed)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_subnets_info.py b/lib/ansible/modules/cloud/openstack/os_subnets_info.py
deleted file mode 100644
index fe0c307cc7..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_subnets_info.py
+++ /dev/null
@@ -1,173 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_subnets_info
-short_description: Retrieve information about one or more OpenStack subnets.
-version_added: "2.0"
-author: "Davide Agnello (@dagnello)"
-description:
- - Retrieve information about one or more subnets from OpenStack.
- - This module was called C(os_subnets_facts) before Ansible 2.9, returning C(ansible_facts).
- Note that the M(os_subnets_info) module no longer returns C(ansible_facts)!
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-options:
- name:
- description:
- - Name or ID of the subnet.
- - Alias 'subnet' added in version 2.8.
- required: false
- aliases: ['subnet']
- filters:
- description:
- - A dictionary of meta data to use for further filtering. Elements of
- this dictionary may be additional dictionaries.
- required: false
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
- required: false
-extends_documentation_fragment: openstack
-'''
-
-EXAMPLES = '''
-- name: Gather information about previously created subnets
- os_subnets_info:
- auth:
- auth_url: https://identity.example.com
- username: user
- password: password
- project_name: someproject
- register: result
-
-- name: Show openstack subnets
- debug:
- msg: "{{ result.openstack_subnets }}"
-
-- name: Gather information about a previously created subnet by name
- os_subnets_info:
- auth:
- auth_url: https://identity.example.com
- username: user
- password: password
- project_name: someproject
- name: subnet1
- register: result
-
-- name: Show openstack subnets
- debug:
- msg: "{{ result.openstack_subnets }}"
-
-- name: Gather information about a previously created subnet with filter
- # Note: name and filters parameters are not mutually exclusive
- os_subnets_info:
- auth:
- auth_url: https://identity.example.com
- username: user
- password: password
- project_name: someproject
- filters:
- tenant_id: 55e2ce24b2a245b09f181bf025724cbe
- register: result
-
-- name: Show openstack subnets
- debug:
- msg: "{{ result.openstack_subnets }}"
-'''
-
-RETURN = '''
-openstack_subnets:
- description: has all the openstack information about the subnets
- returned: always, but can be null
- type: complex
- contains:
- id:
- description: Unique UUID.
- returned: success
- type: str
- name:
- description: Name given to the subnet.
- returned: success
- type: str
- network_id:
- description: Network ID this subnet belongs in.
- returned: success
- type: str
- cidr:
- description: Subnet's CIDR.
- returned: success
- type: str
- gateway_ip:
- description: Subnet's gateway ip.
- returned: success
- type: str
- enable_dhcp:
- description: DHCP enable flag for this subnet.
- returned: success
- type: bool
- ip_version:
- description: IP version for this subnet.
- returned: success
- type: int
- tenant_id:
- description: Tenant id associated with this subnet.
- returned: success
- type: str
- dns_nameservers:
- description: DNS name servers for this subnet.
- returned: success
- type: list
- elements: str
- allocation_pools:
- description: Allocation pools associated with this subnet.
- returned: success
- type: list
- elements: dict
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_cloud_from_module
-
-
-def main():
-
- argument_spec = openstack_full_argument_spec(
- name=dict(required=False, default=None, aliases=['subnet']),
- filters=dict(required=False, type='dict', default=None)
- )
- module = AnsibleModule(argument_spec)
- is_old_facts = module._name == 'os_subnets_facts'
- if is_old_facts:
- module.deprecate("The 'os_subnets_facts' module has been renamed to 'os_subnets_info', "
- "and the renamed one no longer returns ansible_facts", version='2.13')
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- subnets = cloud.search_subnets(module.params['name'],
- module.params['filters'])
- if is_old_facts:
- module.exit_json(changed=False, ansible_facts=dict(
- openstack_subnets=subnets))
- else:
- module.exit_json(changed=False, openstack_subnets=subnets)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_user.py b/lib/ansible/modules/cloud/openstack/os_user.py
deleted file mode 100644
index 93e0351b93..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_user.py
+++ /dev/null
@@ -1,296 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_user
-short_description: Manage OpenStack Identity Users
-extends_documentation_fragment: openstack
-author: David Shrewsbury (@Shrews)
-version_added: "2.0"
-description:
- - Manage OpenStack Identity users. Users can be created,
- updated or deleted using this module. A user will be updated
- if I(name) matches an existing user and I(state) is present.
- The value for I(name) cannot be updated without deleting and
- re-creating the user.
-options:
- name:
- description:
- - Username for the user
- required: true
- password:
- description:
- - Password for the user
- update_password:
- required: false
- choices: ['always', 'on_create']
- version_added: "2.3"
- description:
- - C(always) will attempt to update password. C(on_create) will only
- set the password for newly created users.
- email:
- description:
- - Email address for the user
- description:
- description:
- - Description about the user
- version_added: "2.4"
- default_project:
- description:
- - Project name or ID that the user should be associated with by default
- domain:
- description:
- - Domain to create the user in if the cloud supports domains
- enabled:
- description:
- - Is the user enabled
- type: bool
- default: 'yes'
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-# Create a user
-- os_user:
- cloud: mycloud
- state: present
- name: demouser
- password: secret
- email: demo@example.com
- domain: default
- default_project: demo
-
-# Delete a user
-- os_user:
- cloud: mycloud
- state: absent
- name: demouser
-
-# Create a user but don't update password if user exists
-- os_user:
- cloud: mycloud
- state: present
- name: demouser
- password: secret
- update_password: on_create
- email: demo@example.com
- domain: default
- default_project: demo
-
-# Create a user without password
-- os_user:
- cloud: mycloud
- state: present
- name: demouser
- email: demo@example.com
- domain: default
- default_project: demo
-'''
-
-
-RETURN = '''
-user:
- description: Dictionary describing the user.
- returned: On success when I(state) is 'present'
- type: complex
- contains:
- default_project_id:
- description: User default project ID. Only present with Keystone >= v3.
- type: str
- sample: "4427115787be45f08f0ec22a03bfc735"
- domain_id:
- description: User domain ID. Only present with Keystone >= v3.
- type: str
- sample: "default"
- email:
- description: User email address
- type: str
- sample: "demo@example.com"
- id:
- description: User ID
- type: str
- sample: "f59382db809c43139982ca4189404650"
- name:
- description: User name
- type: str
- sample: "demouser"
-'''
-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
-
-
-def _needs_update(params_dict, user):
- for k in params_dict:
- if k not in ('password', 'update_password') and user[k] != params_dict[k]:
- return True
-
- # We don't get password back in the user object, so assume any supplied
- # password is a change.
- if (params_dict['password'] is not None and
- params_dict['update_password'] == 'always'):
- return True
-
- return False
-
-
-def _get_domain_id(cloud, domain):
- try:
- # We assume admin is passing domain id
- domain_id = cloud.get_domain(domain)['id']
- except Exception:
- # If we fail, maybe admin is passing a domain name.
- # Note that domains have unique names, just like id.
- try:
- domain_id = cloud.search_domains(filters={'name': domain})[0]['id']
- except Exception:
- # Ok, let's hope the user is non-admin and passing a sane id
- domain_id = domain
-
- return domain_id
-
-
-def _get_default_project_id(cloud, default_project, domain_id, module):
- project = cloud.get_project(default_project, domain_id=domain_id)
- if not project:
- module.fail_json(msg='Default project %s is not valid' % default_project)
-
- return project['id']
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- password=dict(required=False, default=None, no_log=True),
- email=dict(required=False, default=None),
- default_project=dict(required=False, default=None),
- description=dict(type='str'),
- domain=dict(required=False, default=None),
- enabled=dict(default=True, type='bool'),
- state=dict(default='present', choices=['absent', 'present']),
- update_password=dict(default=None, choices=['always', 'on_create']),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(
- argument_spec,
- **module_kwargs)
-
- name = module.params['name']
- password = module.params.get('password')
- email = module.params['email']
- default_project = module.params['default_project']
- domain = module.params['domain']
- enabled = module.params['enabled']
- state = module.params['state']
- update_password = module.params['update_password']
- description = module.params['description']
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- domain_id = None
- if domain:
- domain_id = _get_domain_id(cloud, domain)
- user = cloud.get_user(name, domain_id=domain_id)
- else:
- user = cloud.get_user(name)
-
- if state == 'present':
- if update_password in ('always', 'on_create'):
- if not password:
- msg = "update_password is %s but a password value is missing" % update_password
- module.fail_json(msg=msg)
- default_project_id = None
- if default_project:
- default_project_id = _get_default_project_id(cloud, default_project, domain_id, module)
-
- if user is None:
- if description is not None:
- user = cloud.create_user(
- name=name, password=password, email=email,
- default_project=default_project_id, domain_id=domain_id,
- enabled=enabled, description=description)
- else:
- user = cloud.create_user(
- name=name, password=password, email=email,
- default_project=default_project_id, domain_id=domain_id,
- enabled=enabled)
- changed = True
- else:
- params_dict = {'email': email, 'enabled': enabled,
- 'password': password,
- 'update_password': update_password}
- if description is not None:
- params_dict['description'] = description
- if domain_id is not None:
- params_dict['domain_id'] = domain_id
- if default_project_id is not None:
- params_dict['default_project_id'] = default_project_id
-
- if _needs_update(params_dict, user):
- if update_password == 'always':
- if description is not None:
- user = cloud.update_user(
- user['id'], password=password, email=email,
- default_project=default_project_id,
- domain_id=domain_id, enabled=enabled, description=description)
- else:
- user = cloud.update_user(
- user['id'], password=password, email=email,
- default_project=default_project_id,
- domain_id=domain_id, enabled=enabled)
- else:
- if description is not None:
- user = cloud.update_user(
- user['id'], email=email,
- default_project=default_project_id,
- domain_id=domain_id, enabled=enabled, description=description)
- else:
- user = cloud.update_user(
- user['id'], email=email,
- default_project=default_project_id,
- domain_id=domain_id, enabled=enabled)
- changed = True
- else:
- changed = False
- module.exit_json(changed=changed, user=user)
-
- elif state == 'absent':
- if user is None:
- changed = False
- else:
- if domain:
- cloud.delete_user(user['id'], domain_id=domain_id)
- else:
- cloud.delete_user(user['id'])
- changed = True
- module.exit_json(changed=changed)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e), extra_data=e.extra_data)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_user_group.py b/lib/ansible/modules/cloud/openstack/os_user_group.py
deleted file mode 100644
index 77373d4fe0..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_user_group.py
+++ /dev/null
@@ -1,107 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_user_group
-short_description: Associate OpenStack Identity users and groups
-extends_documentation_fragment: openstack
-version_added: "2.0"
-author: "Monty Taylor (@emonty)"
-description:
- - Add and remove users from groups
-options:
- user:
- description:
- - Name or id for the user
- required: true
- group:
- description:
- - Name or id for the group.
- required: true
- state:
- description:
- - Should the user be present or absent in the group
- choices: [present, absent]
- default: present
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
- required: false
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-# Add the demo user to the demo group
-- os_user_group:
- cloud: mycloud
- user: demo
- group: demo
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _system_state_change(state, in_group):
- if state == 'present' and not in_group:
- return True
- if state == 'absent' and in_group:
- return True
- return False
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- user=dict(required=True),
- group=dict(required=True),
- state=dict(default='present', choices=['absent', 'present']),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- user = module.params['user']
- group = module.params['group']
- state = module.params['state']
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- in_group = cloud.is_user_in_group(user, group)
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(state, in_group))
-
- changed = False
- if state == 'present':
- if not in_group:
- cloud.add_user_to_group(user, group)
- changed = True
-
- elif state == 'absent':
- if in_group:
- cloud.remove_user_from_group(user, group)
- changed = True
-
- module.exit_json(changed=changed)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e), extra_data=e.extra_data)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_user_info.py b/lib/ansible/modules/cloud/openstack/os_user_info.py
deleted file mode 100644
index 758b041938..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_user_info.py
+++ /dev/null
@@ -1,174 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2016 Hewlett-Packard Enterprise Corporation
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_user_info
-short_description: Retrieve information about one or more OpenStack users
-extends_documentation_fragment: openstack
-version_added: "2.1"
-author: "Ricardo Carrillo Cruz (@rcarrillocruz)"
-description:
- - Retrieve information about a one or more OpenStack users
- - This module was called C(os_user_facts) before Ansible 2.9, returning C(ansible_facts).
- Note that the M(os_user_info) module no longer returns C(ansible_facts)!
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-options:
- name:
- description:
- - Name or ID of the user
- required: true
- domain:
- description:
- - Name or ID of the domain containing the user if the cloud supports domains
- filters:
- description:
- - A dictionary of meta data to use for further filtering. Elements of
- this dictionary may be additional dictionaries.
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-'''
-
-EXAMPLES = '''
-# Gather information about previously created users
-- os_user_info:
- cloud: awesomecloud
- register: result
-- debug:
- msg: "{{ result.openstack_users }}"
-
-# Gather information about a previously created user by name
-- os_user_info:
- cloud: awesomecloud
- name: demouser
- register: result
-- debug:
- msg: "{{ result.openstack_users }}"
-
-# Gather information about a previously created user in a specific domain
-- os_user_info:
- cloud: awesomecloud
- name: demouser
- domain: admindomain
- register: result
-- debug:
- msg: "{{ result.openstack_users }}"
-
-# Gather information about a previously created user in a specific domain with filter
-- os_user_info:
- cloud: awesomecloud
- name: demouser
- domain: admindomain
- filters:
- enabled: False
- register: result
-- debug:
- msg: "{{ result.openstack_users }}"
-'''
-
-
-RETURN = '''
-openstack_users:
- description: has all the OpenStack information about users
- returned: always, but can be null
- type: complex
- contains:
- id:
- description: Unique UUID.
- returned: success
- type: str
- name:
- description: Name given to the user.
- returned: success
- type: str
- enabled:
- description: Flag to indicate if the user is enabled
- returned: success
- type: bool
- domain_id:
- description: Domain ID containing the user
- returned: success
- type: str
- default_project_id:
- description: Default project ID of the user
- returned: success
- type: str
- email:
- description: Email of the user
- returned: success
- type: str
- username:
- description: Username of the user
- returned: success
- type: str
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def main():
-
- argument_spec = openstack_full_argument_spec(
- name=dict(required=False, default=None),
- domain=dict(required=False, default=None),
- filters=dict(required=False, type='dict', default=None),
- )
-
- module = AnsibleModule(argument_spec)
- is_old_facts = module._name == 'os_user_facts'
- if is_old_facts:
- module.deprecate("The 'os_user_facts' module has been renamed to 'os_user_info', "
- "and the renamed one no longer returns ansible_facts", version='2.13')
-
- sdk, opcloud = openstack_cloud_from_module(module)
- try:
- name = module.params['name']
- domain = module.params['domain']
- filters = module.params['filters']
-
- if domain:
- try:
- # We assume admin is passing domain id
- dom = opcloud.get_domain(domain)['id']
- domain = dom
- except Exception:
- # If we fail, maybe admin is passing a domain name.
- # Note that domains have unique names, just like id.
- dom = opcloud.search_domains(filters={'name': domain})
- if dom:
- domain = dom[0]['id']
- else:
- module.fail_json(msg='Domain name or ID does not exist')
-
- if not filters:
- filters = {}
-
- filters['domain_id'] = domain
-
- users = opcloud.search_users(name, filters)
- if is_old_facts:
- module.exit_json(changed=False, ansible_facts=dict(
- openstack_users=users))
- else:
- module.exit_json(changed=False, openstack_users=users)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_user_role.py b/lib/ansible/modules/cloud/openstack/os_user_role.py
deleted file mode 100644
index 936ccb2bbd..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_user_role.py
+++ /dev/null
@@ -1,200 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2016 IBM
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_user_role
-short_description: Associate OpenStack Identity users and roles
-extends_documentation_fragment: openstack
-author: "Monty Taylor (@emonty), David Shrewsbury (@Shrews)"
-version_added: "2.1"
-description:
- - Grant and revoke roles in either project or domain context for
- OpenStack Identity Users.
-options:
- role:
- description:
- - Name or ID for the role.
- required: true
- user:
- description:
- - Name or ID for the user. If I(user) is not specified, then
- I(group) is required. Both may not be specified.
- group:
- description:
- - Name or ID for the group. Valid only with keystone version 3.
- If I(group) is not specified, then I(user) is required. Both
- may not be specified.
- project:
- description:
- - Name or ID of the project to scope the role association to.
- If you are using keystone version 2, then this value is required.
- domain:
- description:
- - Name or ID of the domain to scope the role association to. Valid only
- with keystone version 3, and required if I(project) is not specified.
- state:
- description:
- - Should the roles be present or absent on the user.
- choices: [present, absent]
- default: present
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-# Grant an admin role on the user admin in the project project1
-- os_user_role:
- cloud: mycloud
- user: admin
- role: admin
- project: project1
-
-# Revoke the admin role from the user barney in the newyork domain
-- os_user_role:
- cloud: mycloud
- state: absent
- user: barney
- role: admin
- domain: newyork
-'''
-
-RETURN = '''
-#
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _system_state_change(state, assignment):
- if state == 'present' and not assignment:
- return True
- elif state == 'absent' and assignment:
- return True
- return False
-
-
-def _build_kwargs(user, group, project, domain):
- kwargs = {}
- if user:
- kwargs['user'] = user
- if group:
- kwargs['group'] = group
- if project:
- kwargs['project'] = project
- if domain:
- kwargs['domain'] = domain
- return kwargs
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- role=dict(required=True),
- user=dict(required=False),
- group=dict(required=False),
- project=dict(required=False),
- domain=dict(required=False),
- state=dict(default='present', choices=['absent', 'present']),
- )
-
- module_kwargs = openstack_module_kwargs(
- required_one_of=[
- ['user', 'group']
- ])
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- role = module.params.get('role')
- user = module.params.get('user')
- group = module.params.get('group')
- project = module.params.get('project')
- domain = module.params.get('domain')
- state = module.params.get('state')
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- filters = {}
-
- r = cloud.get_role(role)
- if r is None:
- module.fail_json(msg="Role %s is not valid" % role)
- filters['role'] = r['id']
-
- if domain:
- d = cloud.get_domain(name_or_id=domain)
- if d is None:
- module.fail_json(msg="Domain %s is not valid" % domain)
- filters['domain'] = d['id']
- if user:
- if domain:
- u = cloud.get_user(user, domain_id=filters['domain'])
- else:
- u = cloud.get_user(user)
-
- if u is None:
- module.fail_json(msg="User %s is not valid" % user)
- filters['user'] = u['id']
- if group:
- g = cloud.get_group(group)
- if g is None:
- module.fail_json(msg="Group %s is not valid" % group)
- filters['group'] = g['id']
- domain_id = None
- if project:
- if domain:
- p = cloud.get_project(project, domain_id=filters['domain'])
- # OpenStack won't allow us to use both a domain and project as
- # filter. Once we identified the project (using the domain as
- # a filter criteria), we need to remove the domain itself from
- # the filters list.
- domain_id = filters.pop('domain')
- else:
- p = cloud.get_project(project)
-
- if p is None:
- module.fail_json(msg="Project %s is not valid" % project)
- filters['project'] = p['id']
-
- assignment = cloud.list_role_assignments(filters=filters)
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(state, assignment))
-
- changed = False
-
- if state == 'present':
- if not assignment:
- kwargs = _build_kwargs(user, group, project, domain_id)
- cloud.grant_role(role, **kwargs)
- changed = True
-
- elif state == 'absent':
- if assignment:
- kwargs = _build_kwargs(user, group, project, domain_id)
- cloud.revoke_role(role, **kwargs)
- changed = True
-
- module.exit_json(changed=changed)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_volume.py b/lib/ansible/modules/cloud/openstack/os_volume.py
deleted file mode 100644
index ffd885f744..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_volume.py
+++ /dev/null
@@ -1,264 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_volume
-short_description: Create/Delete Cinder Volumes
-extends_documentation_fragment: openstack
-version_added: "2.0"
-author: "Monty Taylor (@emonty)"
-description:
- - Create or Remove cinder block storage volumes
-options:
- size:
- description:
- - Size of volume in GB. This parameter is required when the
- I(state) parameter is 'present'.
- display_name:
- description:
- - Name of volume
- required: true
- display_description:
- description:
- - String describing the volume
- volume_type:
- description:
- - Volume type for volume
- image:
- description:
- - Image name or id for boot from volume
- snapshot_id:
- description:
- - Volume snapshot id to create from
- volume:
- description:
- - Volume name or id to create from
- version_added: "2.3"
- bootable:
- description:
- - Bootable flag for volume.
- type: bool
- default: False
- version_added: "2.10"
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
- scheduler_hints:
- description:
- - Scheduler hints passed to volume API in form of dict
- version_added: "2.4"
- metadata:
- description:
- - Metadata for the volume
- version_added: "2.8"
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-# Creates a new volume
-- name: create a volume
- hosts: localhost
- tasks:
- - name: create 40g test volume
- os_volume:
- state: present
- cloud: mordred
- availability_zone: az2
- size: 40
- display_name: test_volume
- scheduler_hints:
- same_host: 243e8d3c-8f47-4a61-93d6-7215c344b0c0
-'''
-
-RETURNS = '''
-id:
- description: Cinder's unique ID for this volume
- returned: always
- type: str
- sample: fcc4ac1c-e249-4fe7-b458-2138bfb44c06
-
-volume:
- description: Cinder's representation of the volume object
- returned: always
- type: dict
- sample: {'...'}
-'''
-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
-
-
-def _needs_update(module, volume):
- '''
- check for differences in updatable values, at the moment
- openstacksdk only supports extending the volume size, this
- may change in the future.
- :returns: bool
- '''
- compare_simple = ['size']
-
- for k in compare_simple:
- if module.params[k] is not None and module.params[k] != volume.get(k):
- return True
-
- return False
-
-
-def _modify_volume(module, cloud):
- '''
- modify volume, the only modification to an existing volume
- available at the moment is extending the size, this is
- limited by the openstacksdk and may change whenever the
- functionality is extended.
- '''
- volume = cloud.get_volume(module.params['display_name'])
- diff = {'before': volume, 'after': ''}
- size = module.params['size']
-
- if size < volume.get('size'):
- module.fail_json(
- msg='Cannot shrink volumes, size: {0} < {1}'.format(size, volume.get('size'))
- )
-
- if not _needs_update(module, volume):
- diff['after'] = volume
- module.exit_json(changed=False, id=volume['id'], volume=volume, diff=diff)
-
- if module.check_mode:
- diff['after'] = volume
- module.exit_json(changed=True, id=volume['id'], volume=volume, diff=diff)
-
- cloud.volume.extend_volume(
- volume.id,
- size
- )
- diff['after'] = cloud.get_volume(module.params['display_name'])
- module.exit_json(changed=True, id=volume['id'], volume=volume, diff=diff)
-
-
-def _present_volume(module, cloud):
- if cloud.volume_exists(module.params['display_name']):
- v = cloud.get_volume(module.params['display_name'])
- if not _needs_update(module, v):
- module.exit_json(changed=False, id=v['id'], volume=v)
- _modify_volume(module, cloud)
-
- diff = {'before': '', 'after': ''}
-
- volume_args = dict(
- size=module.params['size'],
- volume_type=module.params['volume_type'],
- display_name=module.params['display_name'],
- display_description=module.params['display_description'],
- snapshot_id=module.params['snapshot_id'],
- bootable=module.params['bootable'],
- availability_zone=module.params['availability_zone'],
- )
- if module.params['image']:
- image_id = cloud.get_image_id(module.params['image'])
- volume_args['imageRef'] = image_id
-
- if module.params['volume']:
- volume_id = cloud.get_volume_id(module.params['volume'])
- if not volume_id:
- module.fail_json(msg="Failed to find volume '%s'" % module.params['volume'])
- volume_args['source_volid'] = volume_id
-
- if module.params['scheduler_hints']:
- volume_args['scheduler_hints'] = module.params['scheduler_hints']
-
- if module.params['metadata']:
- volume_args['metadata'] = module.params['metadata']
-
- if module.check_mode:
- diff['after'] = volume_args
- module.exit_json(changed=True, id=None, volume=volume_args, diff=diff)
-
- volume = cloud.create_volume(
- wait=module.params['wait'], timeout=module.params['timeout'],
- **volume_args)
- diff['after'] = volume
- module.exit_json(changed=True, id=volume['id'], volume=volume, diff=diff)
-
-
-def _absent_volume(module, cloud, sdk):
- changed = False
- diff = {'before': '', 'after': ''}
-
- if cloud.volume_exists(module.params['display_name']):
- volume = cloud.get_volume(module.params['display_name'])
- diff['before'] = volume
-
- if module.check_mode:
- module.exit_json(changed=True, diff=diff)
-
- try:
- changed = cloud.delete_volume(name_or_id=module.params['display_name'],
- wait=module.params['wait'],
- timeout=module.params['timeout'])
- except sdk.exceptions.ResourceTimeout:
- diff['after'] = volume
- module.exit_json(changed=changed, diff=diff)
-
- module.exit_json(changed=changed, diff=diff)
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- size=dict(default=None, type='int'),
- volume_type=dict(default=None),
- display_name=dict(required=True, aliases=['name']),
- display_description=dict(default=None, aliases=['description']),
- image=dict(default=None),
- snapshot_id=dict(default=None),
- volume=dict(default=None),
- state=dict(default='present', choices=['absent', 'present']),
- scheduler_hints=dict(default=None, type='dict'),
- metadata=dict(default=None, type='dict'),
- bootable=dict(type='bool', default=False)
- )
- module_kwargs = openstack_module_kwargs(
- mutually_exclusive=[
- ['image', 'snapshot_id', 'volume'],
- ],
- )
- module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True, **module_kwargs)
-
- state = module.params['state']
-
- if state == 'present' and not module.params['size']:
- module.fail_json(msg="Size is required when state is 'present'")
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- if state == 'present':
- _present_volume(module, cloud)
- if state == 'absent':
- _absent_volume(module, cloud, sdk)
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_volume_snapshot.py b/lib/ansible/modules/cloud/openstack/os_volume_snapshot.py
deleted file mode 100644
index 29fae78a5e..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_volume_snapshot.py
+++ /dev/null
@@ -1,178 +0,0 @@
-#!/usr/bin/python
-# coding: utf-8 -*-
-
-# Copyright (c) 2016, Mario Santos <mario.rf.santos@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'status': ['preview'],
- 'supported_by': 'community',
- 'metadata_version': '1.1'}
-
-DOCUMENTATION = '''
----
-module: os_volume_snapshot
-short_description: Create/Delete Cinder Volume Snapshots
-extends_documentation_fragment: openstack
-version_added: "2.6"
-author: "Mario Santos (@ruizink)"
-description:
- - Create or Delete cinder block storage volume snapshots
-options:
- display_name:
- description:
- - Name of the snapshot
- required: true
- aliases: ['name']
- display_description:
- description:
- - String describing the snapshot
- aliases: ['description']
- volume:
- description:
- - The volume name or id to create/delete the snapshot
- required: True
- force:
- description:
- - Allows or disallows snapshot of a volume to be created when the volume
- is attached to an instance.
- type: bool
- default: 'no'
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- availability_zone:
- description:
- - Availability zone in which to create the snapshot.
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-# Creates a snapshot on volume 'test_volume'
-- name: create and delete snapshot
- hosts: localhost
- tasks:
- - name: create snapshot
- os_volume_snapshot:
- state: present
- cloud: mordred
- availability_zone: az2
- display_name: test_snapshot
- volume: test_volume
- - name: delete snapshot
- os_volume_snapshot:
- state: absent
- cloud: mordred
- availability_zone: az2
- display_name: test_snapshot
- volume: test_volume
-'''
-
-RETURN = '''
-snapshot:
- description: The snapshot instance after the change
- returned: success
- type: dict
- sample:
- id: 837aca54-c0ee-47a2-bf9a-35e1b4fdac0c
- name: test_snapshot
- volume_id: ec646a7c-6a35-4857-b38b-808105a24be6
- size: 2
- status: available
- display_name: test_snapshot
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import (openstack_full_argument_spec,
- openstack_module_kwargs,
- openstack_cloud_from_module)
-
-
-def _present_volume_snapshot(module, cloud):
- volume = cloud.get_volume(module.params['volume'])
- snapshot = cloud.get_volume_snapshot(module.params['display_name'],
- filters={'volume_id': volume.id})
- if not snapshot:
- snapshot = cloud.create_volume_snapshot(volume.id,
- force=module.params['force'],
- wait=module.params['wait'],
- timeout=module.params[
- 'timeout'],
- name=module.params['display_name'],
- description=module.params.get(
- 'display_description')
- )
- module.exit_json(changed=True, snapshot=snapshot)
- else:
- module.exit_json(changed=False, snapshot=snapshot)
-
-
-def _absent_volume_snapshot(module, cloud):
- volume = cloud.get_volume(module.params['volume'])
- snapshot = cloud.get_volume_snapshot(module.params['display_name'],
- filters={'volume_id': volume.id})
- if not snapshot:
- module.exit_json(changed=False)
- else:
- cloud.delete_volume_snapshot(name_or_id=snapshot.id,
- wait=module.params['wait'],
- timeout=module.params['timeout'],
- )
- module.exit_json(changed=True, snapshot_id=snapshot.id)
-
-
-def _system_state_change(module, cloud):
- volume = cloud.get_volume(module.params['volume'])
- snapshot = cloud.get_volume_snapshot(module.params['display_name'],
- filters={'volume_id': volume.id})
- state = module.params['state']
-
- if state == 'present':
- return snapshot is None
- if state == 'absent':
- return snapshot is not None
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- display_name=dict(required=True, aliases=['name']),
- display_description=dict(default=None, aliases=['description']),
- volume=dict(required=True),
- force=dict(required=False, default=False, type='bool'),
- state=dict(default='present', choices=['absent', 'present']),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- sdk, cloud = openstack_cloud_from_module(module)
-
- state = module.params['state']
-
- try:
- if cloud.volume_exists(module.params['volume']):
- if module.check_mode:
- module.exit_json(changed=_system_state_change(module, cloud))
- if state == 'present':
- _present_volume_snapshot(module, cloud)
- if state == 'absent':
- _absent_volume_snapshot(module, cloud)
- else:
- module.fail_json(
- msg="No volume with name or id '{0}' was found.".format(
- module.params['volume']))
- except (sdk.exceptions.OpenStackCloudException, sdk.exceptions.ResourceTimeout) as e:
- module.fail_json(msg=e.message)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/cloud/openstack/os_zone.py b/lib/ansible/modules/cloud/openstack/os_zone.py
deleted file mode 100644
index 2103130d0b..0000000000
--- a/lib/ansible/modules/cloud/openstack/os_zone.py
+++ /dev/null
@@ -1,243 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2016 Hewlett-Packard Enterprise
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = '''
----
-module: os_zone
-short_description: Manage OpenStack DNS zones
-extends_documentation_fragment: openstack
-version_added: "2.2"
-author: "Ricardo Carrillo Cruz (@rcarrillocruz)"
-description:
- - Manage OpenStack DNS zones. Zones can be created, deleted or
- updated. Only the I(email), I(description), I(ttl) and I(masters) values
- can be updated.
-options:
- name:
- description:
- - Zone name
- required: true
- zone_type:
- description:
- - Zone type
- choices: [primary, secondary]
- email:
- description:
- - Email of the zone owner (only applies if zone_type is primary)
- description:
- description:
- - Zone description
- ttl:
- description:
- - TTL (Time To Live) value in seconds
- masters:
- description:
- - Master nameservers (only applies if zone_type is secondary)
- state:
- description:
- - Should the resource be present or absent.
- choices: [present, absent]
- default: present
- availability_zone:
- description:
- - Ignored. Present for backwards compatibility
-requirements:
- - "python >= 2.7"
- - "openstacksdk"
-'''
-
-EXAMPLES = '''
-# Create a zone named "example.net"
-- os_zone:
- cloud: mycloud
- state: present
- name: example.net.
- zone_type: primary
- email: test@example.net
- description: Test zone
- ttl: 3600
-
-# Update the TTL on existing "example.net." zone
-- os_zone:
- cloud: mycloud
- state: present
- name: example.net.
- ttl: 7200
-
-# Delete zone named "example.net."
-- os_zone:
- cloud: mycloud
- state: absent
- name: example.net.
-'''
-
-RETURN = '''
-zone:
- description: Dictionary describing the zone.
- returned: On success when I(state) is 'present'.
- type: complex
- contains:
- id:
- description: Unique zone ID
- type: str
- sample: "c1c530a3-3619-46f3-b0f6-236927b2618c"
- name:
- description: Zone name
- type: str
- sample: "example.net."
- type:
- description: Zone type
- type: str
- sample: "PRIMARY"
- email:
- description: Zone owner email
- type: str
- sample: "test@example.net"
- description:
- description: Zone description
- type: str
- sample: "Test description"
- ttl:
- description: Zone TTL value
- type: int
- sample: 3600
- masters:
- description: Zone master nameservers
- type: list
- sample: []
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module
-
-
-def _system_state_change(state, email, description, ttl, masters, zone):
- if state == 'present':
- if not zone:
- return True
- if email is not None and zone.email != email:
- return True
- if description is not None and zone.description != description:
- return True
- if ttl is not None and zone.ttl != ttl:
- return True
- if masters is not None and zone.masters != masters:
- return True
- if state == 'absent' and zone:
- return True
- return False
-
-
-def _wait(timeout, cloud, zone, state, module, sdk):
- """Wait for a zone to reach the desired state for the given state."""
-
- for count in sdk.utils.iterate_timeout(
- timeout,
- "Timeout waiting for zone to be %s" % state):
-
- if (state == 'absent' and zone is None) or (state == 'present' and zone and zone.status == 'ACTIVE'):
- return
-
- try:
- zone = cloud.get_zone(zone.id)
- except Exception:
- continue
-
- if zone and zone.status == 'ERROR':
- module.fail_json(msg="Zone reached ERROR state while waiting for it to be %s" % state)
-
-
-def main():
- argument_spec = openstack_full_argument_spec(
- name=dict(required=True),
- zone_type=dict(required=False, choices=['primary', 'secondary']),
- email=dict(required=False, default=None),
- description=dict(required=False, default=None),
- ttl=dict(required=False, default=None, type='int'),
- masters=dict(required=False, default=None, type='list'),
- state=dict(default='present', choices=['absent', 'present']),
- )
-
- module_kwargs = openstack_module_kwargs()
- module = AnsibleModule(argument_spec,
- supports_check_mode=True,
- **module_kwargs)
-
- name = module.params.get('name')
- state = module.params.get('state')
- wait = module.params.get('wait')
- timeout = module.params.get('timeout')
-
- sdk, cloud = openstack_cloud_from_module(module)
- try:
- zone = cloud.get_zone(name)
-
- if state == 'present':
- zone_type = module.params.get('zone_type')
- email = module.params.get('email')
- description = module.params.get('description')
- ttl = module.params.get('ttl')
- masters = module.params.get('masters')
-
- if module.check_mode:
- module.exit_json(changed=_system_state_change(state, email,
- description, ttl,
- masters, zone))
-
- if zone is None:
- zone = cloud.create_zone(
- name=name, zone_type=zone_type, email=email,
- description=description, ttl=ttl, masters=masters)
- changed = True
- else:
- if masters is None:
- masters = []
-
- pre_update_zone = zone
- changed = _system_state_change(state, email,
- description, ttl,
- masters, pre_update_zone)
- if changed:
- zone = cloud.update_zone(
- name, email=email,
- description=description,
- ttl=ttl, masters=masters)
-
- if wait:
- _wait(timeout, cloud, zone, state, module, sdk)
-
- module.exit_json(changed=changed, zone=zone)
-
- elif state == 'absent':
- if module.check_mode:
- module.exit_json(changed=_system_state_change(state, None,
- None, None,
- None, zone))
-
- if zone is None:
- changed = False
- else:
- cloud.delete_zone(name)
- changed = True
-
- if wait:
- _wait(timeout, cloud, zone, state, module, sdk)
-
- module.exit_json(changed=changed)
-
- except sdk.exceptions.OpenStackCloudException as e:
- module.fail_json(msg=str(e))
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/plugins/doc_fragments/openstack.py b/lib/ansible/plugins/doc_fragments/openstack.py
deleted file mode 100644
index 746c1fed8c..0000000000
--- a/lib/ansible/plugins/doc_fragments/openstack.py
+++ /dev/null
@@ -1,101 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2014, Hewlett-Packard Development Company, L.P.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-
-class ModuleDocFragment(object):
-
- # Standard openstack documentation fragment
- DOCUMENTATION = r'''
-options:
- cloud:
- description:
- - Named cloud or cloud config to operate against.
- If I(cloud) is a string, it references a named cloud config as defined
- in an OpenStack clouds.yaml file. Provides default values for I(auth)
- and I(auth_type). This parameter is not needed if I(auth) is provided
- or if OpenStack OS_* environment variables are present.
- If I(cloud) is a dict, it contains a complete cloud configuration like
- would be in a section of clouds.yaml.
- type: raw
- auth:
- description:
- - Dictionary containing auth information as needed by the cloud's auth
- plugin strategy. For the default I(password) plugin, this would contain
- I(auth_url), I(username), I(password), I(project_name) and any
- information about domains (for example, I(os_user_domain_name) or I(os_project_domain_name)) if the cloud supports them.
- For other plugins,
- this param will need to contain whatever parameters that auth plugin
- requires. This parameter is not needed if a named cloud is provided or
- OpenStack OS_* environment variables are present.
- type: dict
- auth_type:
- description:
- - Name of the auth plugin to use. If the cloud uses something other than
- password authentication, the name of the plugin should be indicated here
- and the contents of the I(auth) parameter should be updated accordingly.
- type: str
- region_name:
- description:
- - Name of the region.
- type: str
- wait:
- description:
- - Should ansible wait until the requested resource is complete.
- type: bool
- default: yes
- timeout:
- description:
- - How long should ansible wait for the requested resource.
- type: int
- default: 180
- api_timeout:
- description:
- - How long should the socket layer wait before timing out for API calls.
- If this is omitted, nothing will be passed to the requests library.
- type: int
- validate_certs:
- description:
- - Whether or not SSL API requests should be verified.
- - Before Ansible 2.3 this defaulted to C(yes).
- type: bool
- default: no
- aliases: [ verify ]
- ca_cert:
- description:
- - A path to a CA Cert bundle that can be used as part of verifying
- SSL API requests.
- type: str
- aliases: [ cacert ]
- client_cert:
- description:
- - A path to a client certificate to use as part of the SSL transaction.
- type: str
- aliases: [ cert ]
- client_key:
- description:
- - A path to a client key to use as part of the SSL transaction.
- type: str
- aliases: [ key ]
- interface:
- description:
- - Endpoint URL type to fetch from the service catalog.
- type: str
- choices: [ admin, internal, public ]
- default: public
- aliases: [ endpoint_type ]
- version_added: "2.3"
-requirements:
- - python >= 2.7
- - openstacksdk >= 0.12.0
-notes:
- - The standard OpenStack environment variables, such as C(OS_USERNAME)
- may be used instead of providing explicit values.
- - Auth information is driven by openstacksdk, which means that values
- can come from a yaml config file in /etc/ansible/openstack.yaml,
- /etc/openstack/clouds.yaml or ~/.config/openstack/clouds.yaml, then from
- standard environment variables, then finally by explicit parameters in
- plays. More information can be found at
- U(https://docs.openstack.org/openstacksdk/)
-'''
diff --git a/lib/ansible/plugins/inventory/openstack.py b/lib/ansible/plugins/inventory/openstack.py
deleted file mode 100644
index 0dbbbeaa10..0000000000
--- a/lib/ansible/plugins/inventory/openstack.py
+++ /dev/null
@@ -1,344 +0,0 @@
-# Copyright (c) 2012, Marco Vito Moscaritolo <marco@agavee.com>
-# Copyright (c) 2013, Jesse Keating <jesse.keating@rackspace.com>
-# Copyright (c) 2015, Hewlett-Packard Development Company, L.P.
-# Copyright (c) 2016, Rackspace Australia
-# Copyright (c) 2017 Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = '''
- name: openstack
- plugin_type: inventory
- author:
- - Marco Vito Moscaritolo <marco@agavee.com>
- - Jesse Keating <jesse.keating@rackspace.com>
- short_description: OpenStack inventory source
- requirements:
- - "openstacksdk >= 0.28"
- extends_documentation_fragment:
- - inventory_cache
- - constructed
- description:
- - Get inventory hosts from OpenStack clouds
- - Uses openstack.(yml|yaml) YAML configuration file to configure the inventory plugin
- - Uses standard clouds.yaml YAML configuration file to configure cloud credentials
- options:
- plugin:
- description: token that ensures this is a source file for the 'openstack' plugin.
- required: True
- choices: ['openstack']
- show_all:
- description: toggles showing all vms vs only those with a working IP
- type: bool
- default: 'no'
- inventory_hostname:
- description: |
- What to register as the inventory hostname.
- If set to 'uuid' the uuid of the server will be used and a
- group will be created for the server name.
- If set to 'name' the name of the server will be used unless
- there are more than one server with the same name in which
- case the 'uuid' logic will be used.
- Default is to do 'name', which is the opposite of the old
- openstack.py inventory script's option use_hostnames)
- type: string
- choices:
- - name
- - uuid
- default: "name"
- expand_hostvars:
- description: |
- Run extra commands on each host to fill in additional
- information about the host. May interrogate cinder and
- neutron and can be expensive for people with many hosts.
- (Note, the default value of this is opposite from the default
- old openstack.py inventory script's option expand_hostvars)
- type: bool
- default: 'no'
- private:
- description: |
- Use the private interface of each server, if it has one, as
- the host's IP in the inventory. This can be useful if you are
- running ansible inside a server in the cloud and would rather
- communicate to your servers over the private network.
- type: bool
- default: 'no'
- only_clouds:
- description: |
- List of clouds from clouds.yaml to use, instead of using
- the whole list.
- type: list
- default: []
- fail_on_errors:
- description: |
- Causes the inventory to fail and return no hosts if one cloud
- has failed (for example, bad credentials or being offline).
- When set to False, the inventory will return as many hosts as
- it can from as many clouds as it can contact. (Note, the
- default value of this is opposite from the old openstack.py
- inventory script's option fail_on_errors)
- type: bool
- default: 'no'
- all_projects:
- description: |
- Lists servers from all projects
- type: bool
- default: 'no'
- version_added: 2.10
- clouds_yaml_path:
- description: |
- Override path to clouds.yaml file. If this value is given it
- will be searched first. The default path for the
- ansible inventory adds /etc/ansible/openstack.yaml and
- /etc/ansible/openstack.yml to the regular locations documented
- at https://docs.openstack.org/os-client-config/latest/user/configuration.html#config-files
- type: list
- env:
- - name: OS_CLIENT_CONFIG_FILE
- compose:
- description: Create vars from jinja2 expressions.
- type: dictionary
- default: {}
- groups:
- description: Add hosts to group based on Jinja2 conditionals.
- type: dictionary
- default: {}
-'''
-
-EXAMPLES = '''
-# file must be named openstack.yaml or openstack.yml
-# Make the plugin behave like the default behavior of the old script
-plugin: openstack
-expand_hostvars: yes
-fail_on_errors: yes
-all_projects: yes
-'''
-
-import collections
-import sys
-
-from ansible.errors import AnsibleParserError
-from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
-
-try:
- # 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_SDK = False
-
-
-class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
- ''' Host inventory provider for ansible using OpenStack clouds. '''
-
- NAME = 'openstack'
-
- def parse(self, inventory, loader, path, cache=True):
-
- super(InventoryModule, self).parse(inventory, loader, path)
-
- cache_key = self._get_cache_prefix(path)
-
- # file is config file
- self._config_data = self._read_config_data(path)
-
- msg = ''
- if not self._config_data:
- msg = 'File empty. this is not my config file'
- elif 'plugin' in self._config_data and self._config_data['plugin'] != self.NAME:
- 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_SDK:
- msg = "openstacksdk is required for the OpenStack inventory plugin. OpenStack inventory sources will be skipped."
-
- if msg:
- raise AnsibleParserError(msg)
-
- # The user has pointed us at a clouds.yaml file. Use defaults for
- # everything.
- if 'clouds' in self._config_data:
- self._config_data = {}
-
- # update cache if the user has caching enabled and the cache is being refreshed
- # will update variable below in the case of an expired cache
- cache_needs_update = not cache and self.get_option('cache')
-
- if cache:
- cache = self.get_option('cache')
- source_data = None
- if cache:
- try:
- source_data = self._cache[cache_key]
- except KeyError:
- # cache expired or doesn't exist yet
- cache_needs_update = True
-
- if not source_data:
- clouds_yaml_path = self._config_data.get('clouds_yaml_path')
- if clouds_yaml_path:
- config_files = (clouds_yaml_path +
- client_config.CONFIG_FILES)
- else:
- config_files = None
-
- # Redict logging to stderr so it does not mix with output
- # particular ansible-inventory JSON output
- # TODO(mordred) Integrate openstack's logging with ansible's logging
- sdk.enable_logging(stream=sys.stderr)
-
- cloud_inventory = sdk_inventory.OpenStackInventory(
- config_files=config_files,
- private=self._config_data.get('private', False))
- only_clouds = self._config_data.get('only_clouds', [])
- if only_clouds and not isinstance(only_clouds, list):
- raise ValueError(
- 'OpenStack Inventory Config Error: only_clouds must be'
- ' a list')
- if only_clouds:
- new_clouds = []
- for cloud in cloud_inventory.clouds:
- if cloud.name in only_clouds:
- new_clouds.append(cloud)
- cloud_inventory.clouds = new_clouds
-
- expand_hostvars = self._config_data.get('expand_hostvars', False)
- fail_on_errors = self._config_data.get('fail_on_errors', False)
- all_projects = self._config_data.get('all_projects', False)
-
- source_data = cloud_inventory.list_hosts(
- expand=expand_hostvars, fail_on_cloud_config=fail_on_errors,
- all_projects=all_projects)
-
- if cache_needs_update:
- self._cache[cache_key] = source_data
-
- self._populate_from_source(source_data)
-
- def _populate_from_source(self, source_data):
- groups = collections.defaultdict(list)
- firstpass = collections.defaultdict(list)
- hostvars = {}
-
- use_server_id = (
- self._config_data.get('inventory_hostname', 'name') != 'name')
- show_all = self._config_data.get('show_all', False)
-
- for server in source_data:
- if 'interface_ip' not in server and not show_all:
- continue
- firstpass[server['name']].append(server)
-
- for name, servers in firstpass.items():
- if len(servers) == 1 and not use_server_id:
- self._append_hostvars(hostvars, groups, name, servers[0])
- else:
- server_ids = set()
- # Trap for duplicate results
- for server in servers:
- server_ids.add(server['id'])
- if len(server_ids) == 1 and not use_server_id:
- self._append_hostvars(hostvars, groups, name, servers[0])
- else:
- for server in servers:
- self._append_hostvars(
- hostvars, groups, server['id'], server,
- namegroup=True)
-
- self._set_variables(hostvars, groups)
-
- def _set_variables(self, hostvars, groups):
-
- # set vars in inventory from hostvars
- for host in hostvars:
-
- # create composite vars
- self._set_composite_vars(
- self._config_data.get('compose'), hostvars[host], host)
-
- # actually update inventory
- for key in hostvars[host]:
- self.inventory.set_variable(host, key, hostvars[host][key])
-
- # constructed groups based on conditionals
- self._add_host_to_composed_groups(
- self._config_data.get('groups'), hostvars[host], host)
-
- # constructed groups based on jinja expressions
- self._add_host_to_keyed_groups(
- self._config_data.get('keyed_groups'), hostvars[host], host)
-
- for group_name, group_hosts in groups.items():
- gname = self.inventory.add_group(group_name)
- for host in group_hosts:
- self.inventory.add_child(gname, host)
-
- def _get_groups_from_server(self, server_vars, namegroup=True):
- groups = []
-
- region = server_vars['region']
- cloud = server_vars['cloud']
- metadata = server_vars.get('metadata', {})
-
- # Create a group for the cloud
- groups.append(cloud)
-
- # Create a group on region
- if region:
- groups.append(region)
-
- # And one by cloud_region
- groups.append("%s_%s" % (cloud, region))
-
- # Check if group metadata key in servers' metadata
- if 'group' in metadata:
- groups.append(metadata['group'])
-
- for extra_group in metadata.get('groups', '').split(','):
- if extra_group:
- groups.append(extra_group.strip())
-
- groups.append('instance-%s' % server_vars['id'])
- if namegroup:
- groups.append(server_vars['name'])
-
- for key in ('flavor', 'image'):
- if 'name' in server_vars[key]:
- groups.append('%s-%s' % (key, server_vars[key]['name']))
-
- for key, value in iter(metadata.items()):
- groups.append('meta-%s_%s' % (key, value))
-
- az = server_vars.get('az', None)
- if az:
- # Make groups for az, region_az and cloud_region_az
- groups.append(az)
- groups.append('%s_%s' % (region, az))
- groups.append('%s_%s_%s' % (cloud, region, az))
- return groups
-
- def _append_hostvars(self, hostvars, groups, current_host,
- server, namegroup=False):
- hostvars[current_host] = dict(
- ansible_ssh_host=server['interface_ip'],
- ansible_host=server['interface_ip'],
- openstack=server)
- self.inventory.add_host(current_host)
-
- for group in self._get_groups_from_server(server, namegroup=namegroup):
- groups[group].append(current_host)
-
- def verify_file(self, path):
-
- if super(InventoryModule, self).verify_file(path):
- for fn in ('openstack', 'clouds'):
- for suffix in ('yaml', 'yml'):
- maybe = '{fn}.{suffix}'.format(fn=fn, suffix=suffix)
- if path.endswith(maybe):
- return True
- return False
diff --git a/test/sanity/ignore.txt b/test/sanity/ignore.txt
index 6a2fa5c9ef..a5e55ffdfe 100644
--- a/test/sanity/ignore.txt
+++ b/test/sanity/ignore.txt
@@ -104,8 +104,6 @@ lib/ansible/module_utils/network/skydive/api.py future-import-boilerplate
lib/ansible/module_utils/network/skydive/api.py metaclass-boilerplate
lib/ansible/module_utils/network/vyos/vyos.py future-import-boilerplate
lib/ansible/module_utils/network/vyos/vyos.py metaclass-boilerplate
-lib/ansible/module_utils/openstack.py future-import-boilerplate
-lib/ansible/module_utils/openstack.py metaclass-boilerplate
lib/ansible/module_utils/ovirt.py future-import-boilerplate
lib/ansible/module_utils/ovirt.py metaclass-boilerplate
lib/ansible/module_utils/parsing/convert_bool.py future-import-boilerplate
@@ -1028,138 +1026,6 @@ lib/ansible/modules/cloud/google/gcp_tpu_node_info.py validate-modules:parameter
lib/ansible/modules/cloud/hcloud/hcloud_network_info.py validate-modules:return-syntax-error
lib/ansible/modules/cloud/hcloud/hcloud_server.py validate-modules:parameter-list-no-elements
lib/ansible/modules/cloud/hcloud/hcloud_server_network.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/cloud/openstack/os_auth.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_client_config.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/cloud/openstack/os_client_config.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_coe_cluster.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_coe_cluster.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_coe_cluster_template.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_coe_cluster_template.py validate-modules:doc-required-mismatch
-lib/ansible/modules/cloud/openstack/os_coe_cluster_template.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_flavor_info.py validate-modules:doc-default-does-not-match-spec
-lib/ansible/modules/cloud/openstack/os_flavor_info.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_flavor_info.py validate-modules:implied-parameter-type-mismatch
-lib/ansible/modules/cloud/openstack/os_flavor_info.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_floating_ip.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_group.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_group_info.py validate-modules:doc-required-mismatch
-lib/ansible/modules/cloud/openstack/os_image.py validate-modules:doc-choices-do-not-match-spec
-lib/ansible/modules/cloud/openstack/os_image.py validate-modules:doc-default-does-not-match-spec
-lib/ansible/modules/cloud/openstack/os_image.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_image.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_image_info.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_ironic.py validate-modules:doc-choices-do-not-match-spec
-lib/ansible/modules/cloud/openstack/os_ironic.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_ironic.py validate-modules:doc-required-mismatch
-lib/ansible/modules/cloud/openstack/os_ironic.py validate-modules:nonexistent-parameter-documented
-lib/ansible/modules/cloud/openstack/os_ironic.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/cloud/openstack/os_ironic.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_ironic.py validate-modules:undocumented-parameter
-lib/ansible/modules/cloud/openstack/os_ironic_inspect.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_ironic_node.py validate-modules:doc-choices-do-not-match-spec
-lib/ansible/modules/cloud/openstack/os_ironic_node.py validate-modules:doc-default-does-not-match-spec
-lib/ansible/modules/cloud/openstack/os_ironic_node.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_ironic_node.py validate-modules:implied-parameter-type-mismatch
-lib/ansible/modules/cloud/openstack/os_ironic_node.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_ironic_node.py validate-modules:undocumented-parameter
-lib/ansible/modules/cloud/openstack/os_keypair.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_keystone_domain.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_keystone_domain_info.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_keystone_domain_info.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_keystone_endpoint.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_keystone_endpoint.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_keystone_endpoint.py validate-modules:undocumented-parameter
-lib/ansible/modules/cloud/openstack/os_keystone_role.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_keystone_service.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_listener.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_listener.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_loadbalancer.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_loadbalancer.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/cloud/openstack/os_loadbalancer.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_member.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_member.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_network.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_network.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_networks_info.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_networks_info.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_nova_flavor.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_nova_flavor.py validate-modules:doc-required-mismatch
-lib/ansible/modules/cloud/openstack/os_nova_flavor.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_nova_host_aggregate.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_nova_host_aggregate.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/cloud/openstack/os_nova_host_aggregate.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_object.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_pool.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_port.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_port.py validate-modules:doc-required-mismatch
-lib/ansible/modules/cloud/openstack/os_port.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/cloud/openstack/os_port.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_port_info.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_port_info.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_project.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_project_access.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_project_access.py validate-modules:doc-required-mismatch
-lib/ansible/modules/cloud/openstack/os_project_access.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_project_info.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_project_info.py validate-modules:doc-required-mismatch
-lib/ansible/modules/cloud/openstack/os_project_info.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_quota.py validate-modules:doc-choices-do-not-match-spec
-lib/ansible/modules/cloud/openstack/os_quota.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_quota.py validate-modules:nonexistent-parameter-documented
-lib/ansible/modules/cloud/openstack/os_quota.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_quota.py validate-modules:return-syntax-error
-lib/ansible/modules/cloud/openstack/os_quota.py validate-modules:undocumented-parameter
-lib/ansible/modules/cloud/openstack/os_recordset.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_recordset.py validate-modules:doc-required-mismatch
-lib/ansible/modules/cloud/openstack/os_recordset.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/cloud/openstack/os_recordset.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_router.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_router.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/cloud/openstack/os_router.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_security_group.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_security_group_rule.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_security_group_rule.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_server.py validate-modules:doc-default-does-not-match-spec
-lib/ansible/modules/cloud/openstack/os_server.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_server.py validate-modules:doc-required-mismatch
-lib/ansible/modules/cloud/openstack/os_server.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/cloud/openstack/os_server.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_server.py validate-modules:undocumented-parameter
-lib/ansible/modules/cloud/openstack/os_server_action.py validate-modules:doc-default-does-not-match-spec
-lib/ansible/modules/cloud/openstack/os_server_action.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_server_action.py validate-modules:doc-required-mismatch
-lib/ansible/modules/cloud/openstack/os_server_group.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_server_group.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/cloud/openstack/os_server_group.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_server_info.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_server_info.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_server_metadata.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_server_metadata.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_server_volume.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_stack.py validate-modules:doc-default-does-not-match-spec
-lib/ansible/modules/cloud/openstack/os_stack.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_stack.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/cloud/openstack/os_stack.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_subnet.py validate-modules:doc-choices-do-not-match-spec
-lib/ansible/modules/cloud/openstack/os_subnet.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_subnet.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/cloud/openstack/os_subnet.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_subnets_info.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_subnets_info.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_user.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_user.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_user_group.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_user_info.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_user_info.py validate-modules:doc-required-mismatch
-lib/ansible/modules/cloud/openstack/os_user_info.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_user_role.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_volume.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_volume.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/cloud/openstack/os_volume.py validate-modules:undocumented-parameter
-lib/ansible/modules/cloud/openstack/os_volume_snapshot.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_zone.py validate-modules:doc-missing-type
-lib/ansible/modules/cloud/openstack/os_zone.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/cloud/openstack/os_zone.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/cloud/ovirt/ovirt_affinity_group.py future-import-boilerplate
lib/ansible/modules/cloud/ovirt/ovirt_affinity_group.py metaclass-boilerplate
lib/ansible/modules/cloud/ovirt/ovirt_affinity_group.py validate-modules:doc-required-mismatch
@@ -2018,8 +1884,6 @@ lib/ansible/plugins/doc_fragments/inventory_cache.py future-import-boilerplate
lib/ansible/plugins/doc_fragments/inventory_cache.py metaclass-boilerplate
lib/ansible/plugins/doc_fragments/junos.py future-import-boilerplate
lib/ansible/plugins/doc_fragments/junos.py metaclass-boilerplate
-lib/ansible/plugins/doc_fragments/openstack.py future-import-boilerplate
-lib/ansible/plugins/doc_fragments/openstack.py metaclass-boilerplate
lib/ansible/plugins/doc_fragments/ovirt.py future-import-boilerplate
lib/ansible/plugins/doc_fragments/ovirt.py metaclass-boilerplate
lib/ansible/plugins/doc_fragments/ovirt_info.py future-import-boilerplate
@@ -2288,8 +2152,6 @@ test/units/module_utils/urls/test_Request.py replace-urlopen
test/units/module_utils/urls/test_fetch_url.py replace-urlopen
test/units/modules/cloud/linode/conftest.py future-import-boilerplate
test/units/modules/cloud/linode/conftest.py metaclass-boilerplate
-test/units/modules/cloud/openstack/test_os_server.py future-import-boilerplate
-test/units/modules/cloud/openstack/test_os_server.py metaclass-boilerplate
test/units/modules/conftest.py future-import-boilerplate
test/units/modules/conftest.py metaclass-boilerplate
test/units/modules/files/test_copy.py future-import-boilerplate
diff --git a/test/units/modules/cloud/openstack/test_os_server.py b/test/units/modules/cloud/openstack/test_os_server.py
deleted file mode 100644
index 450e536b68..0000000000
--- a/test/units/modules/cloud/openstack/test_os_server.py
+++ /dev/null
@@ -1,228 +0,0 @@
-import collections
-import inspect
-import mock
-import pytest
-import yaml
-
-from ansible.module_utils.six import string_types
-from ansible.modules.cloud.openstack import os_server
-
-
-class AnsibleFail(Exception):
- pass
-
-
-class AnsibleExit(Exception):
- pass
-
-
-def params_from_doc(func):
- '''This function extracts the docstring from the specified function,
- parses it as a YAML document, and returns parameters for the os_server
- module.'''
-
- doc = inspect.getdoc(func)
- cfg = yaml.load(doc)
-
- for task in cfg:
- for module, params in task.items():
- for k, v in params.items():
- if k in ['nics'] and isinstance(v, string_types):
- params[k] = [v]
- task[module] = collections.defaultdict(str,
- params)
-
- return cfg[0]['os_server']
-
-
-class FakeCloud(object):
- ports = [
- {'name': 'port1', 'id': '1234'},
- {'name': 'port2', 'id': '4321'},
- ]
-
- networks = [
- {'name': 'network1', 'id': '5678'},
- {'name': 'network2', 'id': '8765'},
- ]
-
- images = [
- {'name': 'cirros', 'id': '1'},
- {'name': 'fedora', 'id': '2'},
- ]
-
- flavors = [
- {'name': 'm1.small', 'id': '1', 'flavor_ram': 1024},
- {'name': 'm1.tiny', 'id': '2', 'flavor_ram': 512},
- ]
-
- def _find(self, source, name):
- for item in source:
- if item['name'] == name or item['id'] == name:
- return item
-
- def get_image_id(self, name, exclude=None):
- image = self._find(self.images, name)
- if image:
- return image['id']
-
- def get_flavor(self, name):
- return self._find(self.flavors, name)
-
- def get_flavor_by_ram(self, ram, include=None):
- for flavor in self.flavors:
- if flavor['ram'] >= ram and (include is None or include in
- flavor['name']):
- return flavor
-
- def get_port(self, name):
- return self._find(self.ports, name)
-
- def get_network(self, name):
- return self._find(self.networks, name)
-
- def get_openstack_vars(self, server):
- return server
-
- def get_server(self, name):
- return None
-
- create_server = mock.MagicMock()
-
-
-class TestNetworkArgs(object):
- '''This class exercises the _network_args function of the
- os_server module. For each test, we parse the YAML document
- contained in the docstring to retrieve the module parameters for the
- test.'''
-
- def setup_method(self, method):
- self.cloud = FakeCloud()
- self.module = mock.MagicMock()
- self.module.params = params_from_doc(method)
-
- def test_nics_string_net_id(self):
- '''
- - os_server:
- nics: net-id=1234
- '''
- args = os_server._network_args(self.module, self.cloud)
- assert(args[0]['net-id'] == '1234')
-
- def test_nics_string_net_id_list(self):
- '''
- - os_server:
- nics: net-id=1234,net-id=4321
- '''
- args = os_server._network_args(self.module, self.cloud)
- assert(args[0]['net-id'] == '1234')
- assert(args[1]['net-id'] == '4321')
-
- def test_nics_string_port_id(self):
- '''
- - os_server:
- nics: port-id=1234
- '''
- args = os_server._network_args(self.module, self.cloud)
- assert(args[0]['port-id'] == '1234')
-
- def test_nics_string_net_name(self):
- '''
- - os_server:
- nics: net-name=network1
- '''
- args = os_server._network_args(self.module, self.cloud)
- assert(args[0]['net-id'] == '5678')
-
- def test_nics_string_port_name(self):
- '''
- - os_server:
- nics: port-name=port1
- '''
- args = os_server._network_args(self.module, self.cloud)
- assert(args[0]['port-id'] == '1234')
-
- def test_nics_structured_net_id(self):
- '''
- - os_server:
- nics:
- - net-id: '1234'
- '''
- args = os_server._network_args(self.module, self.cloud)
- assert(args[0]['net-id'] == '1234')
-
- def test_nics_structured_mixed(self):
- '''
- - os_server:
- nics:
- - net-id: '1234'
- - port-name: port1
- - 'net-name=network1,port-id=4321'
- '''
- args = os_server._network_args(self.module, self.cloud)
- assert(args[0]['net-id'] == '1234')
- assert(args[1]['port-id'] == '1234')
- assert(args[2]['net-id'] == '5678')
- assert(args[3]['port-id'] == '4321')
-
-
-class TestCreateServer(object):
- def setup_method(self, method):
- self.cloud = FakeCloud()
- self.module = mock.MagicMock()
- self.module.params = params_from_doc(method)
- self.module.fail_json.side_effect = AnsibleFail()
- self.module.exit_json.side_effect = AnsibleExit()
- self.module.check_mode = False
-
- self.meta = mock.MagicMock()
- self.meta.gett_hostvars_from_server.return_value = {
- 'id': '1234'
- }
- os_server.meta = self.meta
-
- def test_create_server(self):
- '''
- - os_server:
- image: cirros
- flavor: m1.tiny
- nics:
- - net-name: network1
- meta:
- - key: value
- '''
- with pytest.raises(AnsibleExit):
- os_server._present_server(self.module, self.cloud)
-
- assert(self.cloud.create_server.call_count == 1)
- assert(self.cloud.create_server.call_args[1]['image'] == self.cloud.get_image_id('cirros'))
- assert(self.cloud.create_server.call_args[1]['flavor'] == self.cloud.get_flavor('m1.tiny')['id'])
- assert(self.cloud.create_server.call_args[1]['nics'][0]['net-id'] == self.cloud.get_network('network1')['id'])
-
- def test_create_server_bad_flavor(self):
- '''
- - os_server:
- image: cirros
- flavor: missing_flavor
- nics:
- - net-name: network1
- '''
- with pytest.raises(AnsibleFail):
- os_server._present_server(self.module, self.cloud)
-
- assert('missing_flavor' in
- self.module.fail_json.call_args[1]['msg'])
-
- def test_create_server_bad_nic(self):
- '''
- - os_server:
- image: cirros
- flavor: m1.tiny
- nics:
- - net-name: missing_network
- '''
- with pytest.raises(AnsibleFail):
- os_server._present_server(self.module, self.cloud)
-
- assert('missing_network' in
- self.module.fail_json.call_args[1]['msg'])
diff --git a/test/units/plugins/inventory/test_openstack.py b/test/units/plugins/inventory/test_openstack.py
deleted file mode 100644
index fec7ae580c..0000000000
--- a/test/units/plugins/inventory/test_openstack.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright 2018 Lars Kellogg-Stedman <lars@redhat.com>
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
-
-# Make coding more python3-ish
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-import pytest
-
-from ansible.plugins.inventory.openstack import InventoryModule
-from ansible.inventory.data import InventoryData
-from ansible.template import Templar
-
-
-config_data = {
- 'plugin': 'openstack',
- 'compose': {
- 'composed_var': '"testvar-" + testvar',
- },
- 'groups': {
- 'testgroup': '"host" in inventory_hostname',
- },
- 'keyed_groups':
- [{
- 'prefix': 'keyed',
- 'key': 'testvar',
- }]
-}
-
-hostvars = {
- 'host0': {
- 'inventory_hostname': 'host0',
- 'testvar': '0',
- },
- 'host1': {
- 'inventory_hostname': 'host1',
- 'testvar': '1',
- },
-}
-
-
-@pytest.fixture(scope="module")
-def inventory():
- inventory = InventoryModule()
- inventory._config_data = config_data
- inventory.inventory = InventoryData()
- inventory.templar = Templar(loader=None)
-
- for host in hostvars:
- inventory.inventory.add_host(host)
-
- return inventory
-
-
-def test_simple_groups(inventory):
- inventory._set_variables(hostvars, {})
- groups = inventory.inventory.get_groups_dict()
- assert 'testgroup' in groups
- assert len(groups['testgroup']) == len(hostvars)
-
-
-def test_keyed_groups(inventory):
- inventory._set_variables(hostvars, {})
- assert 'keyed_0' in inventory.inventory.groups
- assert 'keyed_1' in inventory.inventory.groups
-
-
-def test_composed_vars(inventory):
- inventory._set_variables(hostvars, {})
-
- for host in hostvars:
- assert host in inventory.inventory.hosts
- host = inventory.inventory.get_host(host)
- assert host.vars['composed_var'] == 'testvar-{testvar}'.format(**hostvars[host.name])