From bc24ef82ecac3c6ab55ca8733eeb3a16d0ffe212 Mon Sep 17 00:00:00 2001 From: zhaohua Date: Wed, 24 Feb 2016 17:41:29 +0800 Subject: [PATCH] Huawei driver improve support of StandaloneNetworkPlugin Add 'None' as a legal value of 'network_type' Add choose the port which has least number of logic port to setup server in flat network. Change-Id: Id6bd63fce62004f8ff54e6959931cb7a175bbf93 Closes-Bug: #1549183 --- manila/share/drivers/huawei/constants.py | 3 ++ manila/share/drivers/huawei/v3/connection.py | 54 +++++++++++++++---- .../share/drivers/huawei/test_huawei_nas.py | 38 +++++++++++++ 3 files changed, 84 insertions(+), 11 deletions(-) diff --git a/manila/share/drivers/huawei/constants.py b/manila/share/drivers/huawei/constants.py index 7b32114d25..c1abd2d19a 100644 --- a/manila/share/drivers/huawei/constants.py +++ b/manila/share/drivers/huawei/constants.py @@ -50,6 +50,9 @@ PORT_TYPE_ETH = '1' PORT_TYPE_BOND = '7' PORT_TYPE_VLAN = '8' +SORT_BY_VLAN = 1 +SORT_BY_LOGICAL = 2 + ALLOC_TYPE_THIN_FLAG = "1" ALLOC_TYPE_THICK_FLAG = "0" diff --git a/manila/share/drivers/huawei/v3/connection.py b/manila/share/drivers/huawei/v3/connection.py index ca6b25de38..c3343572a0 100644 --- a/manila/share/drivers/huawei/v3/connection.py +++ b/manila/share/drivers/huawei/v3/connection.py @@ -1215,7 +1215,7 @@ class V3StorageConnection(driver.HuaweiBase): } def _check_network_type_validate(self, network_type): - if network_type not in ('flat', 'vlan'): + if network_type not in ('flat', 'vlan', None): err_msg = (_( 'Invalid network type. Network type must be flat or vlan.')) raise exception.NetworkBadConfigurationException(reason=err_msg) @@ -1335,7 +1335,7 @@ class V3StorageConnection(driver.HuaweiBase): self.helper.add_LDAP_config(server, domain) def _create_vlan_and_logical_port(self, vlan_tag, ip, subnet): - optimal_port, port_type = self._get_optimal_port() + optimal_port, port_type = self._get_optimal_port(vlan_tag) port_id = self.helper.get_port_id(optimal_port, port_type) home_port_id = port_id home_port_type = port_type @@ -1372,7 +1372,7 @@ class V3StorageConnection(driver.HuaweiBase): return vlan_id, logical_port_id - def _get_optimal_port(self): + def _get_optimal_port(self, vlan_tag): """Get an optimal physical port or bond port.""" root = self.helper._read_xml() port_info = [] @@ -1385,8 +1385,14 @@ class V3StorageConnection(driver.HuaweiBase): port_info.append(port) eth_port, bond_port = self._get_online_port(port_info) - optimal_port, port_type = ( - self._get_least_vlan_port(eth_port, bond_port)) + if vlan_tag: + optimal_port, port_type = ( + self._get_least_port(eth_port, bond_port, + sort_type=constants.SORT_BY_VLAN)) + else: + optimal_port, port_type = ( + self._get_least_port(eth_port, bond_port, + sort_type=constants.SORT_BY_LOGICAL)) if not optimal_port: err_msg = (_("Cannot find optimal port. port_info: %s.") @@ -1438,28 +1444,33 @@ class V3StorageConnection(driver.HuaweiBase): return filtered_eth_port, filtered_bond_port - def _get_least_vlan_port(self, eth_port, bond_port): + def _get_least_port(self, eth_port, bond_port, sort_type): sorted_eth = [] sorted_bond = [] + if sort_type == constants.SORT_BY_VLAN: + _get_sorted_least_port = self._get_sorted_least_port_by_vlan + else: + _get_sorted_least_port = self._get_sorted_least_port_by_logical + if eth_port: - sorted_eth = self._get_sorted_least_port(eth_port) + sorted_eth = _get_sorted_least_port(eth_port) if bond_port: - sorted_bond = self._get_sorted_least_port(bond_port) + sorted_bond = _get_sorted_least_port(bond_port) if sorted_eth and sorted_bond: if sorted_eth[1] >= sorted_bond[1]: return sorted_bond[0], constants.PORT_TYPE_BOND else: return sorted_eth[0], constants.PORT_TYPE_ETH - elif sorted_eth and not sorted_bond: + elif sorted_eth: return sorted_eth[0], constants.PORT_TYPE_ETH - elif not sorted_eth and sorted_bond: + elif sorted_bond: return sorted_bond[0], constants.PORT_TYPE_BOND else: return None, None - def _get_sorted_least_port(self, port_list): + def _get_sorted_least_port_by_vlan(self, port_list): if not port_list: return None @@ -1478,6 +1489,27 @@ class V3StorageConnection(driver.HuaweiBase): return sort_port[0] + def _get_sorted_least_port_by_logical(self, port_list): + if not port_list: + return None + + logical_list = self.helper.get_all_logical_port() + count = {} + for item in port_list: + count[item] = 0 + for logical in logical_list: + if logical['HOMEPORTTYPE'] == constants.PORT_TYPE_VLAN: + pos = logical['HOMEPORTNAME'].rfind('.') + if logical['HOMEPORTNAME'][:pos] == item: + count[item] += 1 + else: + if logical['HOMEPORTNAME'] == item: + count[item] += 1 + + sort_port = sorted(count.items(), key=lambda count: count[1]) + + return sort_port[0] + def teardown_server(self, server_details, security_services=None): if not server_details: LOG.debug('Server details are empty.') diff --git a/manila/tests/share/drivers/huawei/test_huawei_nas.py b/manila/tests/share/drivers/huawei/test_huawei_nas.py index bbdac98962..deb0682ea0 100644 --- a/manila/tests/share/drivers/huawei/test_huawei_nas.py +++ b/manila/tests/share/drivers/huawei/test_huawei_nas.py @@ -2989,6 +2989,44 @@ class HuaweiShareDriverTestCase(test.TestCase): self.assertEqual(self.fake_network_allocations[0]['ip_address'], backend_details['ip']) + @dec_driver_handles_share_servers + def test_setup_server_choose_least_logic_port(self): + self.recreate_fake_conf_file( + logical_port='CTE0.A.H0;CTE0.A.H2;CTE0.B.H0;BOND0') + self.driver.plugin.configuration.manila_huawei_conf_file = ( + self.fake_conf_file) + fake_network_info = { + 'server_id': '0', + 'segmentation_id': None, + 'cidr': '111.111.111.0/24', + 'network_allocations': self.fake_network_allocations, + 'network_type': None, + } + self.mock_object(self.driver.plugin, '_get_online_port', + mock.Mock(return_value=(['CTE0.A.H0', 'CTE0.A.H2', + 'CTE0.B.H0'], ['BOND0']))) + self.mock_object(self.driver.plugin.helper, 'get_all_logical_port', + mock.Mock(return_value=[ + {'HOMEPORTTYPE': constants.PORT_TYPE_ETH, + 'HOMEPORTNAME': 'CTE0.A.H0'}, + {'HOMEPORTTYPE': constants.PORT_TYPE_VLAN, + 'HOMEPORTNAME': 'CTE0.B.H0.10'}, + {'HOMEPORTTYPE': constants.PORT_TYPE_BOND, + 'HOMEPORTNAME': 'BOND0'}])) + self.mock_object(self.driver.plugin.helper, + 'get_port_id', + mock.Mock(return_value=4)) + + backend_details = self.driver.setup_server(fake_network_info) + + self.assertEqual(self.fake_network_allocations[0]['ip_address'], + backend_details['ip']) + self.driver.plugin._get_online_port.assert_called_once_with( + ['CTE0.A.H0', 'CTE0.A.H2', 'CTE0.B.H0', 'BOND0']) + self.assertTrue(self.driver.plugin.helper.get_all_logical_port.called) + self.driver.plugin.helper.get_port_id.assert_called_once_with( + 'CTE0.A.H2', constants.PORT_TYPE_ETH) + @dec_driver_handles_share_servers def test_setup_server_create_vlan_fail(self): def call_create_vlan_fail(*args, **kwargs):