quantum_subnet 9.72 KB
Newer Older
bennojoy committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
#!/usr/bin/python
#coding: utf-8 -*-

# (c) 2013, Benno Joy <benno@ansibleworks.com>
#
# 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/>.

try:
    from quantumclient.quantum import client
    from keystoneclient.v2_0 import client as ksclient
except ImportError:
    print("failed=True msg='quantum and keystone client are required'")

DOCUMENTATION = '''
---
27
module: quantum_subnet
28
version_added: "1.2"
29
short_description: Add/Remove floating IP from an instance
bennojoy committed
30
description:
31
   - Add or Remove a floating IP to an instance
bennojoy committed
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
options:
   login_username:
     description:
        - login username to authenticate to keystone
     required: true
     default: admin
   login_password:
     description:
        - Password of login user
     required: true
     default: True
   login_tenant_name:
     description:
        - The tenant name of the login user
     required: true
     default: True
   auth_url:
     description:
50
        - The keystone URL for authentication
bennojoy committed
51 52 53 54 55 56 57 58 59 60 61 62 63 64
     required: false
     default: 'http://127.0.0.1:35357/v2.0/'
   region_name:
     description:
        - Name of the region
     required: false
     default: None
   state:
     description:
        - Indicate desired state of the resource
     choices: ['present', 'absent']
     default: present
   network_name:
     description:
65
        - Name of the network to which the subnet should be attached
bennojoy committed
66 67 68 69
     required: true
     default: None
   cidr:
     description:
70
        - The CIDR representation of the subnet that should be assigned to the subnet
bennojoy committed
71 72 73 74 75 76 77 78 79 80 81 82 83 84
     required: true
     default: None
   tenant_name:
     description:
        - The name of the tenant for whom the subnet should be created
     required: false
     default: None
   ip_version:
     description:
        - The IP version of the subnet 4 or 6 
     required: false
     default: 4
   enable_dhcp:
     description:
Michael DeHaan committed
85
        - Whether DHCP should be enabled for this subnet.
bennojoy committed
86 87 88 89 90 91 92
     required: false
     default: true
   gateway_ip:
     description:
        - The ip that would be assigned to the gateway for this subnet
     required: false
     default: None
93 94 95 96 97
   dns_nameservers:
     description:
        - DNS nameservers for this subnet, comma-separated
     required: false
     default: None
bennojoy committed
98 99
   allocation_pool_start:
     description:
100
        - From the subnet pool the starting address from which the IP should be allocated
bennojoy committed
101 102 103 104
     required: false
     default: None
   allocation_pool_end:
     description:
105
        - From the subnet pool the last IP that should be assigned to the virtual machines
bennojoy committed
106 107 108 109 110
     required: false
     default: None
requirements: ["quantum", "keystoneclient"]
'''

111 112 113 114 115 116 117
EXAMPLES = '''
# Create a subnet for a tenant with the specified subnet
- quantum_subnet: state=present login_username=admin login_password=admin
                  login_tenant_name=admin tenant_name=tenant1
                  network_name=network1 name=net1subnet cidr=192.168.0.0/24"
'''

bennojoy committed
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
_os_keystone   = None
_os_tenant_id  = None
_os_network_id = None

def _get_ksclient(module, kwargs):
    try:
        kclient = ksclient.Client(username=kwargs.get('login_username'),
                                 password=kwargs.get('login_password'),
                                 tenant_name=kwargs.get('login_tenant_name'),
                                 auth_url=kwargs.get('auth_url'))
    except Exception as e:   
        module.fail_json(msg = "Error authenticating to the keystone: %s" %e.message)
    global _os_keystone 
    _os_keystone = kclient
    return kclient 
 

def _get_endpoint(module, ksclient):
    try:
        endpoint = ksclient.service_catalog.url_for(service_type='network', endpoint_type='publicURL')
    except Exception as e:
        module.fail_json(msg = "Error getting endpoint for glance: %s" % e.message)
    return endpoint

def _get_quantum_client(module, kwargs):
    _ksclient = _get_ksclient(module, kwargs)
    token     = _ksclient.auth_token
    endpoint  = _get_endpoint(module, _ksclient)
    kwargs = {
            'token':        token,
148
            'endpoint_url': endpoint
bennojoy committed
149 150
    }
    try:
151
        quantum = client.Client('2.0', **kwargs)
bennojoy committed
152 153 154 155 156 157 158 159 160 161 162 163 164 165
    except Exception as e:
        module.fail_json(msg = " Error in connecting to quantum: %s" % e.message)
    return quantum

def _set_tenant_id(module):
    global _os_tenant_id
    if not module.params['tenant_name']:
        tenant_name = module.params['login_tenant_name']
    else:
        tenant_name = module.params['tenant_name']

    for tenant in _os_keystone.tenants.list():
        if tenant.name == tenant_name:
            _os_tenant_id = tenant.id
166
            break
bennojoy committed
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
    if not _os_tenant_id:
            module.fail_json(msg = "The tenant id cannot be found, please check the paramters")

def _get_net_id(quantum, module):
    kwargs = {
        'tenant_id': _os_tenant_id,
        'name': module.params['network_name'],
    }
    try:
        networks = quantum.list_networks(**kwargs)
    except Exception as e:
        module.fail_json("Error in listing quantum networks: %s" % e.message)
    if not networks['networks']:
            return None
    return networks['networks'][0]['id']


def _get_subnet_id(module, quantum):
    global _os_network_id
    subnet_id = None
    _os_network_id = _get_net_id(quantum, module)
    if not _os_network_id:
189
        module.fail_json(msg = "network id of network not found.")
bennojoy committed
190
    else:
191
        kwargs = {
bennojoy committed
192 193 194
            'tenant_id': _os_tenant_id,
            'name': module.params['name'],
        }
195 196 197 198 199 200 201
        try:
            subnets = quantum.list_subnets(**kwargs)
        except Exception as 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']
bennojoy committed
202 203 204 205

def _create_subnet(module, quantum):
    quantum.format = 'json'
    subnet = {
206 207 208 209 210 211 212 213
            'name':            module.params['name'],
            'ip_version':      module.params['ip_version'],
            'enable_dhcp':     module.params['enable_dhcp'],
            'tenant_id':       _os_tenant_id,
            'gateway_ip':      module.params['gateway_ip'],
            'dns_nameservers': module.params['dns_nameservers'],
            'network_id':      _os_network_id,
            'cidr':            module.params['cidr'],
bennojoy committed
214 215
    }
    if module.params['allocation_pool_start'] and module.params['allocation_pool_end']:
216 217 218 219 220 221 222
        allocation_pools = [
            { 
                'start' : module.params['allocation_pool_start'],
                'end'   :  module.params['allocation_pool_end']
            }
        ]
        subnet.update({'allocation_pools': allocation_pools})
bennojoy committed
223
    if not module.params['gateway_ip']:
224
        subnet.pop('gateway_ip')
225 226 227 228
    if module.params['dns_nameservers']:
        subnet['dns_nameservers'] = module.params['dns_nameservers'].split(',')
    else:
        subnet.pop('dns_nameservers')
bennojoy committed
229
    try:
230 231 232
        new_subnet = quantum.create_subnet(dict(subnet=subnet))
    except Exception, e:
        module.fail_json(msg = "Failure in creating subnet: %s" % e.message) 
bennojoy committed
233
    return new_subnet['subnet']['id']
234 235
        
                
bennojoy committed
236 237
def _delete_subnet(module, quantum, subnet_id):
    try:
238
        quantum.delete_subnet(subnet_id)
bennojoy committed
239
    except Exception as e:
240
        module.fail_json( msg = "Error in deleting subnet: %s" % e.message)
bennojoy committed
241
    return True
242 243
        
                
bennojoy committed
244 245 246
def main():
    
    module = AnsibleModule(
247 248 249 250 251 252 253 254 255 256 257 258 259 260
        argument_spec = dict(
            login_username          = dict(default='admin'),
            login_password          = dict(required=True),
            login_tenant_name       = dict(required='True'),
            auth_url                = dict(default='http://127.0.0.1:35357/v2.0/'),
            region_name             = dict(default=None),
            name                    = dict(required=True),
            network_name            = dict(required=True),
            cidr                    = dict(required=True),
            tenant_name             = dict(default=None),
            state                   = dict(default='present', choices=['absent', 'present']),
            ip_version              = dict(default='4', choices=['4', '6']),
            enable_dhcp             = dict(default='true', choices=BOOLEANS),
            gateway_ip              = dict(default=None),
261
            dns_nameservers         = dict(default=None),
262 263
            allocation_pool_start   = dict(default=None),
            allocation_pool_end     = dict(default=None),
bennojoy committed
264 265 266 267 268
        ),
    )
    quantum = _get_quantum_client(module, module.params)
    _set_tenant_id(module)
    if module.params['state'] == 'present':
269 270 271 272 273 274
        subnet_id = _get_subnet_id(module, quantum)
        if not subnet_id:
            subnet_id = _create_subnet(module, quantum)
            module.exit_json(changed = True, result = "Created" , id = subnet_id)
        else:
            module.exit_json(changed = False, result = "success" , id = subnet_id)
bennojoy committed
275
    else:
276 277
        subnet_id = _get_subnet_id(module, quantum)
        if not subnet_id:
278
            module.exit_json(changed = False, result = "success")
279
        else:
280 281
            _delete_subnet(module, quantum, subnet_id)
            module.exit_json(changed = True, result = "deleted")
282
                
bennojoy committed
283
# this is magic, see lib/ansible/module.params['common.py
284
from ansible.module_utils.basic import *
bennojoy committed
285 286
main()