Exemplo n.º 1
0
    def test_get_backing_device(self, m_list, m_sysp, m_back):
        """ extract sysfs path to backing device from bcache kname."""
        bcache_kname = self.random_string()
        backing_kname = self.random_string()
        caching_kname = self.random_string()
        m_list.return_value = [backing_kname, caching_kname]
        m_sysp.side_effect = lambda x: '/sys/class/block/%s/bcache' % x
        m_back.side_effect = iter([True, False])

        self.assertEqual('/sys/class/block/%s/bcache' % backing_kname,
                         bcache.get_backing_device(bcache_kname))
Exemplo n.º 2
0
def shutdown_bcache(device):
    """
    Shut down bcache for specified bcache device

    1. wipe the bcache device contents
    2. extract the cacheset uuid (if cached)
    3. extract the backing device
    4. stop cacheset (if present)
    5. stop the bcacheN device
    6. wait for removal of sysfs path to bcacheN, bcacheN/bcache and
       backing/bcache to go away
    """
    if not device.startswith('/sys/class/block'):
        raise ValueError(
            'Invalid Device (%s): '
            'Device path must start with /sys/class/block/', device)

    # bcache device removal should be fast but in an extreme
    # case, might require the cache device to flush large
    # amounts of data to a backing device.  The strategy here
    # is to wait for approximately 30 seconds but to check
    # frequently since curtin cannot proceed until devices
    # cleared.
    bcache_shutdown_message = ('shutdown_bcache running on {} has determined '
                               'that the device has already been shut down '
                               'during handling of another bcache dev. '
                               'skipping'.format(device))

    if not os.path.exists(device):
        LOG.info(bcache_shutdown_message)
        return

    LOG.info('Wiping superblock on bcache device: %s', device)
    _wipe_superblock(block.sysfs_to_devpath(device), exclusive=False)

    # collect required information before stopping bcache device
    # UUID from /sys/fs/cache/UUID
    cset_uuid = bcache.get_attached_cacheset(device)
    # /sys/class/block/vdX which is a backing dev of device (bcacheN)
    backing_sysfs = bcache.get_backing_device(block.path_to_kname(device))
    # /sys/class/block/bcacheN/bache
    bcache_sysfs = bcache.sysfs_path(device, strict=False)

    # stop cacheset if one is presennt
    if cset_uuid:
        LOG.info('%s was attached to cacheset %s, stopping cacheset', device,
                 cset_uuid)
        bcache.stop_cacheset(cset_uuid)

        # let kernel settle before the next remove
        udev.udevadm_settle()
        LOG.info('bcache cacheset stopped: %s', cset_uuid)

    # test and log whether the device paths are still present
    to_check = [bcache_sysfs, backing_sysfs]
    found_devs = [os.path.exists(p) for p in to_check]
    LOG.debug('os.path.exists on blockdevs:\n%s',
              list(zip(to_check, found_devs)))
    if not any(found_devs):
        LOG.info('bcache backing device already removed: %s (%s)',
                 bcache_sysfs, device)
        LOG.debug('bcache backing device checked: %s', backing_sysfs)
    else:
        LOG.info('stopping bcache backing device at: %s', bcache_sysfs)
        bcache.stop_device(bcache_sysfs)
    return
Exemplo n.º 3
0
 def test_get_backing_device_raise_empty_dir(self, m_list, m_sysp, m_back):
     """ get_backing_device raises RuntimeError on empty deps dir."""
     bcache_kname = self.random_string()
     m_list.return_value = []
     with self.assertRaises(RuntimeError):
         bcache.get_backing_device(bcache_kname)
Exemplo n.º 4
0
 def test_get_backing_device_none_empty_dir(self, m_list, m_sysp, m_back):
     """ get_backing_device returns None on missing deps dir. """
     bcache_kname = self.random_string()
     m_list.side_effect = FileMissingError('does not exist')
     self.assertEqual(None, bcache.get_backing_device(bcache_kname))