[Neutron] Fix the "port show" command for trunk details
In [1], the "port list --long" command received a new column, showing the trunk subports related to a parent port. The problem of this patch is that the ``_formatters`` definition, that is shared with the "port show" command too, is changed. The "trunk_details" information presented in both commands differ: * In the "port list" command, only the subports are presented, in order to print a list of dictionaries without showing the ``trunk_id``. * In the "port show" command, it is presented all the trunk information, including the ``trunk_id``. This patch includes functional tests to validate the fix. [1]https://review.opendev.org/c/openstack/python-openstackclient/+/926611 Closes-Bug: #2098950 Change-Id: Ib1107fb3dbb025b39a7c55f90f5fe51ae433a72f
This commit is contained in:
		@@ -65,8 +65,9 @@ _formatters = {
 | 
			
		||||
    'fixed_ips': format_columns.ListDictColumn,
 | 
			
		||||
    'security_group_ids': format_columns.ListColumn,
 | 
			
		||||
    'tags': format_columns.ListColumn,
 | 
			
		||||
    'trunk_details': SubPortColumn,
 | 
			
		||||
}
 | 
			
		||||
_list_formatters = copy.deepcopy(_formatters)
 | 
			
		||||
_list_formatters.update({'trunk_details': SubPortColumn})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _get_columns(item):
 | 
			
		||||
@@ -952,7 +953,7 @@ class ListPort(command.Lister):
 | 
			
		||||
                utils.get_item_properties(
 | 
			
		||||
                    s,
 | 
			
		||||
                    attrs,
 | 
			
		||||
                    formatters=_formatters,
 | 
			
		||||
                    formatters=_list_formatters,
 | 
			
		||||
                )
 | 
			
		||||
                for s in data
 | 
			
		||||
            ),
 | 
			
		||||
 
 | 
			
		||||
@@ -289,3 +289,82 @@ class PortTests(common.NetworkTagTests):
 | 
			
		||||
            f'{self.base_command} create --network {self.NETWORK_NAME} {args} {name}',
 | 
			
		||||
            parse_output=True,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def _trunk_creation(self):
 | 
			
		||||
        pport = uuid.uuid4().hex
 | 
			
		||||
        sport1 = uuid.uuid4().hex
 | 
			
		||||
        sport2 = uuid.uuid4().hex
 | 
			
		||||
        trunk = uuid.uuid4().hex
 | 
			
		||||
        json_output = self.openstack(
 | 
			
		||||
            'port create ' f'--network {self.NETWORK_NAME} {pport}',
 | 
			
		||||
            parse_output=True,
 | 
			
		||||
        )
 | 
			
		||||
        pport_id = json_output.get('id')
 | 
			
		||||
        json_output = self.openstack(
 | 
			
		||||
            'port create ' f'--network {self.NETWORK_NAME} {sport1}',
 | 
			
		||||
            parse_output=True,
 | 
			
		||||
        )
 | 
			
		||||
        sport1_id = json_output.get('id')
 | 
			
		||||
        json_output = self.openstack(
 | 
			
		||||
            'port create ' f'--network {self.NETWORK_NAME} {sport2}',
 | 
			
		||||
            parse_output=True,
 | 
			
		||||
        )
 | 
			
		||||
        sport2_id = json_output.get('id')
 | 
			
		||||
 | 
			
		||||
        self.openstack(
 | 
			
		||||
            f'network trunk create --parent-port {pport} {trunk}',
 | 
			
		||||
        )
 | 
			
		||||
        self.openstack(
 | 
			
		||||
            f'network trunk set --subport port={sport1},'
 | 
			
		||||
            f'segmentation-type=vlan,segmentation-id=100 {trunk}',
 | 
			
		||||
        )
 | 
			
		||||
        self.openstack(
 | 
			
		||||
            f'network trunk set --subport port={sport2},'
 | 
			
		||||
            f'segmentation-type=vlan,segmentation-id=101 {trunk}',
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        # NOTE(ralonsoh): keep this order to first delete the trunk and then
 | 
			
		||||
        # the ports.
 | 
			
		||||
        self.addCleanup(self.openstack, f'port delete {pport_id}')
 | 
			
		||||
        self.addCleanup(self.openstack, f'port delete {sport1_id}')
 | 
			
		||||
        self.addCleanup(self.openstack, f'port delete {sport2_id}')
 | 
			
		||||
        self.addCleanup(self.openstack, f'network trunk delete {trunk}')
 | 
			
		||||
 | 
			
		||||
        return pport_id, sport1_id, sport2_id
 | 
			
		||||
 | 
			
		||||
    def check_subports(self, subports, pport_id, sport1_id, sport2_id):
 | 
			
		||||
        self.assertEqual(2, len(subports))
 | 
			
		||||
        for subport in subports:
 | 
			
		||||
            if subport['port_id'] == sport1_id:
 | 
			
		||||
                self.assertEqual(100, subport['segmentation_id'])
 | 
			
		||||
            elif subport['port_id'] == sport2_id:
 | 
			
		||||
                self.assertEqual(101, subport['segmentation_id'])
 | 
			
		||||
            else:
 | 
			
		||||
                self.fail(
 | 
			
		||||
                    f'Port {pport_id} does not have subport '
 | 
			
		||||
                    f'{subport["port_id"]}'
 | 
			
		||||
                )
 | 
			
		||||
            self.assertEqual('vlan', subport['segmentation_type'])
 | 
			
		||||
 | 
			
		||||
    def test_port_list_with_trunk(self):
 | 
			
		||||
        pport_id, sport1_id, sport2_id = self._trunk_creation()
 | 
			
		||||
 | 
			
		||||
        # List all ports with "--long" flag to retrieve the trunk details
 | 
			
		||||
        json_output = self.openstack(
 | 
			
		||||
            'port list --long',
 | 
			
		||||
            parse_output=True,
 | 
			
		||||
        )
 | 
			
		||||
        port = next(port for port in json_output if port['ID'] == pport_id)
 | 
			
		||||
        subports = port['Trunk subports']
 | 
			
		||||
        self.check_subports(subports, pport_id, sport1_id, sport2_id)
 | 
			
		||||
 | 
			
		||||
    def test_port_show_with_trunk(self):
 | 
			
		||||
        pport_id, sport1_id, sport2_id = self._trunk_creation()
 | 
			
		||||
 | 
			
		||||
        # List all ports with "--long" flag to retrieve the trunk details
 | 
			
		||||
        port = self.openstack(
 | 
			
		||||
            f'port show {pport_id}',
 | 
			
		||||
            parse_output=True,
 | 
			
		||||
        )
 | 
			
		||||
        subports = port['trunk_details']['sub_ports']
 | 
			
		||||
        self.check_subports(subports, pport_id, sport1_id, sport2_id)
 | 
			
		||||
 
 | 
			
		||||
@@ -122,7 +122,7 @@ class TestPort(network_fakes.TestNetworkV2):
 | 
			
		||||
            fake_port.status,
 | 
			
		||||
            format_columns.ListColumn(fake_port.tags),
 | 
			
		||||
            fake_port.trusted,
 | 
			
		||||
            port.SubPortColumn(fake_port.trunk_details),
 | 
			
		||||
            fake_port.trunk_details,
 | 
			
		||||
            fake_port.updated_at,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user