From e3b112dc937191cdd7112e3265767f369bbef4c7 Mon Sep 17 00:00:00 2001 From: esberglu Date: Tue, 19 Jun 2018 14:44:58 -0500 Subject: [PATCH] Snapshot In-tree Backports This contains backports for code changes made during in-tree driver instance snapshot development [1]. - Renames boot_disk_path_for_instance() to get_bootdisk_path() for clarity - Makes disk_match_func() private and static - Renames instance_disk_iter() to _get_bootdisk_iter() and remove unnecessary parameters. - Other minor cleanup [1] https://review.openstack.org/#/c/543023/ Change-Id: I8f2eef1063b7e40c0cd71fc4adb04cbf6d35ece1 --- .../tests/virt/powervm/disk/test_localdisk.py | 15 +++-- .../tests/virt/powervm/disk/test_ssp.py | 18 +++--- .../tests/virt/powervm/tasks/test_image.py | 4 +- .../tests/virt/powervm/tasks/test_storage.py | 14 ++--- nova_powervm/tests/virt/powervm/test_image.py | 8 +-- nova_powervm/virt/powervm/disk/driver.py | 55 ++++++------------- nova_powervm/virt/powervm/disk/localdisk.py | 16 ++---- nova_powervm/virt/powervm/disk/ssp.py | 15 ++--- nova_powervm/virt/powervm/driver.py | 25 ++++----- nova_powervm/virt/powervm/image.py | 6 +- nova_powervm/virt/powervm/mgmt.py | 7 +-- nova_powervm/virt/powervm/tasks/image.py | 6 +- nova_powervm/virt/powervm/tasks/storage.py | 26 +++++---- 13 files changed, 93 insertions(+), 122 deletions(-) diff --git a/nova_powervm/tests/virt/powervm/disk/test_localdisk.py b/nova_powervm/tests/virt/powervm/disk/test_localdisk.py index 9e212782..33bd7aea 100644 --- a/nova_powervm/tests/virt/powervm/disk/test_localdisk.py +++ b/nova_powervm/tests/virt/powervm/disk/test_localdisk.py @@ -1,4 +1,4 @@ -# Copyright 2015, 2017 IBM Corp. +# Copyright IBM Corp. and contributors # # All Rights Reserved. # @@ -362,7 +362,7 @@ class TestLocalDisk(test.NoDBTestCase): vios1.scsi_mappings[0].backing_storage.name = 'b_Name_Of__d506' return inst, lpar_wrap, vios1 - def test_boot_disk_path_for_instance(self): + def test_get_bootdisk_path(self): local = self.get_ls(self.apt) inst = mock.Mock() inst.name = 'Name Of Instance' @@ -371,17 +371,20 @@ class TestLocalDisk(test.NoDBTestCase): vios1.scsi_mappings[0].server_adapter.backing_dev_name = 'boot_7f81628' vios1.scsi_mappings[0].backing_storage.name = 'b_Name_Of__f921' self.mock_vios_get.return_value = vios1 - dev_name = local.boot_disk_path_for_instance(inst, vios1.uuid) + dev_name = local.get_bootdisk_path(inst, vios1.uuid) self.assertEqual('boot_7f81628', dev_name) + @mock.patch('nova_powervm.virt.powervm.vm.get_instance_wrapper', + autospec=True) @mock.patch('pypowervm.wrappers.storage.VG.get', new=mock.Mock()) - def test_instance_disk_iter(self): + def test_get_bootdisk_iter(self, mock_lpar_wrap): local = self.get_ls(self.apt) inst, lpar_wrap, vios1 = self._bld_mocks_for_instance_disk() + mock_lpar_wrap.return_value = lpar_wrap # Good path self.mock_vios_get.return_value = vios1 - for vdisk, vios in local.instance_disk_iter(inst, lpar_wrap=lpar_wrap): + for vdisk, vios in local._get_bootdisk_iter(inst): self.assertEqual(vios1.scsi_mappings[0].backing_storage, vdisk) self.assertEqual(vios1.uuid, vios.uuid) self.mock_vios_get.assert_called_once_with( @@ -390,7 +393,7 @@ class TestLocalDisk(test.NoDBTestCase): # Not found because no storage of that name self.mock_vios_get.reset_mock() self.mock_find_maps.return_value = [] - for vdisk, vios in local.instance_disk_iter(inst, lpar_wrap=lpar_wrap): + for vdisk, vios in local._get_bootdisk_iter(inst): self.fail() self.mock_vios_get.assert_called_once_with( self.apt, uuid='vios-uuid', xag=[pvm_const.XAG.VIO_SMAP]) diff --git a/nova_powervm/tests/virt/powervm/disk/test_ssp.py b/nova_powervm/tests/virt/powervm/disk/test_ssp.py index 9ee48bf7..05e105c1 100644 --- a/nova_powervm/tests/virt/powervm/disk/test_ssp.py +++ b/nova_powervm/tests/virt/powervm/disk/test_ssp.py @@ -1,4 +1,4 @@ -# Copyright 2015, 2017 IBM Corp. +# Copyright IBM Corp. and contributors # # All Rights Reserved. # @@ -519,7 +519,7 @@ class TestSSPDiskAdapter(test.NoDBTestCase): 'vios_uuids', new_callable=mock.PropertyMock) @mock.patch('nova_powervm.virt.powervm.vm.get_instance_wrapper') @mock.patch('pypowervm.wrappers.virtual_io_server.VIOS.get') - def test_instance_disk_iter(self, mock_vio_get, mock_lw, mock_vio_uuids): + def test_get_bootdisk_iter(self, mock_vio_get, mock_lw, mock_vio_uuids): inst, lpar_wrap, vio1, vio2, vio3 = self._bld_mocks_for_instance_disk() mock_lw.return_value = lpar_wrap mock_vio_uuids.return_value = [1, 2] @@ -528,7 +528,7 @@ class TestSSPDiskAdapter(test.NoDBTestCase): # Test with two VIOSes, both of which contain the mapping. Force the # method to get the lpar_wrap. mock_vio_get.side_effect = [vio1, vio2] - idi = ssp_stor.instance_disk_iter(inst) + idi = ssp_stor._get_bootdisk_iter(inst) lu, vios = next(idi) self.assertEqual('lu_udid', lu.udid) self.assertEqual('vios1', vios.name) @@ -544,12 +544,11 @@ class TestSSPDiskAdapter(test.NoDBTestCase): mock_lw.assert_called_once_with(self.apt, inst) # Same, but prove that breaking out of the loop early avoids the second - # get call. Supply lpar_wrap from here on, and prove no calls to - # get_instance_wrapper + # get call. mock_vio_get.reset_mock() mock_lw.reset_mock() mock_vio_get.side_effect = [vio1, vio2] - for lu, vios in ssp_stor.instance_disk_iter(inst, lpar_wrap=lpar_wrap): + for lu, vios in ssp_stor._get_bootdisk_iter(inst): self.assertEqual('lu_udid', lu.udid) self.assertEqual('vios1', vios.name) break @@ -559,7 +558,7 @@ class TestSSPDiskAdapter(test.NoDBTestCase): # Now the first VIOS doesn't have the mapping, but the second does mock_vio_get.reset_mock() mock_vio_get.side_effect = [vio3, vio2] - idi = ssp_stor.instance_disk_iter(inst, lpar_wrap=lpar_wrap) + idi = ssp_stor._get_bootdisk_iter(inst) lu, vios = next(idi) self.assertEqual('lu_udid', lu.udid) self.assertEqual('vios2', vios.name) @@ -572,12 +571,9 @@ class TestSSPDiskAdapter(test.NoDBTestCase): # No hits mock_vio_get.reset_mock() mock_vio_get.side_effect = [vio3, vio3] - self.assertEqual([], list(ssp_stor.instance_disk_iter( - inst, lpar_wrap=lpar_wrap))) + self.assertEqual([], list(ssp_stor._get_bootdisk_iter(inst))) self.assertEqual(2, mock_vio_get.call_count) - mock_lw.assert_not_called() - @mock.patch('nova_powervm.virt.powervm.disk.ssp.SSPDiskAdapter.' 'vios_uuids', new_callable=mock.PropertyMock) @mock.patch('nova_powervm.virt.powervm.vm.get_instance_wrapper') diff --git a/nova_powervm/tests/virt/powervm/tasks/test_image.py b/nova_powervm/tests/virt/powervm/tasks/test_image.py index 12286b4f..878c6c78 100644 --- a/nova_powervm/tests/virt/powervm/tasks/test_image.py +++ b/nova_powervm/tests/virt/powervm/tasks/test_image.py @@ -1,4 +1,4 @@ -# Copyright 2015, 2018 IBM Corp. +# Copyright IBM Corp. and contributors # # All Rights Reserved. # @@ -44,7 +44,7 @@ class TestImage(test.NoDBTestCase): @mock.patch('nova_powervm.virt.powervm.image.stream_blockdev_to_glance', autospec=True) - @mock.patch('nova_powervm.virt.powervm.image.snapshot_metadata', + @mock.patch('nova_powervm.virt.powervm.image.generate_snapshot_metadata', autospec=True) def test_stream_to_glance(self, mock_metadata, mock_stream): mock_metadata.return_value = 'metadata' diff --git a/nova_powervm/tests/virt/powervm/tasks/test_storage.py b/nova_powervm/tests/virt/powervm/tasks/test_storage.py index f7838c6c..d5be7927 100644 --- a/nova_powervm/tests/virt/powervm/tasks/test_storage.py +++ b/nova_powervm/tests/virt/powervm/tasks/test_storage.py @@ -1,4 +1,4 @@ -# Copyright 2015, 2018 IBM Corp. +# Copyright IBM Corp. and contributors # # All Rights Reserved. # @@ -214,7 +214,7 @@ class TestStorage(test.NoDBTestCase): # Good path - find_maps returns one result mock_find.return_value = ['one_mapping'] tf = tf_stg.InstanceDiskToMgmt(disk_dvr, mock_instance) - self.assertEqual('connect_and_discover_instance_disk_to_mgmt', tf.name) + self.assertEqual('instance_disk_to_mgmt', tf.name) self.assertEqual((mock_stg, mock_vwrap, '/dev/disk'), tf.execute()) disk_dvr.connect_instance_disk_to_mgmt.assert_called_with( mock_instance) @@ -241,18 +241,18 @@ class TestStorage(test.NoDBTestCase): 'stg_name') mock_rm.assert_called_with('/dev/disk') - # Management Partition is VIOS and Novalink hosted storage + # Management Partition is VIOS and NovaLink hosted storage reset_mocks() disk_dvr.vios_uuids = ['mp_uuid'] dev_name = '/dev/vg/fake_name' - disk_dvr.boot_disk_path_for_instance.return_value = dev_name + disk_dvr.get_bootdisk_path.return_value = dev_name tf = tf_stg.InstanceDiskToMgmt(disk_dvr, mock_instance) self.assertEqual((None, None, dev_name), tf.execute()) - # Management Partition is VIOS and not Novalink hosted storage + # Management Partition is VIOS and not NovaLink hosted storage reset_mocks() disk_dvr.vios_uuids = ['mp_uuid'] - disk_dvr.boot_disk_path_for_instance.return_value = None + disk_dvr.get_bootdisk_path.return_value = None tf = tf_stg.InstanceDiskToMgmt(disk_dvr, mock_instance) tf.execute() disk_dvr.connect_instance_disk_to_mgmt.assert_called_with( @@ -296,7 +296,7 @@ class TestStorage(test.NoDBTestCase): with mock.patch('taskflow.task.Task.__init__') as tf: tf_stg.InstanceDiskToMgmt(disk_dvr, mock_instance) tf.assert_called_once_with( - name='connect_and_discover_instance_disk_to_mgmt', + name='instance_disk_to_mgmt', provides=['stg_elem', 'vios_wrap', 'disk_path']) @mock.patch('nova_powervm.virt.powervm.mgmt.remove_block_dev', diff --git a/nova_powervm/tests/virt/powervm/test_image.py b/nova_powervm/tests/virt/powervm/test_image.py index f48d0738..9c0c56bf 100644 --- a/nova_powervm/tests/virt/powervm/test_image.py +++ b/nova_powervm/tests/virt/powervm/test_image.py @@ -1,4 +1,4 @@ -# Copyright 2015, 2017 IBM Corp. +# Copyright IBM Corp. and contributors # # All Rights Reserved. # @@ -42,12 +42,12 @@ class TestImage(test.NoDBTestCase): 'mock_stream') @mock.patch('nova.image.api.API', autospec=True) - def test_snapshot_metadata(self, mock_api): + def test_generate_snapshot_metadata(self, mock_api): mock_api.get.return_value = {'name': 'image_name'} mock_instance = mock.Mock() mock_instance.project_id = 'project_id' - ret = image.snapshot_metadata('context', mock_api, 'image_id', - mock_instance) + ret = image.generate_snapshot_metadata('context', mock_api, 'image_id', + mock_instance) mock_api.get.assert_called_with('context', 'image_id') self.assertEqual({ 'name': 'image_name', diff --git a/nova_powervm/virt/powervm/disk/driver.py b/nova_powervm/virt/powervm/disk/driver.py index 5aae8e2a..5092b9e1 100644 --- a/nova_powervm/virt/powervm/disk/driver.py +++ b/nova_powervm/virt/powervm/disk/driver.py @@ -1,5 +1,5 @@ # Copyright 2013 OpenStack Foundation -# Copyright 2015, 2017 IBM Corp. +# Copyright IBM Corp. and contributors # # All Rights Reserved. # @@ -129,36 +129,26 @@ class DiskAdapter(object): return _('The configured disk driver does not support migration ' 'or resize.') - def disk_match_func(self, disk_type, instance): + def _disk_match_func(self, disk_type, instance): """Return a matching function to locate the disk for an instance. :param disk_type: One of the DiskType enum values. :param instance: The instance whose disk is to be found. :return: Callable suitable for the match_func parameter of the - pypowervm.tasks.scsi_mapper.find_maps method, with the - following specification: - def match_func(storage_elem) - param storage_elem: A backing storage element wrapper (VOpt, - VDisk, PV, or LU) to be analyzed. - return: True if the storage_elem's mapping should be included; - False otherwise. + pypowervm.tasks.scsi_mapper.find_maps method. """ raise NotImplementedError() - def boot_disk_path_for_instance(self, instance, vios_uuid): - """Find scsi mappings on given VIOS for the instance. - - This method finds all scsi mappings on a given vios that are associated - with the instance and disk_type. + def get_bootdisk_path(self, instance, vios_uuid): + """Find the local path for the instance's boot disk. :param instance: nova.objects.instance.Instance object owning the requested disk. :param vios_uuid: PowerVM UUID of the VIOS to search for mappings. - :return: Iterator of scsi mappings that are associated with the - instance and disk_type. + :return: Local path for instance's boot disk. """ vm_uuid = vm.get_pvm_uuid(instance) - match_func = self.disk_match_func(DiskType.BOOT, instance) + match_func = self._disk_match_func(DiskType.BOOT, instance) vios_wrap = pvm_vios.VIOS.get(self.adapter, uuid=vios_uuid, xag=[pvm_const.XAG.VIO_SMAP]) maps = tsk_map.find_maps(vios_wrap.scsi_mappings, @@ -167,27 +157,20 @@ class DiskAdapter(object): return maps[0].server_adapter.backing_dev_name return None - def instance_disk_iter(self, instance, disk_type=DiskType.BOOT, - lpar_wrap=None): - """Return the instance's storage element wrapper of the specified type. + def _get_bootdisk_iter(self, instance): + """Return an iterator of (storage_elem, VIOS) tuples for the instance. + + This method returns an iterator of (storage_elem, VIOS) tuples, where + storage_elem is a pypowervm storage element wrapper associated with + the instance boot disk and VIOS is the wrapper of the Virtual I/O + server owning that storage element. :param instance: nova.objects.instance.Instance object owning the requested disk. - :param disk_type: The type of disk to find, one of the DiskType enum - values. - :param lpar_wrap: pypowervm.wrappers.logical_partition.LPAR - corresponding to the instance. If not specified, it - will be retrieved; i.e. specify this parameter to - save on REST calls. - :return: Iterator of tuples of (storage_elem, VIOS), where storage_elem - is a storage element wrapper (pypowervm.wrappers.storage.VOpt, - VDisk, PV, or LU) associated with the instance; and VIOS is - the wrapper of the Virtual I/O Server owning that storage - element. + :return: Iterator of tuples of (storage_elem, VIOS). """ - if lpar_wrap is None: - lpar_wrap = vm.get_instance_wrapper(self.adapter, instance) - match_func = self.disk_match_func(disk_type, instance) + lpar_wrap = vm.get_instance_wrapper(self.adapter, instance) + match_func = self._disk_match_func(DiskType.BOOT, instance) for vios_uuid in self.vios_uuids: vios_wrap = pvm_vios.VIOS.get( self.adapter, uuid=vios_uuid, xag=[pvm_const.XAG.VIO_SMAP]) @@ -205,9 +188,7 @@ class DiskAdapter(object): made. :raise InstanceDiskMappingFailed: If the mapping could not be done. """ - lpar_wrap = vm.get_instance_wrapper(self.adapter, instance) - for stg_elem, vios in self.instance_disk_iter(instance, - lpar_wrap=lpar_wrap): + for stg_elem, vios in self._get_bootdisk_iter(instance): msg_args = {'disk_name': stg_elem.name, 'vios_name': vios.name} # Create a new mapping. NOTE: If there's an existing mapping on diff --git a/nova_powervm/virt/powervm/disk/localdisk.py b/nova_powervm/virt/powervm/disk/localdisk.py index d00ad1a6..cfbfb428 100644 --- a/nova_powervm/virt/powervm/disk/localdisk.py +++ b/nova_powervm/virt/powervm/disk/localdisk.py @@ -1,5 +1,5 @@ # Copyright 2013 OpenStack Foundation -# Copyright 2015, 2017 IBM Corp. +# Copyright IBM Corp. and contributors # # All Rights Reserved. # @@ -83,21 +83,17 @@ class LocalStorage(disk_dvr.DiskAdapter): """ return [self._vios_uuid] - def disk_match_func(self, disk_type, instance): + @staticmethod + def _disk_match_func(disk_type, instance): """Return a matching function to locate the disk for an instance. :param disk_type: One of the DiskType enum values. :param instance: The instance whose disk is to be found. :return: Callable suitable for the match_func parameter of the - pypowervm.tasks.scsi_mapper.find_maps method, with the - following specification: - def match_func(storage_elem) - param storage_elem: A backing storage element wrapper (VOpt, - VDisk, PV, or LU) to be analyzed. - return: True if the storage_elem's mapping should be included; - False otherwise. + pypowervm.tasks.scsi_mapper.find_maps method. """ - disk_name = self._get_disk_name(disk_type, instance, short=True) + disk_name = LocalStorage._get_disk_name(disk_type, instance, + short=True) return tsk_map.gen_match_func(pvm_stg.VDisk, names=[disk_name]) @property diff --git a/nova_powervm/virt/powervm/disk/ssp.py b/nova_powervm/virt/powervm/disk/ssp.py index bd10a34c..ea308c82 100644 --- a/nova_powervm/virt/powervm/disk/ssp.py +++ b/nova_powervm/virt/powervm/disk/ssp.py @@ -1,4 +1,4 @@ -# Copyright 2015, 2017 IBM Corp. +# Copyright IBM Corp. and contributors # # All Rights Reserved. # @@ -448,19 +448,14 @@ class SSPDiskAdapter(disk_drv.DiskAdapter): """ return random.choice(self.vios_uuids) - def disk_match_func(self, disk_type, instance): + @staticmethod + def _disk_match_func(disk_type, instance): """Return a matching function to locate the disk for an instance. :param disk_type: One of the DiskType enum values. :param instance: The instance whose disk is to be found. :return: Callable suitable for the match_func parameter of the - pypowervm.tasks.scsi_mapper.find_maps method, with the - following specification: - def match_func(storage_elem) - param storage_elem: A backing storage element wrapper (VOpt, - VDisk, PV, or LU) to be analyzed. - return: True if the storage_elem's mapping should be included; - False otherwise. + pypowervm.tasks.scsi_mapper.find_maps method. """ - disk_name = self._get_disk_name(disk_type, instance) + disk_name = SSPDiskAdapter._get_disk_name(disk_type, instance) return tsk_map.gen_match_func(pvm_stg.LU, names=[disk_name]) diff --git a/nova_powervm/virt/powervm/driver.py b/nova_powervm/virt/powervm/driver.py index 6b1ff065..384a04ae 100644 --- a/nova_powervm/virt/powervm/driver.py +++ b/nova_powervm/virt/powervm/driver.py @@ -1,4 +1,4 @@ -# Copyright 2014, 2018 IBM Corp. +# Copyright IBM Corp. and contributors # # All Rights Reserved. # @@ -800,20 +800,15 @@ class PowerVMDriver(driver.ComputeDriver): """Snapshots the specified instance. :param context: security context - :param instance: Instance object as returned by DB layer. - :param image_id: Reference to a pre-created image that will - hold the snapshot. - :param update_task_state: Callable to update the state of the snapshot - task with one of the IMAGE_* consts from - nova.compute.task_states. Call spec - (inferred from compute driver source): - update_task_state(task_state, expected_task_state=None) - param task_state: The nova.compute.task_states.IMAGE_* state to - set. - param expected_state: The nova.compute.task_state.IMAGE_* state - which should be in place before this - update. The driver will raise if this - doesn't match. + :param instance: nova.objects.instance.Instance + :param image_id: Reference to a pre-created image that will hold the + snapshot. + :param update_task_state: Callback function to update the task_state + on the instance while the snapshot operation progresses. The + function takes a task_state argument and an optional + expected_task_state kwarg which defaults to + nova.compute.task_states.IMAGE_SNAPSHOT. See + nova.objects.instance.Instance.save for expected_task_state usage. """ if not self.disk_dvr.capabilities.get('snapshot'): raise exception.NotSupportedWithOption( diff --git a/nova_powervm/virt/powervm/image.py b/nova_powervm/virt/powervm/image.py index bc722e11..289d9d3e 100644 --- a/nova_powervm/virt/powervm/image.py +++ b/nova_powervm/virt/powervm/image.py @@ -1,4 +1,4 @@ -# Copyright 2015 IBM Corp. +# Copyright IBM Corp. and contributors # # All Rights Reserved. # @@ -47,14 +47,14 @@ def stream_blockdev_to_glance(context, image_api, image_id, metadata, devpath): image_api.update(context, image_id, metadata, stream) -def snapshot_metadata(context, image_api, image_id, instance): +def generate_snapshot_metadata(context, image_api, image_id, instance): """Generate a metadata dictionary for an instance snapshot. :param context: Nova security context :param image_api: Handle to the glance image API. :param image_id: UUID of the prepared glance image. :param instance: The Nova instance whose disk is to be snapshotted. - :return: A dict of metadata suitable for image_api.upload. + :return: A dict of metadata suitable for image_api.update. """ image = image_api.get(context, image_id) metadata = { diff --git a/nova_powervm/virt/powervm/mgmt.py b/nova_powervm/virt/powervm/mgmt.py index 62b5bf95..c03646b9 100644 --- a/nova_powervm/virt/powervm/mgmt.py +++ b/nova_powervm/virt/powervm/mgmt.py @@ -1,4 +1,4 @@ -# Copyright 2015, 2017 IBM Corp. +# Copyright IBM Corp. and contributors # # All Rights Reserved. # @@ -23,9 +23,10 @@ aixlinux, but with the is_mgmt_partition property set to True. The PowerVM Nova Compute service runs on the management partition. """ import glob +import os + from nova import exception from nova.privsep import path as priv_path -import os from oslo_concurrency import lockutils from oslo_log import log as logging from pypowervm.tasks import partition as pvm_par @@ -71,8 +72,6 @@ def discover_vscsi_disk(mapping, scan_timeout=300): :raise UniqueDiskDiscoveryException: If more than one disk appears with the expected UDID. """ - # TODO(IBM): Support for other host platforms. - # Calculate the Linux slot number from the client adapter slot number. lslot = 0x30000000 | mapping.client_adapter.lpar_slot_num # We'll match the device ID based on the UDID, which is actually the last diff --git a/nova_powervm/virt/powervm/tasks/image.py b/nova_powervm/virt/powervm/tasks/image.py index 2c25b62e..018b45f1 100644 --- a/nova_powervm/virt/powervm/tasks/image.py +++ b/nova_powervm/virt/powervm/tasks/image.py @@ -1,4 +1,4 @@ -# Copyright 2015, 2018 IBM Corp. +# Copyright IBM Corp. and contributors # # All Rights Reserved. # @@ -72,8 +72,8 @@ class StreamToGlance(task.Task): requires='disk_path') def execute(self, disk_path): - metadata = image.snapshot_metadata(self.context, self.image_api, - self.image_id, self.instance) + metadata = image.generate_snapshot_metadata( + self.context, self.image_api, self.image_id, self.instance) LOG.info("Starting stream of boot device (local blockdev %(devpath)s) " "to glance image %(img_id)s.", {'devpath': disk_path, 'img_id': self.image_id}, diff --git a/nova_powervm/virt/powervm/tasks/storage.py b/nova_powervm/virt/powervm/tasks/storage.py index 109c7987..15ef7eb9 100644 --- a/nova_powervm/virt/powervm/tasks/storage.py +++ b/nova_powervm/virt/powervm/tasks/storage.py @@ -1,4 +1,4 @@ -# Copyright 2015, 2018 IBM Corp. +# Copyright IBM Corp. and contributors # # All Rights Reserved. # @@ -14,9 +14,9 @@ # License for the specific language governing permissions and limitations # under the License. -from pypowervm.tasks import scsi_mapper as pvm_smap - from oslo_log import log as logging +from pypowervm import exceptions as pvm_exc +from pypowervm.tasks import scsi_mapper as pvm_smap from taskflow import task from taskflow.types import failure as task_fail @@ -201,10 +201,11 @@ class ConnectDisk(task.Task): class InstanceDiskToMgmt(task.Task): - """Connect an instance's disk to the management partition, discover it. + """The Task to connect an instance's disk to the management partition. - We do these two pieces together because their reversion doesn't happen in - the opposite order. + This task will connect the instance's disk to the management partition and + discover it. We do these two pieces together because their reversion + happens in the same order. """ def __init__(self, disk_dvr, instance): @@ -223,7 +224,7 @@ class InstanceDiskToMgmt(task.Task): :param instance: The nova instance whose boot disk is to be connected. """ super(InstanceDiskToMgmt, self).__init__( - name='connect_and_discover_instance_disk_to_mgmt', + name='instance_disk_to_mgmt', provides=['stg_elem', 'vios_wrap', 'disk_path']) self.disk_dvr = disk_dvr self.instance = instance @@ -234,9 +235,9 @@ class InstanceDiskToMgmt(task.Task): def execute(self): """Map the instance's boot disk and discover it.""" - # Search for boot disk on the Novalink partition + # Search for boot disk on the NovaLink partition if self.disk_dvr.mp_uuid in self.disk_dvr.vios_uuids: - dev_name = self.disk_dvr.boot_disk_path_for_instance( + dev_name = self.disk_dvr.get_bootdisk_path( self.instance, self.disk_dvr.mp_uuid) if dev_name is not None: return None, None, dev_name @@ -282,7 +283,12 @@ class InstanceDiskToMgmt(task.Task): return LOG.warning("Removing disk %(dpath)s from the management partition.", {'dpath': self.disk_path}, instance=self.instance) - mgmt.remove_block_dev(self.disk_path) + try: + mgmt.remove_block_dev(self.disk_path) + except pvm_exc.Error: + # Don't allow revert exceptions to interrupt the revert flow. + LOG.exception("Remove disk failed during revert. Ignoring.", + instance=self.instance) class RemoveInstanceDiskFromMgmt(task.Task):