# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import mock from cinder import context from cinder.tests.unit.targets import targets_fixture as tf from cinder import utils from cinder.volume.targets import scst from cinder.volume import utils as vutils class TestSCSTAdmDriver(tf.TargetDriverFixture): def setUp(self): super(TestSCSTAdmDriver, self).setUp() self.target = scst.SCSTAdm(root_helper=utils.get_root_helper(), configuration=self.configuration) self.fake_iscsi_scan = \ ('Collecting current configuration: done.\n' 'Driver Target\n' '----------------------------------------------\n' 'iscsi iqn.2010-10.org.openstack:' 'volume-ed2c2222-5fc0-11e4-aa15-123b93f75cba\n' 'All done.\n') self.fake_iscsi_attribute_scan = \ ('Collecting current configuration: done.\n' 'Attribute Value Writable KEY\n' '------------------------------------------\n' 'rel_tgt_id 1 Yes Yes\n' 'Dynamic attributes available\n' '----------------------------\n' 'IncomingUser\n' 'OutgoingUser\n' 'allowed_portal\n' 'LUN CREATE attributes available\n' '-------------------------------\n' 'read_only\n' 'All done.\n') self.fake_list_group = \ ('org.openstack:volume-vedams\n' 'Collecting current configuration: done.\n' 'Driver: iscsi\n' 'Target: iqn.2010-10.org.openstack:volume-vedams\n' 'Driver/target \'iscsi/iqn.2010-10.org.openstack:volume-vedams\'' 'has no associated LUNs.\n' 'Group: iqn.1993-08.org.debian:01:626bf14ebdc\n' 'Assigned LUNs:\n' 'LUN Device\n' '------------------\n' '1 1b67387810256\n' '2 2a0f1cc9cd595\n' 'Assigned Initiators:\n' 'Initiator\n' '-------------------------------------\n' 'iqn.1993-08.org.debian:01:626bf14ebdc\n' 'All done.\n') self.target.db = mock.MagicMock( volume_get=lambda x, y: {'provider_auth': 'IncomingUser foo bar'}) @mock.patch.object(utils, 'execute') @mock.patch.object(scst.SCSTAdm, '_target_attribute') @mock.patch.object(scst.SCSTAdm, 'scst_execute') def test_get_target(self, mock_execute, mock_target_attribute, mock_scst_execute): mock_target_attribute.return_value = 1 mock_execute.return_value = (self.fake_iscsi_scan, None) expected = 1 self.assertEqual(expected, self.target._get_target( 'iqn.2010-10.org.openstack:' 'volume-ed2c2222-5fc0-11e4-aa15-123b93f75cba')) @mock.patch('cinder.privsep.targets.scst.run_scstadmin') def test_target_attribute(self, mock_privsep): mock_privsep.return_value = (self.fake_iscsi_attribute_scan, None) self.assertEqual(str(1), self.target._target_attribute( 'iqn.2010-10.org.openstack:' 'volume-ed2c2222-5fc0-11e4-aa15-123b93f75cba')) def test_single_lun_get_target_and_lun(self): ctxt = context.get_admin_context() self.assertEqual((0, 1), self.target._get_target_and_lun( ctxt, self.testvol)) @mock.patch.object(utils, 'execute') @mock.patch.object(scst.SCSTAdm, '_get_group') @mock.patch.object(scst.SCSTAdm, 'scst_execute') def test_multi_lun_get_target_and_lun(self, mock_execute, mock_get_group, mock_scst_execute): mock_execute.return_value = (self.fake_list_group, None) mock_get_group.return_value = self.fake_list_group ctxt = context.get_admin_context() with mock.patch.object(self.target, 'target_name', return_value='iqn.2010-10.org.openstack:' 'volume-vedams'): self.assertEqual((0, 3), self.target._get_target_and_lun( ctxt, self.testvol)) @mock.patch.object(utils, 'execute') @mock.patch.object(scst.SCSTAdm, '_get_target') @mock.patch.object(scst.SCSTAdm, 'scst_execute') def test_create_iscsi_target(self, mock_execute, mock_get_target, mock_scst_execute): mock_execute.return_value = (None, None) mock_get_target.return_value = 1 self.assertEqual(1, self.target.create_iscsi_target( 'iqn.2010-10.org.openstack:' 'volume-ed2c2222-5fc0-11e4-aa15-123b93f75cba', 'vol1', 0, 1, self.fake_volumes_dir)) @mock.patch.object(utils, 'execute') @mock.patch.object(scst.SCSTAdm, '_get_target') @mock.patch.object(scst.SCSTAdm, 'scst_execute') def test_create_export(self, mock_execute, mock_get_target, mock_scst_execute): mock_execute.return_value = (None, None) mock_scst_execute.return_value = (None, None) mock_get_target.return_value = 1 def _fake_get_target_and_lun(*args, **kwargs): return 0, 1 def _fake_iscsi_location(*args, **kwargs): return '10.9.8.7:3260,1 iqn.2010-10.org.openstack:' \ 'volume-ed2c2222-5fc0-11e4-aa15-123b93f75cba 1' def _fake_get_target_chap_auth(*args, **kwargs): return ('QZJbisGmn9AL954FNF4D', 'P68eE7u9eFqDGexd28DQ') ctxt = context.get_admin_context() expected_result = {'location': '10.9.8.7:3260,1 ' 'iqn.2010-10.org.openstack:' 'volume-ed2c2222-5fc0-11e4-aa15-123b93f75cba 1', 'auth': 'CHAP ' 'QZJbisGmn9AL954FNF4D P68eE7u9eFqDGexd28DQ'} with mock.patch.object(self.target, '_get_target_and_lun', side_effect=_fake_get_target_and_lun),\ mock.patch.object(self.target, '_get_target_chap_auth', side_effect=_fake_get_target_chap_auth),\ mock.patch.object(self.target, 'initiator_iqn', return_value='iqn.1993-08.org.debian:' '01:626bf14ebdc'),\ mock.patch.object(self.target, '_iscsi_location', side_effect=_fake_iscsi_location),\ mock.patch.object(self.target, 'target_driver', return_value='iscsi'),\ mock.patch.object(vutils, 'generate_username', side_effect=lambda: 'QZJbisGmn9AL954FNF4D'),\ mock.patch.object(vutils, 'generate_password', side_effect=lambda: 'P68eE7u9eFqDGexd28DQ'): self.assertEqual(expected_result, self.target.create_export(ctxt, self.testvol, self.fake_volumes_dir)) @mock.patch('cinder.utils.execute') @mock.patch.object(scst.SCSTAdm, '_get_target') @mock.patch.object(scst.SCSTAdm, 'scst_execute') def test_ensure_export(self, mock_execute, mock_get_target, mock_scst_execute): mock_execute.return_value = (None, None) mock_scst_execute.return_value = (None, None) mock_get_target.return_value = 1 ctxt = context.get_admin_context() def _fake_get_target_and_lun(*args, **kwargs): return 0, 1 def _fake_get_target_chap_auth(*args, **kwargs): return ('QZJbisGmn9AL954FNF4D', 'P68eE7u9eFqDGexd28DQ') with mock.patch.object(self.target, 'create_iscsi_target'),\ mock.patch.object(self.target, '_get_target_chap_auth', side_effect=_fake_get_target_chap_auth),\ mock.patch.object(self.target, '_get_target_and_lun', side_effect=_fake_get_target_and_lun): self.target.ensure_export(ctxt, self.testvol, self.fake_volumes_dir) self.target.create_iscsi_target.assert_called_once_with( 'iqn.2010-10.org.openstack:testvol', 'ed2c2222-5fc0-11e4-aa15-123b93f75cba', 0, 1, self.fake_volumes_dir, _fake_get_target_chap_auth()) @mock.patch('cinder.utils.execute') @mock.patch.object(scst.SCSTAdm, '_get_target') @mock.patch.object(scst.SCSTAdm, 'scst_execute') def test_ensure_export_chap(self, mock_execute, mock_get_target, mock_scst_execute): mock_execute.return_value = (None, None) mock_scst_execute.return_value = (None, None) mock_get_target.return_value = 1 ctxt = context.get_admin_context() def _fake_get_target_and_lun(*args, **kwargs): return 0, 1 def _fake_get_target_chap_auth(*args, **kwargs): return None with mock.patch.object(self.target, 'create_iscsi_target'),\ mock.patch.object(self.target, '_get_target_chap_auth', side_effect=_fake_get_target_chap_auth),\ mock.patch.object(self.target, '_get_target_and_lun', side_effect=_fake_get_target_and_lun): self.target.ensure_export(ctxt, self.testvol, self.fake_volumes_dir) self.target.create_iscsi_target.assert_called_once_with( 'iqn.2010-10.org.openstack:testvol', 'ed2c2222-5fc0-11e4-aa15-123b93f75cba', 0, 1, self.fake_volumes_dir, None)