]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
HP 3PAR configurable ssh-host-key-policy
authorMark Sturdevant <mark.sturdevant@hp.com>
Tue, 2 Sep 2014 23:25:47 +0000 (16:25 -0700)
committerMark Sturdevant <mark.sturdevant@hp.com>
Wed, 10 Sep 2014 18:22:56 +0000 (11:22 -0700)
Cinder added configurable SSH strict key policy (RejectPolicy)
and configurable known_hosts_file.  This patch configures the
hp3parclient (used by the 3PAR drivers) using those settings.

Change-Id: I71fa7d8be28d1cb7c0102590e03cba994b6035a0
Closes-bug: 1365697

cinder/tests/fake_hp_client_exceptions.py
cinder/tests/test_hp3par.py
cinder/volume/drivers/san/hp/hp_3par_common.py

index 5f61e8b5cdc0057ed7953dfbe6d86e44265bf489..eda6efabcaeb27c5ddeb0cb6b649882cb0c8be62 100644 (file)
 """Fake HP client exceptions to use when mocking HP clients."""
 
 
+class UnsupportedVersion(Exception):
+    """Unsupported version of the client."""
+    pass
+
+
 class ClientException(Exception):
     """The base exception class for these fake exceptions."""
     _error_code = None
index 9875a5678d079427e3fd94333e28df437994d380..274145a84c382ea3111d2abf6ddbc68e4ea76428 100644 (file)
@@ -19,6 +19,8 @@ import mock
 
 import ast
 
+from oslo.config import cfg
+
 from cinder import context
 from cinder import exception
 from cinder.openstack.common import log as logging
@@ -34,6 +36,8 @@ hpexceptions = hp3parclient.hpexceptions
 
 LOG = logging.getLogger(__name__)
 
+CONF = cfg.CONF
+
 HP3PAR_CPG = 'OpenStackCPG'
 HP3PAR_CPG_SNAP = 'OpenStackCPGSnap'
 HP3PAR_USER_NAME = 'testUser'
@@ -385,6 +389,90 @@ class HP3PARBaseDriver(object):
         self.driver.do_setup(None)
         return _m_client
 
+    @mock.patch('hp3parclient.version', "3.0.9")
+    def test_unsupported_client_version(self):
+
+        self.assertRaises(exception.InvalidInput,
+                          self.setup_driver)
+
+    @mock.patch('hp3parclient.version', "3.1.0")
+    def test_ssh_options_310(self):
+
+        self.ctxt = context.get_admin_context()
+        mock_client = self.setup_mock_client(driver=hpfcdriver.HP3PARFCDriver)
+        expected = [
+            mock.call.setSSHOptions(
+                HP3PAR_SAN_IP,
+                HP3PAR_USER_NAME,
+                HP3PAR_USER_PASS,
+                privatekey=HP3PAR_SAN_SSH_PRIVATE,
+                port=HP3PAR_SAN_SSH_PORT,
+                conn_timeout=HP3PAR_SAN_SSH_CON_TIMEOUT),
+            mock.call.login(HP3PAR_USER_NAME, HP3PAR_USER_PASS),
+            mock.call.getCPG(HP3PAR_CPG),
+            mock.call.logout()]
+        mock_client.assert_has_calls(expected)
+
+    @mock.patch('hp3parclient.version', "3.1.1")
+    def test_ssh_options(self):
+
+        expected_hosts_key_file = "test_hosts_key_file"
+        orig_ssh_hosts_key_file = CONF.ssh_hosts_key_file
+        orig_strict_ssh_host_key_policy = CONF.strict_ssh_host_key_policy
+        CONF.ssh_hosts_key_file = expected_hosts_key_file
+        CONF.strict_ssh_host_key_policy = False
+
+        self.ctxt = context.get_admin_context()
+        mock_client = self.setup_mock_client(driver=hpfcdriver.HP3PARFCDriver)
+
+        CONF.ssh_hosts_key_file = orig_ssh_hosts_key_file
+        CONF.strict_ssh_host_key_policy = orig_strict_ssh_host_key_policy
+
+        expected = [
+            mock.call.setSSHOptions(
+                HP3PAR_SAN_IP,
+                HP3PAR_USER_NAME,
+                HP3PAR_USER_PASS,
+                privatekey=HP3PAR_SAN_SSH_PRIVATE,
+                known_hosts_file=expected_hosts_key_file,
+                missing_key_policy="AutoAddPolicy",
+                port=HP3PAR_SAN_SSH_PORT,
+                conn_timeout=HP3PAR_SAN_SSH_CON_TIMEOUT),
+            mock.call.login(HP3PAR_USER_NAME, HP3PAR_USER_PASS),
+            mock.call.getCPG(HP3PAR_CPG),
+            mock.call.logout()]
+        mock_client.assert_has_calls(expected)
+
+    @mock.patch('hp3parclient.version', "3.1.1")
+    def test_ssh_options_strict(self):
+
+        expected_hosts_key_file = "test_hosts_key_file"
+        orig_ssh_hosts_key_file = CONF.ssh_hosts_key_file
+        orig_strict_ssh_host_key_policy = CONF.strict_ssh_host_key_policy
+        CONF.ssh_hosts_key_file = expected_hosts_key_file
+        CONF.strict_ssh_host_key_policy = True
+
+        self.ctxt = context.get_admin_context()
+        mock_client = self.setup_mock_client(driver=hpfcdriver.HP3PARFCDriver)
+
+        CONF.ssh_hosts_key_file = orig_ssh_hosts_key_file
+        CONF.strict_ssh_host_key_policy = orig_strict_ssh_host_key_policy
+
+        expected = [
+            mock.call.setSSHOptions(
+                HP3PAR_SAN_IP,
+                HP3PAR_USER_NAME,
+                HP3PAR_USER_PASS,
+                privatekey=HP3PAR_SAN_SSH_PRIVATE,
+                known_hosts_file=expected_hosts_key_file,
+                missing_key_policy="RejectPolicy",
+                port=HP3PAR_SAN_SSH_PORT,
+                conn_timeout=HP3PAR_SAN_SSH_CON_TIMEOUT),
+            mock.call.login(HP3PAR_USER_NAME, HP3PAR_USER_PASS),
+            mock.call.getCPG(HP3PAR_CPG),
+            mock.call.logout()]
+        mock_client.assert_has_calls(expected)
+
     def test_task_waiter(self):
 
         task_statuses = [self.STATUS_ACTIVE, self.STATUS_ACTIVE]
index 759c2173765073d4f1ab52620b666e3147d8fd5b..3e26e0a7fb06bac4cbceb3bd3304c513528f4c4a 100644 (file)
@@ -67,6 +67,7 @@ from taskflow.patterns import linear_flow
 LOG = logging.getLogger(__name__)
 
 MIN_CLIENT_VERSION = '3.1.0'
+MIN_CLIENT_SSH_ARGS_VERSION = '3.1.1'
 
 hp3par_opts = [
     cfg.StrOpt('hp3par_api_url',
@@ -146,10 +147,11 @@ class HP3PARCommon(object):
                  and hp3parclient 3.1.0
         2.0.18 - HP 3PAR manage_existing with volume-type support
         2.0.19 - Update default persona from Generic to Generic-ALUA
+        2.0.20 - Configurable SSH missing key policy and known hosts file
 
     """
 
-    VERSION = "2.0.19"
+    VERSION = "2.0.20"
 
     stats = {}
 
@@ -210,12 +212,26 @@ class HP3PARCommon(object):
             LOG.error(ex_msg)
             raise exception.InvalidInput(reason=ex_msg)
 
-        cl.setSSHOptions(self.config.san_ip,
-                         self.config.san_login,
-                         self.config.san_password,
-                         port=self.config.san_ssh_port,
-                         conn_timeout=self.config.ssh_conn_timeout,
-                         privatekey=self.config.san_private_key)
+        if client_version < MIN_CLIENT_SSH_ARGS_VERSION:
+            cl.setSSHOptions(self.config.san_ip,
+                             self.config.san_login,
+                             self.config.san_password,
+                             port=self.config.san_ssh_port,
+                             conn_timeout=self.config.ssh_conn_timeout,
+                             privatekey=self.config.san_private_key)
+        else:
+            known_hosts_file = CONF.ssh_hosts_key_file
+            policy = "AutoAddPolicy"
+            if CONF.strict_ssh_host_key_policy:
+                policy = "RejectPolicy"
+            cl.setSSHOptions(self.config.san_ip,
+                             self.config.san_login,
+                             self.config.san_password,
+                             port=self.config.san_ssh_port,
+                             conn_timeout=self.config.ssh_conn_timeout,
+                             privatekey=self.config.san_private_key,
+                             missing_key_policy=policy,
+                             known_hosts_file=known_hosts_file)
 
         return cl