def reduceLV(vgName, lvName, size_mb, force=False): log.info("Reducing LV %s/%s to %s megabytes (force=%s)", vgName, lvName, size_mb, force) cmd = ("lvreduce", ) + LVM_NOBACKUP if force: cmd += ("--force", ) cmd += ("--size", "%sm" % (size_mb, ), "%s/%s" % (vgName, lvName)) rc, out, err = _lvminfo.cmd(cmd, _lvminfo._getVGDevs((vgName, ))) if rc != 0: # Since this runs only on the SPM, assume that cached vg and lv # metadata is correct. vg = getVG(vgName) lv = getLV(vgName, lvName) # Convert sizes to extents extent_size = int(vg.extent_size) lv_extents = int(lv.size) // extent_size requested_size = size_mb * constants.MEGAB requested_extents = (requested_size + extent_size - 1) // extent_size if lv_extents <= requested_extents: log.debug("LV %s/%s already reduced (extents=%d, requested=%d)", vgName, lvName, lv_extents, requested_extents) return # TODO: add and raise LogicalVolumeReduceError raise se.LogicalVolumeExtendError(vgName, lvName, "%sm" % (size_mb, )) _lvminfo._invalidatevgs(vgName) _lvminfo._invalidatelvs(vgName, lvName)
def extendLV(vgName, lvName, size_mb): log.info("Extending LV %s/%s to %s megabytes", vgName, lvName, size_mb) cmd = ("lvextend", ) + LVM_NOBACKUP cmd += ("--size", "%sm" % (size_mb, ), "%s/%s" % (vgName, lvName)) rc, out, err = _lvminfo.cmd(cmd, _lvminfo._getVGDevs((vgName, ))) if rc != 0: # Since this runs only on the SPM, assume that cached vg and lv # metadata is correct. vg = getVG(vgName) lv = getLV(vgName, lvName) # Convert sizes to extents to match lvm behavior. extent_size = int(vg.extent_size) lv_extents = int(lv.size) // extent_size requested_size = size_mb * constants.MEGAB requested_extents = (requested_size + extent_size - 1) // extent_size if lv_extents >= requested_extents: log.debug("LV %s/%s already extended (extents=%d, requested=%d)", vgName, lvName, lv_extents, requested_extents) return needed_extents = requested_extents - lv_extents free_extents = int(vg.free_count) if free_extents < needed_extents: raise se.VolumeGroupSizeError( "Not enough free extents for extending LV %s/%s (free=%d, " "needed=%d)" % (vgName, lvName, free_extents, needed_extents)) raise se.LogicalVolumeExtendError(vgName, lvName, "%sm" % (size_mb, )) _lvminfo._invalidatevgs(vgName) _lvminfo._invalidatelvs(vgName, lvName)
def _resizeLV(op, vgName, lvName, size): """ Size units: MB (1024 ** 2 = 2 ** 20)B. """ # WARNING! From man vgs: # All sizes are output in these units: (h)uman-readable, (b)ytes, # (s)ectors,(k)ilobytes, (m)egabytes, (g)igabytes, (t)erabytes, # (p)etabytes, (e)xabytes. # Capitalise to use multiples of 1000 (S.I.) instead of 1024. cmd = (op, ) + LVM_NOBACKUP cmd += ("--size", "%sm" % (size, ), "%s/%s" % (vgName, lvName)) rc, out, err = _lvminfo.cmd(cmd, _lvminfo._getVGDevs((vgName, ))) if rc == 0: _lvminfo._invalidatevgs(vgName) _lvminfo._invalidatelvs(vgName, lvName) elif rc == 3: # In LVM we trust. Hope that 3 is only for this. log.debug("New size (in extents) matches existing size (in extents).") elif rc != 0: # get the free extents size # YaRC vg = getVG(vgName) free_size = int(vg.extent_size) * int(vg.free_count) # in B if free_size < int(size) * constants.MEGAB: raise se.VolumeGroupSizeError( "%s/%s %d > %d (MiB)" % (vgName, lvName, int(size), free_size / constants.MEGAB)) raise se.LogicalVolumeExtendError(vgName, lvName, "%sM" % (size, ))
def extendLV(self, vgName, lvName, size_mb, refresh=True): try: lv = self.lvmd[(vgName, lvName)] except KeyError: raise se.LogicalVolumeExtendError("cmd", 5, ["out"], ["err"]) size = self._size_param_to_bytes(size_mb) current_size = int(lv["size"]) if current_size >= size: # In real lvm code we call call lvm and check after the call if the # lvm is already in the corect size. return lv['size'] = str(size) self._extend_lv_file(vgName, lvName, lv['active'], size)
def test_reduce_failure(self): with self.make_env(sd_type='block', format='cow', chain_len=4) as env: base_vol = env.chain[0] top_vol = env.chain[1] subchain_info = dict(sd_id=base_vol.sdUUID, img_id=base_vol.imgUUID, base_id=base_vol.volUUID, top_id=top_vol.volUUID, base_generation=0) subchain = merge.SubchainInfo(subchain_info, 0) fake_sd = env.sdcache.domains[env.sd_manifest.sdUUID] fake_base_vol = fake_sd.produceVolume(subchain.img_id, subchain.base_id) fake_base_vol.errors["reduce"] = se.LogicalVolumeExtendError( "vgname", "lvname", base_vol.optimal_size()) with pytest.raises(se.LogicalVolumeExtendError): merge.finalize(subchain) # verify syncVolumeChain arguments self.check_sync_volume_chain(subchain, env.chain[-1].volUUID)