Files
openstack-ansible-plugins/plugins/action/provider_networks
Dmitriy Rabotyagov 4ce9e713ce Make plugins usable as part of collection
Since we're converting plugins repo to collection, we make plugins
usable from collection. For that we change repo structure.

Symlinks to old destinations are created for backwards compatability

Change-Id: I15b4a9f50910794c11b57457f9f4fbb34f321654
2022-01-12 13:41:09 +00:00

369 lines
12 KiB
Python

#!/usr/bin/python
# (c) 2014, Kevin Carter <kevin.carter@rackspace.com>
#
# Copyright 2014, Rackspace US, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# import module snippets
from ansible.module_utils.basic import *
DOCUMENTATION = """
---
module: provider_networks
version_added: "1.8.6"
short_description:
- Parse a list of networks and return data that Ansible can use
description:
- Parse a list of networks and return data that Ansible can use
options:
provider_networks:
description:
- List of networks to parse
required: true
is_metal:
description:
- Enable handling of on metal hosts
required: false
bind_prefix:
description:
- Add a prefix to all network interfaces.
required: false
author: Kevin Carter
"""
EXAMPLES = """
## This is what the provider_networks list should look like.
# provider_networks:
# - network:
# container_bridge: "br-mgmt"
# container_type: "veth"
# container_interface: "eth1"
# ip_from_q: "container"
# type: "raw"
# group_binds:
# - all_containers
# - hosts
# is_container_address: true
# is_ssh_address: true
# - network:
# container_bridge: "br-vxlan"
# container_type: "veth"
# container_interface: "eth10"
# ip_from_q: "tunnel"
# type: "vxlan"
# range: "1:1000"
# net_name: "vxlan"
# group_binds:
# - neutron_linuxbridge_agent
# - network:
# container_bridge: "br-vxlan"
# container_type: "veth"
# container_interface: "eth10"
# ip_from_q: "tunnel"
# type: "geneve"
# range: "1:1000"
# net_name: "geneve"
# group_binds:
# - neutron_ovn_northd
# - neutron_ovn_controller
# - network:
# container_bridge: "br-vlan"
# container_type: "veth"
# container_interface: "eth12"
# host_bind_override: "eth12"
# type: "flat"
# net_name: "flat"
# group_binds:
# - neutron_linuxbridge_agent
# - network:
# container_bridge: "br-vlan"
# container_type: "veth"
# container_interface: "eth11"
# host_bind_override: "eth11"
# sriov_host_interfaces: "p1p1,p1p2"
# type: "vlan"
# range: "1:1, 101:101"
# net_name: "vlan"
# group_binds:
# - neutron_linuxbridge_agent
# - network:
# container_bridge: "br-provider"
# container_type: "veth"
# container_interface: "eth11"
# network_interface: "bond1"
# type: "vlan"
# range: "1:1, 101:101"
# net_name: "physnet1"
# group_binds:
# - neutron_openvswitch_agent
# - network:
# container_bridge: "br-storage"
# container_type: "veth"
# container_interface: "eth2"
# ip_from_q: "storage"
# type: "raw"
# group_binds:
# - glance_api
# - cinder_api
# - cinder_volume
# - nova_compute
# - swift_proxy
- name: Test provider networks
provider_networks:
provider_networks: "{{ provider_networks }}"
register: pndata1
- name: Test provider networks is metal
provider_networks:
provider_networks: "{{ provider_networks }}"
is_metal: true
register: pndata2
- name: Test provider networks with prfix
provider_networks:
provider_networks: "{{ provider_networks }}"
bind_prefix: "brx"
is_metal: true
register: pndata3
## Module output:
# {
# "network_flat_networks": "flat",
# "network_flat_networks_list": [
# "flat"
# ],
# "network_mappings": "flat:brx-eth12,vlan:brx-eth11",
# "network_mappings_list": [
# "flat:brx-eth12",
# "vlan:brx-eth11"
# ],
# "network_sriov_mappings": "physnet1:p1p1,physnet1:p1p2",
# "network_sriov_mappings_list": [
# "physnet1:p1p1"
# "physnet1:p1p2"
# ],
# "network_types": "vxlan,flat,vlan,geneve",
# "network_types_list": [
# "vxlan",
# "flat",
# "vlan",
# "geneve"
# ],
# "network_vlan_ranges": "vlan:1:1,vlan:1024:1025",
# "network_vlan_ranges_list": [
# "vlan:1:1",
# "vlan:1024:1025"
# ],
# "network_vxlan_ranges": "1:1000",
# "network_vxlan_ranges_list": [
# "1:1000"
# ]
# "network_geneve_ranges": "1:1000",
# "network_geneve_ranges_list": [
# "1:1000"
# ]
# }
"""
class ProviderNetworksParsing(object):
def __init__(self, module):
"""Generate an integer from a name.
:param module: Load the ansible module
:type module: ``object``
"""
self.module = module
self.network_vlan_ranges = list()
self.network_vxlan_ranges = list()
self.network_geneve_ranges = list()
self.network_flat_networks = list()
self.network_mappings = list()
self.network_types = list()
self.network_sriov_mappings = list()
self.network_interface_mappings = list()
def load_networks(self, provider_networks, is_metal=False,
bind_prefix=None, group_names=None):
"""Load the lists of network and network data types.
:param provider_networks: list of networks defined in user_config
:type provider_networks: ``list``
:param is_metal: Enable of disable handling of on metal nodes
:type is_metal: ``bol``
:param bind_prefix: Pre-interface prefix forced within the network map
:type bind_prefix: ``str``
:param group_names: list of groups associated with node
:type group_names: ``list``
"""
for net in provider_networks:
if net['network']['type'] == "vlan":
if (
set(
net["network"]["group_binds"]
).intersection(group_names)
or "neutron_server" in group_names
):
if "vlan" not in self.network_types:
self.network_types.append('vlan')
for vlan_range in net['network']['range'].split(','):
self.network_vlan_ranges.append(
'%s:%s' % (
net['network']['net_name'], vlan_range.strip()
)
)
elif net['network']['type'] == "vxlan":
if "vxlan" not in self.network_types:
self.network_types.append('vxlan')
self.network_vxlan_ranges.append(net['network']['range'])
elif net['network']['type'] == "geneve":
if "geneve" not in self.network_types:
self.network_types.append('geneve')
self.network_geneve_ranges.append(net['network']['range'])
elif net['network']['type'] == "flat":
if (
set(
net["network"]["group_binds"]
).intersection(group_names)
or "neutron_server" in group_names
):
if "flat" not in self.network_types:
self.network_types.append('flat')
self.network_flat_networks.append(
net['network']['net_name']
)
# Create the network mappings
if net['network']['type'] not in ['raw', 'vxlan', 'geneve']:
if (
set(
net["network"]["group_binds"]
).intersection(group_names)
):
if 'net_name' in net['network']:
if is_metal:
if 'host_bind_override' in net['network']:
bind_device = \
net['network']['host_bind_override']
else:
bind_device = \
net['network']['container_bridge']
else:
bind_device = net['network']['container_interface']
if bind_prefix:
bind_device = '%s-%s' % (bind_prefix, bind_device)
self.network_mappings.append(
'%s:%s' % (
net['network']['net_name'],
bind_device
)
)
# Builds a list of provider bridge to physical
# interface mappings and is used when adding OVS
# ports to bridges
if 'network_interface' in net['network']:
self.network_interface_mappings.append(
'%s:%s' % (
net['network']['container_bridge'],
net['network']['network_interface']
)
)
# SR-IOV interface mappings
if 'sriov_host_interfaces' in net['network']:
host_interfaces = \
net['network']['sriov_host_interfaces']
for interface in host_interfaces.split(','):
self.network_sriov_mappings.append(
'%s:%s' % (
net['network']['net_name'],
interface
)
)
def main():
module = AnsibleModule(
argument_spec=dict(
provider_networks=dict(
type='list',
required=True
),
is_metal=dict(
type='bool',
default='false'
),
bind_prefix=dict(
type='str',
required=False,
default=None
),
group_names=dict(
type='list',
required=False,
default=None
)
),
supports_check_mode=False
)
try:
pnp = ProviderNetworksParsing(module=module)
pnp.load_networks(
provider_networks=module.params.get('provider_networks'),
is_metal=module.params.get('is_metal'),
bind_prefix=module.params.get('bind_prefix'),
group_names=module.params.get('group_names')
)
# Response dictionary, this adds commas to all list items in string
# format as well as preserves the list functionality for future data
# processing.
resp = {
'network_vlan_ranges': ','.join(pnp.network_vlan_ranges),
'network_vlan_ranges_list': pnp.network_vlan_ranges,
'network_vxlan_ranges': ','.join(pnp.network_vxlan_ranges),
'network_vxlan_ranges_list': pnp.network_vxlan_ranges,
'network_geneve_ranges': ','.join(pnp.network_geneve_ranges),
'network_geneve_ranges_list': pnp.network_geneve_ranges,
'network_flat_networks': ','.join(pnp.network_flat_networks),
'network_flat_networks_list': pnp.network_flat_networks,
'network_mappings': ','.join(list(set(pnp.network_mappings))),
'network_mappings_list': pnp.network_mappings,
'network_types': ','.join(pnp.network_types),
'network_sriov_mappings': ','.join(pnp.network_sriov_mappings),
'network_sriov_mappings_list': pnp.network_sriov_mappings,
'network_interface_mappings': ','.join(
pnp.network_interface_mappings
),
'network_interface_mappings_list': pnp.network_interface_mappings
}
module.exit_json(changed=True, **resp)
except Exception as exp:
resp = {'stderr': exp}
module.fail_json(msg='Failed Process', **resp)
if __name__ == '__main__':
main()