diff --git a/nova_powervm/tests/virt/powervm/volume/test_vscsi.py b/nova_powervm/tests/virt/powervm/volume/test_vscsi.py index 029e8fdf..cb8d73ae 100644 --- a/nova_powervm/tests/virt/powervm/volume/test_vscsi.py +++ b/nova_powervm/tests/virt/powervm/volume/test_vscsi.py @@ -24,6 +24,7 @@ from oslo_config import cfg from nova_powervm.tests.virt.powervm import fixtures as fx from nova_powervm.virt.powervm.volume import vscsi +import pypowervm.exceptions as pexc from pypowervm.tasks import hdisk from pypowervm.tests.wrappers.util import pvmhttp @@ -31,6 +32,8 @@ CONF = cfg.CONF VIOS_FEED = 'fake_vios_feed.txt' +I_WWPN_1 = '21000024FF649104' + class TestVSCSIAdapter(test.TestCase): """Tests the vSCSI Volume Connector Adapter.""" @@ -60,8 +63,8 @@ class TestVSCSIAdapter(test.TestCase): @mock.patch('pypowervm.tasks.scsi_mapper.add_vscsi_mapping') def test_connect_volume(self, mock_add_vscsi_mapping, mock_discover_hdisk, mock_build_itls): - con_info = {'data': {'initiator_target_map': {'i1': ['t1'], - 'i2': ['t2', 't3']}, + con_info = {'data': {'initiator_target_map': {I_WWPN_1: ['t1'], + I_WWPN_1: ['t2', 't3']}, 'target_lun': '1', 'volume_id': 'id'}} mock_discover_hdisk.return_value = ( hdisk.LUAStatus.DEVICE_AVAILABLE, 'devname', 'udid') @@ -70,6 +73,8 @@ class TestVSCSIAdapter(test.TestCase): mock_instance = mock.Mock() mock_instance.system_metadata = {} + mock_build_itls.return_value = [mock.MagicMock()] + vscsi.VscsiVolumeAdapter().connect_volume(self.adpt, 'host_uuid', 'vm_uuid', mock_instance, con_info) @@ -79,6 +84,30 @@ class TestVSCSIAdapter(test.TestCase): 'host_uuid', '3443DB77-AED1-47ED-9AA5-3DB9C6CF7089', 'vm_uuid', mock.ANY) + @mock.patch('pypowervm.tasks.hdisk.build_itls') + @mock.patch('pypowervm.tasks.hdisk.discover_hdisk') + @mock.patch('pypowervm.tasks.scsi_mapper.add_vscsi_mapping') + def test_connect_volume_to_initiatiors(self, mock_add_vscsi_mapping, + mock_discover_hdisk, + mock_build_itls): + """Tests that the connect w/out initiators throws errors.""" + con_info = {'data': {'initiator_target_map': {I_WWPN_1: ['t1'], + I_WWPN_1: ['t2', 't3']}, + 'target_lun': '1', 'volume_id': 'id'}} + mock_discover_hdisk.return_value = ( + hdisk.LUAStatus.DEVICE_AVAILABLE, 'devname', 'udid') + + self.adpt.read.return_value = self.vios_feed_resp + mock_instance = mock.Mock() + mock_instance.system_metadata = {} + + mock_build_itls.return_value = [] + + self.assertRaises(pexc.VolumeAttachFailed, + vscsi.VscsiVolumeAdapter().connect_volume, + self.adpt, 'host_uuid', 'vm_uuid', mock_instance, + con_info) + @mock.patch('pypowervm.tasks.hdisk.remove_hdisk') @mock.patch('pypowervm.tasks.scsi_mapper.remove_pv_mapping') @mock.patch('nova_powervm.virt.powervm.vm.get_vm_id') diff --git a/nova_powervm/virt/powervm/volume/vscsi.py b/nova_powervm/virt/powervm/volume/vscsi.py index 55c2e293..56b48e19 100644 --- a/nova_powervm/virt/powervm/volume/vscsi.py +++ b/nova_powervm/virt/powervm/volume/vscsi.py @@ -85,10 +85,6 @@ class VscsiVolumeAdapter(v_driver.FibreChannelVolumeAdapter): device_name = None i_wwpns = it_map.keys() - t_wwpns = [] - # Build single list of target wwpns - for it_list in it_map.values(): - t_wwpns.extend(it_list) # Get VIOS feed vios_feed = vios.get_active_vioses(adapter, host_uuid, xag=_XAGS) @@ -98,9 +94,19 @@ class VscsiVolumeAdapter(v_driver.FibreChannelVolumeAdapter): # Reduce the initiatior WWPNs to the list on this given VIOS. vio_wwpns = self._wwpns_on_vios(i_wwpns, vio_wrap) + # Build single list of target wwpns + t_wwpns = [] + for it_key in vio_wwpns: + t_wwpns.extend(it_map[it_key]) + # Build the ITL map and discover the hdisks on the Virtual I/O # Server (if any). itls = hdisk.build_itls(vio_wwpns, t_wwpns, lun) + if len(itls) == 0: + LOG.debug('No ITLs for VIOS %(vios)s for volume %(volume_id)s.' + % {'vios': vio_wrap.name, 'volume_id': volume_id}) + continue + status, device_name, udid = hdisk.discover_hdisk( adapter, vio_wrap.uuid, itls) if device_name is not None and status in [