From f0e0388159e1b9bfffb7a80b62e7fa5f098ff040 Mon Sep 17 00:00:00 2001 From: Austin Jamias Date: Fri, 14 Nov 2025 14:36:12 -0500 Subject: [PATCH] Add ability to allocate floating IP Currently, you would only use this module to create a floating IP if it doesn't exist and attempt to attach it to a Nova server. This commit adds support for creating a standalone floating IP not attached to anything, and optionally attaching it to a fixed IP in a fixed network. Change-Id: Id65ce98674b6b9d93dd4cfbbdf2c5c51798fca38 Signed-off-by: Austin Jamias --- ci/roles/floating_ip/tasks/main.yml | 187 +++++++++++- plugins/modules/floating_ip.py | 423 ++++++++++++++++++---------- 2 files changed, 446 insertions(+), 164 deletions(-) diff --git a/ci/roles/floating_ip/tasks/main.yml b/ci/roles/floating_ip/tasks/main.yml index aaad1ecd..3038b140 100644 --- a/ci/roles/floating_ip/tasks/main.yml +++ b/ci/roles/floating_ip/tasks/main.yml @@ -27,6 +27,12 @@ name: ansible_external external: true +- name: Gather information about external network + openstack.cloud.networks_info: + cloud: "{{ cloud }}" + name: ansible_external + register: external_network + - name: Create external subnet openstack.cloud.subnet: cloud: "{{ cloud }}" @@ -98,6 +104,17 @@ - ip_address: 10.7.7.102 register: port3 +- name: Create internal port 4 + openstack.cloud.port: + cloud: "{{ cloud }}" + state: present + name: ansible_internal_port4 + network: ansible_internal + fixed_ips: + - ip_address: 10.7.7.103 + - ip_address: 10.7.7.104 + register: port4 + - name: Create router 1 openstack.cloud.router: cloud: "{{ cloud }}" @@ -136,10 +153,31 @@ selectattr('floating_network_id', '==', public_network.networks.0.id)| list|length > 0 }}" -# TODO: Replace with appropriate Ansible module once available - name: Create a floating ip on public network (required for simplest, first floating ip test) - command: openstack --os-cloud={{ cloud }} floating ip create public when: not public_network_had_fips + block: + - name: Create a floating ip on public network + openstack.cloud.floating_ip: + cloud: "{{ cloud }}" + state: present + network: public + register: public_fip_result + + - name: Verify floating ip got created + assert: + that: + - public_fip_result.floating_ip.floating_network_id == public_network.networks.0.id + + - name: Create a floating ip on public network again + openstack.cloud.floating_ip: + cloud: "{{ cloud }}" + state: present + network: public + register: public_fip_result + + - name: Verify idempotency + assert: + that: public_fip_result is not changed # TODO: Replace with appropriate Ansible module once available - name: Create floating ip 1 on external network @@ -151,6 +189,90 @@ when: fips.floating_ips|length == 0 or "10.6.6.150" not in fips.floating_ips|map(attribute="floating_ip_address")|list +- name: Create floating ip 2 on external network + openstack.cloud.floating_ip: + cloud: "{{ cloud }}" + state: present + network: ansible_external + floating_ip_address: 10.6.6.151 + register: external_fip2_result + +- name: Verify floating ip got created + assert: + that: + - external_fip2_result.floating_ip.floating_network_id == external_network.networks.0.id + +- name: Update floating ip 2 on external network + openstack.cloud.floating_ip: + cloud: "{{ cloud }}" + state: present + network: ansible_external + floating_ip_address: 10.6.6.151 + nat_destination: ansible_internal + fixed_address: 10.7.7.104 + register: external_fip2_result + +- name: Verify floating ip got updated + assert: + that: + - external_fip2_result is changed + - external_fip2_result.floating_ip.floating_ip_address == "10.6.6.151" + - external_fip2_result.floating_ip.port_id == port4.port.id + - external_fip2_result.floating_ip.fixed_ip_address == "10.7.7.104" + +- name: Update floating ip 2 on external network again + openstack.cloud.floating_ip: + cloud: "{{ cloud }}" + state: present + network: ansible_external + floating_ip_address: 10.6.6.151 + nat_destination: ansible_internal + fixed_address: 10.7.7.104 + register: external_fip2_result + +- name: Verify idempotency + assert: + that: + - external_fip2_result is not changed + +- name: Detatch floating ip 2 on external network from port + openstack.cloud.floating_ip: + cloud: "{{ cloud }}" + state: absent + network: ansible_external + floating_ip_address: 10.6.6.151 + +- name: Get floating ip 2 info + openstack.cloud.floating_ip_info: + cloud: "{{ cloud }}" + floating_ip_address: 10.6.6.151 + register: external_fip2_result + +- name: Verify floating ip got detached + assert: + that: + - external_fip2_result.floating_ips.0.floating_ip_address == "10.6.6.151" + - external_fip2_result.floating_ips.0.fixed_ip_address == none + - external_fip2_result.floating_ips.0.port_id == none + +- name: Detatch floating ip 2 on external network from port again + openstack.cloud.floating_ip: + cloud: "{{ cloud }}" + state: absent + network: ansible_external + floating_ip_address: 10.6.6.151 + +- name: Get floating ip 2 info + openstack.cloud.floating_ip_info: + cloud: "{{ cloud }}" + floating_ip_address: 10.6.6.151 + register: external_fip2_result + +- name: Verify idempotency + assert: + that: + - external_fip2_result is not changed + - name: Create server 1 with one nic openstack.cloud.server: cloud: "{{ cloud }}" @@ -433,18 +555,41 @@ cloud: "{{ cloud }}" register: fips -# TODO: Replace with appropriate Ansible module once available - name: Delete floating ip on public network if we created it when: not public_network_had_fips - command: > - openstack --os-cloud={{ cloud }} floating ip delete - {{ fips.floating_ips|selectattr('floating_network_id', '==', public_network.networks.0.id)| - map(attribute="floating_ip_address")|list|join(' ') }} + openstack.cloud.floating_ip: + cloud: "{{ cloud }}" + state: absent + purge: true + floating_ip_address: "{{ public_fip }}" + network: public + loop: >- + {{ + fips.floating_ips | + selectattr('floating_network_id', '==', public_network.networks.0.id) | + map(attribute="floating_ip_address") | + list + }} + loop_control: + loop_var: public_fip -# TODO: Replace with appropriate Ansible module once available - name: Delete floating ip 1 - command: openstack --os-cloud={{ cloud }} floating ip delete 10.6.6.150 when: fips.floating_ips|length > 0 and "10.6.6.150" in fips.floating_ips|map(attribute="floating_ip_address")|list + openstack.cloud.floating_ip: + cloud: "{{ cloud }}" + state: absent + purge: true + floating_ip_address: 10.6.6.150 + network: ansible_external + +- name: Delete floating ip 2 + when: fips.floating_ips|length > 0 and "10.6.6.151" in fips.floating_ips|map(attribute="floating_ip_address")|list + openstack.cloud.floating_ip: + cloud: "{{ cloud }}" + state: absent + purge: true + floating_ip_address: 10.6.6.151 + network: ansible_external - name: Get remaining floating ips on external network openstack.cloud.floating_ip_info: @@ -452,14 +597,24 @@ floating_network: ansible_external register: fips -# TODO: Replace with appropriate Ansible module once available # The first, simple floating ip test might have allocated a floating ip on the external network. # This floating ip must be removed before external network can be deleted. - name: Delete remaining floating ips on external network when: fips.floating_ips|length > 0 - command: > - openstack --os-cloud={{ cloud }} floating ip delete - {{ fips.floating_ips|map(attribute="floating_ip_address")|list|join(' ') }} + openstack.cloud.floating_ip: + cloud: "{{ cloud }}" + state: absent + purge: true + floating_ip_address: "{{ external_fip }}" + network: ansible_external + loop: >- + {{ + fips.floating_ips | + map(attribute="floating_ip_address") | + list + }} + loop_control: + loop_var: external_fip # Remove routers after floating ips have been detached and disassociated else removal fails with # Error detaching interface from router ***: Client Error for url: ***, @@ -478,6 +633,12 @@ state: absent name: ansible_router1 +- name: Delete internal port 4 + openstack.cloud.port: + cloud: "{{ cloud }}" + state: absent + name: ansible_internal_port4 + - name: Delete internal port 3 openstack.cloud.port: cloud: "{{ cloud }}" diff --git a/plugins/modules/floating_ip.py b/plugins/modules/floating_ip.py index 873aaefe..9573e0d1 100644 --- a/plugins/modules/floating_ip.py +++ b/plugins/modules/floating_ip.py @@ -17,8 +17,9 @@ description: options: fixed_address: description: - - To which fixed IP of server the floating IP address should be + - To which fixed IP of attached port the floating IP address should be attached to. + aliases: ["fixed_ip_address"] type: str floating_ip_address: description: @@ -35,6 +36,7 @@ options: network: description: - The name or ID of a neutron external network or a nova pool name. + - When I(server) is not defined, I(network) is required type: str purge: description: @@ -57,7 +59,6 @@ options: description: - The name or ID of the server to which the IP address should be assigned. - required: true type: str state: description: @@ -183,23 +184,24 @@ from ansible_collections.openstack.cloud.plugins.module_utils.openstack import O class NetworkingFloatingIPModule(OpenStackModule): argument_spec = dict( - fixed_address=dict(), + fixed_address=dict(aliases=['fixed_ip_address']), floating_ip_address=dict(), nat_destination=dict(aliases=['fixed_network', 'internal_network']), network=dict(), purge=dict(type='bool', default=False), reuse=dict(type='bool', default=False), - server=dict(required=True), + server=dict(), state=dict(default='present', choices=['absent', 'present']), ) module_kwargs = dict( required_if=[ - ['state', 'absent', ['floating_ip_address']] + ['state', 'present', ['server', 'network'], True], + ['state', 'absent', ['floating_ip_address'], False], ], required_by={ 'floating_ip_address': ('network'), - } + }, ) def run(self): @@ -214,139 +216,174 @@ class NetworkingFloatingIPModule(OpenStackModule): changed = False fixed_address = self.params['fixed_address'] floating_ip_address = self.params['floating_ip_address'] - nat_destination_name_or_id = self.params['nat_destination'] + nat_destination_id = ( + self.nat_destination['id'] if self.nat_destination else None + ) network_id = self.network['id'] if self.network else None + server = self.server ips = self._find_ips( - server=self.server, + server=server, floating_ip_address=floating_ip_address, network_id=network_id, fixed_address=fixed_address, - nat_destination_name_or_id=nat_destination_name_or_id) + nat_destination_id=nat_destination_id + ) - # First floating ip satisfies our requirements - ip = ips[0] if ips else None + ip = None - if floating_ip_address: - # A specific floating ip address has been requested + if not ips: + if server: + if floating_ip_address: + # Requested floating ip address does not exist + self.conn.add_ip_list( + server=server, + ips=[floating_ip_address], + wait=self.params['wait'], + timeout=self.params['timeout'], + fixed_address=fixed_address + ) + changed = True - if not ip: - # If a specific floating ip address has been requested - # and it does not exist yet then create it + else: + # No specific floating ip has been requested and none of the + # floating ips which have been assigned to the server matches + # requirements - # openstacksdk's create_ip requires floating_ip_address - # and floating_network_id to be set - self.conn.network.create_ip( - floating_ip_address=floating_ip_address, - floating_network_id=network_id) + # add_ips_to_server() will handle several scenarios: + # + # If a specific floating ip address has been requested then it + # will be attached to the server. The floating ip address has + # either been created in previous steps or it already existed. + # Ref.: https://github.com/openstack/openstacksdk/blob/ + # 9d3ee1d32149ba2a8bb3dc894295e180746cdddc/openstack/cloud + # /_floating_ip.py#L985 + # + # If no specific floating ip address has been requested, reuse + # is allowed and a network has been given (with ip_pool) from + # which floating ip addresses will be drawn, then any existing + # floating ip address from ip_pool=network which is not + # attached to any other server will be attached to the server. + # If no such floating ip address exists or if reuse is not + # allowed, then a new floating ip address will be created + # within ip_pool=network and attached to the server. + # Ref.: https://github.com/openstack/openstacksdk/blob/ + # 9d3ee1d32149ba2a8bb3dc894295e180746cdddc/openstack/cloud/ + # _floating_ip.py#L981 + # + # If no specific floating ip address has been requested and no + # network has been given (with ip_pool) from which floating ip + # addresses will be taken, then a floating ip address might be + # added to the server, refer to _needs_floating_ip() for + # details. + # Ref.: + # * https://github.com/openstack/openstacksdk/blob/ + # 9d3ee1d32149ba2a8bb3dc894295e180746cdddc/openstack/cloud/\ + # _floating_ip.py#L989 + # * https://github.com/openstack/openstacksdk/blob/ + # 9d3ee1d32149ba2a8bb3dc894295e180746cdddc/openstack/cloud/ + # _floating_ip.py#L995 + # + # Both floating_ip_address and network are mutually exclusive + # in add_ips_to_server(), i.e.add_ips_to_server will ignore + # floating_ip_address if network is not None. To prefer + # attaching a specific floating ip address over assigning any + # fip, ip_pool is only defined if floating_ip_address is None. + # Ref.: https://github.com/openstack/openstacksdk/blob/ + # a6b0ece2821ea79330c4067100295f6bdcbe456e/openstack/cloud/ + # _floating_ip.py#L987 + self.conn.add_ips_to_server( + server=server, + ip_pool=network_id, + ips=None, # No specific floating ip requested + reuse=self.params['reuse'], + fixed_address=fixed_address, + wait=self.params['wait'], + timeout=self.params['timeout'], + nat_destination=nat_destination_id + ) + changed = True + + else: # not server + kwargs = self._params_to_kwargs( + floating_ip_address, + network_id, + fixed_address, + self.nat_destination + ) + + # create the ip + ip = self.conn.network.create_ip(**kwargs) changed = True - else: # ip - # Requested floating ip address exists already + else: # ips + ip = ips[0] - if ip.port_details and (ip.port_details['status'] == 'ACTIVE') \ - and (floating_ip_address not in self._filter_ips( - self.server)): - # Floating ip address exists and has been attached - # but to a different server + if server: + server_ips = self._filter_ips(server) + if ip.floating_ip_address not in server_ips: + port_details = ip.port_details + if (port_details + and port_details['status'] == 'ACTIVE'): + # Requested ip has been attached to different server + self.fail_json( + msg="Floating ip {0} has been attached to " + "different server".format( + floating_ip_address)) - # Requested ip has been attached to different server - self.fail_json( - msg="Floating ip {0} has been attached to different " - "server".format(floating_ip_address)) + else: + # Requested floating ip address has not been + # assigned to server + self.conn.add_ip_list( + server=server, + ips=[ip.floating_ip_address], + wait=self.params['wait'], + timeout=self.params['timeout'], + fixed_address=fixed_address + ) + changed = True - if not ip \ - or floating_ip_address not in self._filter_ips(self.server): - # Requested floating ip address does not exist or has not been - # assigned to server + else: + # floating ip is already assigned to the server + pass + + elif len(ips) > 1: # not server + self.fail_json(msg='Found more than one floating ip') - self.conn.add_ip_list( - server=self.server, - ips=[floating_ip_address], - wait=self.params['wait'], - timeout=self.params['timeout'], - fixed_address=fixed_address) - changed = True else: - # Requested floating ip address has been assigned to server - pass + kwargs = self._params_to_kwargs( + floating_ip_address, + network_id, + fixed_address, + self.nat_destination + ) + for key, value in kwargs.items(): + if ip[key] != value: + self.conn.network.update_ip(ip, **kwargs) + changed = True + break - elif not ips: # and not floating_ip_address - # No specific floating ip has been requested and none of the - # floating ips which have been assigned to the server matches - # requirements - - # add_ips_to_server() will handle several scenarios: - # - # If a specific floating ip address has been requested then it - # will be attached to the server. The floating ip address has - # either been created in previous steps or it already existed. - # Ref.: https://github.com/openstack/openstacksdk/blob/ - # 9d3ee1d32149ba2a8bb3dc894295e180746cdddc/openstack/cloud - # /_floating_ip.py#L985 - # - # If no specific floating ip address has been requested, reuse - # is allowed and a network has been given (with ip_pool) from - # which floating ip addresses will be drawn, then any existing - # floating ip address from ip_pool=network which is not - # attached to any other server will be attached to the server. - # If no such floating ip address exists or if reuse is not - # allowed, then a new floating ip address will be created - # within ip_pool=network and attached to the server. - # Ref.: https://github.com/openstack/openstacksdk/blob/ - # 9d3ee1d32149ba2a8bb3dc894295e180746cdddc/openstack/cloud/ - # _floating_ip.py#L981 - # - # If no specific floating ip address has been requested and no - # network has been given (with ip_pool) from which floating ip - # addresses will be taken, then a floating ip address might be - # added to the server, refer to _needs_floating_ip() for - # details. - # Ref.: - # * https://github.com/openstack/openstacksdk/blob/ - # 9d3ee1d32149ba2a8bb3dc894295e180746cdddc/openstack/cloud/\ - # _floating_ip.py#L989 - # * https://github.com/openstack/openstacksdk/blob/ - # 9d3ee1d32149ba2a8bb3dc894295e180746cdddc/openstack/cloud/ - # _floating_ip.py#L995 - # - # Both floating_ip_address and network are mutually exclusive - # in add_ips_to_server(), i.e.add_ips_to_server will ignore - # floating_ip_address if network is not None. To prefer - # attaching a specific floating ip address over assigning any - # fip, ip_pool is only defined if floating_ip_address is None. - # Ref.: https://github.com/openstack/openstacksdk/blob/ - # a6b0ece2821ea79330c4067100295f6bdcbe456e/openstack/cloud/ - # _floating_ip.py#L987 - self.conn.add_ips_to_server( - server=self.server, - ip_pool=network_id, - ips=None, # No specific floating ip requested - reuse=self.params['reuse'], - fixed_address=fixed_address, - wait=self.params['wait'], - timeout=self.params['timeout'], - nat_destination=nat_destination_name_or_id) - changed = True - else: - # Found one or more floating ips which satisfy requirements - pass - - if changed: + if changed and server: # update server details such as addresses - self.server = self.conn.compute.get_server(self.server) + server = self.conn.compute.get_server(server) # Update the floating ip resource ips = self._find_ips( - self.server, floating_ip_address, network_id, - fixed_address, nat_destination_name_or_id) + server, + floating_ip_address, + network_id, + fixed_address, + nat_destination_id + ) - # ips can be empty, e.g. when server has no private ipv4 - # address to which a floating ip address can be attached + # ips can be empty, e.g. when server has no private ipv4 + # address to which a floating ip address can be attached + ip = ips[0] if ips else None self.exit_json( changed=changed, - floating_ip=ips[0].to_dict(computed=False) if ips else None) + floating_ip=ip.to_dict(computed=False) + ) def _detach_and_delete(self): ips = self._find_ips( @@ -354,7 +391,7 @@ class NetworkingFloatingIPModule(OpenStackModule): floating_ip_address=self.params['floating_ip_address'], network_id=self.network['id'] if self.network else None, fixed_address=self.params['fixed_address'], - nat_destination_name_or_id=self.params['nat_destination']) + nat_destination_id=self.nat_destination['id'] if self.nat_destination else None) if not ips: # Nothing to detach @@ -362,19 +399,22 @@ class NetworkingFloatingIPModule(OpenStackModule): changed = False for ip in ips: - if ip['fixed_ip_address']: - # Silently ignore that ip might not be attached to server - # - # self.conn.network.update_ip(ip_id, port_id=None) does not - # handle nova network but self.conn.detach_ip_from_server() - # does so - self.conn.detach_ip_from_server(server_id=self.server['id'], - floating_ip_id=ip['id']) - - # OpenStackSDK sets {"port_id": None} to detach a floating - # ip from a device, but there might be a delay until a - # server does not list it in addresses any more. - changed = True + if self.server: + if ip['fixed_ip_address']: + # Silently ignore that ip might not be attached to server + # + # self.conn.network.update_ip(ip_id, port_id=None) does not + # handle nova network but self.conn.detach_ip_from_server() + # does so + changed = self.conn.detach_ip_from_server(server_id=self.server['id'], + floating_ip_id=ip['id']) + # OpenStackSDK sets {"port_id": None} to detach a floating + # ip from a device, but there might be a delay until a + # server does not list it in addresses any more. + else: # not self.server + if ip['port_id']: + changed = True + self.conn.network.update_ip(floating_ip=ip['id'], port_id=None) if self.params['purge']: self.conn.network.delete_ip(ip['id']) @@ -397,39 +437,56 @@ class NetworkingFloatingIPModule(OpenStackModule): # Returns a list not an iterator here because # it is iterated several times below - return [address['addr'] - for address in _flatten(server['addresses'].values()) - if address['OS-EXT-IPS:type'] == 'floating'] + addresses = _flatten(server['addresses'].values()) + return [ + address['addr'] + for address in addresses + if address['OS-EXT-IPS:type'] == 'floating' + ] def _find_ips(self, server, floating_ip_address, network_id, fixed_address, - nat_destination_name_or_id): + nat_destination_id): # Check which floating ips matches our requirements. # They might or might not be attached to our server. if floating_ip_address: # A specific floating ip address has been requested ip = self.conn.network.find_ip(floating_ip_address) return [ip] if ip else [] - elif (not fixed_address and nat_destination_name_or_id): - # No specific floating ip and no specific fixed ip have been - # requested but a private network (nat_destination) has been - # given where the floating ip should be attached to. - return self._find_ips_by_nat_destination( - server, nat_destination_name_or_id) - else: - # not floating_ip_address - # and (fixed_address or not nat_destination_name_or_id) + elif server: + if (not fixed_address and nat_destination_id): + # No specific floating ip and no specific fixed ip have been + # requested but a private network (nat_destination) has been + # given where the floating ip should be attached to. + return self._find_ips_by_nat_destination( + server, nat_destination_id) + else: + # not floating_ip_address + # and (fixed_address or not nat_destination_id) - # An analysis of all floating ips of server is required - return self._find_ips_by_network_id_and_fixed_address( - server, fixed_address, network_id) + # An analysis of all floating ips of server is required + return self._find_ips_by_network_id_and_fixed_address( + server, fixed_address, network_id) + elif fixed_address or nat_destination_id: + ports = self._find_ports_by_fixed_address_or_nat_destination(fixed_address, nat_destination_id) + + floating_ips = [] + for port in ports: + ips = list(self.conn.network.ips(port_id=port.id)) + floating_ips.extend(ips) + + return floating_ips + elif network_id: + return list(self.conn.network.ips(floating_network_id=network_id)) + else: + return [] def _find_ips_by_nat_destination(self, server, - nat_destination_name_or_id): + nat_destination_id): if not server['addresses']: return None @@ -437,7 +494,7 @@ class NetworkingFloatingIPModule(OpenStackModule): # Check if we have any floating ip on # the given nat_destination network nat_destination = self.conn.network.find_network( - nat_destination_name_or_id, ignore_missing=False) + nat_destination_id, ignore_missing=False) fips_with_nat_destination = [ addr for addr @@ -467,7 +524,7 @@ class NetworkingFloatingIPModule(OpenStackModule): # match network of floating ip continue - if not fixed_address: # and not nat_destination_name_or_id + if not fixed_address: # and not nat_destination_id # Any floating ip will fullfil these requirements matching_ips.append(ip) @@ -478,20 +535,84 @@ class NetworkingFloatingIPModule(OpenStackModule): return matching_ips + def _params_to_kwargs(self, + floating_ip_address, + network_id, + fixed_address, + nat_destination): + kwargs = {} + + kwargs['floating_network_id'] = network_id + + if fixed_address: + # must indicate internal port identifier + ports = self._find_ports_by_fixed_address_or_nat_destination( + fixed_address, nat_destination + ) + if len(ports) > 1: + self.fail_json( + msg='There are multiple subnets with the fixed ip ' + 'address {0}'.format(fixed_address) + ) + elif len(ports) == 0: + self.fail_json( + msg='No port found with fixed ip address {0}'.format( + fixed_address) + ) + else: + kwargs['fixed_ip_address'] = fixed_address + kwargs['port_id'] = ports[0].id + + if floating_ip_address: + kwargs['floating_ip_address'] = floating_ip_address + + return kwargs + + def _find_ports_by_fixed_address_or_nat_destination(self, + fixed_address, + nat_destination): + port_kwargs = {} + + if fixed_address: + port_kwargs['fixed_ips'] = f'ip_address={fixed_address}' + if nat_destination: + port_kwargs['network_id'] = nat_destination.id + + ports = self.conn.network.ports(**port_kwargs) + return list(ports) + def _init(self): server_name_or_id = self.params['server'] - server = self.conn.compute.find_server(server_name_or_id, - ignore_missing=False) - # fetch server details such as addresses - self.server = self.conn.compute.get_server(server) + if server_name_or_id: + self.server = self.conn.compute.find_server( + name_or_id=server_name_or_id, ignore_missing=False + ) + else: + self.server = None + + if (self.server is None and self.params['fixed_address'] + and self.params['nat_destination'] is None): + self.fail_json( + msg='fixed_address requires nat_destination to be defined ' + 'when server isn\'t' + ) network_name_or_id = self.params['network'] if network_name_or_id: self.network = self.conn.network.find_network( - name_or_id=network_name_or_id, ignore_missing=False) + name_or_id=network_name_or_id, ignore_missing=False + ) else: self.network = None + nat_destination_name_or_id = self.params['nat_destination'] + if nat_destination_name_or_id: + self.nat_destination = self.conn.network.find_network( + name_or_id=nat_destination_name_or_id, ignore_missing=False + ) + else: + self.nat_destination = None + def main(): module = NetworkingFloatingIPModule()