#
import mock
+from oslo_concurrency import processutils
from oslo_config import cfg
from cinder.openstack.common import log as logging
from cinder import test
from cinder import utils
from cinder.volume.drivers.hds import hnas_backend
-
+from cinder.volume.drivers.hds import nfs
CONF = cfg.CONF
1031 cinder2 0xaadfcf7e0769a6bc 1 EVSTest1\n\
1024 fs02-husvm 0xaac8715e2e9406cd 2 EVSTest2\n\
\n"
+
HNAS_RESULT2 = "cluster MAC: 83-68-96-AA-DA-5D"
+
HNAS_RESULT3 = "\n\
Model: HNAS 4040 \n\
Software: 11.2.3319.14 (built 2013-09-19 12:34:24+01:00) \n\
board MCP \n\
Serial no B1339109 (Thu Jan 1 00:00:49 2009) \n\
\n"
+
HNAS_RESULT4 = "\n\
EVS Type Label IP Address Mask Port \n\
---------- --------------- ------------------ --------------- ------\n\
evs 1 EVSTest1 10.0.0.20 255.255.255.0 ag1 \n\
evs 2 EVSTest2 172.24.44.21 255.255.255.0 ag1 \n\
\n"
+
HNAS_RESULT5 = "\n\
- ID Label EVS Size Used Snapshots Deduped Avail\
- Thin ThinSize ThinAvail FS Type \n\
----- ----------- --- ------- ------------- --------- -------- -------\
------- ---- -------- --------- ---------------------------------- \n\
-1025 fs01-husvm 1 250 GB 21.4 GB (9%) 0 B (0%) NA 228 GB\
- (91%) No 32 KB,WFS-2,128 DSBs\n\
-1026 gold 1 19.9 GB 2.30 GB (12% NA 0 B (0%) 17.6 GB\
- (88%) No 4 KB,WFS-2,128 DSBs,dedupe enabled\n\
-1027 large-files 1 19.8 GB 2.43 GB (12%) 0 B (0%) NA 17.3 GB\
- (88%) No 32 KB,WFS-2,128 DSBs\n\
-1028 platinun 1 19.9 GB 2.30 GB (12%) NA 0 B (0%) 17.6 GB\
- (88%) No 4 KB,WFS-2,128 DSBs,dedupe enabled\n\
-1029 silver 1 19.9 GB 3.19 GB (16%) 0 B (0%) NA 6.7 GB\
- (84%) No 4 KB,WFS-2,128 DSBs\n\
-1030 cinder1 1 40.8 GB 2.24 GB (5%) 0 B (0%) NA 38.5 GB\
- (95%) No 4 KB,WFS-2,128 DSBs\n\
-1031 cinder2 1 39.8 GB 2.23 GB (6%) 0 B (0%) NA 37.6 GB\
- (94%) No 4 KB,WFS-2,128 DSBs\n\
-1024 fs02-husvm 2 49.8 GB 3.54 GB (7%) 0 B (0%) NA 46.2 GB\
- (93%) No 32 KB,WFS-2,128 DSBs\n\
-1032 test 2 3.97 GB 2.12 GB (53%) 0 B (0%) NA 1.85 GB\
- (47%) No 4 KB,WFS-2,128 DSBs\n\
+ ID Label EVS Size Used Snapshots Deduped\
+ Avail Thin ThinSize ThinAvail \
+ FS Type \n\
+---- ----------- --- ------- ------------- --------- -------\
+- ------------- ---- -------- --------- ---------------------\
+------------- \n\
+1025 fs01-husvm 1 250 GB 21.4 GB (9%) 0 B (0%) NA \
+ 228 GB (91%) No 32 KB,\
+ WFS-2,128 DSBs\n\
+1026 gold 1 19.9 GB 2.30 GB (12% NA 0 B (0%)\
+ 17.6 GB (88%) No 4 KB,WFS-2,128 DSBs,\
+ dedupe enabled\n\
+1027 large-files 1 19.8 GB 2.43 GB (12%) 0 B (0%) NA \
+ 17.3 GB (88%) No 32 KB,\
+ WFS-2,128 DSBs\n\
+1028 platinun 1 19.9 GB 2.30 GB (12%) NA 0 B (0%)\
+ 17.6 GB (88%) No 4 KB,WFS-2,128 DSBs,\
+ dedupe enabled\n\
+1029 silver 1 19.9 GB 3.19 GB (16%) 0 B (0%) NA \
+ 6.7 GB (84%) No 4 KB,\
+ WFS-2,128 DSBs\n\
+1030 cinder1 1 40.8 GB 2.24 GB (5%) 0 B (0%) NA \
+ 38.5 GB (95%) No 4 KB,\
+ WFS-2,128 DSBs\n\
+1031 cinder2 1 39.8 GB 2.23 GB (6%) 0 B (0%) NA \
+ 37.6 GB (94%) No 4 KB,\
+ WFS-2,128 DSBs\n\
+1024 fs02-husvm 2 49.8 GB 3.54 GB (7%) 0 B (0%) NA \
+ 46.2 GB (93%) No 32 KB,\
+ WFS-2,128 DSBs\n\
+1032 test 2 3.97 GB 2.12 GB (53%) 0 B (0%) NA \
+ 1.85 GB (47%) No 4 KB,\
+ WFS-2,128 DSBs\n\
\n"
+
HNAS_RESULT6 = "\n\
-ID Label EVS Size Used Snapshots Deduped Avail\
- Thin ThinSize ThinAvail FS Type\n\
----- ---------- --- ------ ------------ --------- ------- ------------\
- ---- -------- --------- --------------------\n\
-1025 fs01-husvm 1 250 GB 21.4 GB (9%) 0 B (0%) NA 228 GB (91%)\
- No 32 KB,WFS-2,128 DSBs\n\
+ID Label EVS Size Used Snapshots Deduped Avail \
+Thin ThinSize ThinAvail FS Type\n\
+---- ---------- --- ------ ------------ --------- ------- ------------ \
+---- -------- --------- --------------------\n\
+1025 fs01-husvm 1 250 GB 21.4 GB (9%) 0 B (0%) NA 228 GB (91%) \
+ No 32 KB,WFS-2,128 DSBs\n\
\n"
+
HNAS_RESULT7 = "\n\
Export configuration: \n\
Export name: /export01-husvm \n\
Recovered = No \n\
Transfer setting = Use file system default \n\
\n"
+
HNAS_RESULT8 = "Logical unit creation started at 2014-12-24 00:38:30+00:00."
HNAS_RESULT9 = "Logical unit deleted successfully."
HNAS_RESULT10 = ""
HNAS_RESULT11 = "Logical unit expansion started at 2014-12-24 01:25:03+00:00."
+
HNAS_RESULT12 = "\n\
Alias : test_iqn \n\
Globally unique name: iqn.2014-12.10.10.10.10:evstest1.cinder-silver \n\
Authentication : Enabled \n\
Logical units : No logical units. \n\
\n"
+
HNAS_RESULT13 = "Logical unit added successfully."
HNAS_RESULT14 = "Logical unit removed successfully."
HNAS_RESULT15 = "Target created successfully."
HNAS_RESULT16 = ""
+
HNAS_RESULT17 = "\n\
EVS Type Label IP Address Mask Port \n\
---------- --------------- ------------------ --------------- ------\n\
\n"
HNAS_CMDS = {
- ('ssc', '-u', 'supervisor', '-p', 'supervisor', '0.0.0.0', 'evsfs',
- u'list'): ["%s" % HNAS_RESULT1, ""],
- ('ssc', '-u', 'supervisor', '-p', 'supervisor', '0.0.0.0',
- 'cluster-getmac'): ["%s" % HNAS_RESULT2, ""],
- ('ssc', '-version',): ["%s" % HNAS_RESULT18, ""],
- ('ssc', '-u', 'supervisor', '-p', 'supervisor', '0.0.0.0', 'ver',):
+ ('ssh', '0.0.0.0', 'supervisor', 'supervisor', 'evsfs', 'list'):
+ ["%s" % HNAS_RESULT1, ""],
+ ('ssh', '0.0.0.0', 'supervisor', 'supervisor', 'cluster-getmac',):
+ ["%s" % HNAS_RESULT2, ""],
+ ('ssh', '-version',): ["%s" % HNAS_RESULT18, ""],
+ ('ssh', '-u', 'supervisor', '-p', 'supervisor', '0.0.0.0', 'ver',):
["%s" % HNAS_RESULT3, ""],
- ('ssc', '-u', 'supervisor', '-p', 'supervisor', '0.0.0.0', 'evsipaddr',
- '-l'): ["%s" % HNAS_RESULT4, ""],
- ('ssc', '-u', 'supervisor', '-p', 'supervisor', '0.0.0.0', 'df', '-a'):
- ["%s" % HNAS_RESULT5, ""],
- ('df', '-f', 'test_hdp'): ["%s" % HNAS_RESULT6, ""],
- ('ssc', '-u', 'supervisor', '-p', 'supervisor', '0.0.0.0', 'for-each-evs',
- '-q', 'nfs-export', 'list'): ["%s" % HNAS_RESULT7, ""],
- ('ssc', '-u', 'supervisor', '-p', 'supervisor', '0.0.0.0',
+ ('ssh', '0.0.0.0', 'supervisor', 'supervisor', 'ver',):
+ ["%s" % HNAS_RESULT3, ""],
+ ('ssh', '0.0.0.0', 'supervisor', 'supervisor', 'evsipaddr', '-l'):
+ ["%s" % HNAS_RESULT4, ""],
+ ('ssh', '0.0.0.0', 'supervisor', 'supervisor', 'df', '-a'):
+ ["%s" % HNAS_RESULT5, ""],
+ ('ssh', '0.0.0.0', 'supervisor', 'supervisor', 'df', '-f', 'test_hdp'):
+ ["%s" % HNAS_RESULT6, ""],
+ ('ssh', '0.0.0.0', 'supervisor', 'supervisor', 'for-each-evs', '-q',
+ 'nfs-export', 'list'):
+ ["%s" % HNAS_RESULT7, ""],
+ ('ssh', '0.0.0.0', 'supervisor', 'supervisor',
'console-context', '--evs', '1', 'iscsi-lu', 'add', '-e', 'test_name',
- 'test_hdp', '/.cinder/test_name.iscsi', '1M'): ["%s" % HNAS_RESULT8, ""],
- ('ssc', '-u', 'supervisor', '-p', 'supervisor', '0.0.0.0',
+ 'test_hdp', '/.cinder/test_name.iscsi',
+ '1M'):
+ ["%s" % HNAS_RESULT8, ""],
+ ('ssh', '0.0.0.0', 'supervisor', 'supervisor',
'console-context', '--evs', '1', 'iscsi-lu', 'del', '-d', '-f',
- 'test_lun'): ["%s" % HNAS_RESULT9, ""],
- ('ssc', '-u', 'supervisor', '-p', 'supervisor', '0.0.0.0',
+ 'test_lun'):
+ ["%s" % HNAS_RESULT9, ""],
+ ('ssh', '0.0.0.0', 'supervisor', 'supervisor',
'console-context', '--evs', '1', 'file-clone-create', '-f', 'fs01-husvm',
- '/.cinder/test_lu.iscsi', 'cloned_lu'): ["%s" % HNAS_RESULT10, ""],
- ('ssc', '-u', 'supervisor', '-p', 'supervisor', '0.0.0.0',
+ '/.cinder/test_lu.iscsi', 'cloned_lu'):
+ ["%s" % HNAS_RESULT10, ""],
+ ('ssh', '0.0.0.0', 'supervisor', 'supervisor',
'console-context', '--evs', '1', 'iscsi-lu', 'expand', 'expanded_lu',
- '1M'): ["%s" % HNAS_RESULT11, ""],
- ('ssc', '-u', 'supervisor', '-p', 'supervisor', '0.0.0.0',
- 'console-context', '--evs', '1', 'iscsi-target', 'list',
- 'test_iqn'): ["%s" % HNAS_RESULT12, ""],
- ('ssc', '-u', 'supervisor', '-p', 'supervisor', '0.0.0.0',
+ '1M'):
+ ["%s" % HNAS_RESULT11, ""],
+ ('ssh', '0.0.0.0', 'supervisor', 'supervisor',
+ 'console-context', '--evs', '1', 'iscsi-target', 'list', 'test_iqn'):
+ ["%s" % HNAS_RESULT12, ""],
+ ('ssh', '0.0.0.0', 'supervisor', 'supervisor',
'console-context', '--evs', '1', 'iscsi-target', 'addlu', 'test_iqn',
- 'test_lun', 0): ["%s" % HNAS_RESULT13, ""],
- ('ssc', '-u', 'supervisor', '-p', 'supervisor', '0.0.0.0',
- 'console-context', '--evs', '1', 'iscsi-target', 'dellu', 'test_iqn', 0):
- ["%s" % HNAS_RESULT14, ""],
- ('ssc', '-u', 'supervisor', '-p', 'supervisor', '0.0.0.0',
- 'console-context', '--evs', '1', 'iscsi-target', 'add', 'test_iqn',
- 'test_secret'): ["%s" % HNAS_RESULT15, ""],
- ('ssc', '-u', 'supervisor', '-p', 'supervisor', '0.0.0.0',
+ 'test_lun', 0):
+ ["%s" % HNAS_RESULT13, ""],
+ ('ssh', '0.0.0.0', 'supervisor', 'supervisor',
+ 'console-context', '--evs', '1', 'iscsi-target', 'dellu', 'test_iqn',
+ 0):
+ ["%s" % HNAS_RESULT14, ""],
+ ('ssh', '0.0.0.0', 'supervisor', 'supervisor',
+ 'console-context', '--evs', '1', 'iscsi-target', 'add', 'myTarget',
+ 'secret'):
+ ["%s" % HNAS_RESULT15, ""],
+ ('ssh', '0.0.0.0', 'supervisor', 'supervisor',
'console-context', '--evs', '1', 'iscsi-target', 'mod', '-s',
'test_secret', '-a', 'enable', 'test_iqn'): ["%s" % HNAS_RESULT15, ""],
- ('ssc', '-u', 'supervisor', '-p', 'supervisor', '0.0.0.0',
+ ('ssh', '0.0.0.0', 'supervisor', 'supervisor',
'console-context', '--evs', '1', 'iscsi-lu', 'clone', '-e', 'test_lu',
- 'test_clone', '/.cinder/test_clone.iscsi'): ["%s" % HNAS_RESULT16, ""],
- ('ssc', '-u', 'supervisor', '-p', 'supervisor', '0.0.0.0', 'evsipaddr',
- '-e', '1'): ["%s" % HNAS_RESULT17, ""]
+ 'test_clone',
+ '/.cinder/test_clone.iscsi'):
+ ["%s" % HNAS_RESULT16, ""],
+ ('ssh', '0.0.0.0', 'supervisor', 'supervisor', 'evsipaddr', '-e', '1'):
+ ["%s" % HNAS_RESULT17, ""]
}
+DRV_CONF = {'ssh_enabled': 'True',
+ 'mgmt_ip0': '0.0.0.0',
+ 'cluster_admin_ip0': None,
+ 'ssh_port': '22',
+ 'ssh_private_key': 'test_key',
+ 'username': 'supervisor',
+ 'password': 'supervisor'}
+
+UTILS_EXEC_OUT = ["output: test_cmd", ""]
+
-def m_execute(*args, **kargs):
+def m_run_cmd(*args, **kargs):
+ print(args)
+ print(HNAS_CMDS.get(args))
return HNAS_CMDS.get(args)
class HDSHNASBendTest(test.TestCase):
- """Test HNAS NFS volume driver."""
def __init__(self, *args, **kwargs):
super(HDSHNASBendTest, self).__init__(*args, **kwargs)
- def setUp(self):
+ @mock.patch.object(nfs, 'factory_bend')
+ def setUp(self, m_factory_bend):
super(HDSHNASBendTest, self).setUp()
- self.hnas_bend = hnas_backend.HnasBackend()
+ self.hnas_bend = hnas_backend.HnasBackend(DRV_CONF)
+
+ @mock.patch('__builtin__.open')
+ @mock.patch('os.path.isfile', return_value=True)
+ @mock.patch('paramiko.RSAKey.from_private_key_file')
+ @mock.patch('paramiko.SSHClient')
+ @mock.patch.object(processutils, 'ssh_execute',
+ return_value=(HNAS_RESULT5, ''))
+ def test_run_cmd(self, m_ssh_exec, m_ssh_cli, m_pvt_key, m_file, m_open):
+ save_hkey_file = CONF.ssh_hosts_key_file
+ save_spath = CONF.state_path
+ CONF.ssh_hosts_key_file = '/var/lib/cinder/ssh_known_hosts'
+ CONF.state_path = '/var/lib/cinder'
+
+ out, err = self.hnas_bend.run_cmd('ssh', '0.0.0.0',
+ 'supervisor', 'supervisor',
+ 'df', '-a')
+ self.assertIn('fs01-husvm', out)
+ self.assertIn('WFS-2,128 DSBs', out)
+
+ CONF.state_path = save_spath
+ CONF.ssh_hosts_key_file = save_hkey_file
- @mock.patch.object(utils, 'execute', side_effect=m_execute)
- def test_get_iscsi_info(self, m_mock):
- out = self.hnas_bend.get_iscsi_info("ssc", "0.0.0.0", "supervisor",
+ @mock.patch.object(hnas_backend.HnasBackend, 'run_cmd',
+ side_effect=m_run_cmd)
+ @mock.patch.object(utils, 'execute', return_value=UTILS_EXEC_OUT)
+ def test_get_version(self, m_cmd, m_exec):
+ out = self.hnas_bend.get_version("ssh", "1.0", "0.0.0.0", "supervisor",
+ "supervisor")
+ self.assertIn('11.2.3319.14', out)
+ self.assertIn('83-68-96-AA-DA-5D', out)
+
+ @mock.patch.object(hnas_backend.HnasBackend, 'run_cmd',
+ side_effect=m_run_cmd)
+ def test_get_iscsi_info(self, m_execute):
+ out = self.hnas_bend.get_iscsi_info("ssh", "0.0.0.0", "supervisor",
"supervisor")
self.assertIn('172.24.44.20', out)
self.assertIn('10.0.0.20', out)
self.assertEqual(len(out.split('\n')), 4)
- @mock.patch.object(utils, 'execute', side_effect=m_execute)
- def test_get_version(self, m_execute):
- out = self.hnas_bend.get_version("ssc", "1.0", "0.0.0.0", "supervisor",
- "supervisor")
-
- self.assertIn('11.2.3319.14', out)
- self.assertIn('11.1.3225.01', out)
- self.assertIn('83-68-96-AA-DA-5D', out)
-
- @mock.patch.object(utils, 'execute')
- def test_get_hdp_info(self, m_exec):
+ @mock.patch.object(hnas_backend.HnasBackend, 'run_cmd')
+ def test_get_hdp_info(self, m_run_cmd):
# tests when there is two or more evs
- m_exec.return_value = (HNAS_RESULT5, "")
+ m_run_cmd.return_value = (HNAS_RESULT5, "")
out = self.hnas_bend.get_hdp_info("ssh", "0.0.0.0", "supervisor",
"supervisor")
self.assertEqual(len(line1.split()), 12)
# test when there is only one evs
- m_exec.return_value = (HNAS_RESULT19, "")
+ m_run_cmd.return_value = (HNAS_RESULT19, "")
out = self.hnas_bend.get_hdp_info("ssh", "0.0.0.0", "supervisor",
"supervisor")
self.assertEqual(len(out.split('\n')), 3)
line1 = out.split('\n')[0]
self.assertEqual(len(line1.split()), 12)
- @mock.patch.object(utils, 'execute', side_effect=m_execute)
- def test_get_nfs_info(self, m_execute):
- out = self.hnas_bend.get_nfs_info("ssc", "0.0.0.0", "supervisor",
+ @mock.patch.object(hnas_backend.HnasBackend, 'run_cmd',
+ side_effect=m_run_cmd)
+ def test_get_nfs_info(self, m_run_cmd):
+ out = self.hnas_bend.get_nfs_info("ssh", "0.0.0.0", "supervisor",
"supervisor")
self.assertEqual(len(out.split('\n')), 2)
self.assertIn('172.24.44.20', out)
self.assertIn('10.0.0.20', out)
- @mock.patch.object(utils, 'execute', side_effect=m_execute)
- def test_create_lu(self, m_execute):
- out = self.hnas_bend.create_lu("ssc", "0.0.0.0", "supervisor",
+ @mock.patch.object(hnas_backend.HnasBackend, 'run_cmd',
+ side_effect=m_run_cmd)
+ def test_create_lu(self, m_cmd):
+ out = self.hnas_bend.create_lu("ssh", "0.0.0.0", "supervisor",
"supervisor", "test_hdp", "1",
"test_name")
self.assertIn('successfully created', out)
- @mock.patch.object(utils, 'execute', side_effect=m_execute)
- def test_delete_lu(self, m_execute):
- out = self.hnas_bend.delete_lu("ssc", "0.0.0.0", "supervisor",
+ @mock.patch.object(hnas_backend.HnasBackend, 'run_cmd',
+ side_effect=m_run_cmd)
+ def test_delete_lu(self, m_cmd):
+ out = self.hnas_bend.delete_lu("ssh", "0.0.0.0", "supervisor",
"supervisor", "test_hdp", "test_lun")
self.assertIn('deleted successfully', out)
- @mock.patch.object(utils, 'execute', side_effect=m_execute)
- def test_create_dup(self, m_execute):
- out = self.hnas_bend.create_dup("ssc", "0.0.0.0", "supervisor",
+ @mock.patch.object(hnas_backend.HnasBackend, 'run_cmd',
+ side_effect=m_run_cmd)
+ def test_create_dup(self, m_cmd):
+
+ out = self.hnas_bend.create_dup("ssh", "0.0.0.0", "supervisor",
"supervisor", "test_lu", "test_hdp",
"1", "test_clone")
self.assertIn('successfully created', out)
- @mock.patch.object(utils, 'execute', side_effect=m_execute)
- def test_file_clone(self, m_execute):
- out = self.hnas_bend.file_clone("ssc", "0.0.0.0", "supervisor",
+ @mock.patch.object(hnas_backend.HnasBackend, 'run_cmd',
+ side_effect=m_run_cmd)
+ def test_file_clone(self, m_cmd):
+ out = self.hnas_bend.file_clone("ssh", "0.0.0.0", "supervisor",
"supervisor", "fs01-husvm",
"/.cinder/test_lu.iscsi", "cloned_lu")
self.assertIn('LUN cloned_lu HDP', out)
- @mock.patch.object(utils, 'execute', side_effect=m_execute)
- def test_extend_vol(self, m_execute):
- out = self.hnas_bend.extend_vol("ssc", "0.0.0.0", "supervisor",
+ @mock.patch.object(hnas_backend.HnasBackend, 'run_cmd',
+ side_effect=m_run_cmd)
+ def test_extend_vol(self, m_cmd):
+ out = self.hnas_bend.extend_vol("ssh", "0.0.0.0", "supervisor",
"supervisor", "test_hdp", "test_lun",
"1", "expanded_lu")
self.assertIn('successfully extended', out)
- @mock.patch.object(utils, 'execute', side_effect=m_execute)
- def test_add_iscsi_conn(self, m_execute):
- out = self.hnas_bend.add_iscsi_conn("ssc", "0.0.0.0", "supervisor",
+ @mock.patch.object(hnas_backend.HnasBackend, 'run_cmd',
+ side_effect=m_run_cmd)
+ def test_add_iscsi_conn(self, m_cmd):
+ out = self.hnas_bend.add_iscsi_conn("ssh", "0.0.0.0", "supervisor",
"supervisor", "test_lun",
"test_hdp", "test_port",
"test_iqn", "test_init")
self.assertIn('successfully paired', out)
- @mock.patch.object(utils, 'execute', side_effect=m_execute)
- def test_del_iscsi_conn(self, m_execute):
- out = self.hnas_bend.del_iscsi_conn("ssc", "0.0.0.0", "supervisor",
+ @mock.patch.object(hnas_backend.HnasBackend, 'run_cmd',
+ side_effect=m_run_cmd)
+ def test_del_iscsi_conn(self, m_cmd):
+ out = self.hnas_bend.del_iscsi_conn("ssh", "0.0.0.0", "supervisor",
"supervisor", "1", "test_iqn", 0)
self.assertIn('already deleted', out)
- @mock.patch.object(utils, 'execute', side_effect=m_execute)
- def test_get_targetiqn(self, m_execute):
- out = self.hnas_bend.get_targetiqn("ssc", "0.0.0.0", "supervisor",
+ @mock.patch.object(hnas_backend.HnasBackend, 'run_cmd',
+ side_effect=m_run_cmd)
+ def test_get_targetiqn(self, m_cmd):
+ out = self.hnas_bend.get_targetiqn("ssh", "0.0.0.0", "supervisor",
"supervisor", "test_iqn",
"test_hdp", "test_secret")
+
self.assertEqual('test_iqn', out)
- @mock.patch.object(utils, 'execute', side_effect=m_execute)
+ @mock.patch.object(hnas_backend.HnasBackend, 'run_cmd',
+ side_effect=m_run_cmd)
def test_set_targetsecret(self, m_execute):
- self.hnas_bend.set_targetsecret("ssc", "0.0.0.0", "supervisor",
+ self.hnas_bend.set_targetsecret("ssh", "0.0.0.0", "supervisor",
"supervisor", "test_iqn",
"test_hdp", "test_secret")
- @mock.patch.object(utils, 'execute')
- def test_get_targetsecret(self, m_exec):
+ @mock.patch.object(hnas_backend.HnasBackend, 'run_cmd')
+ def test_get_targetsecret(self, m_run_cmd):
# test when target has secret
- m_exec.return_value = (HNAS_RESULT12, "")
+ m_run_cmd.return_value = (HNAS_RESULT12, "")
out = self.hnas_bend.get_targetsecret("ssh", "0.0.0.0", "supervisor",
"supervisor", "test_iqn",
"test_hdp")
self.assertEqual('test_secret', out)
# test when target don't have secret
- m_exec.return_value = (HNAS_RESULT20, "")
+ m_run_cmd.return_value = (HNAS_RESULT20, "")
out = self.hnas_bend.get_targetsecret("ssh", "0.0.0.0", "supervisor",
"supervisor", "test_iqn",
"test_hdp")
import re
+from oslo_concurrency import processutils
from oslo_utils import units
+import six
+from cinder.i18n import _LE, _LW, _LI
from cinder.openstack.common import log as logging
+from cinder import ssh_utils
from cinder import utils
LOG = logging.getLogger("cinder.volume.driver")
-class HnasBackend():
+class HnasBackend(object):
"""Back end. Talks to HUS-HNAS."""
+ def __init__(self, drv_configs):
+ self.drv_configs = drv_configs
+ self.sshpool = None
+
+ def run_cmd(self, cmd, ip0, user, pw, *args, **kwargs):
+ """Run a command on SMU or using SSH
+
+ :param cmd: the command that will be run on SMU
+ :param ip0: string IP address of controller
+ :param user: string user authentication for array
+ :param pw: string password authentication for array
+ :returns: formated string with version information
+ """
+ LOG.debug('Enable ssh: %s',
+ six.text_type(self.drv_configs['ssh_enabled']))
+
+ if self.drv_configs['ssh_enabled'] != 'True':
+ # Direct connection via ssc
+ args = (cmd, '-u', user, '-p', pw, ip0) + args
+ out, err = utils.execute(*args, **kwargs)
+ LOG.debug("command %(cmd)s result: out = %(out)s - err = "
+ "%(err)s", {'cmd': cmd, 'out': out, 'err': err})
+ return out, err
+ else:
+ if self.drv_configs['cluster_admin_ip0'] is None:
+ # Connect to SMU through SSH and run ssc locally
+ args = (cmd, 'localhost') + args
+ else:
+ args = (cmd, '--smuauth',
+ self.drv_configs['cluster_admin_ip0']) + args
+
+ utils.check_ssh_injection(args)
+ command = ' '.join(args)
+ command = command.replace('"', '\\"')
+
+ if not self.sshpool:
+ server = self.drv_configs['mgmt_ip0']
+ port = int(self.drv_configs['ssh_port'])
+ username = self.drv_configs['username']
+ # We only accept private/public key auth
+ password = ""
+ privatekey = self.drv_configs['ssh_private_key']
+ self.sshpool = ssh_utils.SSHPool(server,
+ port,
+ None,
+ username,
+ password=password,
+ privatekey=privatekey)
+
+ with self.sshpool.item() as ssh:
+ try:
+ out, err = processutils.ssh_execute(ssh, command,
+ check_exit_code=True)
+ LOG.debug("command %(cmd)s result: out = %(out)s - err = "
+ "%(err)s", {'cmd': cmd, 'out': out, 'err': err})
+ return out, err
+ except processutils.ProcessExecutionError:
+ LOG.error(_LE("Error running SSH command."))
+ raise
+
def get_version(self, cmd, ver, ip0, user, pw):
"""Gets version information from the storage unit
:param pw: string password authentication for array
:returns: formated string with version information
"""
- out, err = utils.execute(cmd,
- "-version",
- check_exit_code=True)
- util = out.split()[1]
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw, ip0,
- "cluster-getmac",
- check_exit_code=True)
+ if (self.drv_configs['ssh_enabled'] == 'True' and
+ self.drv_configs['cluster_admin_ip0'] is not None):
+ util = 'SMU ' + cmd
+ else:
+ out, err = utils.execute(cmd,
+ "-version",
+ check_exit_code=True)
+ util = out.split()[1]
+
+ out, err = self.run_cmd(cmd, ip0, user, pw, "cluster-getmac",
+ check_exit_code=True)
hardware = out.split()[2]
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, 'ver',
- check_exit_code=True)
+ out, err = self.run_cmd(cmd, ip0, user, pw, "ver",
+ check_exit_code=True)
lines = out.split('\n')
model = ""
out = "Array_ID: %s (%s) version: %s LU: 256 RG: 0 RG_LU: 0 \
Utility_version: %s" % (hardware, model, ver, util)
- LOG.debug('get_version: ' + out + ' -- ' + err)
+ LOG.debug('get_version: %(out)s -- %(err)s', {'out': out, 'err': err})
return out
def get_iscsi_info(self, cmd, ip0, user, pw):
:returns: formated string with iSCSI information
"""
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw, ip0,
- 'evsipaddr', '-l',
- check_exit_code=True)
+ out, err = self.run_cmd(cmd, ip0, user, pw,
+ 'evsipaddr', '-l',
+ check_exit_code=True)
lines = out.split('\n')
newout = ""
newout += "CTL: %s Port: 0 IP: %s Port: 3260 Link: Up\n" \
% (evsnum, ip)
- LOG.debug('get_iscsi_info: ' + out + ' -- ' + err)
+ LOG.debug('get_iscsi_info: %(out)s -- %(err)s',
+ {'out': out, 'err': err})
return newout
def get_hdp_info(self, cmd, ip0, user, pw):
:returns: formated string with filesystems and fsids
"""
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, 'df', '-a',
- check_exit_code=True)
+ out, err = self.run_cmd(cmd, ip0, user, pw, 'df', '-a',
+ check_exit_code=True)
lines = out.split('\n')
single_evs = True
int(float(used) * usedmultiplier),
int(percent), fslabel)
- LOG.debug('get_hdp_info: ' + newout + ' -- ' + err)
+ LOG.debug('get_hdp_info: %(out)s -- %(err)s',
+ {'out': newout, 'err': err})
return newout
def _get_evs(self, cmd, ip0, user, pw, fsid):
"""Gets the EVSID for the named filesystem."""
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw, ip0,
- "evsfs", "list",
- check_exit_code=True)
- LOG.debug('get_evs: out ' + out)
+ out, err = self.run_cmd(cmd, ip0, user, pw, "evsfs", "list",
+ check_exit_code=True)
+ LOG.debug('get_evs: out %s', out)
lines = out.split('\n')
for line in lines:
if fsid in line and (fsid == inf[0] or fsid == inf[1]):
return inf[3]
- LOG.warn('get_evs: ' + out + ' -- ' + 'No info for ' + fsid)
+ LOG.warning(_LW('get_evs: %(out)s -- No find for %(fsid)s'),
+ {'out': out, 'fsid': fsid})
return 0
def _get_evsips(self, cmd, ip0, user, pw, evsid):
"""Gets the EVS IPs for the named filesystem."""
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw, ip0,
- 'evsipaddr', '-e', evsid,
- check_exit_code=True)
+ out, err = self.run_cmd(cmd, ip0, user, pw,
+ 'evsipaddr', '-e', evsid,
+ check_exit_code=True)
iplist = ""
lines = out.split('\n')
if 'evs' in line:
iplist += inf[3] + ' '
- LOG.debug('get_evsips: ' + iplist)
+ LOG.debug('get_evsips: %s', iplist)
return iplist
def _get_fsid(self, cmd, ip0, user, pw, fslabel):
"""Gets the FSID for the named filesystem."""
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, 'evsfs', 'list',
- check_exit_code=True)
- LOG.debug('get_fsid: out ' + out)
+ out, err = self.run_cmd(cmd, ip0, user, pw, 'evsfs', 'list',
+ check_exit_code=True)
+ LOG.debug('get_fsid: out %s', out)
lines = out.split('\n')
for line in lines:
inf = line.split()
if fslabel in line and fslabel == inf[1]:
- LOG.debug('get_fsid: ' + line)
+ LOG.debug('get_fsid: %s', line)
return inf[0]
- LOG.warn('get_fsid: ' + out + ' -- ' + 'No infor for ' + fslabel)
+ LOG.warning(_LW('get_fsid: %(out)s -- No info for %(fslabel)s'),
+ {'out': out, 'fslabel': fslabel})
return 0
def get_nfs_info(self, cmd, ip0, user, pw):
:returns: formated string
"""
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw, ip0,
- 'for-each-evs', '-q',
- 'nfs-export', 'list',
- check_exit_code=True)
+ out, err = self.run_cmd(cmd, ip0, user, pw,
+ 'for-each-evs', '-q',
+ 'nfs-export', 'list',
+ check_exit_code=True)
lines = out.split('\n')
newout = ""
% (export, path, fs, fsid, evsid, ips)
fs = ""
- LOG.debug('get_nfs_info: ' + newout + ' -- ' + err)
+ LOG.debug('get_nfs_info: %(out)s -- %(err)s',
+ {'out': newout, 'err': err})
return newout
def create_lu(self, cmd, ip0, user, pw, hdp, size, name):
"""
_evsid = self._get_evs(cmd, ip0, user, pw, hdp)
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, "console-context",
- "--evs", _evsid,
- 'iscsi-lu', 'add', "-e",
- name, hdp,
- '/.cinder/' + name + '.iscsi',
- size + 'M',
- check_exit_code=True)
+ out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
+ "--evs", _evsid,
+ 'iscsi-lu', 'add', "-e",
+ name, hdp,
+ '/.cinder/' + name + '.iscsi',
+ size + 'M',
+ check_exit_code=True)
out = "LUN %s HDP: %s size: %s MB, is successfully created" \
% (name, hdp, size)
- LOG.debug('create_lu: ' + out)
+ LOG.debug('create_lu: %s', out)
return out
def delete_lu(self, cmd, ip0, user, pw, hdp, lun):
"""
_evsid = self._get_evs(cmd, ip0, user, pw, hdp)
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, "console-context",
- "--evs", _evsid,
- 'iscsi-lu', 'del', '-d',
- '-f', lun,
- check_exit_code=True)
-
- LOG.debug('delete_lu: ' + out + ' -- ' + err)
+ out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
+ "--evs", _evsid,
+ 'iscsi-lu', 'del', '-d',
+ '-f', lun,
+ check_exit_code=True)
+
+ LOG.debug('delete_lu: %(out)s -- %(err)s', {'out': out, 'err': err})
return out
def create_dup(self, cmd, ip0, user, pw, src_lun, hdp, size, name):
"""
_evsid = self._get_evs(cmd, ip0, user, pw, hdp)
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, "console-context",
- "--evs", _evsid,
- 'iscsi-lu', 'clone', '-e',
- src_lun, name,
- '/.cinder/' + name + '.iscsi',
- check_exit_code=True)
+ out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
+ "--evs", _evsid,
+ 'iscsi-lu', 'clone', '-e',
+ src_lun, name,
+ '/.cinder/' + name + '.iscsi',
+ check_exit_code=True)
out = "LUN %s HDP: %s size: %s MB, is successfully created" \
% (name, hdp, size)
- LOG.debug('create_dup: ' + out + ' -- ' + err)
+ LOG.debug('create_dup: %(out)s -- %(err)s', {'out': out, 'err': err})
return out
def file_clone(self, cmd, ip0, user, pw, fslabel, src, name):
_fsid = self._get_fsid(cmd, ip0, user, pw, fslabel)
_evsid = self._get_evs(cmd, ip0, user, pw, _fsid)
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, "console-context",
- "--evs", _evsid,
- 'file-clone-create', '-f', fslabel,
- src, name,
- check_exit_code=True)
+ out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
+ "--evs", _evsid,
+ 'file-clone-create', '-f', fslabel,
+ src, name,
+ check_exit_code=True)
out = "LUN %s HDP: %s Clone: %s -> %s" % (name, _fsid, src, name)
- LOG.debug('file_clone: ' + out + ' -- ' + err)
+ LOG.debug('file_clone: %(out)s -- %(err)s', {'out': out, 'err': err})
return out
def extend_vol(self, cmd, ip0, user, pw, hdp, lun, new_size, name):
"""
_evsid = self._get_evs(cmd, ip0, user, pw, hdp)
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, "console-context",
- "--evs", _evsid,
- 'iscsi-lu', 'expand',
- name, new_size + 'M',
- check_exit_code=True)
+ out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
+ "--evs", _evsid,
+ 'iscsi-lu', 'expand',
+ name, new_size + 'M',
+ check_exit_code=True)
out = ("LUN: %s successfully extended to %s MB" % (name, new_size))
- LOG.debug('extend_vol: ' + out)
+ LOG.debug('extend_vol: %s', out)
return out
def add_iscsi_conn(self, cmd, ip0, user, pw, lun, hdp,
"""
_evsid = self._get_evs(cmd, ip0, user, pw, hdp)
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, "console-context",
- "--evs", _evsid,
- 'iscsi-target', 'list', iqn,
- check_exit_code=True)
+ out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
+ "--evs", _evsid,
+ 'iscsi-target', 'list', iqn,
+ check_exit_code=True)
# even though ssc uses the target alias, need to return the full iqn
fulliqn = ""
if lunline[0].isdigit():
# see if already mounted
if vol[:29] == lun[:29]:
- LOG.info('lun: %s already mounted %s' % (lun, lunline))
+ LOG.info(_LI('lun: %(lun)s already mounted (lline)%s'),
+ {'lun': lun, 'lline': lunline})
conn = (int(lunline), lun, initiator, hlun, fulliqn,
hlun, hdp, port)
out = "H-LUN: %d alreadymapped LUN: %s, iSCSI \
Initiator: %s @ index: %d, and Target: %s \
@ index %d is successfully paired @ CTL: \
%s, Port: %s" % conn
- LOG.debug('add_iscsi_conn: returns ' + out)
+ LOG.debug('add_iscsi_conn: returns %s', out)
return out
if int(lunline) == hlun:
# found a hole
break
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, "console-context",
- "--evs", _evsid,
- 'iscsi-target', 'addlu',
- iqn, lun, hlun,
- check_exit_code=True)
+ out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
+ "--evs", _evsid,
+ 'iscsi-target', 'addlu',
+ iqn, lun, hlun,
+ check_exit_code=True)
conn = (int(hlun), lun, initiator, int(hlun), fulliqn, int(hlun),
hdp, port)
@ index: %d, and Target: %s @ index %d is \
successfully paired @ CTL: %s, Port: %s" % conn
- LOG.debug('add_iscsi_conn: returns ' + out)
+ LOG.debug('add_iscsi_conn: returns %s', out)
return out
def del_iscsi_conn(self, cmd, ip0, user, pw, evsid, iqn, hlun):
:return: formated string
"""
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, "console-context",
- "--evs", evsid,
- 'iscsi-target', 'list', iqn,
- check_exit_code=True)
+ out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
+ "--evs", evsid,
+ 'iscsi-target', 'list', iqn,
+ check_exit_code=True)
lines = out.split('\n')
out = ("H-LUN: %d already deleted from target %s" % (int(hlun), iqn))
if out != "":
# hlun wasn't found
- LOG.info('del_iscsi_conn: hlun not found' + out)
+ LOG.info(_LI('del_iscsi_conn: hlun not found %s'), out)
return out
# remove the LU from the target
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, "console-context",
- "--evs", evsid,
- 'iscsi-target', 'dellu',
- '-f', iqn, hlun,
- check_exit_code=True)
+ out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
+ "--evs", evsid,
+ 'iscsi-target', 'dellu',
+ '-f', iqn, hlun,
+ check_exit_code=True)
out = "H-LUN: %d successfully deleted from target %s" \
% (int(hlun), iqn)
- LOG.debug('del_iscsi_conn: ' + out + ' -- ')
+ LOG.debug('del_iscsi_conn: %s', out)
return out
def get_targetiqn(self, cmd, ip0, user, pw, targetalias, hdp, secret):
"""
_evsid = self._get_evs(cmd, ip0, user, pw, hdp)
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, "console-context",
- "--evs", _evsid,
- 'iscsi-target', 'list', targetalias,
- check_exit_code=True)
+ out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
+ "--evs", _evsid,
+ 'iscsi-target', 'list', targetalias,
+ check_exit_code=True)
if "does not exist" in out:
if secret == "":
secret = '""'
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, "console-context",
- "--evs", _evsid,
- 'iscsi-target', 'add',
- targetalias, secret,
- check_exit_code=True)
+ out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
+ "--evs", _evsid,
+ 'iscsi-target', 'add',
+ targetalias, secret,
+ check_exit_code=True)
else:
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, "console-context",
- "--evs", _evsid,
- 'iscsi-target', 'add',
- targetalias, secret,
- check_exit_code=True)
+ out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
+ "--evs", _evsid,
+ 'iscsi-target', 'add',
+ targetalias, secret,
+ check_exit_code=True)
lines = out.split('\n')
# returns the first iqn
"""
_evsid = self._get_evs(cmd, ip0, user, pw, hdp)
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, "console-context",
- "--evs", _evsid,
- 'iscsi-target', 'list',
- targetalias,
- check_exit_code=False)
+ out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
+ "--evs", _evsid,
+ 'iscsi-target', 'list',
+ targetalias,
+ check_exit_code=False)
if "does not exist" in out:
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, "console-context",
- "--evs", _evsid,
- 'iscsi-target', 'add',
- targetalias, secret,
- check_exit_code=True)
+ out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
+ "--evs", _evsid,
+ 'iscsi-target', 'add',
+ targetalias, secret,
+ check_exit_code=True)
else:
- LOG.info('targetlist: ' + targetalias + ' -- ' + out)
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, "console-context",
- "--evs", _evsid,
- 'iscsi-target', 'mod',
- '-s', secret, '-a', 'enable',
- targetalias,
- check_exit_code=True)
+ LOG.info(_LI('targetlist: %s'), targetalias)
+ out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
+ "--evs", _evsid,
+ 'iscsi-target', 'mod',
+ '-s', secret, '-a', 'enable',
+ targetalias,
+ check_exit_code=True)
def get_targetsecret(self, cmd, ip0, user, pw, targetalias, hdp):
"""Returns the chap secret for the specified target.
"""
_evsid = self._get_evs(cmd, ip0, user, pw, hdp)
- out, err = utils.execute(cmd,
- '-u', user, '-p', pw,
- ip0, "console-context",
- "--evs", _evsid,
- 'iscsi-target', 'list', targetalias,
- check_exit_code=True)
+ out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
+ "--evs", _evsid,
+ 'iscsi-target', 'list', targetalias,
+ check_exit_code=True)
enabled = ""
secret = ""