diff --git a/doc/source/support-matrix.ini b/doc/source/support-matrix.ini index aa6c3c58..3f091909 100644 --- a/doc/source/support-matrix.ini +++ b/doc/source/support-matrix.ini @@ -105,7 +105,7 @@ notes=The extend volume operation provides a means to extend Therefore this operation is not considered to be mandatory to support. cli=cinder extend driver-impl-powervm=partial -driver-notes-powervm=Extend volume only supported for fileio volumes. +driver-notes-powervm=Extend volume only supported for fileio and iSCSI volumes. [operation.maintenance-mode] title=Set the host in a maintenance mode diff --git a/nova_powervm/tests/virt/powervm/volume/test_iscsi.py b/nova_powervm/tests/virt/powervm/volume/test_iscsi.py index 969ef526..5feea3d9 100644 --- a/nova_powervm/tests/virt/powervm/volume/test_iscsi.py +++ b/nova_powervm/tests/virt/powervm/volume/test_iscsi.py @@ -16,11 +16,15 @@ import mock +from nova import exception as nova_exc + from nova_powervm import conf as cfg from nova_powervm.tests.virt.powervm.volume import test_driver as test_vol +from nova_powervm.virt.powervm import exception as p_exc from nova_powervm.virt.powervm.volume import iscsi from pypowervm import const as pvm_const +from pypowervm import exceptions as pvm_exc from pypowervm.tasks import hdisk from pypowervm.tests.tasks.util import load_file from pypowervm.tests import test_fixtures as pvm_fx @@ -126,6 +130,39 @@ class TestISCSIAdapter(test_vol.TestVolumeAdapter): self.adpt, self.host_ip, self.user, self.password, self.iqn, self.feed[0].uuid, transport_type=self.trans_type) + @mock.patch('pypowervm.tasks.partition.get_active_vioses', autospec=True) + @mock.patch('pypowervm.tasks.storage.rescan_vstor', autospec=True) + def test_extend_volume(self, mock_rescan, mock_active_vioses): + self.vol_drv._set_udid("vstor_uuid") + mock_vios = mock.Mock(uuid='fake_uuid') + # Test single vios + mock_active_vioses.return_value = [mock_vios] + self.vol_drv.extend_volume() + mock_rescan.assert_called_once_with(self.vol_drv.vios_uuids[0], + "vstor_uuid", self.adpt) + mock_rescan.side_effect = pvm_exc.JobRequestFailed( + operation_name='RescanVirtualDisk', error='fake_err') + self.assertRaises(p_exc.VolumeExtendFailed, self.vol_drv.extend_volume) + mock_rescan.side_effect = pvm_exc.VstorNotFound( + stor_udid='stor_udid', vios_uuid='uuid') + self.assertRaises(p_exc.VolumeExtendFailed, self.vol_drv.extend_volume) + + # Test multiple vios + mock_active_vioses.return_value = [mock_vios, mock_vios] + mock_rescan.reset_mock() + mock_rescan.side_effect = [pvm_exc.JobRequestFailed( + operation_name='RescanVirtualDisk', error='fake_err'), None] + self.assertRaises(p_exc.VolumeExtendFailed, self.vol_drv.extend_volume) + self.assertEqual(2, mock_rescan.call_count) + mock_rescan.reset_mock() + mock_rescan.side_effect = [None, pvm_exc.VstorNotFound( + stor_udid='stor_udid', vios_uuid='uuid')] + self.vol_drv.extend_volume() + self.assertEqual(2, mock_rescan.call_count) + + self.vol_drv._set_udid(None) + self.assertRaises(nova_exc.InvalidBDM, self.vol_drv.extend_volume) + @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 e0e3bb33..8436051d 100644 --- a/nova_powervm/virt/powervm/volume/iscsi.py +++ b/nova_powervm/virt/powervm/volume/iscsi.py @@ -16,6 +16,7 @@ from oslo_concurrency import lockutils from oslo_log import log as logging +from nova import exception as nova_exc from nova_powervm import conf as cfg from nova_powervm.virt.powervm import exception as p_exc from nova_powervm.virt.powervm import vm @@ -122,6 +123,13 @@ class IscsiVolumeAdapter(volume.VscsiVolumeAdapter, return False + def extend_volume(self): + """Rescan virtual disk so client VM can see extended size.""" + udid = self._get_udid() + if udid is None: + raise nova_exc.InvalidBDM() + self._extend_volume(udid) + def _disconnect_volume(self, slot_mgr): """Disconnect the volume.