Example #1
0
    def execute(self, stg_elem, vios_wrap, disk_path):
        """Unmap and remove an instance's boot disk from the mgmt partition.

        Input parameters ('requires') provided by InstanceDiskToMgmt task.

        :param stg_elem: The storage element wrapper (pypowervm LU, PV, etc.)
                         to be disconnected.
        :param vios_wrap: The Virtual I/O Server wrapper from which the
                          mapping is to be removed.
        :param disk_path: The local path to the disk device to be removed, e.g.
                          '/dev/sde'
        """
        # stg_elem is None if boot disk was not mapped to management partition
        if stg_elem is None:
            return
        LOG.info(
            "Unmapping boot disk %(disk_name)s from the management "
            "partition via Virtual I/O Server %(vios_name)s.", {
                'disk_name': stg_elem.name,
                'vios_name': vios_wrap.name
            },
            instance=self.instance)
        self.disk_dvr.disconnect_disk_from_mgmt(vios_wrap.uuid, stg_elem.name)
        LOG.info("Removing disk %(disk_path)s from the management partition.",
                 {'disk_path': disk_path},
                 instance=self.instance)
        mgmt.remove_block_dev(disk_path)
Example #2
0
    def revert(self, result, flow_failures):
        """Unmap the disk and then remove it from the management partition.

        We use this order to avoid rediscovering the device in case some other
        thread scans the SCSI bus between when we remove and when we unmap.
        """
        if self.vios_wrap is None or self.stg_elem is None:
            # We never even got connected - nothing to do
            return
        LOG.warning(
            "Unmapping boot disk %(disk_name)s from the management "
            "partition via Virtual I/O Server %(vioname)s.", {
                'disk_name': self.stg_elem.name,
                'vioname': self.vios_wrap.name
            },
            instance=self.instance)
        self.disk_dvr.disconnect_disk_from_mgmt(self.vios_wrap.uuid,
                                                self.stg_elem.name)

        if self.disk_path is None:
            # We did not discover the disk - nothing else to do.
            return
        LOG.warning("Removing disk %(dpath)s from the management partition.",
                    {'dpath': self.disk_path},
                    instance=self.instance)
        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)
Example #3
0
    def revert_impl(self, result, flow_failures):
        """Unmap the disk and then remove it from the management partition.

        We use this order to avoid rediscovering the device in case some other
        thread scans the SCSI bus between when we remove and when we unmap.
        """
        if self.vios_wrap is None or self.stg_elem is None:
            # We never even got connected - nothing to do
            return
        LOG.warning(
            _LW("Unmapping boot disk %(disk_name)s of instance "
                "%(instance_name)s from management partition via "
                "Virtual I/O Server %(vios_name)s."), {
                    'disk_name': self.stg_elem.name,
                    'instance_name': self.instance.name,
                    'vios_name': self.vios_wrap.name
                })
        self.disk_dvr.disconnect_disk_from_mgmt(self.vios_wrap.uuid,
                                                self.stg_elem.name)

        if self.disk_path is None:
            # We did not discover the disk - nothing else to do.
            return
        LOG.warning(
            _LW("Removing disk %(disk_path)s from the management "
                "partition."), {'disk_path': self.disk_path})
        mgmt.remove_block_dev(self.disk_path)
Example #4
0
    def test_remove_block_dev(self, mock_exec, mock_stat, mock_realpath,
                              mock_sleep):
        link = '/dev/link/foo'
        realpath = '/dev/sde'
        delpath = '/sys/block/sde/device/delete'
        mock_realpath.return_value = realpath

        # Good path
        mock_stat.side_effect = (None, None, OSError())
        mgmt.remove_block_dev(link)
        mock_realpath.assert_called_with(link)
        mock_stat.assert_has_calls(
            [mock.call(realpath),
             mock.call(delpath),
             mock.call(realpath)])
        mock_exec.assert_called_with('tee',
                                     '-a',
                                     delpath,
                                     process_input='1',
                                     run_as_root=True)
        self.assertEqual(0, mock_sleep.call_count)

        # Device param not found
        mock_exec.reset_mock()
        mock_stat.reset_mock()
        mock_stat.side_effect = (OSError(), None, None)
        self.assertRaises(exception.InvalidDevicePath, mgmt.remove_block_dev,
                          link)
        # stat was called once; exec was not called
        self.assertEqual(1, mock_stat.call_count)
        self.assertEqual(0, mock_exec.call_count)

        # Delete special file not found
        mock_exec.reset_mock()
        mock_stat.reset_mock()
        mock_stat.side_effect = (None, OSError(), None)
        self.assertRaises(exception.InvalidDevicePath, mgmt.remove_block_dev,
                          link)
        # stat was called twice; exec was not called
        self.assertEqual(2, mock_stat.call_count)
        self.assertEqual(0, mock_exec.call_count)

        # Deletion was attempted, but device is still there
        mock_exec.reset_mock()
        mock_stat.reset_mock()
        mock_sleep.reset_mock()
        mock_stat.side_effect = lambda path: 1
        self.assertRaises(npvmex.DeviceDeletionException,
                          mgmt.remove_block_dev, link)
        # stat was called many times; exec was called once
        self.assertTrue(mock_stat.call_count > 4)
        self.assertEqual(1, mock_exec.call_count)
        # sleep was called many times
        self.assertTrue(mock_sleep.call_count)
Example #5
0
    def test_remove_block_dev(self, mock_exec, mock_stat, mock_realpath,
                              mock_sleep):
        link = '/dev/link/foo'
        realpath = '/dev/sde'
        delpath = '/sys/block/sde/device/delete'
        mock_realpath.return_value = realpath

        # Good path
        mock_stat.side_effect = (None, None, OSError())
        mgmt.remove_block_dev(link)
        mock_realpath.assert_called_with(link)
        mock_stat.assert_has_calls([mock.call(realpath), mock.call(delpath),
                                    mock.call(realpath)])
        mock_exec.assert_called_with('tee', '-a', delpath, process_input='1',
                                     run_as_root=True)
        self.assertEqual(0, mock_sleep.call_count)

        # Device param not found
        mock_exec.reset_mock()
        mock_stat.reset_mock()
        mock_stat.side_effect = (OSError(), None, None)
        self.assertRaises(exception.InvalidDevicePath, mgmt.remove_block_dev,
                          link)
        # stat was called once; exec was not called
        self.assertEqual(1, mock_stat.call_count)
        self.assertEqual(0, mock_exec.call_count)

        # Delete special file not found
        mock_exec.reset_mock()
        mock_stat.reset_mock()
        mock_stat.side_effect = (None, OSError(), None)
        self.assertRaises(exception.InvalidDevicePath, mgmt.remove_block_dev,
                          link)
        # stat was called twice; exec was not called
        self.assertEqual(2, mock_stat.call_count)
        self.assertEqual(0, mock_exec.call_count)

        # Deletion was attempted, but device is still there
        mock_exec.reset_mock()
        mock_stat.reset_mock()
        mock_sleep.reset_mock()
        mock_stat.side_effect = lambda path: 1
        self.assertRaises(
            npvmex.DeviceDeletionException, mgmt.remove_block_dev, link)
        # stat was called many times; exec was called once
        self.assertTrue(mock_stat.call_count > 4)
        self.assertEqual(1, mock_exec.call_count)
        # sleep was called many times
        self.assertTrue(mock_sleep.call_count)
Example #6
0
    def execute(self, stg_elem, vios_wrap, disk_path):
        """Unmap and remove an instance's boot disk from the mgmt partition.

        Input parameters ('requires') provided by InstanceDiskToMgmt task.

        :param stg_elem: The storage element wrapper (pypowervm LU, PV, etc.)
                         to be disconnected.
        :param vios_wrap: The Virtual I/O Server wrapper from which the
                          mapping is to be removed.
        :param disk_path: The local path to the disk device to be removed, e.g.
                          '/dev/sde'
        """
        LOG.info(_LI("Unmapping boot disk %(disk_name)s of instance "
                     "%(instance_name)s from management partition via Virtual "
                     "I/O Server %(vios_name)s."),
                 {'disk_name': stg_elem.name,
                  'instance_name': self.instance.name,
                  'vios_name': vios_wrap.name})
        self.disk_dvr.disconnect_disk_from_mgmt(vios_wrap.uuid, stg_elem.name)
        LOG.info(_LI("Removing disk %(disk_path)s from the management "
                     "partition."), {'disk_path': disk_path})
        mgmt.remove_block_dev(disk_path)
Example #7
0
    def revert(self, result, flow_failures):
        """Unmap the disk and then remove it from the management partition.

        We use this order to avoid rediscovering the device in case some other
        thread scans the SCSI bus between when we remove and when we unmap.
        """
        if self.vios_wrap is None or self.stg_elem is None:
            # We never even got connected - nothing to do
            return
        LOG.warn(_LW("Unmapping boot disk %(disk_name)s of instance "
                     "%(instance_name)s from management partition via Virtual "
                     "I/O Server %(vios_name)s."),
                 {'disk_name': self.stg_elem.name,
                  'instance_name': self.instance.name,
                  'vios_name': self.vios_wrap.name})
        self.disk_dvr.disconnect_disk_from_mgmt(self.vios_wrap.uuid,
                                                self.stg_elem.name)

        if self.disk_path is None:
            # We did not discover the disk - nothing else to do.
            return
        LOG.warn(_LW("Removing disk %(disk_path)s from the management "
                     "partition."), {'disk_path': self.disk_path})
        mgmt.remove_block_dev(self.disk_path)
Example #8
0
    def test_remove_block_dev(self, mock_dacw, mock_stat, mock_realpath,
                              mock_sleep):
        link = '/dev/link/foo'
        realpath = '/dev/sde'
        delpath = '/sys/block/sde/device/delete'
        mock_realpath.return_value = realpath

        # Good path
        mock_stat.side_effect = (None, None, OSError())
        mgmt.remove_block_dev(link)
        mock_realpath.assert_called_with(link)
        mock_stat.assert_has_calls(
            [mock.call(realpath),
             mock.call(delpath),
             mock.call(realpath)])
        mock_dacw.assert_called_with(delpath, 'a', '1')
        self.assertEqual(0, mock_sleep.call_count)

        # Device param not found
        mock_dacw.reset_mock()
        mock_stat.reset_mock()
        mock_stat.side_effect = (OSError(), None, None)
        self.assertRaises(exception.InvalidDevicePath, mgmt.remove_block_dev,
                          link)
        # stat was called once; privsep write was not called
        self.assertEqual(1, mock_stat.call_count)
        mock_dacw.assert_not_called()

        # Delete special file not found
        mock_stat.reset_mock()
        mock_stat.side_effect = (None, OSError(), None)
        self.assertRaises(exception.InvalidDevicePath, mgmt.remove_block_dev,
                          link)
        # stat was called twice; privsep write was not called
        self.assertEqual(2, mock_stat.call_count)
        mock_dacw.assert_not_called()