def manage_lvm(device, dirname): """Add the device to the VG corresponding to the dirname. In this case, logical volume name will be dirname with / replaced by _ symbols. If logical volume already exists, then, device is added as a new physical device and the entire logical volume is resized. If logical volume name does not exist, then prepare the physical device and add to the newly created volume. """ lv_name = "lvm" + dirname.replace("/", "_") vg_name = "vg" + dirname.replace("/", "_") pv = device try: if list_lvm_volume_group(device): # PV already used, raise this as an issue pv = None except subprocess.CalledProcessError: # Device does not exist in the list, continue pass if not pv: raise DiskMapHelperPVAlreadyTakenForLVM(device, lv_name) if not is_lvm_physical_volume(device): # This is not a PV yet, create one create_lvm_physical_volume(device) if lv_name not in list_logical_volumes(): # lv_name is always associated 1:1 with vg_name # If one does not exist, so we need to create both. create_lvm_volume_group(vg_name, pv) create_logical_volume(lv_name, vg_name) else: # Now extend the lv_name: extend_logical_volume_by_device(lv_name, pv) # TODO: find FS already present and resize it as well return "/dev/{}/{}".format(vg_name, lv_name)
def configure_lvm_storage(block_devices, volume_group, overwrite=False, remove_missing=False, remove_missing_force=False): ''' Configure LVM storage on the list of block devices provided :param block_devices: list: List of whitelisted block devices to detect and use if found :param overwrite: bool: Scrub any existing block data if block device is not already in-use :param remove_missing: bool: Remove missing physical volumes from volume group if logical volume not allocated on them :param remove_missing_force: bool: Remove missing physical volumes from volume group even if logical volumes are allocated on them. Overrides 'remove_missing' if set. ''' log_lvm_info() devices = [] for block_device in block_devices: (block_device, size) = _parse_block_device(block_device) if not is_device_mounted(block_device): if size == 0 and is_block_device(block_device): devices.append(block_device) elif size > 0: devices.append(ensure_loopback_device(block_device, str(size))) # NOTE(jamespage) # might need todo an initial one-time scrub on install if need be vg_found = False new_devices = [] for device in devices: if not is_lvm_physical_volume(device): # Unused device if overwrite is True or not has_partition_table(device): prepare_volume(device) new_devices.append(device) elif (is_lvm_physical_volume(device) and list_lvm_volume_group(device) != volume_group): # Existing LVM but not part of required VG or new device if overwrite is True: prepare_volume(device) new_devices.append(device) elif (is_lvm_physical_volume(device) and list_lvm_volume_group(device) == volume_group): # Mark vg as found vg_found = True log_lvm_info() if vg_found is False and len(new_devices) > 0: if overwrite: ensure_lvm_volume_group_non_existent(volume_group) # Create new volume group from first device create_lvm_volume_group(volume_group, new_devices[0]) new_devices.remove(new_devices[0]) # Remove missing physical volumes from volume group try: if remove_missing_force: reduce_lvm_volume_group_missing(volume_group, extra_args=['--force']) elif remove_missing: reduce_lvm_volume_group_missing(volume_group) except subprocess.CalledProcessError as e: juju_log( "reduce_lvm_volume_group_missing() didn't complete." " LVM may not be fully configured yet. Error was: '{}'.".format( str(e))) if len(new_devices) > 0: # Extend the volume group as required for new_device in new_devices: extend_lvm_volume_group(volume_group, new_device) thin_pools = list_thin_logical_volume_pools(path_mode=True) if len(thin_pools) == 0: juju_log("No thin pools found") elif len(thin_pools) == 1: juju_log("Thin pool {} found, extending with {}".format( thin_pools[0], new_device)) extend_logical_volume_by_device(thin_pools[0], new_device) else: juju_log("Multiple thin pools ({}) found, " "skipping auto extending with {}".format( ','.join(thin_pools), new_device)) log_lvm_info()
def configure_lvm_storage(block_devices, volume_group, overwrite=False, remove_missing=False, remove_missing_force=False): ''' Configure LVM storage on the list of block devices provided :param block_devices: list: List of whitelisted block devices to detect and use if found :param overwrite: bool: Scrub any existing block data if block device is not already in-use :param remove_missing: bool: Remove missing physical volumes from volume group if logical volume not allocated on them :param remove_missing_force: bool: Remove missing physical volumes from volume group even if logical volumes are allocated on them. Overrides 'remove_missing' if set. ''' log_lvm_info() devices = [] for block_device in block_devices: (block_device, size) = _parse_block_device(block_device) if not is_device_mounted(block_device): if size == 0 and is_block_device(block_device): devices.append(block_device) elif size > 0: devices.append(ensure_loopback_device(block_device, str(size))) # NOTE(jamespage) # might need todo an initial one-time scrub on install if need be vg_found = False new_devices = [] for device in devices: if not is_lvm_physical_volume(device): # Unused device if overwrite is True or not has_partition_table(device): prepare_volume(device) new_devices.append(device) elif (is_lvm_physical_volume(device) and list_lvm_volume_group(device) != volume_group): # Existing LVM but not part of required VG or new device if overwrite is True: prepare_volume(device) new_devices.append(device) elif (is_lvm_physical_volume(device) and list_lvm_volume_group(device) == volume_group): # Mark vg as found vg_found = True log_lvm_info() if vg_found is False and len(new_devices) > 0: if overwrite: ensure_lvm_volume_group_non_existent(volume_group) # Create new volume group from first device create_lvm_volume_group(volume_group, new_devices[0]) new_devices.remove(new_devices[0]) # Remove missing physical volumes from volume group if remove_missing_force: reduce_lvm_volume_group_missing(volume_group, extra_args=['--force']) elif remove_missing: reduce_lvm_volume_group_missing(volume_group) if len(new_devices) > 0: # Extend the volume group as required for new_device in new_devices: extend_lvm_volume_group(volume_group, new_device) thin_pools = list_thin_logical_volume_pools(path_mode=True) if len(thin_pools) == 0: juju_log("No thin pools found") elif len(thin_pools) == 1: juju_log("Thin pool {} found, extending with {}".format( thin_pools[0], new_device)) extend_logical_volume_by_device(thin_pools[0], new_device) else: juju_log("Multiple thin pools ({}) found, " "skipping auto extending with {}".format( ','.join(thin_pools), new_device)) log_lvm_info()
def test_extend_logical_volume_by_device(self): """It correctly calls pvcreate for a given block dev""" with patch(STORAGE_LINUX_LVM + '.check_call') as check_call: lvm.extend_logical_volume_by_device('mylv', '/dev/foo') check_call.assert_called_with(['lvextend', 'mylv', '/dev/foo'])