mirror of
https://opendev.org/openstack/ansible-collections-openstack.git
synced 2026-05-07 13:53:15 +00:00
Merge "Add ability to allocate floating IP"
This commit is contained in:
@@ -27,6 +27,12 @@
|
|||||||
name: ansible_external
|
name: ansible_external
|
||||||
external: true
|
external: true
|
||||||
|
|
||||||
|
- name: Gather information about external network
|
||||||
|
openstack.cloud.networks_info:
|
||||||
|
cloud: "{{ cloud }}"
|
||||||
|
name: ansible_external
|
||||||
|
register: external_network
|
||||||
|
|
||||||
- name: Create external subnet
|
- name: Create external subnet
|
||||||
openstack.cloud.subnet:
|
openstack.cloud.subnet:
|
||||||
cloud: "{{ cloud }}"
|
cloud: "{{ cloud }}"
|
||||||
@@ -98,6 +104,17 @@
|
|||||||
- ip_address: 10.7.7.102
|
- ip_address: 10.7.7.102
|
||||||
register: port3
|
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
|
- name: Create router 1
|
||||||
openstack.cloud.router:
|
openstack.cloud.router:
|
||||||
cloud: "{{ cloud }}"
|
cloud: "{{ cloud }}"
|
||||||
@@ -136,10 +153,31 @@
|
|||||||
selectattr('floating_network_id', '==', public_network.networks.0.id)|
|
selectattr('floating_network_id', '==', public_network.networks.0.id)|
|
||||||
list|length > 0 }}"
|
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)
|
- 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
|
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
|
# TODO: Replace with appropriate Ansible module once available
|
||||||
- name: Create floating ip 1 on external network
|
- name: Create floating ip 1 on external network
|
||||||
@@ -151,6 +189,90 @@
|
|||||||
when: fips.floating_ips|length == 0 or
|
when: fips.floating_ips|length == 0 or
|
||||||
"10.6.6.150" not in fips.floating_ips|map(attribute="floating_ip_address")|list
|
"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
|
- name: Create server 1 with one nic
|
||||||
openstack.cloud.server:
|
openstack.cloud.server:
|
||||||
cloud: "{{ cloud }}"
|
cloud: "{{ cloud }}"
|
||||||
@@ -433,18 +555,41 @@
|
|||||||
cloud: "{{ cloud }}"
|
cloud: "{{ cloud }}"
|
||||||
register: fips
|
register: fips
|
||||||
|
|
||||||
# TODO: Replace with appropriate Ansible module once available
|
|
||||||
- name: Delete floating ip on public network if we created it
|
- name: Delete floating ip on public network if we created it
|
||||||
when: not public_network_had_fips
|
when: not public_network_had_fips
|
||||||
command: >
|
openstack.cloud.floating_ip:
|
||||||
openstack --os-cloud={{ cloud }} floating ip delete
|
cloud: "{{ cloud }}"
|
||||||
{{ fips.floating_ips|selectattr('floating_network_id', '==', public_network.networks.0.id)|
|
state: absent
|
||||||
map(attribute="floating_ip_address")|list|join(' ') }}
|
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
|
- 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
|
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
|
- name: Get remaining floating ips on external network
|
||||||
openstack.cloud.floating_ip_info:
|
openstack.cloud.floating_ip_info:
|
||||||
@@ -452,14 +597,24 @@
|
|||||||
floating_network: ansible_external
|
floating_network: ansible_external
|
||||||
register: fips
|
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.
|
# 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.
|
# This floating ip must be removed before external network can be deleted.
|
||||||
- name: Delete remaining floating ips on external network
|
- name: Delete remaining floating ips on external network
|
||||||
when: fips.floating_ips|length > 0
|
when: fips.floating_ips|length > 0
|
||||||
command: >
|
openstack.cloud.floating_ip:
|
||||||
openstack --os-cloud={{ cloud }} floating ip delete
|
cloud: "{{ cloud }}"
|
||||||
{{ fips.floating_ips|map(attribute="floating_ip_address")|list|join(' ') }}
|
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
|
# Remove routers after floating ips have been detached and disassociated else removal fails with
|
||||||
# Error detaching interface from router ***: Client Error for url: ***,
|
# Error detaching interface from router ***: Client Error for url: ***,
|
||||||
@@ -478,6 +633,12 @@
|
|||||||
state: absent
|
state: absent
|
||||||
name: ansible_router1
|
name: ansible_router1
|
||||||
|
|
||||||
|
- name: Delete internal port 4
|
||||||
|
openstack.cloud.port:
|
||||||
|
cloud: "{{ cloud }}"
|
||||||
|
state: absent
|
||||||
|
name: ansible_internal_port4
|
||||||
|
|
||||||
- name: Delete internal port 3
|
- name: Delete internal port 3
|
||||||
openstack.cloud.port:
|
openstack.cloud.port:
|
||||||
cloud: "{{ cloud }}"
|
cloud: "{{ cloud }}"
|
||||||
|
|||||||
@@ -17,8 +17,9 @@ description:
|
|||||||
options:
|
options:
|
||||||
fixed_address:
|
fixed_address:
|
||||||
description:
|
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.
|
attached to.
|
||||||
|
aliases: ["fixed_ip_address"]
|
||||||
type: str
|
type: str
|
||||||
floating_ip_address:
|
floating_ip_address:
|
||||||
description:
|
description:
|
||||||
@@ -35,6 +36,7 @@ options:
|
|||||||
network:
|
network:
|
||||||
description:
|
description:
|
||||||
- The name or ID of a neutron external network or a nova pool name.
|
- 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
|
type: str
|
||||||
purge:
|
purge:
|
||||||
description:
|
description:
|
||||||
@@ -57,7 +59,6 @@ options:
|
|||||||
description:
|
description:
|
||||||
- The name or ID of the server to which the IP address
|
- The name or ID of the server to which the IP address
|
||||||
should be assigned.
|
should be assigned.
|
||||||
required: true
|
|
||||||
type: str
|
type: str
|
||||||
state:
|
state:
|
||||||
description:
|
description:
|
||||||
@@ -183,23 +184,24 @@ from ansible_collections.openstack.cloud.plugins.module_utils.openstack import O
|
|||||||
|
|
||||||
class NetworkingFloatingIPModule(OpenStackModule):
|
class NetworkingFloatingIPModule(OpenStackModule):
|
||||||
argument_spec = dict(
|
argument_spec = dict(
|
||||||
fixed_address=dict(),
|
fixed_address=dict(aliases=['fixed_ip_address']),
|
||||||
floating_ip_address=dict(),
|
floating_ip_address=dict(),
|
||||||
nat_destination=dict(aliases=['fixed_network', 'internal_network']),
|
nat_destination=dict(aliases=['fixed_network', 'internal_network']),
|
||||||
network=dict(),
|
network=dict(),
|
||||||
purge=dict(type='bool', default=False),
|
purge=dict(type='bool', default=False),
|
||||||
reuse=dict(type='bool', default=False),
|
reuse=dict(type='bool', default=False),
|
||||||
server=dict(required=True),
|
server=dict(),
|
||||||
state=dict(default='present', choices=['absent', 'present']),
|
state=dict(default='present', choices=['absent', 'present']),
|
||||||
)
|
)
|
||||||
|
|
||||||
module_kwargs = dict(
|
module_kwargs = dict(
|
||||||
required_if=[
|
required_if=[
|
||||||
['state', 'absent', ['floating_ip_address']]
|
['state', 'present', ['server', 'network'], True],
|
||||||
|
['state', 'absent', ['floating_ip_address'], False],
|
||||||
],
|
],
|
||||||
required_by={
|
required_by={
|
||||||
'floating_ip_address': ('network'),
|
'floating_ip_address': ('network'),
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
@@ -214,139 +216,174 @@ class NetworkingFloatingIPModule(OpenStackModule):
|
|||||||
changed = False
|
changed = False
|
||||||
fixed_address = self.params['fixed_address']
|
fixed_address = self.params['fixed_address']
|
||||||
floating_ip_address = self.params['floating_ip_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
|
network_id = self.network['id'] if self.network else None
|
||||||
|
server = self.server
|
||||||
|
|
||||||
ips = self._find_ips(
|
ips = self._find_ips(
|
||||||
server=self.server,
|
server=server,
|
||||||
floating_ip_address=floating_ip_address,
|
floating_ip_address=floating_ip_address,
|
||||||
network_id=network_id,
|
network_id=network_id,
|
||||||
fixed_address=fixed_address,
|
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 = None
|
||||||
ip = ips[0] if ips else None
|
|
||||||
|
|
||||||
if floating_ip_address:
|
if not ips:
|
||||||
# A specific floating ip address has been requested
|
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:
|
else:
|
||||||
# If a specific floating ip address has been requested
|
# No specific floating ip has been requested and none of the
|
||||||
# and it does not exist yet then create it
|
# floating ips which have been assigned to the server matches
|
||||||
|
# requirements
|
||||||
|
|
||||||
# openstacksdk's create_ip requires floating_ip_address
|
# add_ips_to_server() will handle several scenarios:
|
||||||
# and floating_network_id to be set
|
#
|
||||||
self.conn.network.create_ip(
|
# If a specific floating ip address has been requested then it
|
||||||
floating_ip_address=floating_ip_address,
|
# will be attached to the server. The floating ip address has
|
||||||
floating_network_id=network_id)
|
# 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
|
changed = True
|
||||||
|
|
||||||
else: # ip
|
else: # ips
|
||||||
# Requested floating ip address exists already
|
ip = ips[0]
|
||||||
|
|
||||||
if ip.port_details and (ip.port_details['status'] == 'ACTIVE') \
|
if server:
|
||||||
and (floating_ip_address not in self._filter_ips(
|
server_ips = self._filter_ips(server)
|
||||||
self.server)):
|
if ip.floating_ip_address not in server_ips:
|
||||||
# Floating ip address exists and has been attached
|
port_details = ip.port_details
|
||||||
# but to a different server
|
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
|
else:
|
||||||
self.fail_json(
|
# Requested floating ip address has not been
|
||||||
msg="Floating ip {0} has been attached to different "
|
# assigned to server
|
||||||
"server".format(floating_ip_address))
|
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 \
|
else:
|
||||||
or floating_ip_address not in self._filter_ips(self.server):
|
# floating ip is already assigned to the server
|
||||||
# Requested floating ip address does not exist or has not been
|
pass
|
||||||
# assigned to server
|
|
||||||
|
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:
|
else:
|
||||||
# Requested floating ip address has been assigned to server
|
kwargs = self._params_to_kwargs(
|
||||||
pass
|
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
|
if changed and server:
|
||||||
# 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:
|
|
||||||
# update server details such as addresses
|
# 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
|
# Update the floating ip resource
|
||||||
ips = self._find_ips(
|
ips = self._find_ips(
|
||||||
self.server, floating_ip_address, network_id,
|
server,
|
||||||
fixed_address, nat_destination_name_or_id)
|
floating_ip_address,
|
||||||
|
network_id,
|
||||||
|
fixed_address,
|
||||||
|
nat_destination_id
|
||||||
|
)
|
||||||
|
|
||||||
# ips can be empty, e.g. when server has no private ipv4
|
# ips can be empty, e.g. when server has no private ipv4
|
||||||
# address to which a floating ip address can be attached
|
# address to which a floating ip address can be attached
|
||||||
|
ip = ips[0] if ips else None
|
||||||
|
|
||||||
self.exit_json(
|
self.exit_json(
|
||||||
changed=changed,
|
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):
|
def _detach_and_delete(self):
|
||||||
ips = self._find_ips(
|
ips = self._find_ips(
|
||||||
@@ -354,7 +391,7 @@ class NetworkingFloatingIPModule(OpenStackModule):
|
|||||||
floating_ip_address=self.params['floating_ip_address'],
|
floating_ip_address=self.params['floating_ip_address'],
|
||||||
network_id=self.network['id'] if self.network else None,
|
network_id=self.network['id'] if self.network else None,
|
||||||
fixed_address=self.params['fixed_address'],
|
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:
|
if not ips:
|
||||||
# Nothing to detach
|
# Nothing to detach
|
||||||
@@ -362,19 +399,22 @@ class NetworkingFloatingIPModule(OpenStackModule):
|
|||||||
|
|
||||||
changed = False
|
changed = False
|
||||||
for ip in ips:
|
for ip in ips:
|
||||||
if ip['fixed_ip_address']:
|
if self.server:
|
||||||
# Silently ignore that ip might not be attached to 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()
|
# self.conn.network.update_ip(ip_id, port_id=None) does not
|
||||||
# does so
|
# handle nova network but self.conn.detach_ip_from_server()
|
||||||
self.conn.detach_ip_from_server(server_id=self.server['id'],
|
# does so
|
||||||
floating_ip_id=ip['id'])
|
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
|
# OpenStackSDK sets {"port_id": None} to detach a floating
|
||||||
# ip from a device, but there might be a delay until a
|
# ip from a device, but there might be a delay until a
|
||||||
# server does not list it in addresses any more.
|
# server does not list it in addresses any more.
|
||||||
changed = True
|
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']:
|
if self.params['purge']:
|
||||||
self.conn.network.delete_ip(ip['id'])
|
self.conn.network.delete_ip(ip['id'])
|
||||||
@@ -397,39 +437,56 @@ class NetworkingFloatingIPModule(OpenStackModule):
|
|||||||
|
|
||||||
# Returns a list not an iterator here because
|
# Returns a list not an iterator here because
|
||||||
# it is iterated several times below
|
# it is iterated several times below
|
||||||
return [address['addr']
|
addresses = _flatten(server['addresses'].values())
|
||||||
for address in _flatten(server['addresses'].values())
|
return [
|
||||||
if address['OS-EXT-IPS:type'] == 'floating']
|
address['addr']
|
||||||
|
for address in addresses
|
||||||
|
if address['OS-EXT-IPS:type'] == 'floating'
|
||||||
|
]
|
||||||
|
|
||||||
def _find_ips(self,
|
def _find_ips(self,
|
||||||
server,
|
server,
|
||||||
floating_ip_address,
|
floating_ip_address,
|
||||||
network_id,
|
network_id,
|
||||||
fixed_address,
|
fixed_address,
|
||||||
nat_destination_name_or_id):
|
nat_destination_id):
|
||||||
# Check which floating ips matches our requirements.
|
# Check which floating ips matches our requirements.
|
||||||
# They might or might not be attached to our server.
|
# They might or might not be attached to our server.
|
||||||
if floating_ip_address:
|
if floating_ip_address:
|
||||||
# A specific floating ip address has been requested
|
# A specific floating ip address has been requested
|
||||||
ip = self.conn.network.find_ip(floating_ip_address)
|
ip = self.conn.network.find_ip(floating_ip_address)
|
||||||
return [ip] if ip else []
|
return [ip] if ip else []
|
||||||
elif (not fixed_address and nat_destination_name_or_id):
|
elif server:
|
||||||
# No specific floating ip and no specific fixed ip have been
|
if (not fixed_address and nat_destination_id):
|
||||||
# requested but a private network (nat_destination) has been
|
# No specific floating ip and no specific fixed ip have been
|
||||||
# given where the floating ip should be attached to.
|
# requested but a private network (nat_destination) has been
|
||||||
return self._find_ips_by_nat_destination(
|
# given where the floating ip should be attached to.
|
||||||
server, nat_destination_name_or_id)
|
return self._find_ips_by_nat_destination(
|
||||||
else:
|
server, nat_destination_id)
|
||||||
# not floating_ip_address
|
else:
|
||||||
# and (fixed_address or not nat_destination_name_or_id)
|
# not floating_ip_address
|
||||||
|
# and (fixed_address or not nat_destination_id)
|
||||||
|
|
||||||
# An analysis of all floating ips of server is required
|
# An analysis of all floating ips of server is required
|
||||||
return self._find_ips_by_network_id_and_fixed_address(
|
return self._find_ips_by_network_id_and_fixed_address(
|
||||||
server, fixed_address, network_id)
|
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,
|
def _find_ips_by_nat_destination(self,
|
||||||
server,
|
server,
|
||||||
nat_destination_name_or_id):
|
nat_destination_id):
|
||||||
|
|
||||||
if not server['addresses']:
|
if not server['addresses']:
|
||||||
return None
|
return None
|
||||||
@@ -437,7 +494,7 @@ class NetworkingFloatingIPModule(OpenStackModule):
|
|||||||
# Check if we have any floating ip on
|
# Check if we have any floating ip on
|
||||||
# the given nat_destination network
|
# the given nat_destination network
|
||||||
nat_destination = self.conn.network.find_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 = [
|
fips_with_nat_destination = [
|
||||||
addr for addr
|
addr for addr
|
||||||
@@ -467,7 +524,7 @@ class NetworkingFloatingIPModule(OpenStackModule):
|
|||||||
# match network of floating ip
|
# match network of floating ip
|
||||||
continue
|
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
|
# Any floating ip will fullfil these requirements
|
||||||
matching_ips.append(ip)
|
matching_ips.append(ip)
|
||||||
|
|
||||||
@@ -478,20 +535,84 @@ class NetworkingFloatingIPModule(OpenStackModule):
|
|||||||
|
|
||||||
return matching_ips
|
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):
|
def _init(self):
|
||||||
server_name_or_id = self.params['server']
|
server_name_or_id = self.params['server']
|
||||||
server = self.conn.compute.find_server(server_name_or_id,
|
if server_name_or_id:
|
||||||
ignore_missing=False)
|
self.server = self.conn.compute.find_server(
|
||||||
# fetch server details such as addresses
|
name_or_id=server_name_or_id, ignore_missing=False
|
||||||
self.server = self.conn.compute.get_server(server)
|
)
|
||||||
|
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']
|
network_name_or_id = self.params['network']
|
||||||
if network_name_or_id:
|
if network_name_or_id:
|
||||||
self.network = self.conn.network.find_network(
|
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:
|
else:
|
||||||
self.network = None
|
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():
|
def main():
|
||||||
module = NetworkingFloatingIPModule()
|
module = NetworkingFloatingIPModule()
|
||||||
|
|||||||
Reference in New Issue
Block a user