From 74c99fb40d4621c6c0915764537dfb54cc6519ca Mon Sep 17 00:00:00 2001 From: Juergen Brendel Date: Wed, 6 Aug 2014 01:23:52 +0000 Subject: [PATCH] Enabled Cisco ML2 driver to use new upstream ncclient The code is still able to handle the old, custom ncclient that we used before. It uses the different function signatures for the ncclient's connect() function to detect which version is installed. Change-Id: I09d81b424d86f4cd35ca048507f06471246b91d8 Closes-Bug: 1352635 --- .../cisco/nexus/nexus_network_driver.py | 22 ++++++++--- .../drivers/cisco/nexus/test_cisco_mech.py | 39 +++++++++++++++++++ 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/neutron/plugins/ml2/drivers/cisco/nexus/nexus_network_driver.py b/neutron/plugins/ml2/drivers/cisco/nexus/nexus_network_driver.py index 983678d11..33ba85e98 100644 --- a/neutron/plugins/ml2/drivers/cisco/nexus/nexus_network_driver.py +++ b/neutron/plugins/ml2/drivers/cisco/nexus/nexus_network_driver.py @@ -65,7 +65,7 @@ class CiscoNexusDriver(object): allowed_exc_strs = [] mgr = self.nxos_connect(nexus_host) try: - mgr.edit_config(target, config=config) + mgr.edit_config(target=target, config=config) except Exception as e: for exc_str in allowed_exc_strs: if exc_str in str(e): @@ -86,16 +86,26 @@ class CiscoNexusDriver(object): nexus_user = self.nexus_switches[nexus_host, const.USERNAME] nexus_password = self.nexus_switches[nexus_host, const.PASSWORD] try: - man = self.ncclient.connect(host=nexus_host, - port=nexus_ssh_port, - username=nexus_user, - password=nexus_password) - self.connections[nexus_host] = man + try: + # With new ncclient version, we can pass device_params... + man = self.ncclient.connect(host=nexus_host, + port=nexus_ssh_port, + username=nexus_user, + password=nexus_password, + device_params={"name": "nexus"}) + except TypeError: + # ... but if that causes an error, we appear to have the old + # ncclient installed, which doesn't understand this parameter. + man = self.ncclient.connect(host=nexus_host, + port=nexus_ssh_port, + username=nexus_user, + password=nexus_password) except Exception as e: # Raise a Neutron exception. Include a description of # the original ncclient exception. raise cexc.NexusConnectFailed(nexus_host=nexus_host, exc=e) + self.connections[nexus_host] = man return self.connections[nexus_host] def create_xml_snippet(self, customized_config): diff --git a/neutron/tests/unit/ml2/drivers/cisco/nexus/test_cisco_mech.py b/neutron/tests/unit/ml2/drivers/cisco/nexus/test_cisco_mech.py index 5968d2422..43d6b41ad 100644 --- a/neutron/tests/unit/ml2/drivers/cisco/nexus/test_cisco_mech.py +++ b/neutron/tests/unit/ml2/drivers/cisco/nexus/test_cisco_mech.py @@ -408,6 +408,45 @@ class TestCiscoPortsV2(CiscoML2MechanismTestCase, self._is_in_last_nexus_cfg(['allowed', 'vlan'])) self.assertFalse(self._is_in_last_nexus_cfg(['name'])) + def test_ncclient_version_detect(self): + """Test ability to handle connection to old and new-style ncclient. + + We used to require a custom version of the ncclient library. However, + recent contributions to the ncclient make this unnecessary. Our + driver was modified to be able to establish a connection via both + the old and new type of ncclient. + + The new style ncclient.connect() function takes one additional + parameter. + + The ML2 driver uses this to detect whether we are dealing with an + old or new ncclient installation. + + """ + # The code we are exercising calls connect() twice, if there is a + # TypeError on the first call (if the old ncclient is installed). + # The second call should succeed. That's what we are simulating here. + connect = self.mock_ncclient.connect + with self._patch_ncclient('connect.side_effect', + [TypeError, connect]): + with self._create_resources() as result: + self.assertEqual(result.status_int, + wexc.HTTPOk.code) + + def test_ncclient_fail_on_second_connect(self): + """Test that other errors during connect() sequences are still handled. + + If the old ncclient is installed, we expect to get a TypeError first, + but should still handle other errors in the usual way, whether they + appear on the first or second call to connect(). + + """ + with self._patch_ncclient('connect.side_effect', + [TypeError, IOError]): + with self._create_resources() as result: + self._assertExpectedHTTP(result.status_int, + c_exc.NexusConnectFailed) + def test_nexus_connect_fail(self): """Test failure to connect to a Nexus switch. -- 2.45.2