diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c60c604..bb995a9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.6", "3.7", "3.8", "3.9"] + python-version: ["3.6", "3.8", "3.9"] steps: - uses: actions/checkout@v3 diff --git a/esiclient/tests/unit/test_utils.py b/esiclient/tests/unit/test_utils.py index 730047a..86279a6 100644 --- a/esiclient/tests/unit/test_utils.py +++ b/esiclient/tests/unit/test_utils.py @@ -52,6 +52,7 @@ def setUp(self): self.neutron_client = mock.Mock() self.neutron_client.get_network.return_value = self.network + self.networks_dict = {"network_uuid": self.network} def test_get_network_info_from_port(self): port = test_utils.create_mock_object({ @@ -61,7 +62,8 @@ def test_get_network_info_from_port(self): "fixed_ips": [{"ip_address": '11.22.33.44'}] }) - results = utils.get_network_info_from_port(port, self.neutron_client) + results = utils.get_network_info_from_port(port, self.neutron_client, + self.networks_dict) self.assertEqual(('test_network (777)', '11.22.33.44'), results) def test_get_network_info_from_port_no_fixed_ips(self): @@ -72,7 +74,8 @@ def test_get_network_info_from_port_no_fixed_ips(self): "fixed_ips": None }) - results = utils.get_network_info_from_port(port, self.neutron_client) + results = utils.get_network_info_from_port(port, self.neutron_client, + self.networks_dict) self.assertEqual(('test_network (777)', ''), results) @@ -105,6 +108,9 @@ def setUp(self): self.neutron_client = mock.Mock() + self.networks_dict = {"network_uuid_1": self.network1, + "network_uuid_2": self.network2} + def mock_network_get(network_uuid): if network_uuid == "network_uuid_1": return self.network1 @@ -137,7 +143,8 @@ def test_get_full_network_info_from_port(self): }) results = utils.get_full_network_info_from_port(port, - self.neutron_client) + self.neutron_client, + self.networks_dict,) self.assertEqual(( ['test_network (777)', 'test_network (777)', 'test_network_2 (888)'], @@ -155,7 +162,8 @@ def test_get_full_network_info_from_port_no_trunk(self): }) results = utils.get_full_network_info_from_port(port, - self.neutron_client) + self.neutron_client, + self.networks_dict) self.assertEqual( (['test_network (777)'], ['test_port'], ['77.77.77.77']), results diff --git a/esiclient/tests/unit/v1/test_node_network.py b/esiclient/tests/unit/v1/test_node_network.py index 1bf9ea1..c364081 100644 --- a/esiclient/tests/unit/v1/test_node_network.py +++ b/esiclient/tests/unit/v1/test_node_network.py @@ -65,17 +65,34 @@ def setUp(self): self.neutron_port1 = utils.create_mock_object({ "id": "neutron_port_uuid_1", "network_id": "network_uuid", - "name": "node1", + "name": "neutron_port_1", "fixed_ips": [{"ip_address": "1.1.1.1"}], "trunk_details": None }) self.neutron_port2 = utils.create_mock_object({ "id": "neutron_port_uuid_2", "network_id": "network_uuid", - "name": "node2", + "name": "neutron_port_2", "fixed_ips": [{"ip_address": "2.2.2.2"}], "trunk_details": None }) + self.floating_network = utils.create_mock_object({ + "id": "floating_network_id", + "name": "floating_network" + }) + self.floating_ip1 = utils.create_mock_object({ + "id": "floating_ip_uuid_1", + "floating_ip_address": "9.9.9.9", + "floating_network_id": "floating_network_id", + "port_id": "neutron_port_uuid_1" + }) + self.floating_ip2 = utils.create_mock_object({ + "id": "floating_ip_uuid_2", + "floating_ip_address": "8.8.8.8", + "floating_network_id": "floating_network_id", + "port_id": "neutron_port_uuid_2" + + }) def mock_node_get(node_uuid): if node_uuid == "11111111-2222-3333-4444-aaaaaaaaaaaa": @@ -101,9 +118,11 @@ def mock_neutron_port_get(port_uuid): self.app.client_manager.network.ports.\ return_value = [self.neutron_port1, self.neutron_port2] self.app.client_manager.network.networks.\ - return_value = [self.network] + return_value = [self.network, self.floating_network] self.app.client_manager.baremetal.node.list.\ return_value = [self.node1, self.node2] + self.app.client_manager.network.ips.\ + return_value = [self.floating_ip1, self.floating_ip2] def test_take_action(self): self.app.client_manager.baremetal.port.list.\ @@ -116,10 +135,13 @@ def test_take_action(self): results = self.cmd.take_action(parsed_args) expected = ( - ["Node", "MAC Address", "Port", "Network", "Fixed IP"], - [['node1', 'aa:aa:aa:aa:aa:aa', 'node1', 'test_network', '1.1.1.1'], - ['node2', 'bb:bb:bb:bb:bb:bb', None, None, None], - ['node2', 'cc:cc:cc:cc:cc:cc', 'node2', 'test_network', '2.2.2.2']] + ["Node", "MAC Address", "Port", "Network", "Fixed IP", + "Floating Network", "Floating IP"], + [['node1', 'aa:aa:aa:aa:aa:aa', 'neutron_port_1', 'test_network', + '1.1.1.1', 'floating_network', '9.9.9.9'], + ['node2', 'bb:bb:bb:bb:bb:bb', None, None, None, None, None], + ['node2', 'cc:cc:cc:cc:cc:cc', 'neutron_port_2', 'test_network', + '2.2.2.2', 'floating_network', '8.8.8.8']] ) self.assertEqual(expected, results) self.app.client_manager.baremetal.port.list.\ @@ -136,8 +158,9 @@ def test_take_action_neutron_port_does_not_exist(self): results = self.cmd.take_action(parsed_args) expected = ( - ["Node", "MAC Address", "Port", "Network", "Fixed IP"], - [["node2", "dd:dd:dd:dd:dd:dd", None, None, None]] + ["Node", "MAC Address", "Port", "Network", "Fixed IP", + "Floating Network", "Floating IP"], + [["node2", "dd:dd:dd:dd:dd:dd", None, None, None, None, None]] ) self.assertEqual(expected, results) self.app.client_manager.baremetal.port.list.\ @@ -154,9 +177,11 @@ def test_take_action_node_filter(self): results = self.cmd.take_action(parsed_args) expected = ( - ["Node", "MAC Address", "Port", "Network", "Fixed IP"], - [['node2', 'bb:bb:bb:bb:bb:bb', None, None, None], - ['node2', 'cc:cc:cc:cc:cc:cc', 'node2', 'test_network', '2.2.2.2']] + ["Node", "MAC Address", "Port", "Network", "Fixed IP", + "Floating Network", "Floating IP"], + [['node2', 'bb:bb:bb:bb:bb:bb', None, None, None, None, None], + ['node2', 'cc:cc:cc:cc:cc:cc', 'neutron_port_2', 'test_network', + '2.2.2.2', 'floating_network', '8.8.8.8']] ) self.assertEqual(expected, results) self.app.client_manager.baremetal.port.list.\ @@ -175,11 +200,14 @@ def test_take_action_network_filter(self): results = self.cmd.take_action(parsed_args) expected = ( - ["Node", "MAC Address", "Port", "Network", "Fixed IP"], + ["Node", "MAC Address", "Port", "Network", "Fixed IP", + "Floating Network", "Floating IP"], [["node1", "aa:aa:aa:aa:aa:aa", - "node1", "test_network", "1.1.1.1"], + "neutron_port_1", "test_network", "1.1.1.1", + "floating_network", "9.9.9.9"], ["node2", "cc:cc:cc:cc:cc:cc", - "node2", "test_network", "2.2.2.2"]] + "neutron_port_2", "test_network", "2.2.2.2", + "floating_network", "8.8.8.8"]] ) self.assertEqual(expected, results) self.app.client_manager.baremetal.port.list.\ @@ -196,9 +224,11 @@ def test_take_action_node_network_filter(self): results = self.cmd.take_action(parsed_args) expected = ( - ["Node", "MAC Address", "Port", "Network", "Fixed IP"], + ["Node", "MAC Address", "Port", "Network", "Fixed IP", + "Floating Network", "Floating IP"], [["node2", "cc:cc:cc:cc:cc:cc", - "node2", "test_network", "2.2.2.2"]] + "neutron_port_2", "test_network", "2.2.2.2", + "floating_network", "8.8.8.8"]] ) self.assertEqual(expected, results) self.app.client_manager.baremetal.port.list.\ diff --git a/esiclient/tests/unit/v1/test_switch.py b/esiclient/tests/unit/v1/test_switch.py index ef9b27e..1ca8d71 100644 --- a/esiclient/tests/unit/v1/test_switch.py +++ b/esiclient/tests/unit/v1/test_switch.py @@ -227,11 +227,13 @@ def setUp(self): self.app.client_manager.baremetal.port.list.\ return_value = [self.port1, self.port2, self.port3, self.port4, self.port5] + self.app.client_manager.network.networks.\ + return_value = [] @mock.patch('esiclient.utils.get_full_network_info_from_port', autospec=True) def test_take_action(self, mock_gfnifp): - def mock_gfnifp_call(np, client): + def mock_gfnifp_call(np, n_dict, client): if np.id == 'neutron_port_uuid_1': return ['net1 (100)', 'net2 (200)'], [], [] elif np.id == 'neutron_port_uuid_2': diff --git a/esiclient/tests/unit/v1/test_trunk.py b/esiclient/tests/unit/v1/test_trunk.py index 2f0bdd1..9bb8e77 100644 --- a/esiclient/tests/unit/v1/test_trunk.py +++ b/esiclient/tests/unit/v1/test_trunk.py @@ -88,6 +88,8 @@ def setUp(self): self.app.client_manager.network.trunks.\ return_value = [self.trunk1, self.trunk2] + self.app.client_manager.network.networks.\ + return_value = [] def mock_get_port(port_id): if port_id == "port_uuid_1": @@ -101,7 +103,7 @@ def mock_get_port(port_id): @mock.patch('esiclient.utils.get_full_network_info_from_port', autospec=True) def test_take_action(self, mock_gfnifp): - def mock_get_fnifp(port, client): + def mock_get_fnifp(port, n_dict, client): if port.id == "port_uuid_1": return (["network1", "network2", "network3"], ["trunk1-network1-trunk-port", @@ -143,8 +145,8 @@ def mock_get_fnifp(port, client): mock.call("port_uuid_4") ]) mock_gfnifp.assert_has_calls([ - mock.call(self.port1, self.app.client_manager.network), - mock.call(self.port2, self.app.client_manager.network) + mock.call(self.port1, self.app.client_manager.network, {}), + mock.call(self.port2, self.app.client_manager.network, {}) ]) diff --git a/esiclient/utils.py b/esiclient/utils.py index 777f598..c326712 100644 --- a/esiclient/utils.py +++ b/esiclient/utils.py @@ -25,13 +25,17 @@ def get_network_display_name(network): return network.name -def get_network_info_from_port(port, client): +def get_network_info_from_port(port, client, networks_dict={}): """Return Neutron network name and ips from port :param port: a Neutron port :param client: neutron client + :param networks_dict: networks dict {id:network} """ - network = client.get_network(port.network_id) + if port.network_id in networks_dict: + network = networks_dict.get(port.network_id) + else: + network = client.get_network(port.network_id) fixed_ip = '' if port.fixed_ips and len(port.fixed_ips) > 0: fixed_ip = port.fixed_ips[0]['ip_address'] @@ -39,19 +43,21 @@ def get_network_info_from_port(port, client): return get_network_display_name(network), fixed_ip -def get_full_network_info_from_port(port, client): +def get_full_network_info_from_port(port, client, networks_dict={}): """Return full Neutron network name and ips from port This code iterates through subports if appropriate :param port: a Neutron port :param client: neutron client + :param networks_dict: networks dict {id:network} """ network_names = [] port_names = [] fixed_ips = [] - network_name, fixed_ip = get_network_info_from_port(port, client) + network_name, fixed_ip = get_network_info_from_port(port, client, + networks_dict) network_names.append(network_name) fixed_ips.append(fixed_ip) port_names.append(port.name) @@ -61,7 +67,7 @@ def get_full_network_info_from_port(port, client): for subport_info in subports: subport = client.get_port(subport_info['port_id']) network_name, fixed_ip = get_network_info_from_port( - subport, client) + subport, client, networks_dict) network_names.append(network_name) fixed_ips.append(fixed_ip) port_names.append(subport.name) @@ -111,3 +117,19 @@ def get_network_from_vlan(vlan_id, neutron_client): provider_network_type='vlan', provider_segmentation_id=vlan_id)) return next(iter(networks), None) + + +def get_floating_ip(port_id, floating_ips, networks_dict): + """Return neutron port floating ips information, if any + + :param port_id: Neutron port ID + :param floating_ips: floating ips list + :param networks_dict: Neutron networks dict {"id": "name"} + """ + floating_ip_addresses = [f_ip.floating_ip_address for f_ip in floating_ips + if f_ip.port_id == port_id] + floating_network_ids = [f_ip.floating_network_id for f_ip in floating_ips + if f_ip.port_id == port_id] + floating_network_names = [networks_dict.get(id).name + for id in floating_network_ids] + return floating_ip_addresses, floating_network_names diff --git a/esiclient/v1/node_network.py b/esiclient/v1/node_network.py index 892ccbc..2163188 100644 --- a/esiclient/v1/node_network.py +++ b/esiclient/v1/node_network.py @@ -72,6 +72,11 @@ def take_action(self, parsed_args): else: neutron_ports = list(neutron_client.ports()) + floating_ips = list(neutron_client.ips()) + + networks = list(neutron_client.networks()) + networks_dict = {n.id: n for n in networks} + data = [] for port in ports: @@ -92,15 +97,26 @@ def take_action(self, parsed_args): if not filter_network or filter_network.id == network_id: network_names, _, fixed_ips \ = utils.get_full_network_info_from_port( - neutron_port, neutron_client) + neutron_port, neutron_client, networks_dict) + floating_ip_addresses, floating_network_names \ + = utils.get_floating_ip(neutron_port_id, + floating_ips, + networks_dict) data.append([node_name, port.address, neutron_port.name, "\n".join(network_names), - "\n".join(fixed_ips)]) + "\n".join(fixed_ips), + "\n".join(floating_network_names) + if floating_network_names else None, + "\n".join(floating_ip_addresses) + if floating_ip_addresses else None] + ) elif not filter_network: - data.append([node_name, port.address, None, None, None]) + data.append([node_name, port.address, + None, None, None, None, None]) - return ["Node", "MAC Address", "Port", "Network", "Fixed IP"], data + return ["Node", "MAC Address", "Port", "Network", "Fixed IP", + "Floating Network", "Floating IP"], data class Attach(command.ShowOne): diff --git a/esiclient/v1/switch.py b/esiclient/v1/switch.py index 73c2403..5cfb5b2 100644 --- a/esiclient/v1/switch.py +++ b/esiclient/v1/switch.py @@ -105,6 +105,8 @@ def take_action(self, parsed_args): if port.local_link_connection.get( 'switch_info') == switch)) neutron_ports = list(neutron_client.ports()) + networks = list(neutron_client.networks()) + networks_dict = {n.id: n for n in networks} data = [] for port in ports: @@ -117,7 +119,7 @@ def take_action(self, parsed_args): if np: network_names, _, _ = \ utils.get_full_network_info_from_port( - np, neutron_client) + np, neutron_client, networks_dict) data.append([switchport, "\n".join(network_names)]) return ["Port", "VLANs"], data diff --git a/esiclient/v1/trunk.py b/esiclient/v1/trunk.py index e92f8b5..851767e 100644 --- a/esiclient/v1/trunk.py +++ b/esiclient/v1/trunk.py @@ -33,13 +33,15 @@ def take_action(self, parsed_args): neutron_client = self.app.client_manager.network trunks = neutron_client.trunks() + networks = list(neutron_client.networks()) + networks_dict = {n.id: n for n in networks} data = [] for trunk in trunks: trunk_port = neutron_client.get_port(trunk.port_id) network_names, port_names, _ \ = utils.get_full_network_info_from_port( - trunk_port, neutron_client) + trunk_port, neutron_client, networks_dict) data.append([trunk.name, "\n".join(port_names), "\n".join(network_names)]) diff --git a/tox.ini b/tox.ini index c2d6c10..67cfc1b 100644 --- a/tox.ini +++ b/tox.ini @@ -2,6 +2,7 @@ minversion = 3.2.0 envlist = pep8,py37,py36 skipsdist = True +ignore_basepython_conflict = true [testenv] basepython = python3