diff --git a/lib/ansible/modules/cloud/openstack/os_subnet b/lib/ansible/modules/cloud/openstack/os_subnet new file mode 100644 index 0000000000..ad3a27c281 --- /dev/null +++ b/lib/ansible/modules/cloud/openstack/os_subnet @@ -0,0 +1,213 @@ +#!/usr/bin/python +#coding: utf-8 -*- + +# (c) 2013, Benno Joy +# +# 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 . + +try: + import shade + HAS_SHADE = True +except ImportError: + HAS_SHADE = False + + +DOCUMENTATION = ''' +--- +module: os_subnet +short_description: Add/Remove subnet to an OpenStack network +extends_documentation_fragment: openstack +version_added: "1.10" +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: true + default: None + name: + description: + - The name of the subnet that should be created + required: true + default: None + cidr: + description: + - The CIDR representation of the subnet that should be assigned to the subnet + required: true + default: None + ip_version: + description: + - The IP version of the subnet 4 or 6 + required: false + default: 4 + enable_dhcp: + description: + - Whether DHCP should be enabled for this subnet. + required: false + default: true + gateway_ip: + description: + - The ip that would be assigned to the gateway for this subnet + required: false + default: None + dns_nameservers: + description: + - DNS nameservers for this subnet, comma-separated + required: false + default: None + version_added: "1.4" + allocation_pool_start: + description: + - From the subnet pool the starting address from which the IP should be allocated + required: false + default: None + allocation_pool_end: + description: + - From the subnet pool the last IP that should be assigned to the virtual machines + required: false + default: None +requirements: ["shade"] +''' + +EXAMPLES = ''' +# Create a subnet with the specified network +- os_subnet: state=present username=admin password=admin + project_name=admin + network_name=network1 name=net1subnet cidr=192.168.0.0/24" +''' + +_os_network_id = None + +def _get_net_id(neutron, module): + kwargs = { + 'name': module.params['network_name'], + } + try: + networks = neutron.list_networks(**kwargs) + except Exception, e: + module.fail_json("Error in listing neutron networks: %s" % e.message) + if not networks['networks']: + return None + return networks['networks'][0]['id'] + + +def _get_subnet_id(module, neutron): + global _os_network_id + subnet_id = None + _os_network_id = _get_net_id(neutron, module) + if not _os_network_id: + module.fail_json(msg = "network id of network not found.") + else: + kwargs = { + 'name': module.params['name'], + } + try: + subnets = neutron.list_subnets(**kwargs) + except Exception, e: + module.fail_json( msg = " Error in getting the subnet list:%s " % e.message) + if not subnets['subnets']: + return None + return subnets['subnets'][0]['id'] + +def _create_subnet(module, neutron): + neutron.format = 'json' + subnet = { + 'name': module.params['name'], + 'ip_version': module.params['ip_version'], + 'enable_dhcp': module.params['enable_dhcp'], + 'gateway_ip': module.params['gateway_ip'], + 'dns_nameservers': module.params['dns_nameservers'], + 'network_id': _os_network_id, + 'cidr': module.params['cidr'], + } + if module.params['allocation_pool_start'] and module.params['allocation_pool_end']: + allocation_pools = [ + { + 'start' : module.params['allocation_pool_start'], + 'end' : module.params['allocation_pool_end'] + } + ] + subnet.update({'allocation_pools': allocation_pools}) + if not module.params['gateway_ip']: + subnet.pop('gateway_ip') + if module.params['dns_nameservers']: + subnet['dns_nameservers'] = module.params['dns_nameservers'].split(',') + else: + subnet.pop('dns_nameservers') + try: + new_subnet = neutron.create_subnet(dict(subnet=subnet)) + except Exception, e: + module.fail_json(msg = "Failure in creating subnet: %s" % e.message) + return new_subnet['subnet']['id'] + + +def _delete_subnet(module, neutron, subnet_id): + try: + neutron.delete_subnet(subnet_id) + except Exception, e: + module.fail_json( msg = "Error in deleting subnet: %s" % e.message) + return True + + +def main(): + + argument_spec = openstack_full_argument_spec( + name = dict(required=True), + network_name = dict(required=True), + cidr = dict(required=True), + ip_version = dict(default='4', choices=['4', '6']), + enable_dhcp = dict(default='true', type='bool'), + gateway_ip = dict(default=None), + dns_nameservers = dict(default=None), + allocation_pool_start = dict(default=None), + allocation_pool_end = dict(default=None), + ) + module_kwargs = openstack_module_kwargs() + module = AnsibleModule(argument_spec, **module_kwargs) + + if not HAS_SHADE: + module.fail_json(msg='shade is required for this module') + + try: + cloud = shade.openstack_cloud(**module.params) + neutron = cloud.neutron_client + if module.params['state'] == 'present': + subnet_id = _get_subnet_id(module, neutron) + if not subnet_id: + subnet_id = _create_subnet(module, neutron) + module.exit_json(changed = True, result = "Created" , id = subnet_id) + else: + module.exit_json(changed = False, result = "success" , id = subnet_id) + else: + subnet_id = _get_subnet_id(module, neutron) + if not subnet_id: + module.exit_json(changed = False, result = "success") + else: + _delete_subnet(module, neutron, subnet_id) + module.exit_json(changed = True, result = "deleted") + except shade.OpenStackCloudException as e: + module.fail_json(msg=e.message) + + +# this is magic, see lib/ansible/module_common.py +from ansible.module_utils.basic import * +from ansible.module_utils.openstack import * +main() +