From ecfb3068e7e939e2b63fd096ba300f4efd27d394 Mon Sep 17 00:00:00 2001 From: Chhavi Agarwal Date: Wed, 21 Mar 2018 13:41:43 -0400 Subject: [PATCH] Use vios_uuids to process required vioses for iSCSI Proposed changes are to improve the performance by processing the (dis)connect volume only for active VIOS. This is a follow-on to [1]. [1] c614c3a9a73641b905ac21f0d17a8deb7149812b Change-Id: I55b77678fd727b9cacf8993b08caeacf67691b35 (cherry picked from commit 7cda551277a0bf1a58ec65db26d50ea385db1108) --- .../tests/virt/powervm/volume/test_iscsi.py | 83 +++++++++++++++++++ nova_powervm/virt/powervm/volume/iscsi.py | 15 ++++ 2 files changed, 98 insertions(+) diff --git a/nova_powervm/tests/virt/powervm/volume/test_iscsi.py b/nova_powervm/tests/virt/powervm/volume/test_iscsi.py index 69b0a9df..49ebdf30 100644 --- a/nova_powervm/tests/virt/powervm/volume/test_iscsi.py +++ b/nova_powervm/tests/virt/powervm/volume/test_iscsi.py @@ -176,6 +176,39 @@ class TestISCSIAdapter(test_vol.TestVolumeAdapter): self.multi_vol_drv.connect_volume(self.slot_mgr) mock_discover.assert_has_calls(multi_calls, any_order=True) + @mock.patch('nova_powervm.virt.powervm.volume.volume.VscsiVolumeAdapter' + '._validate_vios_on_connection') + @mock.patch('pypowervm.tasks.scsi_mapper.add_map', autospec=True) + @mock.patch('pypowervm.tasks.scsi_mapper.build_vscsi_mapping', + autospec=True) + @mock.patch('nova_powervm.virt.powervm.volume.driver.PowerVMVolumeAdapter.' + 'vios_uuids', new_callable=mock.PropertyMock) + @mock.patch('pypowervm.tasks.hdisk.discover_iscsi', autospec=True) + @mock.patch('nova_powervm.virt.powervm.vm.get_vm_id') + def test_connect_volume_active_vios(self, mock_get_vm_id, mock_discover, + mock_vios_uuids, mock_build_map, + mock_add_map, mock_validate_vios): + # Mockups + mock_build_map.return_value = 'fake_map' + mock_get_vm_id.return_value = '2' + mock_add_map.return_value = None + mock_get_vm_id.return_value = 'partition_id' + mock_discover.return_value = '/dev/fake', 'fake_udid' + vios_ids = ['1300C76F-9814-4A4D-B1F0-5B69352A7DEA', + '7DBBE705-E4C4-4458-8223-3EBE07015CA9'] + mock_vios_uuids.return_value = vios_ids + + self.multi_vol_drv.connect_volume(self.slot_mgr) + self.assertEqual(2, mock_discover.call_count) + + # If the vios entries exists in the list + mock_discover.reset_mock() + mock_discover.return_value = '/dev/fake2', 'fake_udid2' + mock_vios_uuids.return_value = [vios_ids[0]] + self.multi_vol_drv.connect_volume(self.slot_mgr) + # Check if discover iscsi is called + self.assertEqual(1, mock_discover.call_count) + @mock.patch('pypowervm.tasks.hdisk.discover_iscsi', autospec=True) @mock.patch('nova_powervm.virt.powervm.vm.get_vm_id') def test_connect_volume_discover_fail(self, mock_get_vm_id, mock_discover): @@ -231,6 +264,56 @@ class TestISCSIAdapter(test_vol.TestVolumeAdapter): self.vol_drv._set_udid(None) self.assertRaises(nova_exc.InvalidBDM, self.vol_drv.extend_volume) + @mock.patch('nova_powervm.virt.powervm.volume.driver.PowerVMVolumeAdapter.' + 'vios_uuids', new_callable=mock.PropertyMock) + @mock.patch('pypowervm.tasks.hdisk.remove_iscsi', autospec=True) + @mock.patch('pypowervm.wrappers.virtual_io_server.VIOS.hdisk_from_uuid', + autospec=True) + @mock.patch('pypowervm.tasks.scsi_mapper.remove_maps', autospec=True) + @mock.patch('nova_powervm.virt.powervm.vm.get_vm_id') + def test_disconnect_on_active_vioses(self, mock_get_vm_id, + mock_remove_maps, + mock_hdisk_from_uuid, + mock_remove_iscsi, + mock_vios_uuids): + # The mock return values + mock_hdisk_from_uuid.return_value = 'device_name' + mock_get_vm_id.return_value = '2' + self.multi_vol_drv._set_devname('/dev/fake') + mock_remove_maps.return_value = 'removed' + vios_ids = ['1300C76F-9814-4A4D-B1F0-5B69352A7DEA', + '7DBBE705-E4C4-4458-8223-3EBE07015CA9'] + mock_vios_uuids.return_value = vios_ids + + # Run the method + self.multi_vol_drv.disconnect_volume(self.slot_mgr) + self.assertEqual(2, mock_remove_iscsi.call_count) + self.assertEqual(2, mock_remove_maps.call_count) + + @mock.patch('nova_powervm.virt.powervm.volume.driver.PowerVMVolumeAdapter.' + 'vios_uuids', new_callable=mock.PropertyMock) + @mock.patch('pypowervm.tasks.hdisk.remove_iscsi', autospec=True) + @mock.patch('pypowervm.wrappers.virtual_io_server.VIOS.hdisk_from_uuid', + autospec=True) + @mock.patch('pypowervm.tasks.scsi_mapper.remove_maps', autospec=True) + @mock.patch('nova_powervm.virt.powervm.vm.get_vm_id') + def test_disconnect_on_single_vios(self, mock_get_vm_id, + mock_remove_maps, + mock_hdisk_from_uuid, + mock_remove_iscsi, + mock_vios_uuids): + # The mock return values + mock_hdisk_from_uuid.return_value = 'device_name' + mock_get_vm_id.return_value = '2' + self.multi_vol_drv._set_devname('/dev/fake') + mock_remove_maps.return_value = 'removed' + mock_vios_uuids.return_value = ['1300C76F-9814-4A4D-B1F0-5B69352A7DEA'] + + # Run the method + self.multi_vol_drv.disconnect_volume(self.slot_mgr) + self.assertEqual(1, mock_remove_iscsi.call_count) + self.assertEqual(1, mock_remove_maps.call_count) + @mock.patch('pypowervm.tasks.hdisk.remove_iscsi', autospec=True) @mock.patch('pypowervm.wrappers.virtual_io_server.VIOS.hdisk_from_uuid', autospec=True) diff --git a/nova_powervm/virt/powervm/volume/iscsi.py b/nova_powervm/virt/powervm/volume/iscsi.py index 2d861d92..23158e61 100644 --- a/nova_powervm/virt/powervm/volume/iscsi.py +++ b/nova_powervm/virt/powervm/volume/iscsi.py @@ -149,6 +149,13 @@ class IscsiVolumeAdapter(volume.VscsiVolumeAdapter, not (could be the Virtual I/O Server does not have connectivity to the hdisk). """ + # check if the vios uuid exist in the expected vios list + if vios_w.uuid not in self.vios_uuids: + LOG.debug("Skipping connect volume %(vol)s from " + "inactive vios uuid %(uuid)s.", + dict(vol=self.volume_id, uuid=vios_w.uuid)) + return False + device_name, udid = self._discover_volume_on_vios(vios_w) if device_name is not None and udid is not None: slot, lua = slot_mgr.build_map.get_vscsi_slot(vios_w, device_name) @@ -200,9 +207,17 @@ class IscsiVolumeAdapter(volume.VscsiVolumeAdapter, :return: True if a remove action was done against this VIOS. False otherwise. """ + # Check if the vios uuid exist in the list + if vios_w.uuid not in self.vios_uuids: + LOG.debug("Skipping disconnect of volume %(vol)s from " + "inactive vios uuid %(uuid)s.", + dict(vol=self.volume_id, uuid=vios_w.uuid)) + return False + LOG.debug("Disconnect volume %(vol)s from vios uuid %(uuid)s", dict(vol=self.volume_id, uuid=vios_w.uuid), instance=self.instance) + device_name = None try: device_name = self._get_devname()