Files
ansible-collections-openstack/ci/roles/server/tasks/main.yml
Jakob Meng a660a35d86 Replaced expensive get_server() and fixed issues in server module
openstacksdk's get_server() [1] calls add_server_interfaces() [2]
which queries OpenStack APIs several times to get all ports and
floating ips attached to a server.

Now we call openstacksdk's compute.find_server() [3] and compute.\
get_server() [4] which result in two API calls, in order to fill
server['addresses'] attribute which we later use to get floating ip
addresses attached to the server.

Do an extra call to compute.get_server() in order to return a pristine
server resource, because openstacksdk's create_server() might call
meta.add_server_interfaces() which alters server attributes such as
server['addresses'] [5].

Fail if options 'auto_ip', 'floating_ips' or 'floating_ip_pools'
are specified but 'wait' is not set to true, because openstacksdk
will add floating ip addresses only if we wait until the server
has been created [6]. This conditional fail will help users to not
shoot their foot.

Marked floating ip support unstable in this module due to various
unresolved issues in openstacksdk's add_ips_to_server() function
such as [9] and [10].

For Zuul CI job ansible-collections-openstack-functional-devstack-\
releases to pass, the minimum required openstacksdk release must be
0.101.0 because [7],[8] are available since that release only.

[1] 3f81d0001d/openstack/cloud/_compute.py (L484)
[2] 3f81d0001d/openstack/cloud/meta.py (L439)
[3] 3f81d0001d/openstack/compute/v2/_proxy.py (L652)
[4] 3f81d0001d/openstack/compute/v2/_proxy.py (L666)
[5] 3f81d0001d/openstack/cloud/_compute.py (L942)
[6] 3f81d0001d/openstack/cloud/_compute.py (L945)
[7] https://review.opendev.org/c/openstack/openstacksdk/+/851976
[8] 0ded7ac398
[9] https://storyboard.openstack.org/#!/story/2010352
[10] https://storyboard.openstack.org/#!/story/2010153

Change-Id: I6a5663433b1b9529f99d5eced22a28c692a1d288
2022-10-06 21:30:15 +02:00

601 lines
16 KiB
YAML

---
- name: Create network for server
openstack.cloud.network:
cloud: "{{ cloud }}"
name: "{{ server_network }}"
state: present
register: network
- name: Create subnet for server
openstack.cloud.subnet:
cidr: 192.168.0.0/24
cloud: "{{ cloud }}"
name: "{{ server_subnet }}"
network_name: "{{ server_network }}"
state: present
register: subnet
- name: Create second network for server
openstack.cloud.network:
cloud: "{{ cloud }}"
name: "{{ server_alt_network }}"
state: present
- name: Create second subnet for server
openstack.cloud.subnet:
cidr: 192.168.1.0/24
cloud: "{{ cloud }}"
name: "{{ server_alt_subnet }}"
network_name: "{{ server_alt_network }}"
state: present
- name: Create router 1 (for attaching floating ips)
openstack.cloud.router:
cloud: "{{ cloud }}"
state: present
name: ansible_router1
network: public
interfaces:
- net: "{{ server_network }}"
subnet: "{{ server_subnet }}"
- net: "{{ server_alt_network }}"
subnet: "{{ server_alt_subnet }}"
- name: Create security group for server
openstack.cloud.security_group:
cloud: "{{ cloud }}"
state: present
name: "{{ server_security_group }}"
register: security_group
- name: Create second security group for server
openstack.cloud.security_group:
cloud: "{{ cloud }}"
state: present
name: "{{ server_alt_security_group }}"
register: security_group_alt
- name: Create server with meta as CSV
openstack.cloud.server:
cloud: "{{ cloud }}"
state: present
name: "{{ server_name }}"
image: "{{ image }}"
flavor: "{{ flavor }}"
network: "{{ server_network }}"
auto_ip: false
metadata: "key1=value1,key2=value2"
wait: true
register: server
- debug: var=server
- name: assert return values of server module
assert:
that:
# allow new fields to be introduced but prevent fields from being removed
- expected_fields|difference(server.server.keys())|length == 0
- name: Assert server
assert:
that:
- server.server.name == server_name
- server.server.metadata.keys()|sort == ['key1', 'key2']
- server.server.metadata['key1'] == 'value1'
- server.server.metadata['key2'] == 'value2'
- server_network in server.server.addresses
- server.server.security_groups|map(attribute='name')|list == ['default']
- name: Get info about all servers
openstack.cloud.server_info:
cloud: "{{ cloud }}"
register: info
- name: Check info about servers
assert:
that:
- info.servers|length > 0
# allow new fields to be introduced but prevent fields from being removed
- expected_fields|difference(info.servers[0].keys())|length == 0
- name: Delete server with meta as CSV
openstack.cloud.server:
cloud: "{{ cloud }}"
state: absent
name: "{{ server_name }}"
wait: true
- name: Get info about all servers
openstack.cloud.server_info:
cloud: "{{ cloud }}"
register: info
- name: Check info about no servers
assert:
that:
- info.servers|length == 0
- name: Create server with meta as dict
openstack.cloud.server:
cloud: "{{ cloud }}"
state: present
name: "{{ server_name }}"
image: "{{ image }}"
flavor: "{{ flavor }}"
auto_ip: false
network: "{{ server_network }}"
metadata:
key1: value1
key2: value2
wait: true
register: server
- debug: var=server
- name: Get info about one server
openstack.cloud.server_info:
cloud: "{{ cloud }}"
server: "{{ server_name }}"
register: info
- name: Check info about server name
assert:
that:
- info.servers[0].name == "{{ server_name }}"
- info.servers[0].id == server.server.id
- name: Filter servers
openstack.cloud.server_info:
cloud: "{{ cloud }}"
filters:
id: "{{ server.server.id }}"
metadata:
key1: value1
key2: value2
register: info
- name: Check filter results
assert:
that: info.servers|map(attribute='id')|list == [server.server.id]
- name: Filter servers with partial data
openstack.cloud.server_info:
cloud: "{{ cloud }}"
filters:
id: "{{ server.server.id }}"
metadata:
key1: value1
# intentially left out parts of metadata here
register: info
- name: Check filter results
assert:
that: info.servers|map(attribute='id')|list == [server.server.id]
- name: Filter servers which should not return results
openstack.cloud.server_info:
cloud: "{{ cloud }}"
filters:
id: "THIS_IS_NOT_A_VALID_ID"
register: info
- name: Check filter results
assert:
that: info.servers|length == 0
- name: Delete server with meta as dict
openstack.cloud.server:
cloud: "{{ cloud }}"
state: absent
name: "{{ server_name }}"
wait: true
- name: Create server (FIP from pool/network)
openstack.cloud.server:
cloud: "{{ cloud }}"
state: present
name: "{{ server_name }}"
image: "{{ image }}"
flavor: "{{ flavor }}"
network: "private"
floating_ip_pools:
- "{{ floating_ip_pool_name }}"
wait: true
register: server
- debug: var=server
- name: Get detailed info about one server
openstack.cloud.server_info:
cloud: "{{ cloud }}"
server: "{{ server_name }}"
detailed: true
register: info
# TODO: Drop ignore_errors once openstacksdk's bug #2010135 has been solved.
# Ref.: https://storyboard.openstack.org/#!/story/2010135
ignore_errors: yes
- name: Check info about server image name
assert:
that:
- info.servers[0].image.name == "{{ image }}"
# TODO: Drop ignore_errors once openstacksdk's bug #2010135 has been solved.
# Ref.: https://storyboard.openstack.org/#!/story/2010135
ignore_errors: yes
- name: Delete server (FIP from pool/network)
openstack.cloud.server:
cloud: "{{ cloud }}"
state: absent
name: "{{ server_name }}"
wait: true
- name: Create server from volume
openstack.cloud.server:
cloud: "{{ cloud }}"
state: present
name: "{{ server_name }}"
image: "{{ image }}"
flavor: "{{ flavor }}"
network: "{{ server_network }}"
auto_ip: false
boot_from_volume: true
volume_size: "{{ boot_volume_size }}"
terminate_volume: true
wait: true
register: server
- debug: var=server
- name: Delete server with volume
openstack.cloud.server:
cloud: "{{ cloud }}"
state: absent
name: "{{ server_name }}"
wait: true
- name: Create a minimal server
openstack.cloud.server:
cloud: "{{ cloud }}"
state: present
name: "{{ server_name }}"
image: "{{ image }}"
flavor: "{{ flavor }}"
network: "{{ server_network }}"
auto_ip: false
wait: true
register: server
- debug: var=server
- name: Get info about servers in all projects
openstack.cloud.server_info:
cloud: "{{ cloud }}"
all_projects: true
register: info
- name: Check info about servers in all projects
assert:
that: info.servers|length > 0
- name: Get info about one server in all projects
openstack.cloud.server_info:
cloud: "{{ cloud }}"
server: "{{ server_name }}"
all_projects: true
register: info
- name: Check info about one server in all projects
assert:
that: info.servers|length > 0
- name: Delete minimal server
openstack.cloud.server:
cloud: "{{ cloud }}"
state: absent
name: "{{ server_name }}"
wait: true
- name: Create server on private network with auto_ip
openstack.cloud.server:
auto_ip: true
cloud: "{{ cloud }}"
flavor: "{{ flavor }}"
image: "{{ image }}"
name: "{{ server_name }}"
nics:
- net-name: "{{ server_network }}"
reuse_ips: false
state: present
wait: true
register: server
- name: Assert server on private network with auto_ip
assert:
that:
- server.server.addresses.values()
|flatten(levels=1)
|selectattr('OS-EXT-IPS:type', 'equalto', 'floating')
|map(attribute='addr')
|list|length == 1
- name: Delete server on private network with auto_ip
openstack.cloud.server:
cloud: "{{ cloud }}"
state: absent
name: "{{ server_name }}"
wait: true
- name: Create server on public network
openstack.cloud.server:
auto_ip: false
cloud: "{{ cloud }}"
flavor: "{{ flavor }}"
image: "{{ image }}"
name: "{{ server_name }}"
nics:
- net-name: 'public'
reuse_ips: false
state: present
wait: true
register: server
- debug: var=server
- name: Assert server on public network
assert:
that:
- server.server.addresses.values()
|flatten(levels=1)
|selectattr('OS-EXT-IPS:type', 'equalto', 'floating')
|map(attribute='addr')
|list|length == 0
- name: Delete server on public network
openstack.cloud.server:
cloud: "{{ cloud }}"
state: absent
name: "{{ server_name }}"
wait: true
- name: Create port to be attached to server
openstack.cloud.port:
cloud: "{{ cloud }}"
state: present
name: "{{ server_port }}"
network: "{{ server_network }}"
no_security_groups: yes
fixed_ips:
- ip_address: 192.168.0.42
register: port
- name: Create server which will be updated
openstack.cloud.server:
auto_ip: false
cloud: "{{ cloud }}"
# TODO: Uncomment once openstacksdk with support for
# description parameter has been released to PyPI.
# Ref.: https://review.opendev.org/c/openstack/openstacksdk/+/850671
#description: "This is a server"
flavor: "{{ flavor }}"
image: "{{ image }}"
metadata:
key1: value1
key2: value2
name: "{{ server_name }}"
nics:
- net-name: "{{ server_network }}"
- port-id: "{{ port.port.id }}"
reuse_ips: false
state: present
wait: true
register: server
- debug: var=server
- name: Assert server is not on public network and does not have a floating ip
assert:
that:
- server.server.addresses.keys()|sort == [server_network]|sort
- server.server.addresses.values()
|flatten(levels=1)
|selectattr('OS-EXT-IPS:type', 'equalto', 'floating')
|map(attribute='addr')
|list|length == 0
- name: Find all floating ips for debugging
openstack.cloud.floating_ip_info:
cloud: "{{ cloud }}"
register: fips
- name: Print all floating ips for debugging
debug: var=fips
- name: Find all servers for debugging
openstack.cloud.server_info:
cloud: "{{ cloud }}"
register: servers
- name: Print all servers for debugging
debug: var=servers
- name: Update server
openstack.cloud.server:
# TODO: Change auto_ip to true once openstacksdk's issue #2010352 has been solved
# Ref.: https://storyboard.openstack.org/#!/story/2010352
auto_ip: false
cloud: "{{ cloud }}"
description: "This server got updated"
# flavor cannot be updated but must be present
flavor: "{{ flavor }}"
# image cannot be updated but must be present
image: "{{ image }}"
metadata:
key2: value2
key3: value3
name: "{{ server_name }}"
# nics cannot be updated
nics:
- net-name: "{{ server_network }}"
- port-id: "{{ port.port.id }}"
reuse_ips: false
security_groups:
- '{{ server_security_group }}'
- '{{ server_alt_security_group }}'
state: present
wait: true
register: server_updated
- debug: var=server_updated
- name: Assert updated server
assert:
that:
- server.server.id == server_updated.server.id
- server_updated is changed
- server_updated.server.description == "This server got updated"
- "'key1' not in server_updated.server.metadata"
- server_updated.server.metadata['key2'] == 'value2'
- server_updated.server.metadata['key3'] == 'value3'
- server_updated.server.security_groups|map(attribute='name')|unique|length == 2
- security_group.secgroup.name in server_updated.server.security_groups|map(attribute='name')
- security_group_alt.secgroup.name in server_updated.server.security_groups|map(attribute='name')
- server_network in server_updated.server.addresses.keys()|list|sort
- server_updated.server.addresses[server_network]|length == 2
- port.port.fixed_ips[0].ip_address in
server_updated.server.addresses[server_network]|map(attribute='addr')
# TODO: Verify networks once openstacksdk's issue #2010352 has been solved
# Ref.: https://storyboard.openstack.org/#!/story/2010352
#- server_updated.server.addresses.public|length > 0
#- (server_updated.server.addresses.keys()|sort == ([server_network, 'public']|sort))
# or (server_updated.server.addresses.values()
# |flatten(levels=1)
# |selectattr('OS-EXT-IPS:type', 'equalto', 'floating')
# |map(attribute='addr')
# |list|length > 0)
- name: Update server again
openstack.cloud.server:
# TODO: Change auto_ip to true once openstacksdk's issue #2010352 has been solved
# Ref.: https://storyboard.openstack.org/#!/story/2010352
auto_ip: false
cloud: "{{ cloud }}"
description: "This server got updated"
# flavor cannot be updated but must be present
flavor: "{{ flavor }}"
# image cannot be updated but must be present
image: "{{ image }}"
metadata:
key2: value2
key3: value3
name: "{{ server_name }}"
# nics cannot be updated
nics:
- net-name: "{{ server_network }}"
- port-id: "{{ port.port.id }}"
reuse_ips: false
security_groups:
- '{{ server_security_group }}'
- '{{ server_alt_security_group }}'
state: present
wait: true
register: server_updated_again
- name: Assert server did not change
assert:
that:
- server.server.id == server_updated_again.server.id
- server_updated_again is not changed
# TODO: Drop failure test once openstacksdk's issue #2010352 has been solved
# Ref.: https://storyboard.openstack.org/#!/story/2010352
- name: Update server again with auto_ip set to true
openstack.cloud.server:
auto_ip: true
cloud: "{{ cloud }}"
description: "This server got updated"
# flavor cannot be updated but must be present
flavor: "{{ flavor }}"
# image cannot be updated but must be present
image: "{{ image }}"
metadata:
key2: value2
key3: value3
name: "{{ server_name }}"
# nics cannot be updated
nics:
- net-name: "{{ server_network }}"
- port-id: "{{ port.port.id }}"
reuse_ips: false
security_groups:
- '{{ server_security_group }}'
- '{{ server_alt_security_group }}'
state: present
wait: true
register: server_updated_again
ignore_errors: true
- name: Assert server update succeeded or failed with expected error
assert:
that:
- not server_updated_again.failed
or ('was found matching your NAT destination network' in server_updated_again.msg)
- name: Delete updated server
openstack.cloud.server:
cloud: "{{ cloud }}"
delete_ips: yes
name: "{{ server_name }}"
state: absent
wait: true
- name: Delete port which was attached to server
openstack.cloud.port:
cloud: "{{ cloud }}"
state: absent
name: "{{ server_port }}"
- name: Delete second security group for server
openstack.cloud.security_group:
cloud: "{{ cloud }}"
state: absent
name: "{{ server_alt_security_group }}"
- name: Delete security group for server
openstack.cloud.security_group:
cloud: "{{ cloud }}"
state: absent
name: "{{ server_security_group }}"
- name: Delete router 1
openstack.cloud.router:
cloud: "{{ cloud }}"
state: absent
name: ansible_router1
- name: Delete second subnet for server
openstack.cloud.subnet:
cloud: "{{ cloud }}"
state: absent
name: "{{ server_alt_subnet }}"
- name: Delete second network for server
openstack.cloud.network:
cloud: "{{ cloud }}"
state: absent
name: "{{ server_alt_network }}"
- name: Delete subnet for server
openstack.cloud.subnet:
cloud: "{{ cloud }}"
state: absent
name: "{{ server_subnet }}"
- name: Delete network for server
openstack.cloud.network:
cloud: "{{ cloud }}"
state: absent
name: "{{ server_network }}"
- import_tasks: server_actions.yml