quantum_router_interface 8.4 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 27 28 29 30 31 32 33 34 35 36 37 38 39
#!/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='quantumclient and keystone client are required'")
DOCUMENTATION = '''
---
module: quantum_router_interface
short_description: Attach/Dettach a subnet's interface to a router
description:
   - Attach/Dettach a subnet interface to a router, to provide a gateway for the subnet.
options:
   login_username:
     description:
        - login username to authenticate to keystone
     required: true
     default: admin
   login_password:
     description:
        - Password of login user
     required: true
40
     default: 'yes'
bennojoy committed
41 42 43 44
   login_tenant_name:
     description:
        - The tenant name of the login user
     required: true
45
     default: 'yes'
bennojoy committed
46 47
   auth_url:
     description:
48
        - The keystone URL for authentication
bennojoy committed
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
     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
   router_name:
     description:
        - Name of the router to which the subnet's interface should be attached.
     required: true
     default: None
   subnet_name:
     description:
        - Name of the subnet to whose interface should be attached to the router.
     required: true
     default: None
   tenant_name:
     description:
        - Name of the tenant whose subnet has to be attached.
     required: false
     default: None
requirements: ["quantumclient", "keystoneclient"]
'''

79 80 81
EXAMPLES = '''
# Attach tenant1's subnet to the external router
- quantum_router_interface: state=present login_username=admin
82 83 84 85 86
                            login_password=admin
                            login_tenant_name=admin 
                            tenant_name=tenant1
                            router_name=external_route
                            subnet_name=t1subnet
87 88 89
'''


bennojoy committed
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
_os_keystone = None
_os_tenant_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,
119
            'endpoint_url': endpoint
bennojoy committed
120 121
    }
    try:
122
        quantum = client.Client('2.0', **kwargs)
bennojoy committed
123 124 125 126 127 128 129 130 131 132 133 134 135
    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']:
        login_tenant_name = module.params['login_tenant_name']
    else:
        login_tenant_name = module.params['tenant_name']

    for tenant in _os_keystone.tenants.list():
        if tenant.name == login_tenant_name:
136 137
            _os_tenant_id = tenant.id
            break
bennojoy committed
138 139 140 141 142 143
    if not _os_tenant_id:
        module.fail_json(msg = "The tenant id cannot be found, please check the paramters")


def _get_router_id(module, quantum):
    kwargs = {
144
        'name': module.params['router_name'],
bennojoy committed
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
    }
    try:
        routers = quantum.list_routers(**kwargs)
    except Exception as e:
        module.fail_json(msg = "Error in getting the router list: %s " % e.message)
    if not routers['routers']:
        return None
    return routers['routers'][0]['id']


def _get_subnet_id(module, quantum):
    subnet_id = None
    kwargs = {
            'tenant_id': _os_tenant_id,
            'name': module.params['subnet_name'],
    }
    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']
168
                
bennojoy committed
169 170
def _get_port_id(quantum, module, router_id, subnet_id):
    kwargs = {
171 172
            'tenant_id': _os_tenant_id,
            'device_id': router_id,
bennojoy committed
173 174
    }
    try:
175
        ports = quantum.list_ports(**kwargs)
bennojoy committed
176
    except Exception as e:
177
        module.fail_json( msg = "Error in listing ports: %s" % e.message)
bennojoy committed
178
    if not ports['ports']:
179
        return None
bennojoy committed
180
    for port in  ports['ports']:
181 182 183
        for subnet in port['fixed_ips']:
            if subnet['subnet_id'] == subnet_id:
                return port['id']
bennojoy committed
184 185 186 187
    return None

def _add_interface_router(quantum, module, router_id, subnet_id):
    kwargs = {
188
        'subnet_id': subnet_id
bennojoy committed
189 190
    }
    try:
191
        quantum.add_interface_router(router_id, kwargs)
bennojoy committed
192
    except Exception as e:
193
        module.fail_json(msg = "Error in adding interface to router: %s" % e.message)
bennojoy committed
194
    return True
195
                
bennojoy committed
196 197 198 199 200 201 202
def  _remove_interface_router(quantum, module, router_id, subnet_id):
    kwargs = {
        'subnet_id': subnet_id
    }
    try:
        quantum.remove_interface_router(router_id, kwargs)
    except Exception as e:
203
        module.fail_json(msg="Error in removing interface from router: %s" % e.message)
bennojoy committed
204
    return True
205
        
bennojoy committed
206 207
def main():
    module = AnsibleModule(
208
        argument_spec                   = dict(
209 210 211 212 213 214 215 216 217
            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),
            router_name                     = dict(required=True),
            subnet_name                     = dict(required=True),
            tenant_name                     = dict(default=None),
            state                           = dict(default='present', choices=['absent', 'present']),
bennojoy committed
218 219
        ),
    )
220
                
bennojoy committed
221 222
    quantum = _get_quantum_client(module, module.params)
    _set_tenant_id(module)
223

bennojoy committed
224 225
    router_id = _get_router_id(module, quantum)
    if not router_id:
226 227
        module.fail_json(msg="failed to get the router id, please check the router name")

228
    subnet_id = _get_subnet_id(module, quantum) 
bennojoy committed
229
    if not subnet_id:
230
        module.fail_json(msg="failed to get the subnet id, please check the subnet name")
231
                
bennojoy committed
232
    if module.params['state'] == 'present':
233 234 235
        port_id = _get_port_id(quantum, module, router_id, subnet_id)
        if not port_id:
            _add_interface_router(quantum, module, router_id, subnet_id)
236 237 238
            module.exit_json(changed=True, result="created", id=port_id)
        module.exit_json(changed=False, result="success", id=port_id)

bennojoy committed
239
    if module.params['state'] == 'absent':
240 241
        port_id = _get_port_id(quantum, module, router_id, subnet_id)
        if not port_id:
Joshua Lund committed
242
            module.exit_json(changed = False, result = "Success")
243
        _remove_interface_router(quantum, module, router_id, subnet_id)
244
        module.exit_json(changed=True, result="Deleted")
245
                        
bennojoy committed
246 247 248 249
# this is magic, see lib/ansible/module.params['common.py
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
main()