def test_bootstrap(tmp_storage, read_only): dev_size = 20 * 1024**3 lvm.set_read_only(False) dev1 = tmp_storage.create_device(dev_size) vg1_name = str(uuid.uuid4()) lvm.createVG(vg1_name, [dev1], "initial-tag", 128) dev2 = tmp_storage.create_device(dev_size) vg2_name = str(uuid.uuid4()) lvm.createVG(vg2_name, [dev2], "initial-tag", 128) vgs = (vg1_name, vg2_name) for vg_name in vgs: # Create active lvs. for lv_name in ("skip", "prepared", "opened", "unused"): lvm.createLV(vg_name, lv_name, 1024) # Create links to prepared lvs. img_dir = os.path.join(sc.P_VDSM_STORAGE, vg_name, "img") os.makedirs(img_dir) os.symlink( lvm.lvPath(vg_name, "prepared"), os.path.join(img_dir, "prepared")) # Open some lvs during bootstrap. vg1_opened = lvm.lvPath(vg1_name, "opened") vg2_opened = lvm.lvPath(vg2_name, "opened") with open(vg1_opened), open(vg2_opened): lvm.set_read_only(read_only) lvm.bootstrap(skiplvs=["skip"]) # Lvs in skiplvs, prepared lvs, and opened lvs should be active. for vg_name in vgs: for lv_name in ("skip", "prepared", "opened"): lv = lvm.getLV(vg_name, lv_name) assert lv.active # Unused lvs should not be active. for vg_name in vgs: lv = lvm.getLV(vg_name, "unused") assert not lv.active
def test_bootstrap(tmp_storage, read_only): dev_size = 20 * GiB lvm.set_read_only(False) dev1 = tmp_storage.create_device(dev_size) vg1_name = str(uuid.uuid4()) lvm.createVG(vg1_name, [dev1], "initial-tag", 128) dev2 = tmp_storage.create_device(dev_size) vg2_name = str(uuid.uuid4()) lvm.createVG(vg2_name, [dev2], "initial-tag", 128) vgs = (vg1_name, vg2_name) for vg_name in vgs: # Create active lvs. for lv_name in ("skip", "prepared", "opened", "unused"): lvm.createLV(vg_name, lv_name, 1024) # Create links to prepared lvs. img_dir = os.path.join(sc.P_VDSM_STORAGE, vg_name, "img") os.makedirs(img_dir) os.symlink( lvm.lvPath(vg_name, "prepared"), os.path.join(img_dir, "prepared")) # Open some lvs during bootstrap. vg1_opened = lvm.lvPath(vg1_name, "opened") vg2_opened = lvm.lvPath(vg2_name, "opened") with open(vg1_opened), open(vg2_opened): lvm.set_read_only(read_only) lvm.bootstrap(skiplvs=["skip"]) # Lvs in skiplvs, prepared lvs, and opened lvs should be active. for vg_name in vgs: for lv_name in ("skip", "prepared", "opened"): lv = lvm.getLV(vg_name, lv_name) assert lv.active # Unused lvs should not be active. for vg_name in vgs: lv = lvm.getLV(vg_name, "unused") assert not lv.active
def _create_image_path(self): image_path = self._get_image_path() if not os.path.isdir(image_path): self.log.info("Create placeholder %s for image's volumes", image_path) os.mkdir(image_path) os.symlink(lvm.lvPath(self.sd_manifest.sdUUID, self.vol_id), self.volume_path)
def _putMetadata(cls, metaId, meta): vgname, offs = metaId data = cls.formatMetadata(meta) data += "\0" * (sc.METADATA_SIZE - len(data)) metavol = lvm.lvPath(vgname, sd.METADATA) with directio.DirectFile(metavol, "r+") as f: f.seek(offs * sc.METADATA_SIZE) f.write(data)
def _create(cls, dom, imgUUID, volUUID, capacity, volFormat, preallocate, volParent, srcImgUUID, srcVolUUID, volPath, initial_size=None, add_bitmaps=False): """ Class specific implementation of volumeCreate. All the exceptions are properly handled and logged in volume.create() """ lv_size = cls.calculate_volume_alloc_size( preallocate, volFormat, capacity, initial_size) lv_size_mb = utils.round(lv_size, MiB) // MiB lvm.createLV(dom.sdUUID, volUUID, lv_size_mb, activate=True, initialTags=(sc.TAG_VOL_UNINIT,)) fileutils.rm_file(volPath) lvPath = lvm.lvPath(dom.sdUUID, volUUID) cls.log.info("Creating volume symlink from %r to %r", lvPath, volPath) os.symlink(lvPath, volPath) if not volParent: cls.log.info("Request to create %s volume %s with capacity = %s", sc.type2name(volFormat), volPath, capacity) if volFormat == sc.COW_FORMAT: operation = qemuimg.create(volPath, size=capacity, format=sc.fmt2str(volFormat), qcow2Compat=dom.qcow2_compat()) operation.run() else: # Create hardlink to template and its meta file cls.log.info("Request to create snapshot %s/%s of volume %s/%s " "with capacity %s", imgUUID, volUUID, srcImgUUID, srcVolUUID, capacity) volParent.clone(volPath, volFormat, capacity) with dom.acquireVolumeMetadataSlot(volUUID) as slot: mdTags = ["%s%s" % (sc.TAG_PREFIX_MD, slot), "%s%s" % (sc.TAG_PREFIX_PARENT, srcVolUUID), "%s%s" % (sc.TAG_PREFIX_IMAGE, imgUUID)] lvm.changeLVsTags( dom.sdUUID, (volUUID,), delTags=[sc.TAG_VOL_UNINIT], addTags=mdTags) try: lvm.deactivateLVs(dom.sdUUID, [volUUID]) except se.CannotDeactivateLogicalVolume: cls.log.warn("Cannot deactivate new created volume %s/%s", dom.sdUUID, volUUID, exc_info=True) return (dom.sdUUID, slot)
def validateVolumePath(self): """ Block SD supports lazy volume link creation. Note that the volume can be still inactive. An explicit prepare is required to validate that the volume is active. """ if not self._imagePath: self.validateImagePath() volPath = os.path.join(self._imagePath, self.volUUID) if not os.path.lexists(volPath): srcPath = lvm.lvPath(self.sdUUID, self.volUUID) self.log.info("Creating symlink from %s to %s", srcPath, volPath) os.symlink(srcPath, volPath) self._volumePath = volPath
def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate, volParent, srcImgUUID, srcVolUUID, volPath, initialSize=None): """ Class specific implementation of volumeCreate. All the exceptions are properly handled and logged in volume.create() """ lvSize = cls.calculate_volume_alloc_size(preallocate, size, initialSize) lvm.createLV(dom.sdUUID, volUUID, lvSize, activate=True, initialTags=(sc.TAG_VOL_UNINIT,)) fileutils.rm_file(volPath) lvPath = lvm.lvPath(dom.sdUUID, volUUID) cls.log.info("Creating volume symlink from %r to %r", lvPath, volPath) os.symlink(lvPath, volPath) if not volParent: cls.log.info("Request to create %s volume %s with size = %s " "blocks", sc.type2name(volFormat), volPath, size) if volFormat == sc.COW_FORMAT: operation = qemuimg.create(volPath, size=size * BLOCK_SIZE, format=sc.fmt2str(volFormat), qcow2Compat=dom.qcow2_compat()) operation.run() else: # Create hardlink to template and its meta file cls.log.info("Request to create snapshot %s/%s of volume %s/%s " "with size %s (blocks)", imgUUID, volUUID, srcImgUUID, srcVolUUID, size) volParent.clone(volPath, volFormat, size) with dom.acquireVolumeMetadataSlot(volUUID) as slot: mdTags = ["%s%s" % (sc.TAG_PREFIX_MD, slot), "%s%s" % (sc.TAG_PREFIX_PARENT, srcVolUUID), "%s%s" % (sc.TAG_PREFIX_IMAGE, imgUUID)] lvm.changeLVTags(dom.sdUUID, volUUID, delTags=[sc.TAG_VOL_UNINIT], addTags=mdTags) try: lvm.deactivateLVs(dom.sdUUID, [volUUID]) except se.CannotDeactivateLogicalVolume: cls.log.warn("Cannot deactivate new created volume %s/%s", dom.sdUUID, volUUID, exc_info=True) return (dom.sdUUID, slot)
def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate, volParent, srcImgUUID, srcVolUUID, volPath, initialSize=None): """ Class specific implementation of volumeCreate. All the exceptions are properly handled and logged in volume.create() """ lvSize = cls.calculate_volume_alloc_size(preallocate, size, initialSize) lvm.createLV(dom.sdUUID, volUUID, "%s" % lvSize, activate=True, initialTags=(sc.TAG_VOL_UNINIT,)) fileutils.rm_file(volPath) os.symlink(lvm.lvPath(dom.sdUUID, volUUID), volPath) if not volParent: cls.log.info("Request to create %s volume %s with size = %s " "sectors", sc.type2name(volFormat), volPath, size) if volFormat == sc.COW_FORMAT: qemuimg.create(volPath, size=size * BLOCK_SIZE, format=sc.fmt2str(volFormat), qcow2Compat=dom.qcow2_compat()) else: # Create hardlink to template and its meta file cls.log.info("Request to create snapshot %s/%s of volume %s/%s", imgUUID, volUUID, srcImgUUID, srcVolUUID) volParent.clone(volPath, volFormat) with dom.acquireVolumeMetadataSlot( volUUID, sc.VOLUME_MDNUMBLKS) as slot: mdTags = ["%s%s" % (sc.TAG_PREFIX_MD, slot), "%s%s" % (sc.TAG_PREFIX_PARENT, srcVolUUID), "%s%s" % (sc.TAG_PREFIX_IMAGE, imgUUID)] lvm.changeLVTags(dom.sdUUID, volUUID, delTags=[sc.TAG_VOL_UNINIT], addTags=mdTags) try: lvm.deactivateLVs(dom.sdUUID, [volUUID]) except se.CannotDeactivateLogicalVolume: cls.log.warn("Cannot deactivate new created volume %s/%s", dom.sdUUID, volUUID, exc_info=True) return (dom.sdUUID, slot)
def getMetadata(self, metaId=None): """ Get Meta data array of key,values lines """ if not metaId: metaId = self.getMetadataId() vgname, offs = metaId try: lines = misc.readblock(lvm.lvPath(vgname, sd.METADATA), offs * sc.METADATA_SIZE, sc.METADATA_SIZE) except Exception as e: self.log.error(e, exc_info=True) raise se.VolumeMetadataReadError("%s: %s" % (metaId, e)) md = VolumeMetadata.from_lines(lines) return md.legacy_info()
def getDevPath(self): """ Return the underlying device (for sharing) """ return lvm.lvPath(self.sdUUID, self.volUUID)