import os from charmhelpers.contrib.storage.linux.utils import ( is_block_device, zap_disk, ) from charmhelpers.contrib.storage.linux.loopback import ( ensure_loopback_device, ) from charmhelpers.contrib.storage.linux.lvm import ( deactivate_lvm_volume_group, is_lvm_physical_volume, remove_lvm_physical_volume, ) from charmhelpers.core.host import ( mounts, umount, restart_on_change, ) from charmhelpers.core.hookenv import ( log, INFO, ERROR, ) from charmhelpers.core.unitdata import ( HookData, kv, ) DEFAULT_LOOPBACK_SIZE = '5G' def ensure_block_device(block_device): ''' Confirm block_device, create as loopback if necessary. :param block_device: str: Full path of block device to ensure. :returns: str: Full path of ensured block device. ''' if block_device.startswith("/"): # Resolve non-relative link(s) if device is a symlink to a real device. # This fixes/prevents bug #1577408. real_device = os.path.realpath(block_device) if real_device != block_device: log('Block device "{}" is a symlink to "{}". Using "{}".'.format( block_device, real_device, real_device), level=INFO) block_device = real_device _none = ['None', 'none', None] if (block_device in _none): log('prepare_storage(): Missing required input: ' 'block_device=%s.' % block_device, level=ERROR) raise if block_device.startswith('/dev/'): bdev = block_device elif block_device.startswith('/'): _bd = block_device.split('|') if len(_bd) == 2: bdev, size = _bd else: bdev = block_device size = DEFAULT_LOOPBACK_SIZE bdev = ensure_loopback_device(bdev, size) else: bdev = '/dev/%s' % block_device if not is_block_device(bdev): log('Failed to locate valid block device at %s' % bdev, level=ERROR) # ignore missing block devices return return bdev def clean_storage(block_device): ''' Ensures a block device is clean. That is: - unmounted - any lvm volume groups are deactivated - any lvm physical device signatures removed - partition table wiped :param block_device: str: Full path to block device to clean. ''' for mp, d in mounts(): if d == block_device: log('clean_storage(): Found %s mounted @ %s, unmounting.' % (d, mp), level=INFO) umount(mp, persist=True) if is_lvm_physical_volume(block_device): deactivate_lvm_volume_group(block_device) remove_lvm_physical_volume(block_device) else: zap_disk(block_device) def is_paused(): """Is the unit paused?""" with HookData()(): if kv().get('unit-paused'): return True else: return False def pause_aware_restart_on_change(restart_map): """Avoids restarting services if config changes when unit is paused.""" def wrapper(f): if is_paused(): return f else: return restart_on_change(restart_map)(f) return wrapper