From de58a1eb954ee69f19275fbe1980ddfe62b7fe34 Mon Sep 17 00:00:00 2001 From: Davide Guerri Date: Sun, 19 Apr 2015 19:42:35 +0100 Subject: Allow subnet without a gateway If "subnet" is not present in the request body, Neuton will use the first address available in the specified subnet as the gateway address. Conversely, using "gateway_ip": null will create a subnet without a gateway. --- neutron_subnet | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/neutron_subnet b/neutron_subnet index 8cb622b..314d8ed 100644 --- a/neutron_subnet +++ b/neutron_subnet @@ -85,6 +85,11 @@ options: - Whether DHCP should be enabled for this subnet. required: false default: true + no_gateway: + description: + - If "true", no gateway will be created for this subnet + required: false + default: false gateway_ip: description: - The ip that would be assigned to the gateway for this subnet @@ -226,8 +231,12 @@ def _create_subnet(module, neutron): } ] subnet.update({'allocation_pools': allocation_pools}) - if not module.params['gateway_ip']: - subnet.pop('gateway_ip') + # "subnet['gateway_ip'] = None" means: "no gateway" + # no gateway_ip in body means: "automatic gateway" + if module.params['no_gateway']: + subnet['gateway_ip'] = None + elif module.params['gateway_ip'] is not None: + subnet['gateway_ip'] = module.params['gateway_ip'] if module.params['dns_nameservers']: subnet['dns_nameservers'] = module.params['dns_nameservers'].split(',') else: @@ -265,6 +274,7 @@ def main(): state = dict(default='present', choices=['absent', 'present']), ip_version = dict(default='4', choices=['4', '6']), enable_dhcp = dict(default='true', choices=BOOLEANS), + no_gateway = dict(default='false', choices=BOOLEANS), gateway_ip = dict(default=None), dns_nameservers = dict(default=None), allocation_pool_start = dict(default=None), -- cgit v1.2.1 From 8ddefcfb1ddd75f61ec09ab4ee2296f45e8de6bb Mon Sep 17 00:00:00 2001 From: Davide Guerri Date: Sun, 19 Apr 2015 19:44:20 +0100 Subject: Allow using neutron_{network, subnet} modules without admin role Admin power is needed in order retrieve the tenant_id of a given tenant name and to create/delete networks for a tenant that is not the one used to authenticate the user. We require an admin role only if the module is invoked with a specific tenant name. --- neutron_network | 25 ++++++++++++++----------- neutron_subnet | 33 ++++++++++++++++++--------------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/neutron_network b/neutron_network index 6dee045..0f492be 100644 --- a/neutron_network +++ b/neutron_network @@ -130,7 +130,7 @@ def _get_ksclient(module, kwargs): global _os_keystone _os_keystone = kclient return kclient - + def _get_endpoint(module, ksclient): try: @@ -155,15 +155,18 @@ def _get_neutron_client(module, kwargs): def _set_tenant_id(module): global _os_tenant_id - if not module.params['tenant_name']: - tenant_name = module.params['login_tenant_name'] - else: + if module.params['tenant_name']: + # We need admin power in order retrieve the tenant_id of a given + # tenant name and to create/delete networks for a tenant that is not + # the one used to authenticate the user. tenant_name = module.params['tenant_name'] - - for tenant in _os_keystone.tenants.list(): - if tenant.name == tenant_name: - _os_tenant_id = tenant.id - break + for tenant in _os_keystone.tenants.list(): + if tenant.name == tenant_name: + _os_tenant_id = tenant.id + break + else: + _os_tenant_id = _os_keystone.tenant_id + if not _os_tenant_id: module.fail_json(msg = "The tenant id cannot be found, please check the paramters") @@ -219,7 +222,7 @@ def _create_network(module, neutron): except Exception as e: module.fail_json(msg = "Error in creating network: %s" % e.message) return net['network']['id'] - + def _delete_network(module, net_id, neutron): try: @@ -229,7 +232,7 @@ def _delete_network(module, net_id, neutron): return True def main(): - + module = AnsibleModule( argument_spec = dict( login_username = dict(default='admin'), diff --git a/neutron_subnet b/neutron_subnet index 314d8ed..f666ef6 100644 --- a/neutron_subnet +++ b/neutron_subnet @@ -140,7 +140,7 @@ def _get_ksclient(module, kwargs): global _os_keystone _os_keystone = kclient return kclient - + def _get_endpoint(module, ksclient): try: @@ -165,17 +165,20 @@ def _get_neutron_client(module, kwargs): def _set_tenant_id(module): global _os_tenant_id - if not module.params['tenant_name']: - tenant_name = module.params['login_tenant_name'] - else: + if module.params['tenant_name']: + # We need admin power in order retrieve the tenant_id of a given + # tenant name and to create/delete networks for a tenant that is not + # the one used to authenticate the user. tenant_name = module.params['tenant_name'] + for tenant in _os_keystone.tenants.list(): + if tenant.name == tenant_name: + _os_tenant_id = tenant.id + break + else: + _os_tenant_id = _os_keystone.tenant_id - for tenant in _os_keystone.tenants.list(): - if tenant.name == tenant_name: - _os_tenant_id = tenant.id - break if not _os_tenant_id: - module.fail_json(msg = "The tenant id cannot be found, please check the paramters") + module.fail_json(msg = "The tenant id cannot be found, please check the paramters") def _get_net_id(neutron, module): kwargs = { @@ -248,18 +251,18 @@ def _create_subnet(module, neutron): 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 as e: module.fail_json( msg = "Error in deleting subnet: %s" % e.message) return True - - + + def main(): - + module = AnsibleModule( argument_spec = dict( login_username = dict(default='admin'), @@ -298,7 +301,7 @@ def main(): else: _delete_subnet(module, neutron, subnet_id) module.exit_json(changed = True, result = "deleted") - + # this is magic, see lib/ansible/module.params['common.py from ansible.module_utils.basic import * main() -- cgit v1.2.1 From 5048748e0a510cb29e1a7a46a009b359528a8309 Mon Sep 17 00:00:00 2001 From: Davide Guerri Date: Mon, 20 Apr 2015 15:04:45 +0100 Subject: Add missing region_name in keystone auth --- neutron_network | 10 ++++++---- neutron_subnet | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/neutron_network b/neutron_network index 0f492be..9c8dc1c 100644 --- a/neutron_network +++ b/neutron_network @@ -121,10 +121,12 @@ _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')) + kclient = ksclient.Client( + username=module.params.get('login_username'), + password=module.params.get('login_password'), + tenant_name=module.params.get('login_tenant_name'), + auth_url=module.params.get('auth_url'), + region_name=module.params.get('region_name')) except Exception as e: module.fail_json(msg = "Error authenticating to the keystone: %s" %e.message) global _os_keystone diff --git a/neutron_subnet b/neutron_subnet index f666ef6..02e3da6 100644 --- a/neutron_subnet +++ b/neutron_subnet @@ -131,10 +131,12 @@ _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')) + kclient = ksclient.Client( + username=module.params.get('login_username'), + password=module.params.get('login_password'), + tenant_name=module.params.get('login_tenant_name'), + auth_url=module.params.get('auth_url'), + region_name=module.params.get('region_name')) except Exception as e: module.fail_json(msg = "Error authenticating to the keystone: %s" %e.message) global _os_keystone -- cgit v1.2.1 From ed8f82e89ba31bcafb97ef338109b339206817af Mon Sep 17 00:00:00 2001 From: Davide Guerri Date: Mon, 20 Apr 2015 15:05:27 +0100 Subject: Avoid numerical tenant_id to be casted to integer --- neutron_sec_group | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/neutron_sec_group b/neutron_sec_group index 0d882c9..a5b8a6d 100644 --- a/neutron_sec_group +++ b/neutron_sec_group @@ -310,7 +310,8 @@ def _update_sg_rules(module, network_client, sg, wanted_rules, tenant_id): clean_new_rule[key] = None continue value = clean_new_rule[key] - if isinstance(value, (str, unicode)) and value.isdigit(): + if isinstance(value, (str, unicode)) and value.isdigit() and \ + key != 'tenant_id': clean_new_rule[key] = int(value) if cmp(clean_old_rule, clean_new_rule) == 0: matched_id = old_id -- cgit v1.2.1 From d5179fe60d6ac5daaf82a00538f6d8e930169036 Mon Sep 17 00:00:00 2001 From: Davide Guerri Date: Mon, 20 Apr 2015 15:06:14 +0100 Subject: Fix json_fail invocation --- neutron_subnet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neutron_subnet b/neutron_subnet index 02e3da6..fa8ab63 100644 --- a/neutron_subnet +++ b/neutron_subnet @@ -190,7 +190,7 @@ def _get_net_id(neutron, module): try: networks = neutron.list_networks(**kwargs) except Exception as e: - module.fail_json("Error in listing Neutron networks: %s" % e.message) + module.fail_json(msg = "Error in listing Neutron networks: %s" % e.message) if not networks['networks']: return None return networks['networks'][0]['id'] -- cgit v1.2.1 From 05836c9bd9e3925c84fb97402bd70718eeb48bff Mon Sep 17 00:00:00 2001 From: Davide Guerri Date: Mon, 20 Apr 2015 15:07:33 +0100 Subject: Do not include router:external when False. Older neutron versions (e.g. current HPCloud) will reject explicitly router:external set to false. Moreover router:external = False is the default. --- neutron_network | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/neutron_network b/neutron_network index 9c8dc1c..a9640d2 100644 --- a/neutron_network +++ b/neutron_network @@ -196,11 +196,15 @@ def _create_network(module, neutron): 'provider:network_type': module.params.get('provider_network_type'), 'provider:physical_network': module.params.get('provider_physical_network'), 'provider:segmentation_id': module.params.get('provider_segmentation_id'), - 'router:external': module.params.get('router_external'), 'shared': module.params.get('shared'), 'admin_state_up': module.params.get('admin_state_up'), } + # Older neutron versions wil reject explicitly router:external set + # to false + if module.params.get('router_external'): + network['router:external'] = True + if module.params['provider_network_type'] == 'local': network.pop('provider:physical_network', None) network.pop('provider:segmentation_id', None) -- cgit v1.2.1 From 89024bf08616a7147f94249ccf7e64617b5ea8b9 Mon Sep 17 00:00:00 2001 From: Davide Guerri Date: Mon, 20 Apr 2015 15:11:12 +0100 Subject: Add missing region_name in keystone auth --- neutron_floating_ip | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/neutron_floating_ip b/neutron_floating_ip index 4c14102..6d3ccd3 100644 --- a/neutron_floating_ip +++ b/neutron_floating_ip @@ -89,10 +89,12 @@ EXAMPLES = ''' 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')) + kclient = ksclient.Client( + username=module.params.get('login_username'), + password=module.params.get('login_password'), + tenant_name=module.params.get('login_tenant_name'), + auth_url=module.params.get('auth_url'), + region_name=module.params.get('region_name')) except Exception as e: module.fail_json(msg = "Error authenticating to the keystone: %s " % e.message) global _os_keystone @@ -136,7 +138,7 @@ def _get_server_state(module, nova): except Exception as e: module.fail_json(msg = "Error in getting the server list: %s" % e.message) return server_info, server - + def _get_port_info(neutron, module, instance_id): if module.params['port_network_name'] is None: kwargs = { @@ -158,7 +160,7 @@ def _get_port_info(neutron, module, instance_id): if not ports['ports']: return None, None return ports['ports'][0]['fixed_ips'][0]['ip_address'], ports['ports'][0]['id'] - + def _get_floating_ip(module, neutron, fixed_ip_address): kwargs = { 'fixed_ip_address': fixed_ip_address @@ -222,7 +224,7 @@ def _update_floating_ip(neutron, module, port_id, floating_ip_id): def main(): - + module = AnsibleModule( argument_spec = dict( login_username = dict(default='admin'), @@ -236,14 +238,14 @@ def main(): state = dict(default='present', choices=['absent', 'present']) ), ) - + try: nova = nova_client.Client(module.params['login_username'], module.params['login_password'], module.params['login_tenant_name'], module.params['auth_url'], service_type='compute') neutron = _get_neutron_client(module, module.params) except Exception as e: module.fail_json(msg="Error in authenticating to nova: %s" % e.message) - + server_info, server_obj = _get_server_state(module, nova) if not server_info: module.fail_json(msg="The instance name provided cannot be found") @@ -271,4 +273,3 @@ def main(): from ansible.module_utils.basic import * main() - -- cgit v1.2.1 From 99faeff36052c73812460fd0f1b8b848881169e2 Mon Sep 17 00:00:00 2001 From: Davide Guerri Date: Mon, 20 Apr 2015 15:26:20 +0100 Subject: Use region_name to retrieve nova VM list --- neutron_floating_ip | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/neutron_floating_ip b/neutron_floating_ip index 6d3ccd3..fbece6c 100644 --- a/neutron_floating_ip +++ b/neutron_floating_ip @@ -241,7 +241,8 @@ def main(): try: nova = nova_client.Client(module.params['login_username'], module.params['login_password'], - module.params['login_tenant_name'], module.params['auth_url'], service_type='compute') + module.params['login_tenant_name'], module.params['auth_url'], service_type='compute', + region_name=module.params.get('region_name')) neutron = _get_neutron_client(module, module.params) except Exception as e: module.fail_json(msg="Error in authenticating to nova: %s" % e.message) -- cgit v1.2.1 From 6edf76c7ba51a5a5d2428a44881cc66f6732fe45 Mon Sep 17 00:00:00 2001 From: Davide Guerri Date: Mon, 20 Apr 2015 15:27:59 +0100 Subject: Use boolean type for enable_dhcp and no_gateway parameters --- neutron_subnet | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neutron_subnet b/neutron_subnet index fa8ab63..afdcef8 100644 --- a/neutron_subnet +++ b/neutron_subnet @@ -278,8 +278,8 @@ def main(): 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), - no_gateway = dict(default='false', choices=BOOLEANS), + enable_dhcp = dict(default=True, type='bool'), + no_gateway = dict(default=False, type='bool'), gateway_ip = dict(default=None), dns_nameservers = dict(default=None), allocation_pool_start = dict(default=None), -- cgit v1.2.1 From 0c1e4c009c19fbdf02db2c32a353157fa287ab61 Mon Sep 17 00:00:00 2001 From: Davide Guerri Date: Tue, 21 Apr 2015 14:51:51 +0100 Subject: Allow non-admin users to create router and router interfaces --- neutron_router | 20 +++++++++++--------- neutron_router_interface | 17 ++++++++++------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/neutron_router b/neutron_router index 56d384d..a724c45 100644 --- a/neutron_router +++ b/neutron_router @@ -126,18 +126,20 @@ def _get_neutron_client(module, kwargs): def _set_tenant_id(module): global _os_tenant_id - if not module.params['tenant_name']: - login_tenant_name = module.params['login_tenant_name'] + if module.params['tenant_name']: + # We need admin power in order retrieve the tenant_id of a given + # tenant name and to create/delete networks for a tenant that is not + # the one used to authenticate the user. + tenant_name = module.params['tenant_name'] + for tenant in _os_keystone.tenants.list(): + if tenant.name == tenant_name: + _os_tenant_id = tenant.id + break else: - login_tenant_name = module.params['tenant_name'] + _os_tenant_id = _os_keystone.tenant_id - for tenant in _os_keystone.tenants.list(): - if tenant.name == login_tenant_name: - _os_tenant_id = tenant.id - break if not _os_tenant_id: - module.fail_json(msg = "The tenant id cannot be found, please check the paramters") - + module.fail_json(msg = "The tenant id cannot be found, please check the paramters") def _get_router_id(module, neutron): kwargs = { diff --git a/neutron_router_interface b/neutron_router_interface index 8d57725..1d6648a 100644 --- a/neutron_router_interface +++ b/neutron_router_interface @@ -127,15 +127,18 @@ def _get_neutron_client(module, kwargs): def _set_tenant_id(module): global _os_tenant_id - if not module.params['tenant_name']: - login_tenant_name = module.params['login_tenant_name'] + if module.params['tenant_name']: + # We need admin power in order retrieve the tenant_id of a given + # tenant name and to create/delete networks for a tenant that is not + # the one used to authenticate the user. + tenant_name = module.params['tenant_name'] + for tenant in _os_keystone.tenants.list(): + if tenant.name == tenant_name: + _os_tenant_id = tenant.id + break else: - login_tenant_name = module.params['tenant_name'] + _os_tenant_id = _os_keystone.tenant_id - for tenant in _os_keystone.tenants.list(): - if tenant.name == login_tenant_name: - _os_tenant_id = tenant.id - break if not _os_tenant_id: module.fail_json(msg = "The tenant id cannot be found, please check the paramters") -- cgit v1.2.1 From ee72221527b96155426da413235a47469e3b4fbd Mon Sep 17 00:00:00 2001 From: Davide Guerri Date: Tue, 21 Apr 2015 14:52:35 +0100 Subject: Use region name for keystone authentication --- neutron_router | 18 ++++++++++-------- neutron_router_gateway | 10 ++++++---- neutron_router_interface | 25 +++++++++++++------------ 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/neutron_router b/neutron_router index a724c45..6baa65f 100644 --- a/neutron_router +++ b/neutron_router @@ -92,16 +92,18 @@ _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')) + kclient = ksclient.Client( + username=module.params.get('login_username'), + password=module.params.get('login_password'), + tenant_name=module.params.get('login_tenant_name'), + auth_url=module.params.get('auth_url'), + region_name=module.params.get('region_name')) 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: @@ -172,7 +174,7 @@ def _delete_router(module, neutron, router_id): except: module.fail_json("Error in deleting the router") return True - + def main(): module = AnsibleModule( argument_spec = dict( @@ -187,7 +189,7 @@ def main(): admin_state_up = dict(type='bool', default=True), ), ) - + neutron = _get_neutron_client(module, module.params) _set_tenant_id(module) @@ -206,7 +208,7 @@ def main(): else: _delete_router(module, neutron, router_id) module.exit_json(changed=True, result="deleted") - + # this is magic, see lib/ansible/module.params['common.py from ansible.module_utils.basic import * main() diff --git a/neutron_router_gateway b/neutron_router_gateway index 93235b8..fec2e1b 100644 --- a/neutron_router_gateway +++ b/neutron_router_gateway @@ -82,10 +82,12 @@ EXAMPLES = ''' _os_keystone = 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')) + kclient = ksclient.Client( + username=module.params.get('login_username'), + password=module.params.get('login_password'), + tenant_name=module.params.get('login_tenant_name'), + auth_url=module.params.get('auth_url'), + region_name=module.params.get('region_name')) except Exception as e: module.fail_json(msg = "Error authenticating to the keystone: %s " % e.message) global _os_keystone diff --git a/neutron_router_interface b/neutron_router_interface index 1d6648a..a3060ff 100644 --- a/neutron_router_interface +++ b/neutron_router_interface @@ -93,16 +93,18 @@ _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')) + kclient = ksclient.Client( + username=module.params.get('login_username'), + password=module.params.get('login_password'), + tenant_name=module.params.get('login_tenant_name'), + auth_url=module.params.get('auth_url'), + region_name=module.params.get('region_name')) 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: @@ -142,7 +144,6 @@ def _set_tenant_id(module): if not _os_tenant_id: module.fail_json(msg = "The tenant id cannot be found, please check the paramters") - def _get_router_id(module, neutron): kwargs = { 'name': module.params['router_name'], @@ -169,7 +170,7 @@ def _get_subnet_id(module, neutron): if not subnets['subnets']: return None return subnets['subnets'][0]['id'] - + def _get_port_id(neutron, module, router_id, subnet_id): kwargs = { 'tenant_id': _os_tenant_id, @@ -196,7 +197,7 @@ def _add_interface_router(neutron, module, router_id, subnet_id): except Exception as e: module.fail_json(msg = "Error in adding interface to router: %s" % e.message) return True - + def _remove_interface_router(neutron, module, router_id, subnet_id): kwargs = { 'subnet_id': subnet_id @@ -206,7 +207,7 @@ def _remove_interface_router(neutron, module, router_id, subnet_id): except Exception as e: module.fail_json(msg="Error in removing interface from router: %s" % e.message) return True - + def main(): module = AnsibleModule( argument_spec = dict( @@ -221,7 +222,7 @@ def main(): state = dict(default='present', choices=['absent', 'present']), ), ) - + neutron = _get_neutron_client(module, module.params) _set_tenant_id(module) @@ -232,7 +233,7 @@ def main(): subnet_id = _get_subnet_id(module, neutron) if not subnet_id: module.fail_json(msg="failed to get the subnet id, please check the subnet name") - + if module.params['state'] == 'present': port_id = _get_port_id(neutron, module, router_id, subnet_id) if not port_id: @@ -246,7 +247,7 @@ def main(): module.exit_json(changed = False, result = "Success") _remove_interface_router(neutron, module, router_id, subnet_id) module.exit_json(changed=True, result="Deleted") - + # this is magic, see lib/ansible/module.params['common.py from ansible.module_utils.basic import * main() -- cgit v1.2.1 From 0a1a8de0f1f45579a7d440bcd389a613307b3203 Mon Sep 17 00:00:00 2001 From: Davide Guerri Date: Tue, 21 Apr 2015 14:54:51 +0100 Subject: make router_gateway module idempotent list_ports() won't return gateway ports unless its performed by an admin. Using router info, we can also save 1 query. --- neutron_router_gateway | 60 +++++++++++++++++++++----------------------------- 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/neutron_router_gateway b/neutron_router_gateway index fec2e1b..3a9b7ce 100644 --- a/neutron_router_gateway +++ b/neutron_router_gateway @@ -93,7 +93,7 @@ def _get_ksclient(module, kwargs): global _os_keystone _os_keystone = kclient return kclient - + def _get_endpoint(module, ksclient): try: @@ -116,7 +116,7 @@ def _get_neutron_client(module, kwargs): module.fail_json(msg = "Error in connecting to neutron: %s " % e.message) return neutron -def _get_router_id(module, neutron): +def _get_router(module, neutron): kwargs = { 'name': module.params['router_name'], } @@ -126,7 +126,7 @@ def _get_router_id(module, neutron): module.fail_json(msg = "Error in getting the router list: %s " % e.message) if not routers['routers']: return None - return routers['routers'][0]['id'] + return routers['routers'][0] def _get_net_id(neutron, module): kwargs = { @@ -141,19 +141,6 @@ def _get_net_id(neutron, module): return None return networks['networks'][0]['id'] -def _get_port_id(neutron, module, router_id, network_id): - kwargs = { - 'device_id': router_id, - 'network_id': network_id, - } - try: - ports = neutron.list_ports(**kwargs) - except Exception as e: - module.fail_json( msg = "Error in listing ports: %s" % e.message) - if not ports['ports']: - return None - return ports['ports'][0]['id'] - def _add_gateway_router(neutron, module, router_id, network_id): kwargs = { 'network_id': network_id @@ -163,16 +150,16 @@ def _add_gateway_router(neutron, module, router_id, network_id): except Exception as e: module.fail_json(msg = "Error in adding gateway to router: %s" % e.message) return True - + def _remove_gateway_router(neutron, module, router_id): try: neutron.remove_gateway_router(router_id) except Exception as e: module.fail_json(msg = "Error in removing gateway to router: %s" % e.message) return True - + def main(): - + module = AnsibleModule( argument_spec = dict( login_username = dict(default='admin'), @@ -185,33 +172,36 @@ def main(): state = dict(default='present', choices=['absent', 'present']), ), ) - + neutron = _get_neutron_client(module, module.params) - router_id = _get_router_id(module, neutron) + router = _get_router(module, neutron) - if not router_id: + if not router: module.fail_json(msg="failed to get the router id, please check the router name") network_id = _get_net_id(neutron, module) if not network_id: module.fail_json(msg="failed to get the network id, please check the network name and make sure it is external") - + if module.params['state'] == 'present': - port_id = _get_port_id(neutron, module, router_id, network_id) - if not port_id: - _add_gateway_router(neutron, module, router_id, network_id) - module.exit_json(changed=True, result="created") - module.exit_json(changed=False, result="success") + if router.get('external_gateway_info') is None: + _add_gateway_router(neutron, module, router['id'], network_id) + module.exit_json(changed=True, updated=False, result="created") + else: + if router['external_gateway_info']['network_id'] == network_id: + module.exit_json(changed=False, updated=False, result="success") + else: + _remove_gateway_router(neutron, module, router['id']) + _add_gateway_router(neutron, module, router['id'], network_id) + module.exit_json(changed=True, updated=True, result="created") if module.params['state'] == 'absent': - port_id = _get_port_id(neutron, module, router_id, network_id) - if not port_id: - module.exit_json(changed=False, result="Success") - _remove_gateway_router(neutron, module, router_id) - module.exit_json(changed=True, result="Deleted") + if router.get('external_gateway_info') is None: + module.exit_json(changed=False, updated=False, result="success") + else: + _remove_gateway_router(neutron, module, router['id']) + module.exit_json(changed=True, updated=False, result="deleted") # this is magic, see lib/ansible/module.params['common.py from ansible.module_utils.basic import * main() - - -- cgit v1.2.1