Use description to store identifier for networks and subnets.

For Neutron networks and subnets, add identifier (which origins from
tags) to the description field as a workaround for inability for create
tagged resources in atomic way. This change might be reverted when
Neutron gain such ability.

Depends-On: https://review.opendev.org/c/openstack/kuryr-tempest-plugin/+/841107
Change-Id: I1750a0b6ae569752b44a4fe682288686868450fe
This commit is contained in:
Roman Dobosz
2022-05-09 13:16:22 +02:00
parent be428a5b4b
commit a47dcf2476
3 changed files with 28 additions and 16 deletions

View File

@@ -120,21 +120,18 @@ class NamespacePodSubnetDriver(default_subnet.DefaultPodSubnetDriver):
os_net = clients.get_network_client() os_net = clients.get_network_client()
ns_name = ns['metadata']['name'] ns_name = ns['metadata']['name']
ns_uid = ns['metadata']['uid'] ns_uid = ns['metadata']['uid']
net_name = c_utils.get_resource_name(ns_name) net_name = c_utils.get_resource_name(ns_name, ns_uid)
old_net_name = c_utils.get_resource_name(ns_name, prefix='ns/', old_net_name = c_utils.get_resource_name(ns_name, prefix='ns/',
suffix='-net') suffix='-net')
# TODO(gryf): remove old_net_name support in next release, and precise # TODO(gryf): remove old_net_name support in next release, and precise
# the query by adding additional query parameter 'description' which # the query by adding additional query parameter 'description' which
# should contain namespace uid. # should contain namespace uid.
networks = os_net.networks(name=(net_name, old_net_name)) networks = os_net.networks(name=(net_name, old_net_name))
tags = ",".join(TAGS)
try: try:
# NOTE(ltomasbo): only one network must exists # NOTE(ltomasbo): only one network must exists
net = next(networks) net = next(networks)
if net.name == net_name and net.description != ns_uid:
# this condition would be unnecessary when guard for old names
# would be eventually removed.
raise ValueError
# NOTE(gryf): It might happen, that network has been created, but # NOTE(gryf): It might happen, that network has been created, but
# for some reason tagging has failed. # for some reason tagging has failed.
if TAGS and not set(TAGS).issubset(set(net.tags)): if TAGS and not set(TAGS).issubset(set(net.tags)):
@@ -145,7 +142,7 @@ class NamespacePodSubnetDriver(default_subnet.DefaultPodSubnetDriver):
mtu_cfg = oslo_cfg.CONF.neutron_defaults.network_device_mtu mtu_cfg = oslo_cfg.CONF.neutron_defaults.network_device_mtu
attrs = {'name': net_name, 'project_id': project_id, attrs = {'name': net_name, 'project_id': project_id,
'description': ns_uid} 'description': tags}
if mtu_cfg: if mtu_cfg:
attrs['mtu'] = mtu_cfg attrs['mtu'] = mtu_cfg
@@ -161,12 +158,14 @@ class NamespacePodSubnetDriver(default_subnet.DefaultPodSubnetDriver):
def create_subnet(self, ns, project_id, net_id): def create_subnet(self, ns, project_id, net_id):
os_net = clients.get_network_client() os_net = clients.get_network_client()
ns_name = ns['metadata']['name'] ns_name = ns['metadata']['name']
ns_uid = ns['metadata']['uid']
tags = ",".join(TAGS)
# NOTE(gryf): assumption is, that all the subnets (well, currently # NOTE(gryf): assumption is, that all the subnets (well, currently
# only one) in specific k8s namespaces are under exactly one network, # only one) in specific k8s namespaces are under exactly one network,
# which have proper namespace uid in its description, so there is no # which have proper namespace uid in its description, so there is no
# need to put it on the subnet as well. # need to put it on the subnet as well.
subnet_name = c_utils.get_resource_name(ns_name) subnet_name = c_utils.get_resource_name(ns_name, ns_uid)
subnets = os_net.subnets(network_id=net_id) subnets = os_net.subnets(network_id=net_id)
try: try:
@@ -185,6 +184,7 @@ class NamespacePodSubnetDriver(default_subnet.DefaultPodSubnetDriver):
try: try:
neutron_subnet = (os_net neutron_subnet = (os_net
.create_subnet(network_id=net_id, .create_subnet(network_id=net_id,
description=tags,
ip_version=ip_version, ip_version=ip_version,
name=subnet_name, name=subnet_name,
enable_dhcp=False, enable_dhcp=False,

View File

@@ -756,24 +756,26 @@ def delete_port(leftover_port):
return False return False
def get_resource_name(name, prefix='', suffix=''): def get_resource_name(name, uid='', prefix='', suffix=''):
"""Get OpenStack resource name out of Kubernetes resources """Get OpenStack resource name out of Kubernetes resources
Return name for the OpenStack resource, which usually is up to 255 chars Return name for the OpenStack resource, which usually is up to 255 chars
long. And while Kubernetes allows to set resource names up to 253 long. And while Kubernetes allows to set resource names up to 253
characters, that makes a risk to have too long name. This function will characters, that makes a risk to have too long name. This function will
prefix and suffix over name of the k8s resource, which will get truncated favor UID, prefix and suffix over name of the k8s resource, which will get
if needed. truncated if needed.
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/ https://kubernetes.io/docs/concepts/overview/working-with-objects/names/
""" """
if uid:
uid += '/'
length = len(f'{prefix}{name}{suffix}') length = len(f'{prefix}{uid}{name}{suffix}')
if length > 255: if length > 255:
name = name[:254-(length-254)] name = name[:254-(length-254)]
return f'{prefix}{name}{suffix}' return f'{prefix}{uid}{name}{suffix}'
def delete_ports(leftover_port_list): def delete_ports(leftover_port_list):

View File

@@ -121,7 +121,7 @@ class TestUtils(test_base.TestCase):
prefix = 'ns/' prefix = 'ns/'
suffix = '-net' suffix = '-net'
new_name = utils.get_resource_name(name, prefix, suffix) new_name = utils.get_resource_name(name, prefix=prefix, suffix=suffix)
self.assertEqual(new_name, self.assertEqual(new_name,
prefix + 248 * 'a' + suffix) prefix + 248 * 'a' + suffix)
@@ -132,7 +132,7 @@ class TestUtils(test_base.TestCase):
prefix = 'ns/' prefix = 'ns/'
suffix = '-foo' suffix = '-foo'
new_name = utils.get_resource_name(name, prefix, suffix) new_name = utils.get_resource_name(name, prefix=prefix, suffix=suffix)
self.assertEqual(new_name, f'{prefix}{name}{suffix}') self.assertEqual(new_name, f'{prefix}{name}{suffix}')
@@ -140,7 +140,7 @@ class TestUtils(test_base.TestCase):
name = 'fun_name' name = 'fun_name'
prefix = 'something/' prefix = 'something/'
new_name = utils.get_resource_name(name, prefix) new_name = utils.get_resource_name(name, prefix=prefix)
self.assertEqual(new_name, f'{prefix}{name}') self.assertEqual(new_name, f'{prefix}{name}')
@@ -157,6 +157,16 @@ class TestUtils(test_base.TestCase):
prefix = 'bar:' prefix = 'bar:'
suffix = ':baz' suffix = ':baz'
new_name = utils.get_resource_name(name, prefix, suffix) new_name = utils.get_resource_name(name, prefix=prefix, suffix=suffix)
self.assertEqual(new_name, f'{prefix}{name}{suffix}') self.assertEqual(new_name, f'{prefix}{name}{suffix}')
def test_get_resource_name_uid(self):
name = 'ns name'
prefix = 'foo:'
suffix = ':bar'
uid = 'b0f21afa-6d7b-496e-b151-6d7f252b8c6c'
new_name = utils.get_resource_name(name, uid, prefix, suffix)
self.assertEqual(new_name, f'{prefix}{uid}/{name}{suffix}')