From a5d669f0b400606ecae2d0d972b7dbcb85c1fb76 Mon Sep 17 00:00:00 2001 From: Jimmy McCrory Date: Tue, 23 May 2017 16:25:19 -0700 Subject: [PATCH] Remove neutron library As of Ansible 2.3, the os_network module now allows more additional options for 'provider_network_type'[0]. Use of OSA's neutron plugin can be removed. [0] https://github.com/ansible/ansible-modules-core/issues/5589 Change-Id: If74185ecca1ea639c2e1526b5542e89dd533084b Implements: blueprint use-std-ansible-modules --- doc/source/actions/neutron.rst | 13 - library/neutron | 465 ------------------ ...ugins-remove-neutron-cbea1235e030e4f5.yaml | 5 + 3 files changed, 5 insertions(+), 478 deletions(-) delete mode 100644 doc/source/actions/neutron.rst delete mode 100644 library/neutron create mode 100644 releasenotes/notes/plugins-remove-neutron-cbea1235e030e4f5.yaml diff --git a/doc/source/actions/neutron.rst b/doc/source/actions/neutron.rst deleted file mode 100644 index 01491f4..0000000 --- a/doc/source/actions/neutron.rst +++ /dev/null @@ -1,13 +0,0 @@ -neutron -~~~~~~~ - -Synopsis --------- -Basic module for interacting with OpenStack neutron. - -Examples --------- -.. literalinclude:: ../../../library/neutron - :language: yaml - :start-after: EXAMPLES = """ - :end-before: """ diff --git a/library/neutron b/library/neutron deleted file mode 100644 index aab51ed..0000000 --- a/library/neutron +++ /dev/null @@ -1,465 +0,0 @@ -#!/usr/bin/env python -# Copyright 2014, Rackspace US, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import keystoneclient.v3.client as ksclient -from neutronclient.neutron import client as nclient - -# import module snippets -from ansible.module_utils.basic import * - - -DOCUMENTATION = """ ---- -module: neutron -short_description: - - Basic module for interacting with openstack neutron -description: - - Basic module for interacting with openstack neutron -options: - command: - description: - - Operation for the module to perform. Currently available - choices: - - create_network - - create_subnet - - create_router - - add_router_interface - - get_networks - required: True - openrc_path: - decription: - - Path to openrc file from which credentials and keystone endpoint - will be extracted - net_name: - description: - - Name of network - subnet_name: - description: - - Name of subnet - allocation_pools: - description: - - List of allocation pools for a subnet. Format is - startip-endip[,startip-endip]... - router_name: - description: - - Name of router - cidr: - description: - - Specify CIDR to use when creating subnet - provider_physical_network: - description: - - Specify provider:physical_network when creating network - provider_network_type: - description: - - Specify provider:network_type when creating network - provider_segmentation_id: - description: - - Specify provider:segmentation_id when creating network - router_external: - description: - - Specify router:external' when creating network - external_gateway_info: - description: - - Specify external_gateway_info when creating router - insecure: - description: - - Explicitly allow client to perform "insecure" TLS - choices: - - false - - true - default: false -author: Hugh Saunders -""" - -EXAMPLES = """ -- name: Create private network - neutron: - command: create_network - openrc_path: /root/openrc - net_name: private -- name: Create public network - neutron: - command: create_network - openrc_path: /root/openrc - net_name: public - provider_network_type: flat - provider_physical_network: vlan - router_external: true -- name: Create private subnet - neutron: - command: create_subnet - openrc_path: /root/openrc - net_name: private - subnet_name: private-subnet - cidr: "192.168.74.0/24" -- name: Create public subnet - neutron: - command: create_subnet - openrc_path: /root/openrc - net_name: public - subnet_name: public-subnet - cidr: "10.1.13.0/24" -- name: Create router - neutron: - command: create_router - openrc_path: /root/openrc - router_name: router - external_gateway_info: public -- name: Add private subnet to router - neutron: - command: add_router_interface - openrc_path: /root/openrc - router_name: router - subnet_name: private-subnet -- name: Get network information - command: get_network - openrc_path: /root/openrc - net_name: public -""" - - -COMMAND_MAP = { - 'create_network': { - 'variables': [ - 'net_name', - 'provider_physical_network', - 'provider_network_type', - 'provider_segmentation_id', - 'router_external', - 'tenant_id' - ] - }, - 'create_subnet': { - 'variables': [ - 'net_name', - 'subnet_name', - 'cidr', - 'tenant_id', - 'allocation_pools' - ] - }, - 'create_router': { - 'variables': [ - 'router_name', - 'external_gateway_info', - 'tenant_id' - ] - }, - 'add_router_interface': { - 'variables': [ - 'router_name', - 'subnet_name' - ] - }, - 'get_networks': { - 'variables': [ - 'net_name' - ] - } -} - - -class ManageNeutron(object): - def __init__(self, module): - self.state_change = False - self.neutron = None - self.keystone = None - self.module = module - - def command_router(self): - """Run the command as its provided to the module.""" - command_name = self.module.params['command'] - if command_name not in COMMAND_MAP: - self.failure( - error='No Command Found', - rc=2, - msg='Command [ %s ] was not found.' % command_name - ) - - action_command = COMMAND_MAP[command_name] - if hasattr(self, '_%s' % command_name): - action = getattr(self, '_%s' % command_name) - try: - self._keystone_authenticate() - self._init_neutron() - except Exception as e: - self.module.fail_json( - err="Initialisation Error: %s" % e, - rc=2, msg=str(e)) - facts = action(variables=action_command['variables']) - if facts is None: - self.module.exit_json(changed=self.state_change) - else: - self.module.exit_json( - changed=self.state_change, - ansible_facts=facts - ) - else: - self.failure( - error='Command not in ManageNeutron class', - rc=2, - msg='Method [ %s ] was not found.' % command_name - ) - - @staticmethod - def _facts(resource_type, resource_data): - """Return a dict for our Ansible facts.""" - key = 'neutron_%s' % resource_type - facts = {key: {}} - for f in resource_data[resource_type]: - res_name = f['name'] - del f['name'] - facts[key][res_name] = f - - return facts - - def _get_vars(self, variables, required=None): - """Return a dict of all variables as found within the module. - - :param variables: ``list`` List of all variables that are available to - use within the Neutron Command. - :param required: ``list`` Name of variables that are required. - """ - return_dict = {} - for variable in variables: - return_dict[variable] = self.module.params.get(variable) - else: - if isinstance(required, list): - for var_name in required: - check = return_dict.get(var_name) - if check is None: - self.failure( - error='Missing [ %s ] from Task or found a None' - ' value' % var_name, - rc=000, - msg='variables %s - available params [ %s ]' - % (variables, self.module.params) - ) - return return_dict - - def failure(self, error, rc, msg): - """Return a Failure when running an Ansible command. - - :param error: ``str`` Error that occurred. - :param rc: ``int`` Return code while executing an Ansible command. - :param msg: ``str`` Message to report. - """ - self.module.fail_json(msg=msg, rc=rc, err=error) - - def _parse_openrc(self): - """Get credentials from an openrc file.""" - openrc_path = self.module.params['openrc_path'] - line_re = re.compile('^export (?POS_\w*)=\'?(?P[^\n\']*)') - with open(openrc_path) as openrc: - matches = [line_re.match(l) for l in openrc] - return dict( - (g.groupdict()['key'], g.groupdict()['value']) - for g in matches if g - ) - - def _keystone_authenticate(self): - """Authenticate with Keystone.""" - openrc = self._parse_openrc() - insecure = self.module.params['insecure'] - self.keystone = ksclient.Client(insecure=insecure, - username=openrc['OS_USERNAME'], - password=openrc['OS_PASSWORD'], - project_name=openrc['OS_PROJECT_NAME'], - auth_url=openrc['OS_AUTH_URL']) - - def _init_neutron(self): - """Create neutron client object using token and url from keystone.""" - openrc = self._parse_openrc() - self.neutron = nclient.Client( - '2.0', - endpoint_url=self.keystone.service_catalog.url_for( - service_type='network', - endpoint_type=openrc['OS_ENDPOINT_TYPE']), - token=self.keystone.get_token(self.keystone.session)) - - def _get_resource_by_name(self, resource_type, resource_name): - action = getattr(self.neutron, 'list_%s' % resource_type) - resource = action(name=resource_name)[resource_type] - - if resource: - return resource[0]['id'] - else: - return None - - def _create_network(self, variables): - required_vars = ['net_name'] - variables_dict = self._get_vars(variables, required=required_vars) - net_name = variables_dict.pop('net_name') - provider_physical_network = variables_dict.pop( - 'provider_physical_network' - ) - provider_network_type = variables_dict.pop('provider_network_type') - provider_segmentation_id = variables_dict.pop( - 'provider_segmentation_id' - ) - router_external = variables_dict.pop('router_external') - tenant_id = variables_dict.pop('tenant_id') - - if not self._get_resource_by_name('networks', net_name): - n = {"name": net_name, "admin_state_up": True} - if provider_physical_network: - n['provider:physical_network'] = provider_physical_network - if provider_network_type: - n['provider:network_type'] = provider_network_type - if provider_segmentation_id: - n['provider:segmentation_id'] = str(provider_segmentation_id) - if router_external: - n['router:external'] = router_external - if tenant_id: - n['tenant_id'] = tenant_id - - self.state_change = True - self.neutron.create_network({"network": n}) - - return self._facts('networks', self.neutron.list_networks()) - - def _create_subnet(self, variables): - required_vars = ['net_name', 'subnet_name', 'cidr'] - variables_dict = self._get_vars(variables, required=required_vars) - net_name = variables_dict.pop('net_name') - subnet_name = variables_dict.pop('subnet_name') - cidr = variables_dict.pop('cidr') - network_id = self._get_resource_by_name('networks', net_name) - tenant_id = variables_dict.pop('tenant_id') - - # allocation_pools is a string with the format: - # startip-endip[,startip-endip]... - allocation_pools_str = variables_dict.get('allocation_pools', "") - allocation_pools = [] - if allocation_pools_str: - for ap in allocation_pools_str.split(','): - if "-" not in ap: - continue - start, end = ap.split('-') - allocation_pools.append({'start': start, 'end': end}) - - if not network_id: - self.failure( - error='Network not found', - rc=1, - msg='The specified network could not be found' - ) - if not self.neutron.list_subnets(cidr=cidr, - network_id=network_id)['subnets']: - self.state_change = True - s = {"name": subnet_name, "cidr": cidr, "ip_version": 4, - "network_id": network_id} - if tenant_id: - s["tenant_id"] = tenant_id - if allocation_pools: - s["allocation_pools"] = allocation_pools - - self.neutron.create_subnet({"subnet": s}) - return self._facts('subnets', self.neutron.list_subnets()) - - def _create_router(self, variables): - required_vars = ['router_name', 'external_gateway_info'] - variables_dict = self._get_vars(variables, required=required_vars) - router_name = variables_dict.pop('router_name') - external_gateway_info = variables_dict.pop('external_gateway_info') - tenant_id = variables_dict.pop('tenant_id') - - if not self._get_resource_by_name('routers', router_name): - self.state_change = True - r = {'name': router_name} - if external_gateway_info: - network_id = self._get_resource_by_name('networks', - external_gateway_info) - r['external_gateway_info'] = {'network_id': network_id} - if tenant_id: - r['tenant_id'] = tenant_id - self.neutron.create_router({'router': r}) - - return self._facts('routers', self.neutron.list_routers()) - - def _add_router_interface(self, variables): - required_vars = ['router_name', 'subnet_name'] - variables_dict = self._get_vars(variables, required=required_vars) - router_name = variables_dict.pop('router_name') - subnet_name = variables_dict.pop('subnet_name') - router_id = self._get_resource_by_name('routers', router_name) - subnet_id = self._get_resource_by_name('subnets', subnet_name) - - if not router_id: - self.failure( - error='Router not found', - rc=1, - msg='The specified router could not be found' - ) - - if not subnet_id: - self.failure( - error='Subnet not found', - rc=1, - msg='The specified subnet could not be found' - ) - - found = False - - for port in self.neutron.list_ports(device_id=router_id)['ports']: - for fixed_ips in port['fixed_ips']: - if fixed_ips['subnet_id'] == subnet_id: - found = True - if not found: - self.state_change = True - self.neutron.add_interface_router(router_id, - {'subnet_id': subnet_id}) - - def _get_networks(self, variables): - variables_dict = self._get_vars(variables) - net_name = variables_dict.pop('net_name') - if net_name: - network_id = self._get_resource_by_name('networks', net_name) - if not network_id: - self.failure( - error='Network not found', - rc=1, - msg='The specified network could not be found' - ) - - return self._facts('networks', self.neutron.list_networks()) - - -def main(): - module = AnsibleModule( - argument_spec=dict( - command=dict(required=True, choices=COMMAND_MAP.keys()), - openrc_path=dict(required=True), - net_name=dict(required=False), - subnet_name=dict(required=False), - cidr=dict(required=False), - provider_physical_network=dict(required=False), - provider_network_type=dict(required=False), - provider_segmentation_id=dict(required=False), - router_external=dict(required=False), - router_name=dict(required=False), - external_gateway_info=dict(required=False), - tenant_id=dict(required=False), - insecure=dict(default=False, required=False, type='bool'), - allocation_pools=dict(required=False) - ), - supports_check_mode=False - ) - mn = ManageNeutron(module) - mn.command_router() - -if __name__ == '__main__': - main() diff --git a/releasenotes/notes/plugins-remove-neutron-cbea1235e030e4f5.yaml b/releasenotes/notes/plugins-remove-neutron-cbea1235e030e4f5.yaml new file mode 100644 index 0000000..63bc758 --- /dev/null +++ b/releasenotes/notes/plugins-remove-neutron-cbea1235e030e4f5.yaml @@ -0,0 +1,5 @@ +--- +upgrade: + - The ``neutron`` library has been removed from OpenStack-Ansible's + plugins. Upstream Ansible modules for managing OpenStack network + resources should be used instead.