diff --git a/nova_powervm/tests/virt/powervm/volume/test_vscsi.py b/nova_powervm/tests/virt/powervm/volume/test_vscsi.py index 6e1d8c54..3f997b03 100644 --- a/nova_powervm/tests/virt/powervm/volume/test_vscsi.py +++ b/nova_powervm/tests/virt/powervm/volume/test_vscsi.py @@ -253,17 +253,19 @@ class TestVSCSIAdapter(BaseVSCSITest): self.assertEqual(1, mock_remove_maps.call_count) self.assertEqual(0, self.ft_fx.patchers['update'].mock.call_count) + @mock.patch('pypowervm.tasks.hdisk.good_discovery') @mock.patch('pypowervm.tasks.hdisk.remove_hdisk') @mock.patch('pypowervm.wrappers.virtual_io_server.VIOS.hdisk_from_uuid') @mock.patch('pypowervm.tasks.scsi_mapper.remove_maps') @mock.patch('nova_powervm.virt.powervm.vm.get_vm_id') def test_disconnect_volume_no_udid( self, mock_get_vm_id, mock_remove_maps, mock_hdisk_from_uuid, - mock_remove_hdisk): + mock_remove_hdisk, mock_good_discover): # The mock return values mock_hdisk_from_uuid.return_value = 'device_name' mock_get_vm_id.return_value = 'partition_id' + mock_good_discover.return_value = True def validate_remove_maps(vios_w, vm_uuid, match_func): self.assertIsInstance(vios_w, pvm_vios.VIOS) @@ -284,6 +286,25 @@ class TestVSCSIAdapter(BaseVSCSITest): mock_remove_hdisk.assert_called_once_with( self.adpt, mock.ANY, 'dev_name', self.vios_uuid) + @mock.patch('pypowervm.tasks.hdisk.good_discovery') + @mock.patch('pypowervm.tasks.hdisk.remove_hdisk') + @mock.patch('pypowervm.tasks.scsi_mapper.remove_maps') + def test_disconnect_volume_no_udid_on_discover( + self, mock_remove_maps, mock_remove_hdisk, mock_good_discover): + """Ensures that if the UDID can not be found, no disconnect.""" + mock_good_discover.return_value = False + with mock.patch.object( + self.vol_drv, '_discover_volume_on_vios', + return_value=('status', 'dev_name', None)): + + # Run the method + self.vol_drv.disconnect_volume() + + # As initialized above, remove_maps returns True to trigger update. + self.assertEqual(0, mock_remove_maps.call_count) + self.assertEqual(0, self.ft_fx.patchers['update'].mock.call_count) + self.assertEqual(0, mock_remove_hdisk.call_count) + @mock.patch('pypowervm.wrappers.virtual_io_server.VIOS.hdisk_from_uuid') @mock.patch('pypowervm.tasks.scsi_mapper.remove_maps') def test_disconnect_volume_no_valid_vio(self, mock_remove_maps, diff --git a/nova_powervm/virt/powervm/volume/vscsi.py b/nova_powervm/virt/powervm/volume/vscsi.py index 2feb4b01..728df981 100644 --- a/nova_powervm/virt/powervm/volume/vscsi.py +++ b/nova_powervm/virt/powervm/volume/vscsi.py @@ -258,6 +258,19 @@ class VscsiVolumeAdapter(v_driver.FibreChannelVolumeAdapter): status, device_name, udid = self._discover_volume_on_vios( vios_w, self.volume_id) + # If we have a device name, but not a udid, at this point + # we should not continue. The hdisk is in a bad state + # in the I/O Server. Subsequent scrub code on future + # deploys will clean this up. + if not hdisk.good_discovery(status, device_name): + LOG.warn(_LW( + "Disconnect Volume: The backing hdisk for volume " + "%(volume_id)s on Virtual I/O Server %(vios)s is " + "not in a valid state. No disconnect " + "actions to be taken as volume is not healthy."), + {'volume_id': self.volume_id, 'vios': vios_w.name}) + return False + if udid and not device_name: device_name = vios_w.hdisk_from_uuid(udid)