From 9272146cf7a7486f6004b52bec420a998e710f45 Mon Sep 17 00:00:00 2001 From: Sagi Shnaidman Date: Wed, 19 Jan 2022 12:24:08 +0200 Subject: [PATCH] Change network modules to work with new SDK Change-Id: I7625d696f6462a7a955008a5c7276f1548acbc2e --- .zuul.yaml | 2 +- ci/roles/floating_ip/tasks/main.yml | 6 +- ci/roles/network/defaults/main.yml | 34 ++++- ci/roles/network/tasks/main.yml | 64 +++++++--- plugins/modules/network.py | 186 ++++++++++++++++------------ plugins/modules/networks_info.py | 119 +++++++++++++----- 6 files changed, 275 insertions(+), 136 deletions(-) diff --git a/.zuul.yaml b/.zuul.yaml index 47b8a48f..2ad67083 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -86,6 +86,7 @@ keystone_idp keystone_mapping loadbalancer + network nova_flavor nova_services object @@ -102,7 +103,6 @@ # failing tags # floating_ip # orchestrate - # network # neutron_rbac # router # server diff --git a/ci/roles/floating_ip/tasks/main.yml b/ci/roles/floating_ip/tasks/main.yml index e724a8cb..df324778 100644 --- a/ci/roles/floating_ip/tasks/main.yml +++ b/ci/roles/floating_ip/tasks/main.yml @@ -8,7 +8,7 @@ - name: Assert that public network exists assert: - that: public_network.openstack_networks|length == 1 + that: public_network.networks|length == 1 - name: Create external network openstack.cloud.network: @@ -120,7 +120,7 @@ - name: Check if public network has any floating ips set_fact: public_network_had_fips: "{{ fips.floating_ips| - selectattr('floating_network_id', '==', public_network.openstack_networks.0.id)| + selectattr('floating_network_id', '==', public_network.networks.0.id)| list|length > 0 }}" # TODO: Replace with appropriate Ansible module once available @@ -371,7 +371,7 @@ when: not public_network_had_fips command: > openstack --os-cloud={{ cloud }} floating ip delete - {{ fips.floating_ips|selectattr('floating_network_id', '==', public_network.openstack_networks.0.id)| + {{ fips.floating_ips|selectattr('floating_network_id', '==', public_network.networks.0.id)| map(attribute="floating_ip_address")|list|join(' ') }} # TODO: Replace with appropriate Ansible module once available diff --git a/ci/roles/network/defaults/main.yml b/ci/roles/network/defaults/main.yml index d049736a..8b592206 100644 --- a/ci/roles/network/defaults/main.yml +++ b/ci/roles/network/defaults/main.yml @@ -1,7 +1,35 @@ +expected_fields: + - availability_zone_hints + - availability_zones + - created_at + - description + - dns_domain + - id + - ipv4_address_scope_id + - ipv6_address_scope_id + - is_admin_state_up + - is_default + - is_port_security_enabled + - is_router_external + - is_shared + - is_vlan_transparent + - mtu + - name + - project_id + - provider_network_type + - provider_physical_network + - provider_segmentation_id + - qos_policy_id + - revision_number + - segments + - status + - subnet_ids + - tags + - updated_at +dns_domain: example.opendev.org +mtu: 1250 +network_external: false network_name: shade_network network_name_newparams: newparams_network network_shared: false -network_external: false -dns_domain: example.opendev.org -mtu: 1250 port_security_enabled: false diff --git a/ci/roles/network/tasks/main.yml b/ci/roles/network/tasks/main.yml index f770d186..60078f16 100644 --- a/ci/roles/network/tasks/main.yml +++ b/ci/roles/network/tasks/main.yml @@ -6,6 +6,28 @@ state: present shared: "{{ network_shared }}" external: "{{ network_external }}" + register: infonet + +- name: Check output of creating network + assert: + that: + - infonet.network + - item in infonet.network + loop: "{{ expected_fields }}" + +- name: Gather networks info + openstack.cloud.networks_info: + cloud: "{{ cloud }}" + name: "{{ infonet.network.id }}" + register: result + +- name: Check output of network info + # TODO: Remove ignore_errors once SDK's search_networks() (re)implemented searching by id + ignore_errors: yes + assert: + that: + - result.networks|length == 1 + - infonet.network.id == result.networks[0].id - name: Gather networks info - generic openstack.cloud.networks_info: @@ -15,12 +37,28 @@ shared: "{{ network_shared|string|capitalize }}" register: result +- name: Check output of network info + assert: + that: + - item in result.networks[0] + loop: "{{ expected_fields }}" + +- name: Gather networks info + openstack.cloud.networks_info: + cloud: "{{ cloud }}" + name: "{{ network_name }}" + filters: + shared: "False" + register: result + - name: Verify networks info - generic assert: that: - - result.openstack_networks.0.name == network_name - - (result.openstack_networks.0.shared|lower) == (network_shared|lower) - - result.openstack_networks[0]['router:external'] == {{ network_external }} + - result.networks.0.name == network_name + - "'is_shared' in result.networks.0" + - result.networks.0['is_shared']|lower == network_shared|lower + - "'is_router_external' in result.networks.0" + - result.networks[0]['is_router_external'] == {{ network_external }} - name: Create network - with new SDK params openstack.cloud.network: @@ -32,29 +70,21 @@ mtu: "{{ mtu }}" port_security_enabled: "{{ port_security_enabled }}" register: result_create_nw_with_new_params - ignore_errors: yes - -- name: Check errors below min sdk version - with new SDK params - assert: - that: - - result_create_nw_with_new_params.failed - - '"the installed version of the openstacksdk library MUST be >=0.18.0." in result_create_nw_with_new_params.msg' - when: sdk_version is version('0.18', '<') + ignore_errors: true - name: Gather networks info - with new SDK params openstack.cloud.networks_info: cloud: "{{ cloud }}" name: "{{ network_name_newparams }}" register: result_newparams - when: sdk_version is version('0.18', '>=') - name: Verify networks info - with new SDK params assert: that: - - result_newparams.openstack_networks.0.name == network_name_newparams - - result_newparams.openstack_networks.0.mtu == mtu - - result_newparams.openstack_networks.0.port_security_enabled == port_security_enabled - when: sdk_version is version('0.18', '>=') + - result_newparams.networks.0.name == network_name_newparams + - result_newparams.networks.0.mtu == mtu + - "'is_port_security_enabled' in result_newparams.networks.0" + - result_newparams.networks.0['is_port_security_enabled'] == port_security_enabled - name: Delete network - generic and with new SDK params openstack.cloud.network: @@ -74,4 +104,4 @@ - name: Verify networks info - deleted assert: that: - - result_nonet.openstack_networks == [] + - result_nonet.networks == [] diff --git a/plugins/modules/network.py b/plugins/modules/network.py index 780d49ba..a1058508 100644 --- a/plugins/modules/network.py +++ b/plugins/modules/network.py @@ -10,7 +10,7 @@ module: network short_description: Creates/removes networks from OpenStack author: OpenStack Ansible SIG description: - - Add or remove network from OpenStack. + - Add or remove network from OpenStack (doesn't update network properties). options: name: description: @@ -61,18 +61,18 @@ options: description: - Whether port security is enabled on the network or not. Network will use OpenStack defaults if this option is - not utilised. Requires openstacksdk>=0.18. + not utilised. type: bool - mtu_size: + mtu: description: - The maximum transmission unit (MTU) value to address fragmentation. Network will use OpenStack defaults if this option is - not provided. Requires openstacksdk>=0.18. + not provided. type: int - aliases: ['mtu'] + aliases: ['mtu_size'] dns_domain: description: - - The DNS domain value to set. Requires openstacksdk>=0.29. + - The DNS domain value to set. Network will use Openstack defaults if this option is not provided. type: str @@ -94,67 +94,96 @@ EXAMPLES = ''' ''' RETURN = ''' +id: + description: Id of network + returned: On success when network exists. + type: str network: description: Dictionary describing the network. - returned: On success when I(state) is 'present'. - type: complex + returned: On success when network exists. + type: dict contains: - id: - description: Network ID. + availability_zone_hints: + description: Availability zone hints type: str - sample: "4bb4f9a5-3bd2-4562-bf6a-d17a6341bb56" - name: - description: Network name. + availability_zones: + description: Availability zones type: str - sample: "ext_network" - shared: - description: Indicates whether this network is shared across all tenants. - type: bool - sample: false - status: - description: Network status. + created_at: + description: Created at timestamp + type: str + description: + description: Description type: str - sample: "ACTIVE" - mtu: - description: The MTU of a network resource. - type: int - sample: 0 dns_domain: - description: The DNS domain of a network resource. + description: Dns domain type: str - sample: "sample.openstack.org." - admin_state_up: - description: The administrative state of the network. - type: bool - sample: true - port_security_enabled: - description: The port security status - type: bool - sample: true - router:external: - description: Indicates whether this network is externally accessible. - type: bool - sample: true - tenant_id: - description: The tenant ID. + id: + description: Id type: str - sample: "06820f94b9f54b119636be2728d216fc" - subnets: - description: The associated subnets. - type: list - sample: [] - "provider:physical_network": - description: The physical network where this network object is implemented. + ipv4_address_scope_id: + description: Ipv4 address scope id type: str - sample: my_vlan_net - "provider:network_type": - description: The type of physical network that maps to this network resource. + ipv6_address_scope_id: + description: Ipv6 address scope id type: str - sample: vlan - "provider:segmentation_id": - description: An isolated segment on the physical network. + is_admin_state_up: + description: Is admin state up + type: str + is_default: + description: Is default + type: str + is_port_security_enabled: + description: Is port security enabled + type: str + is_router_external: + description: Is router external + type: str + is_shared: + description: Is shared + type: str + is_vlan_transparent: + description: Is vlan transparent + type: str + mtu: + description: Mtu + type: str + name: + description: Name + type: str + project_id: + description: Project id + type: str + provider_network_type: + description: Provider network type + type: str + provider_physical_network: + description: Provider physical network + type: str + provider_segmentation_id: + description: Provider segmentation id + type: str + qos_policy_id: + description: Qos policy id + type: str + revision_number: + description: Revision number + type: str + segments: + description: Segments + type: str + status: + description: Status + type: str + subnet_ids: + description: Subnet ids + type: str + tags: + description: Tags + type: str + updated_at: + description: Updated at timestamp type: str - sample: 101 ''' from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule @@ -172,9 +201,9 @@ class NetworkModule(OpenStackModule): provider_segmentation_id=dict(required=False, type='int'), state=dict(default='present', choices=['absent', 'present']), project=dict(default=None), - port_security_enabled=dict(type='bool', min_ver='0.18.0'), - mtu_size=dict(required=False, type='int', min_ver='0.18.0', aliases=['mtu']), - dns_domain=dict(required=False, min_ver='0.29.0') + port_security_enabled=dict(type='bool'), + mtu=dict(required=False, type='int', aliases=['mtu_size']), + dns_domain=dict(required=False) ) def run(self): @@ -189,41 +218,38 @@ class NetworkModule(OpenStackModule): provider_segmentation_id = self.params['provider_segmentation_id'] project = self.params['project'] - kwargs = self.check_versioned( - mtu_size=self.params['mtu_size'], port_security_enabled=self.params['port_security_enabled'], - dns_domain=self.params['dns_domain'] - ) + kwargs = {} + for arg in ('port_security_enabled', 'mtu', 'dns_domain'): + if self.params[arg] is not None: + kwargs[arg] = self.params[arg] if project is not None: - proj = self.conn.get_project(project) - if proj is None: - self.fail_json(msg='Project %s could not be found' % project) + proj = self.conn.identity.find_project(project, ignore_missing=False) project_id = proj['id'] - filters = {'tenant_id': project_id} + net_kwargs = {'project_id': project_id} else: project_id = None - filters = None - net = self.conn.get_network(name, filters=filters) + net_kwargs = {} + net = self.conn.network.find_network(name, **net_kwargs) if state == 'present': if not net: - provider = {} if provider_physical_network: - provider['physical_network'] = provider_physical_network + kwargs['provider_physical_network'] = provider_physical_network if provider_network_type: - provider['network_type'] = provider_network_type + kwargs['provider_network_type'] = provider_network_type if provider_segmentation_id: - provider['segmentation_id'] = provider_segmentation_id + kwargs['provider_segmentation_id'] = provider_segmentation_id if project_id is not None: - net = self.conn.create_network(name, shared, admin_state_up, - external, provider, project_id, - **kwargs) - else: - net = self.conn.create_network(name, shared, admin_state_up, - external, provider, - **kwargs) + kwargs['project_id'] = project_id + net = self.conn.network.create_network(name=name, + shared=shared, + admin_state_up=admin_state_up, + is_router_external=external, + **kwargs) changed = True + net = net.to_dict(computed=False) else: changed = False self.exit(changed=changed, network=net, id=net['id']) @@ -232,7 +258,7 @@ class NetworkModule(OpenStackModule): if not net: self.exit(changed=False) else: - self.conn.delete_network(name) + self.conn.network.delete_network(net['id']) self.exit(changed=True) diff --git a/plugins/modules/networks_info.py b/plugins/modules/networks_info.py index 251af3e7..669fcdcf 100644 --- a/plugins/modules/networks_info.py +++ b/plugins/modules/networks_info.py @@ -44,7 +44,7 @@ EXAMPLES = ''' - name: Show openstack networks debug: - msg: "{{ result.openstack_networks }}" + msg: "{{ result.networks }}" - name: Gather information about a previously created network by name openstack.cloud.networks_info: @@ -58,7 +58,7 @@ EXAMPLES = ''' - name: Show openstack networks debug: - msg: "{{ result.openstack_networks }}" + msg: "{{ result.networks }}" - name: Gather information about a previously created network with filter # Note: name and filters parameters are Not mutually exclusive @@ -77,40 +77,97 @@ EXAMPLES = ''' - name: Show openstack networks debug: - msg: "{{ result.openstack_networks }}" + msg: "{{ result.networks }}" ''' RETURN = ''' -openstack_networks: +networks: description: has all the openstack information about the networks - returned: always, but can be null - type: complex + returned: always, but can be empty list + type: list + elements: dict contains: + availability_zone_hints: + description: Availability zone hints + type: str + availability_zones: + description: Availability zones + type: str + created_at: + description: Created at timestamp + type: str + description: + description: Description + type: str + dns_domain: + description: Dns domain + type: str id: - description: Unique UUID. - returned: success + description: Id + type: str + ipv4_address_scope_id: + description: Ipv4 address scope id + type: str + ipv6_address_scope_id: + description: Ipv6 address scope id + type: str + is_admin_state_up: + description: Is admin state up + type: str + is_default: + description: Is default + type: str + is_port_security_enabled: + description: Is port security enabled + type: str + is_router_external: + description: Is router external + type: str + is_shared: + description: Is shared + type: str + is_vlan_transparent: + description: Is vlan transparent + type: str + mtu: + description: Mtu type: str name: - description: Name given to the network. - returned: success + description: Name + type: str + project_id: + description: Project id + type: str + provider_network_type: + description: Provider network type + type: str + provider_physical_network: + description: Provider physical network + type: str + provider_segmentation_id: + description: Provider segmentation id + type: str + qos_policy_id: + description: Qos policy id + type: str + revision_number: + description: Revision number + type: str + segments: + description: Segments type: str status: - description: Network status. - returned: success + description: Status type: str - subnets: - description: Subnet(s) included in this network. - returned: success - type: list - elements: str - tenant_id: - description: Tenant id associated with this network. - returned: success + subnet_ids: + description: Subnet ids + type: str + tags: + description: Tags + type: str + updated_at: + description: Updated at timestamp type: str - shared: - description: Network shared flag. - returned: success - type: bool ''' from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule @@ -129,15 +186,13 @@ class NetworkInfoModule(OpenStackModule): ) def run(self): - - kwargs = self.check_versioned( - filters=self.params['filters'] - ) - if self.params['name']: - kwargs['name_or_id'] = self.params['name'] + kwargs = { + 'filters': self.params['filters'], + 'name_or_id': self.params['name'] + } networks = self.conn.search_networks(**kwargs) - - self.exit(changed=False, openstack_networks=networks) + networks = [i.to_dict(computed=False) for i in networks] + self.exit(changed=False, networks=networks) def main():