Merge "Use project_id with neutron resources"

This commit is contained in:
Zuul 2021-07-01 20:37:48 +00:00 committed by Gerrit Code Review
commit 9bc1adea28
10 changed files with 122 additions and 97 deletions

View File

@ -17,16 +17,18 @@
import collections
import ipaddress
import jsonschema
import os
import yaml
import jsonschema
RES_ID = 'physical_resource_id'
TYPE_NET = 'OS::Neutron::Net'
TYPE_SUBNET = 'OS::Neutron::Subnet'
RES_TYPE = 'resource_type'
TYPE_SEGMENT = 'OS::Neutron::Segment'
NET_VIP_SUFFIX = '_virtual_ip'
_DUMMY_PROJECT_ID = 'dummy_project_id'
DOMAIN_NAME_REGEX = (r'^(?=^.{1,255}$)(?!.*\.\..*)(.{1,63}\.)'
r'+(.{0,63}\.?)|(?!\.)(?!.*\.\..*)(^.{1,63}$)'
@ -280,6 +282,13 @@ required:
'''.format(domain_name_regex=DOMAIN_NAME_REGEX)
def get_project_id(connection):
"""Returns current project id"""
project_id = connection.session.get_project_id(
connection.session.auth) or _DUMMY_PROJECT_ID
return project_id
def _get_detailed_errors(error, depth, absolute_schema_path, absolute_schema,
filter_errors=True):
"""Returns a list of error messages from all subschema validations.

View File

@ -191,7 +191,7 @@ def validate_network_update(module, network, net_spec):
return net_spec
def create_or_update_network(conn, module, net_spec):
def create_or_update_network(conn, module, net_spec, project_id=None):
changed = False
# Need to use set_tags for the tags ...
@ -199,7 +199,8 @@ def create_or_update_network(conn, module, net_spec):
network = conn.network.find_network(net_spec['name'])
if not network:
network = conn.network.create_network(**net_spec)
network = conn.network.create_network(project_id=project_id,
**net_spec)
changed = True
else:
net_spec = validate_network_update(module, network, net_spec)
@ -246,7 +247,8 @@ def validate_segment_update(module, segment, segment_spec):
return segment_spec
def create_or_update_segment(conn, module, segment_spec, segment_id=None):
def create_or_update_segment(conn, module, segment_spec,
segment_id=None, project_id=None):
changed = False
if segment_id:
@ -256,7 +258,8 @@ def create_or_update_segment(conn, module, segment_spec, segment_id=None):
segment_spec['name'], network_id=segment_spec['network_id'])
if not segment:
segment = conn.network.create_segment(**segment_spec)
segment = conn.network.create_segment(project_id=project_id,
**segment_spec)
changed = True
else:
segment_spec = validate_segment_update(module, segment, segment_spec)
@ -346,7 +349,7 @@ def validate_subnet_update(module, subnet, subnet_spec):
return subnet_spec
def create_or_update_subnet(conn, module, subnet_spec):
def create_or_update_subnet(conn, module, subnet_spec, project_id=None):
changed = False
# Need to use set_tags for the tags ...
tags = subnet_spec.pop('tags')
@ -355,7 +358,8 @@ def create_or_update_subnet(conn, module, subnet_spec):
ip_version=subnet_spec['ip_version'],
network_id=subnet_spec['network_id'])
if not subnet:
subnet = conn.network.create_subnet(**subnet_spec)
subnet = conn.network.create_subnet(project_id=project_id,
**subnet_spec)
changed = True
else:
subnet_spec = validate_subnet_update(module, subnet, subnet_spec)
@ -370,7 +374,8 @@ def create_or_update_subnet(conn, module, subnet_spec):
return changed
def adopt_the_implicit_segment(conn, module, segments, subnets, network):
def adopt_the_implicit_segment(conn, module, segments, subnets, network,
project_id=None):
changed = False
# Check for implicit segment
implicit_segment = [s for s in segments if s['name'] is None]
@ -391,7 +396,8 @@ def adopt_the_implicit_segment(conn, module, segments, subnets, network):
network.id, network.name, subnet_associated.name,
physical_network=implicit_segment.physical_network)
create_or_update_segment(conn, module, segment_spec,
segment_id=implicit_segment.id)
segment_id=implicit_segment.id,
project_id=project_id)
changed = True
return changed
@ -431,11 +437,13 @@ def run_module():
try:
_, conn = openstack_cloud_from_module(module)
project_id = network_data_v2.get_project_id(conn)
ipv6_enabled = net_data.get('ipv6', False)
# Create or update the network
net_spec = create_net_spec(
net_data, get_overcloud_domain_name(conn, default_network), idx)
changed, network = create_or_update_network(conn, module, net_spec)
changed, network = create_or_update_network(conn, module,
net_spec, project_id)
result['changed'] = changed if changed else result['changed']
# Get current segments and subnets on the network
@ -443,7 +451,7 @@ def run_module():
subnets = list(conn.network.subnets(network_id=network.id))
changed = adopt_the_implicit_segment(conn, module, segments,
subnets, network)
subnets, network, project_id)
result['changed'] = changed if changed else result['changed']
for subnet_name, subnet_data in net_data.get('subnets', {}).items():
segment_spec = create_segment_spec(
@ -453,17 +461,19 @@ def run_module():
network.id, subnet_name, subnet_data, ipv6_enabled)
changed, segment = create_or_update_segment(
conn, module, segment_spec)
conn, module, segment_spec, project_id=project_id)
result['changed'] = changed if changed else result['changed']
if subnet_v4_spec:
subnet_v4_spec.update({'segment_id': segment.id})
changed = create_or_update_subnet(conn, module, subnet_v4_spec)
changed = create_or_update_subnet(conn, module, subnet_v4_spec,
project_id)
result['changed'] = changed if changed else result['changed']
if subnet_v6_spec:
subnet_v6_spec.update({'segment_id': segment.id})
changed = create_or_update_subnet(conn, module, subnet_v6_spec)
changed = create_or_update_subnet(conn, module, subnet_v6_spec,
project_id)
result['changed'] = changed if changed else result['changed']
result['success'] = True

View File

@ -295,7 +295,7 @@ def create_ports(result, conn, port_defs, inst_ports, tags, net_maps,
result['changed'] = True
def generate_port_defs(net_maps, instance, inst_ports):
def generate_port_defs(net_maps, instance, inst_ports, project_id=None):
hostname = instance['hostname']
create_port_defs = []
update_port_defs = []
@ -332,6 +332,8 @@ def generate_port_defs(net_maps, instance, inst_ports):
port_def = dict(name=port_name, dns_name=hostname, network_id=net_id,
fixed_ips=fixed_ips)
if project_id:
port_def['project_id'] = project_id
if port_name not in existing_port_names:
create_port_defs.append(port_def)
@ -360,7 +362,7 @@ def delete_removed_nets(result, conn, instance, net_maps, inst_ports):
def _provision_ports(result, conn, stack, instance, net_maps, ports_by_node,
ironic_uuid, role):
ironic_uuid, role, project_id=None):
hostname = instance['hostname']
network_config = instance.get('network_config', {})
tags = ['tripleo_stack_name={}'.format(stack),
@ -381,8 +383,8 @@ def _provision_ports(result, conn, stack, instance, net_maps, ports_by_node,
delete_removed_nets(result, conn, instance, net_maps, inst_ports)
pre_provisioned_ports(result, conn, net_maps, instance, inst_ports, tags)
create_port_defs, update_port_defs = generate_port_defs(net_maps, instance,
inst_ports)
create_port_defs, update_port_defs = generate_port_defs(
net_maps, instance, inst_ports, project_id)
if create_port_defs:
create_ports(result, conn, create_port_defs, inst_ports, tags,
@ -446,7 +448,8 @@ def validate_instance_nets_in_net_map(instances, net_maps):
def manage_instances_ports(result, conn, stack, instances, concurrency, state,
uuid_by_hostname, hostname_role_map, net_maps):
uuid_by_hostname, hostname_role_map, net_maps,
project_id=None):
if not instances:
return
@ -473,7 +476,8 @@ def manage_instances_ports(result, conn, stack, instances, concurrency, state,
net_maps,
ports_by_node,
ironic_uuid,
role)
role,
project_id)
)
elif state == 'absent':
provision_jobs.append(
@ -530,7 +534,7 @@ def tag_metalsmith_managed_ports(result, conn, concurrency, stack,
concurrency = len(uuid_by_hostname)
provisioner = metalsmith.Provisioner(cloud_region=conn.config)
provisioner.connection = conn
provision_jobs = []
exceptions = []
with futures.ThreadPoolExecutor(max_workers=concurrency) as p:
@ -589,6 +593,7 @@ def run_module():
try:
_, conn = openstack_cloud_from_module(module)
project_id = n_utils.get_project_id(conn)
net_maps = n_utils.create_name_id_maps(conn)
if state == 'present' and uuid_by_hostname:
@ -598,7 +603,7 @@ def run_module():
manage_instances_ports(result, conn, stack, instances, concurrency,
state, uuid_by_hostname, hostname_role_map,
net_maps)
net_maps, project_id)
result['success'] = True
module.exit_json(**result)
except Exception as err:

View File

@ -152,7 +152,8 @@ def create_port_def(vip_spec, net_maps):
return port_def
def provision_vip_port(conn, stack, net_maps, vip_spec, managed_ports):
def provision_vip_port(conn, stack, net_maps, vip_spec,
managed_ports, project_id):
port_def = create_port_def(vip_spec, net_maps)
tags = ['tripleo_stack_name={}'.format(stack),
@ -171,7 +172,8 @@ def provision_vip_port(conn, stack, net_maps, vip_spec, managed_ports):
conn.network.update_port(port.id, **port_def)
break
except StopIteration:
port = conn.network.create_port(**port_def)
port = conn.network.create_port(project_id=project_id,
**port_def)
conn.network.set_tags(port, tags)
managed_ports.append(port.id)
@ -221,6 +223,8 @@ def run_module():
try:
_, conn = openstack_cloud_from_module(module)
project_id = n_utils.get_project_id(conn)
net_maps = n_utils.create_name_id_maps(conn)
validate_vip_nets_in_net_map(vip_data, net_maps)
@ -235,7 +239,8 @@ def run_module():
for vip_spec in vip_data:
provision_jobs.append(p.submit(
provision_vip_port, conn, stack, net_maps, vip_spec,
managed_ports))
managed_ports,
project_id))
for job in futures.as_completed(provision_jobs):
e = job.exception()

View File

@ -19,8 +19,6 @@ from concurrent import futures
import os
import yaml
import keystoneauth1.exceptions as kauth1_exc
try:
from ansible.module_utils import network_data_v2
except ImportError:
@ -126,11 +124,12 @@ NET_NAME = 'ovn_mac_addr_net'
NET_DESCRIPTION = 'Network used to allocate MAC addresses for OVN chassis.'
def create_ovn_mac_address_network(result, conn):
def create_ovn_mac_address_network(result, conn, project_id):
network = conn.network.find_network(NET_NAME)
if network is None:
network = conn.network.create_network(name=NET_NAME,
description=NET_DESCRIPTION)
description=NET_DESCRIPTION,
project_id=project_id)
result['changed'] = True
@ -147,14 +146,15 @@ def port_exists(conn, net_id, tags, name):
def create_ovn_mac_address_ports(result, conn, net_id, tags, physnets,
server):
server, project_id):
for physnet in physnets:
name = '_'.join([server, 'ovn_physnet', physnet])
if port_exists(conn, net_id, tags, name):
continue
port = conn.network.create_port(network_id=net_id, name=name,
dns_name=server)
dns_name=server,
project_id=project_id)
conn.network.set_tags(
port, tags + ['tripleo_ovn_physnet={}'.format(physnet)])
@ -240,16 +240,11 @@ def run_module():
try:
if not static_mappings:
try:
_, conn = openstack_cloud_from_module(module)
if conn.identity.find_service('neutron') is None:
result['success'] = True
module.exit_json(**result)
except kauth1_exc.MissingRequiredOptions:
result['success'] = True
module.exit_json(**result)
_, conn = openstack_cloud_from_module(module)
project_id = network_data_v2.get_project_id(conn)
net_id = create_ovn_mac_address_network(
result, conn, project_id)
net_id = create_ovn_mac_address_network(result, conn)
tags = ['tripleo_stack_name={}'.format(stack)]
if role_name:
tags.append('tripleo_role={}'.format(role_name))
@ -265,7 +260,7 @@ def run_module():
for server in servers:
jobs.append(p.submit(create_ovn_mac_address_ports,
result, conn, net_id, tags,
physnets, server))
physnets, server, project_id))
for job in futures.as_completed(jobs):
e = job.exception()
@ -275,8 +270,11 @@ def run_module():
if exceptions:
raise exceptions[0]
remove_obsolete_ports(result, conn, net_id, tags, servers,
physnets)
try:
remove_obsolete_ports(result, conn, net_id, tags, servers,
physnets)
except Exception:
pass
if static_mappings or servers:
write_vars_file(conn, playbook_dir, net_id, tags, static_mappings)

View File

@ -18,8 +18,6 @@
import os
import yaml
import keystoneauth1.exceptions as kauth1_exc
try:
from ansible.module_utils import network_data_v2
except ImportError:
@ -136,7 +134,8 @@ def create_or_update_port(conn, net, stack=None, service=None,
tags = {'tripleo_stack_name={}'.format(stack),
'tripleo_service_vip={}'.format(service)}
port_def = dict(name=service + VIRTUAL_IP_NAME_SUFFIX, network_id=net.id)
port_def = dict(name=service + VIRTUAL_IP_NAME_SUFFIX,
network_id=net.id,)
try:
port = next(conn.network.ports(tags=list(tags), network_id=net.id))
@ -164,7 +163,10 @@ def create_or_update_port(conn, net, stack=None, service=None,
fixed_ips_def.append(ip_def)
if not port:
port = conn.network.create_port(**port_def)
project_id = network_data_v2.get_project_id(conn)
port = conn.network.create_port(project_id=project_id,
**port_def)
else:
# TODO: Check if port needs update
port = conn.network.update_port(port, **port_def)
@ -259,25 +261,19 @@ def _openstack_cloud_from_module(module):
def delete_service_vip(module, stack, service='all'):
try:
_, conn = _openstack_cloud_from_module(module)
_use_neutron = conn.identity.find_service('neutron') is not None
except kauth1_exc.MissingRequiredOptions:
return
if not _use_neutron:
return
if service == 'all':
tags = {'tripleo_stack_name={}'.format(stack)}
ports = conn.network.ports(tags=list(tags))
matching = [p for p in ports
if any("tripleo_service_vip" in tag for tag in p.tags)]
else:
tags = {'tripleo_stack_name={}'.format(stack),
'tripleo_service_vip={}'.format(service)}
matching = conn.network.ports(tags=list(tags))
for p in matching:
try:
if service == 'all':
tags = {'tripleo_stack_name={}'.format(stack)}
ports = conn.network.ports(tags=list(tags))
matching = [p for p in ports
if any("tripleo_service_vip" in tag for tag in p.tags)]
else:
tags = {'tripleo_stack_name={}'.format(stack),
'tripleo_service_vip={}'.format(service)}
matching = conn.network.ports(tags=list(tags))
for p in matching:
conn.network.delete_port(p.id)
except Exception:
pass
except Exception:
pass
def create_service_vip(module, stack, service, network, fixed_ips,
@ -289,13 +285,7 @@ def create_service_vip(module, stack, service, network, fixed_ips,
break
if _use_neutron:
try:
_, conn = _openstack_cloud_from_module(module)
_use_neutron = conn.identity.find_service('neutron') is not None
except kauth1_exc.MissingRequiredOptions:
_use_neutron = False
if _use_neutron:
_, conn = _openstack_cloud_from_module(module)
port = use_neutron(conn, stack, service, network, fixed_ips)
else:
port = use_fake(service, fixed_ips)

View File

@ -138,8 +138,9 @@ class TestTripleoComposableNetwork(tests_base.TestCase):
mock_conn.network.find_network.return_value = None
mock_conn.network.create_network.return_value = fake_network
changed, network = plugin.create_or_update_network(
mock_conn, mock_module, net_spec)
mock_conn.network.create_network.assert_called_once_with(**net_spec)
mock_conn, mock_module, net_spec, 'admin')
mock_conn.network.create_network.assert_called_once_with(
project_id='admin', **net_spec)
mock_conn.network.set_tags.assert_called_once_with(
network, ['tripleo_foo=bar'])
self.assertEqual(True, changed)
@ -170,7 +171,7 @@ class TestTripleoComposableNetwork(tests_base.TestCase):
)
mock_conn.network.find_network.return_value = fake_network
changed, network = plugin.create_or_update_network(
mock_conn, mock_module, net_spec)
mock_conn, mock_module, net_spec, 'admin')
mock_conn.network.update_network.assert_called_once_with(
'foo', **{'name': 'new_name'})
mock_conn.network.set_tags.assert_called_once_with(
@ -253,9 +254,9 @@ class TestTripleoComposableNetwork(tests_base.TestCase):
'network_type': plugin.DEFAULT_NETWORK_TYPE}
mock_conn.network.find_segment.return_value = None
changed, segment = plugin.create_or_update_segment(
mock_conn, mock_module, segment_spec)
mock_conn, mock_module, segment_spec, project_id='admin')
mock_conn.network.create_segment.assert_called_once_with(
**segment_spec)
project_id='admin', **segment_spec)
self.assertEqual(True, changed)
@mock.patch.object(openstack.connection, 'Connection', autospec=True)
@ -461,7 +462,7 @@ class TestTripleoComposableNetwork(tests_base.TestCase):
mock.call(
msg='Cannot update segment_id in existing subnet, Current '
'segment_id: {} Update segment_id: {}'.format(
'segment_id', 'new_segment_id')
'segment_id', 'new_segment_id')
),
])
expected_spec = {
@ -497,8 +498,9 @@ class TestTripleoComposableNetwork(tests_base.TestCase):
}
mock_conn.network.find_subnet.return_value = None
changed = plugin.create_or_update_subnet(mock_conn, mock_module,
subnet_spec)
mock_conn.network.create_subnet.assert_called_once_with(**subnet_spec)
subnet_spec, 'admin')
mock_conn.network.create_subnet.assert_called_once_with(
project_id='admin', **subnet_spec)
mock_conn.network.set_tags.assert_called_once_with(
mock.ANY, ['tripleo_vlan_id=100'])
self.assertEqual(True, changed)
@ -539,7 +541,7 @@ class TestTripleoComposableNetwork(tests_base.TestCase):
)
mock_conn.network.find_subnet.return_value = fake_subnet
changed = plugin.create_or_update_subnet(mock_conn, mock_module,
subnet_spec)
subnet_spec, 'admin')
mock_conn.network.find_subnet.ssert_called_once_with(
'subnet_name', network_id='net_id')
mock_conn.network.create_subnet.assert_not_called()
@ -563,13 +565,15 @@ class TestTripleoComposableNetwork(tests_base.TestCase):
segment_id='segment_id')]
changed = plugin.adopt_the_implicit_segment(
mock.ANY, mock.ANY, fake_segments, fake_subnets, fake_network)
mock.ANY, mock.ANY, fake_segments, fake_subnets, fake_network,
project_id='admin')
mock_create_segment_spec.assert_called_once_with(
fake_network.id, fake_network.name, fake_subnets[0].name,
physical_network=fake_segments[0].physical_network)
mock_create_or_update_segment.assert_called_once_with(
mock.ANY, mock.ANY, mock.ANY, segment_id=fake_segments[0].id)
mock.ANY, mock.ANY, mock.ANY, segment_id=fake_segments[0].id,
project_id='admin')
self.assertTrue(changed)
def test_implicit_segment_already_adopted(self):

View File

@ -122,8 +122,9 @@ class TestTripleoOvercloudVipProvision(tests_base.TestCase):
mock_conn.network.ports.return_value = self.a2g([])
managed_ports = list()
plugin.provision_vip_port(mock_conn, 'stack', NET_MAPS, vip_spec,
managed_ports)
managed_ports, 'admin')
mock_conn.network.create_port.assert_called_with(
project_id='admin',
dns_name='overcloud',
fixed_ips=[{'ip_address': '1.2.3.4'}],
name='network1_virtual_ip',
@ -146,8 +147,8 @@ class TestTripleoOvercloudVipProvision(tests_base.TestCase):
mock_conn.network.ports.return_value = self.a2g([fake_port])
managed_ports = list()
plugin.provision_vip_port(mock_conn, 'stack', NET_MAPS, vip_spec,
managed_ports)
self.assertEqual([fake_port.id], managed_ports)
managed_ports, 'admin')
self.assertEqual([fake_port.id], managed_ports, 'admin')
mock_conn.network.create_port.assert_not_called()
mock_conn.network.update_port.assert_not_called()
mock_conn.network.set_tags.assert_not_called()
@ -171,7 +172,7 @@ class TestTripleoOvercloudVipProvision(tests_base.TestCase):
mock_conn.network.ports.return_value = self.a2g([fake_port])
managed_ports = list()
plugin.provision_vip_port(mock_conn, 'stack', NET_MAPS, vip_spec,
managed_ports)
managed_ports, 'admin')
self.assertEqual([fake_port.id], managed_ports)
mock_conn.network.create_port.assert_not_called()
mock_conn.network.update_port.assert_called_with(fake_port.id,

View File

@ -14,7 +14,6 @@
# under the License.
#
import copy
import mock
import openstack
@ -56,11 +55,13 @@ class TestTripleoOVNMacAddresses(tests_base.TestCase):
mock_conn.network.find_network.return_value = None
mock_conn.network.create_network.return_value = FAKE_NETWORK
net_id = plugin.create_ovn_mac_address_network(result, mock_conn)
net_id = plugin.create_ovn_mac_address_network(
result, mock_conn, 'admin')
mock_conn.network.create_network.assert_called_with(
name=plugin.NET_NAME,
description=plugin.NET_DESCRIPTION)
description=plugin.NET_DESCRIPTION,
project_id='admin')
self.assertTrue(result['changed'])
self.assertEqual(FAKE_NETWORK.id, net_id)
@ -68,7 +69,8 @@ class TestTripleoOVNMacAddresses(tests_base.TestCase):
result = dict(changed=False)
mock_conn.network.find_network.return_value = FAKE_NETWORK
net_id = plugin.create_ovn_mac_address_network(result, mock_conn)
net_id = plugin.create_ovn_mac_address_network(
result, mock_conn, 'admin')
mock_conn.network.create_network.assert_not_called()
self.assertFalse(result['changed'])
@ -102,14 +104,16 @@ class TestTripleoOVNMacAddresses(tests_base.TestCase):
mock_port_exists.return_value = False
plugin.create_ovn_mac_address_ports(result, mock_conn,
FAKE_NETWORK.id, tags,
physnets, server)
physnets, server, 'admin')
mock_conn.network.create_port.assert_has_calls(
[mock.call(network_id=FAKE_NETWORK.id,
name=server + '_ovn_physnet_net-a',
dns_name=server),
dns_name=server,
project_id='admin'),
mock.call(network_id=FAKE_NETWORK.id,
name=server + '_ovn_physnet_net-b',
dns_name=server)])
dns_name=server,
project_id='admin')])
mock_conn.network.set_tags.assert_has_calls(
[mock.call(mock.ANY, tags + ['tripleo_ovn_physnet=net-a']),
mock.call(mock.ANY, tags + ['tripleo_ovn_physnet=net-b'])])
@ -125,7 +129,7 @@ class TestTripleoOVNMacAddresses(tests_base.TestCase):
mock_port_exists.return_value = True
plugin.create_ovn_mac_address_ports(result, mock_conn,
FAKE_NETWORK.id, tags,
physnets, server)
physnets, server, 'admin')
mock_conn.network.create_port.assert_not_called()
mock_conn.network.set_tags.assert_not_called()

View File

@ -12,7 +12,6 @@
# 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 mock
import openstack
@ -54,7 +53,7 @@ class TestTripleoServiceVip(tests_base.TestCase):
service='test', fixed_ips=fixed_ips)
mock_conn.network.create_port.assert_called_once_with(
name='test_virtual_ip', network_id='net_id',
fixed_ips=[{'subnet_id': 'subnet_id'}])
fixed_ips=[{'subnet_id': 'subnet_id'}], project_id=mock.ANY)
mock_conn.network.update_port.assert_not_called()
mock_conn.network.set_tags.assert_called_once_with(
fake_port, [mock.ANY, mock.ANY])