Correction of a typo in the 'sub_ports' field

Problem: In the "_extend_port_trunk_details_bulk"
method for the trunk plugin, the search of subports
takes place using the key 'subports' instead 'sub_ports'.
That cause the mac address field has never added to the subports.
It also leads to consistency with the documented API:
https://docs.openstack.org/api-ref/network/v2/index.html#show-trunk-details

Closes-Bug: #2020552
Change-Id: I113714a21692bfb6be9a21586de172a62191619f
This commit is contained in:
Maksim Kostrow
2025-04-02 11:47:59 +03:00
parent 79d9b0cc36
commit 1c93c84d1c
2 changed files with 39 additions and 11 deletions

View File

@@ -93,7 +93,7 @@ class TrunkPlugin(service_base.ServicePluginBase):
for port in ports:
subports[port['id']]['mac_address'] = port['mac_address']
trunk_details = {'trunk_id': port_db.trunk_port.id,
'sub_ports': list(subports.values())}
trunk_apidef.SUB_PORTS: list(subports.values())}
port_res['trunk_details'] = trunk_details
return port_res
@@ -112,9 +112,10 @@ class TrunkPlugin(service_base.ServicePluginBase):
subport_ids = []
trunk_ports = []
for p in ports_res:
if 'trunk_details' in p and 'subports' in p['trunk_details']:
if 'trunk_details' in p and \
trunk_apidef.SUB_PORTS in p['trunk_details']:
trunk_ports.append(p)
for subp in p['trunk_details']['subports']:
for subp in p['trunk_details'][trunk_apidef.SUB_PORTS]:
subport_ids.append(subp['port_id'])
if not subport_ids:
return ports_res
@@ -125,7 +126,7 @@ class TrunkPlugin(service_base.ServicePluginBase):
subport_macs = {p['id']: p['mac_address'] for p in subports}
for tp in trunk_ports:
for subp in tp['trunk_details']['subports']:
for subp in tp['trunk_details'][trunk_apidef.SUB_PORTS]:
subp['mac_address'] = subport_macs[subp['port_id']]
return ports_res
@@ -203,8 +204,10 @@ class TrunkPlugin(service_base.ServicePluginBase):
trunk_details['port_id'] = trunk_validator.validate(context)
subports_validator = rules.SubPortsValidator(
self._segmentation_types, trunk['sub_ports'], trunk['port_id'])
trunk_details['sub_ports'] = subports_validator.validate(context)
self._segmentation_types, trunk[trunk_apidef.SUB_PORTS],
trunk['port_id'])
trunk_details[trunk_apidef.SUB_PORTS] = (
subports_validator.validate(context))
return trunk_details
def get_plugin_description(self):
@@ -240,7 +243,7 @@ class TrunkPlugin(service_base.ServicePluginBase):
port_id=p['port_id'],
segmentation_id=p['segmentation_id'],
segmentation_type=p['segmentation_type'])
for p in trunk['sub_ports']]
for p in trunk[trunk_apidef.SUB_PORTS]]
admin_state_up = trunk.get('admin_state_up', True)
# NOTE(status_police): a trunk is created in DOWN status. Depending
# on the nature of the create request, a driver may set the status
@@ -334,7 +337,7 @@ class TrunkPlugin(service_base.ServicePluginBase):
# Check for basic validation since the request body here is not
# automatically validated by the API layer.
subports = subports['sub_ports']
subports = subports[trunk_apidef.SUB_PORTS]
subports_validator = rules.SubPortsValidator(
self._segmentation_types, subports, trunk['port_id'])
subports = subports_validator.validate(
@@ -364,7 +367,7 @@ class TrunkPlugin(service_base.ServicePluginBase):
segmentation_type=subport['segmentation_type'],
segmentation_id=subport['segmentation_id'])
obj.create()
trunk['sub_ports'].append(obj)
trunk[trunk_apidef.SUB_PORTS].append(obj)
added_subports.append(obj)
payload = events.DBEventPayload(context, resource_id=trunk_id,
states=(original_trunk, trunk,),
@@ -387,7 +390,7 @@ class TrunkPlugin(service_base.ServicePluginBase):
@db_base_plugin_common.convert_result_to_dict
def remove_subports(self, context, trunk_id, subports):
"""Remove one or more subports from trunk."""
subports = subports['sub_ports']
subports = subports[trunk_apidef.SUB_PORTS]
with db_api.CONTEXT_WRITER.using(context):
trunk = self._get_trunk(context, trunk_id)
original_trunk = copy.deepcopy(trunk)
@@ -446,7 +449,7 @@ class TrunkPlugin(service_base.ServicePluginBase):
def get_subports(self, context, trunk_id, fields=None):
"""Return subports for the specified trunk."""
trunk = self.get_trunk(context, trunk_id)
return {'sub_ports': trunk['sub_ports']}
return {trunk_apidef.SUB_PORTS: trunk[trunk_apidef.SUB_PORTS]}
def _get_trunk(self, context, trunk_id):
"""Return the trunk object or raise if not found."""

View File

@@ -367,6 +367,31 @@ class TrunkPluginTestCase(test_plugin.Ml2PluginV2TestCase):
self.assertEqual(final_trunk_status, current_trunk.status)
return trunk, current_trunk
def test_get_trunk_subport(self):
with self.port() as parent_port, self.port() as child_port:
trunk = self._create_test_trunk(parent_port)
subport = create_subport_dict(child_port['port']['id'])
self.trunk_plugin.add_subports(
self.context, trunk['id'], {'sub_ports': [subport]})
portid = parent_port['port']['id']
pl = directory.get_plugin()
res = pl.get_ports(self.context, filters={'id': [portid]})
expected_trunk_details = {
'trunk_id': trunk['id'],
'sub_ports': [
{
'segmentation_id': subport['segmentation_id'],
'port_id': subport['port_id'],
'segmentation_type': subport['segmentation_type'],
'mac_address': child_port['port']['mac_address'],
}
]
}
self.assertEqual(expected_trunk_details, res[0]['trunk_details'])
class TrunkPluginCompatDriversTestCase(test_plugin.Ml2PluginV2TestCase):