def zeroImgVolumes(sdUUID, imgUUID, volUUIDs): ProcVol = namedtuple("ProcVol", "proc, vol") # Put a sensible value for dd zeroing a 128 M or 1 G chunk and lvremove # spent time. ZEROING_TIMEOUT = 60000 # [miliseconds] log.debug("sd: %s, LVs: %s, img: %s", sdUUID, volUUIDs, imgUUID) # Following call to changelv is separate since setting rw permission on an # LV fails if the LV is already set to the same value, hence we would not # be able to differentiate between a real failure of deltag/addtag and one # we would like to ignore (permission is the same) try: lvm.changelv(sdUUID, volUUIDs, ("--permission", "rw")) except se.StorageException as e: # Hope this only means that some volumes were already writable. log.debug("Ignoring failed permission change: %s", e) # blank the volumes. zerofds = {} poller = select.poll() for volUUID in volUUIDs: proc = _zeroVolume(sdUUID, volUUID) fd = proc.stdout.fileno() zerofds[fd] = ProcVol(proc, volUUID) poller.register(fd, select.EPOLLHUP) # Wait until all the asyncs procs return # Yes, this is a potentially infinite loop. Kill the vdsm task. while zerofds: fdevents = poller.poll(ZEROING_TIMEOUT) # [(fd, event)] toDelete = [] for fd, event in fdevents: proc, vol = zerofds[fd] if not proc.wait(0): continue else: poller.unregister(fd) zerofds.pop(fd) if proc.returncode != 0: log.error( "zeroing %s/%s failed. Zero and remove this " "volume manually. rc=%s %s", sdUUID, vol, proc.returncode, proc.stderr.read(1000)) else: log.debug("%s/%s was zeroed and will be deleted", sdUUID, volUUID) toDelete.append(vol) if toDelete: try: deleteVolumes(sdUUID, toDelete) except se.CannotRemoveLogicalVolume: # TODO: Add the list of removed fail volumes to the exception. log.error( "Remove failed for some of VG: %s zeroed volumes: " "%s", sdUUID, toDelete, exc_info=True) log.debug("finished with VG:%s LVs: %s, img: %s", sdUUID, volUUIDs, imgUUID) return
def __markForDelVols(self, sdUUID, imgUUID, volUUIDs, opTag): """ Mark volumes that will be zeroed or removed. Mark for delete just in case that lvremove [lvs] success partialy. Mark for zero just in case that zero process is interrupted. Tagging is preferable to rename since it can be done in a single lvm operation and is resilient to open LVs, etc. """ try: lvm.changelv( sdUUID, volUUIDs, ( ("-a", "y"), ("--deltag", blockVolume.TAG_PREFIX_IMAGE + imgUUID), ("--addtag", blockVolume.TAG_PREFIX_IMAGE + opTag + imgUUID), ), ) except se.StorageException as e: log.error( "Can't activate or change LV tags in SD %s. " "failing Image %s %s operation for vols: %s. %s", sdUUID, imgUUID, opTag, volUUIDs, e, ) raise
def _postZero(sdUUID, volumes): # Assumed that there is no any thread that can deactivate these LVs # on this host or change the rw permission on this or any other host. lvNames = tuple(vol.volUUID for vol in volumes) # Assert volumes are writable. (Don't do this at home.) try: lvm.changelv(sdUUID, lvNames, ("--permission", "rw")) except se.StorageException: # Hope this only means that some volumes were already writable. pass lvm.activateLVs(sdUUID, lvNames) for lv in lvm.getLV(sdUUID): if lv.name in lvNames: # wipe out the whole volume try: misc.ddWatchCopy( "/dev/zero", lvm.lvPath(sdUUID, lv.name), vars.task.aborting, int(lv.size), recoveryCallback=volume.baseAsyncTasksRollback) except utils.ActionStopped: raise except Exception: raise se.VolumesZeroingError(lv.name)
def zeroImgVolumes(sdUUID, imgUUID, volUUIDs): ProcVol = namedtuple("ProcVol", "proc, vol") # Put a sensible value for dd zeroing a 128 M or 1 G chunk and lvremove # spent time. ZEROING_TIMEOUT = 60000 # [miliseconds] log.debug("sd: %s, LVs: %s, img: %s", sdUUID, volUUIDs, imgUUID) # Following call to changelv is separate since setting rw permission on an # LV fails if the LV is already set to the same value, hence we would not # be able to differentiate between a real failure of deltag/addtag and one # we would like to ignore (permission is the same) try: lvm.changelv(sdUUID, volUUIDs, ("--permission", "rw")) except se.StorageException as e: # Hope this only means that some volumes were already writable. log.debug("Ignoring failed permission change: %s", e) # blank the volumes. zerofds = {} poller = select.poll() for volUUID in volUUIDs: proc = _zeroVolume(sdUUID, volUUID) fd = proc.stdout.fileno() zerofds[fd] = ProcVol(proc, volUUID) poller.register(fd, select.EPOLLHUP) # Wait until all the asyncs procs return # Yes, this is a potentially infinite loop. Kill the vdsm task. while zerofds: fdevents = poller.poll(ZEROING_TIMEOUT) # [(fd, event)] toDelete = [] for fd, event in fdevents: proc, vol = zerofds[fd] if not proc.wait(0): continue else: poller.unregister(fd) zerofds.pop(fd) if proc.returncode != 0: log.error( "zeroing %s/%s failed. Zero and remove this " "volume manually. rc=%s %s", sdUUID, vol, proc.returncode, proc.stderr.read(1000), ) else: log.debug("%s/%s was zeroed and will be deleted", sdUUID, volUUID) toDelete.append(vol) if toDelete: try: deleteVolumes(sdUUID, toDelete) except se.CannotRemoveLogicalVolume: # TODO: Add the list of removed fail volumes to the exception. log.error("Remove failed for some of VG: %s zeroed volumes: " "%s", sdUUID, toDelete, exc_info=True) log.debug("finished with VG:%s LVs: %s, img: %s", sdUUID, volUUIDs, imgUUID) return
def _postZero(sdUUID, volumes): #Assumed here that the volume is active. #To activate all the volumes of an image at once get its resource. #See http://gerrit.usersys.redhat.com/771 #Assert volumes are writable. (Don't do this at home.) lvNames = (vol.volUUID for vol in volumes) try: lvm.changelv(sdUUID, lvNames, "--permission", "rw") except se.StorageException, e: #Hope this only means that some volumes were already writable pass
def __markForDelVols(self, sdUUID, imgUUID, volUUIDs, opTag): """ Mark volumes that will be zeroed or removed. Mark for delete just in case that lvremove [lvs] success partialy. Mark for zero just in case that zero process is interrupted. Tagging is preferable to rename since it can be done in a single lvm operation and is resilient to open LVs, etc. """ try: lvm.changelv(sdUUID, volUUIDs, (("-a", "y"), ("--deltag", blockVolume.TAG_PREFIX_IMAGE + imgUUID), ("--addtag", blockVolume.TAG_PREFIX_IMAGE + opTag + imgUUID))) except se.StorageException as e: log.error("Can't activate or change LV tags in SD %s. " "failing Image %s %s operation for vols: %s. %s", sdUUID, imgUUID, opTag, volUUIDs, e) raise