def __format_filesystem(self): logging.info("Formating %s filesystem on %s" % (self.fstype, self.disk.device)) args = ["/sbin/mkfs." + self.fstype] if self.fstype.startswith("ext"): args = args + [ "-F", "-L", self.fslabel, "-m", "1", "-b", str(self.blocksize) ] elif self.fstype == "xfs": args = args + [ "-L", self.fslabel[0:10], "-b", "size=%s" % str(self.blocksize) ] elif self.fstype == "btrfs": args = args + ["-L", self.fslabel] args = args + [self.disk.device] print(args) rc = call(args) if rc != 0: raise MountError("Error creating %s filesystem" % (self.fstype, )) logging.info("Tuning filesystem on %s" % self.disk.device) call([ "/sbin/tune2fs", "-c0", "-i0", "-Odir_index", "-ouser_xattr,acl", self.disk.device ])
def unmount(self): if self.mounted: logging.info("Unmounting directory %s" % self.mountdir) rc = call(["/bin/umount", self.mountdir]) if rc == 0: self.mounted = False else: logging.warning( "Unmounting directory %s failed, using lazy umount" % self.mountdir) print("Unmounting directory %s failed, using lazy umount" % self.mountdir, file=sys.stdout) rc = call(["/bin/umount", "-l", self.mountdir]) if rc != 0: raise MountError("Unable to unmount filesystem at %s" % self.mountdir) else: logging.info("lazy umount succeeded on %s" % self.mountdir) print("lazy umount succeeded on %s" % self.mountdir, file=sys.stdout) self.mounted = False if self.rmdir and not self.mounted: try: os.rmdir(self.mountdir) except OSError as e: pass self.rmdir = False
def unmount(self): if not self.mounted: return rc = call(["/bin/umount", self.dest]) if rc != 0: logging.info("Unable to unmount %s normally, using lazy unmount" % self.dest) rc = call(["/bin/umount", "-l", self.dest]) if rc != 0: raise MountError("Unable to unmount fs at %s" % self.dest) else: logging.info("lazy umount succeeded on %s" % self.dest) print("lazy umount succeeded on %s" % self.dest, file=sys.stdout) self.mounted = False
def create(self): if self.__created: return self.imgloop.create() self.cowloop.create() self.__name = "imgcreate-%d-%d" % (os.getpid(), random.randint(0, 2 ** 16)) size = os.stat(self.imgloop.lofile)[stat.ST_SIZE] table = "0 %d snapshot %s %s p 8" % (size // 512, self.imgloop.device, self.cowloop.device) args = [ "/sbin/dmsetup", "create", self.__name, "-vv", "--verifyudev", "--uuid", "LIVECD-%s" % self.__name, "--table", table, ] if call(args) != 0: self.cowloop.cleanup() self.imgloop.cleanup() raise SnapshotError("Could not create snapshot device using: " + " ".join(args)) self.__created = True
def create(self): if self.__created: return self.imgloop.create() self.cowloop.create() self.__name = "imgcreate-%d-%d" % (os.getpid(), random.randint( 0, 2**16)) size = os.stat(self.imgloop.lofile)[stat.ST_SIZE] table = "0 %d snapshot %s %s p 8" % (size // 512, self.imgloop.device, self.cowloop.device) args = [ "/sbin/dmsetup", "create", self.__name, "-vv", "--verifyudev", "--uuid", "LIVECD-%s" % self.__name, "--table", table ] if call(args) != 0: self.cowloop.cleanup() self.imgloop.cleanup() raise SnapshotError("Could not create snapshot device using: " + " ".join(args)) self.__created = True
def __format_filesystem(self): logging.info("Formating %s filesystem on %s" % (self.fstype, self.disk.device)) args = ["/sbin/mkfs." + self.fstype] if self.fstype.startswith("ext"): args = args + ["-F", "-L", self.fslabel, "-m", "1", "-b", str(self.blocksize)] elif self.fstype == "xfs": args = args + ["-L", self.fslabel[0:10], "-b", "size=%s" % str(self.blocksize)] elif self.fstype == "btrfs": args = args + ["-L", self.fslabel] args = args + [self.disk.device] print(args) rc = call(args) if rc != 0: raise MountError("Error creating %s filesystem" % (self.fstype,)) logging.info("Tuning filesystem on %s" % self.disk.device) call(["/sbin/tune2fs", "-c0", "-i0", "-Odir_index", "-ouser_xattr,acl", self.disk.device])
def mount(self): if self.mounted: return makedirs(self.dest) rc = call(["/bin/mount", "--bind", self.src, self.dest]) if rc != 0: raise MountError("Bind-mounting '%s' to '%s' failed" % (self.src, self.dest)) self.mounted = True
def mksquashfs(in_img, out_img, compress_type): # Allow gzip to work for older versions of mksquashfs if not compress_type or compress_type == "gzip": args = ["/sbin/mksquashfs", in_img, out_img] else: args = ["/sbin/mksquashfs", in_img, out_img, "-comp", compress_type] if not sys.stdout.isatty(): args.append("-no-progress") ret = call(args) if ret != 0: raise SquashfsError("'%s' exited with error (%d)" % (" ".join(args), ret))
def unmount(self): if self.mounted: logging.info("Unmounting directory %s" % self.mountdir) rc = call(["/bin/umount", self.mountdir]) if rc == 0: self.mounted = False else: logging.warning("Unmounting directory %s failed, using lazy umount" % self.mountdir) print("Unmounting directory %s failed, using lazy umount" % self.mountdir, file=sys.stdout) rc = call(["/bin/umount", "-l", self.mountdir]) if rc != 0: raise MountError("Unable to unmount filesystem at %s" % self.mountdir) else: logging.info("lazy umount succeeded on %s" % self.mountdir) print("lazy umount succeeded on %s" % self.mountdir, file=sys.stdout) self.mounted = False if self.rmdir and not self.mounted: try: os.rmdir(self.mountdir) except OSError as e: pass self.rmdir = False
def remove(self, ignore_errors=False): if not self.__created: return # sleep to try to avoid any dm shenanigans time.sleep(2) rc = call(["/sbin/dmsetup", "remove", self.__name]) if not ignore_errors and rc != 0: raise SnapshotError("Could not remove snapshot device") self.__name = None self.__created = False self.cowloop.cleanup() self.imgloop.cleanup()
def loopsetup(self): if self.losetup: return losetupProc = subprocess.Popen(["/sbin/losetup", "-f"], stdout=subprocess.PIPE) losetupOutput = losetupProc.communicate()[0] if losetupProc.returncode: raise MountError("Failed to allocate loop device for '%s'" % self.lofile) self.loopdev = losetupOutput.split()[0] rc = call(["/sbin/losetup", self.loopdev, self.lofile]) if rc != 0: raise MountError("Failed to allocate loop device for '%s'" % self.lofile) self.losetup = True
def create(self): if self.device is not None: return losetupProc = subprocess.Popen(["/sbin/losetup", "-f"], stdout=subprocess.PIPE) losetupOutput = losetupProc.communicate()[0] if losetupProc.returncode: raise MountError("Failed to allocate loop device for '%s'" % self.lofile) device = losetupOutput.split()[0].decode("utf-8") logging.info("Losetup add %s mapping to %s" % (device, self.lofile)) rc = call(["/sbin/losetup", device, self.lofile]) if rc != 0: raise MountError("Failed to allocate loop device for '%s'" % self.lofile) self.device = device
def mount(self): if self.mounted: return if not os.path.isdir(self.mountdir): logging.info("Creating mount point %s" % self.mountdir) os.makedirs(self.mountdir) self.rmdir = self.rmmountdir self.__create() logging.info("Mounting %s at %s" % (self.disk.device, self.mountdir)) args = ["/bin/mount", self.disk.device, self.mountdir] if self.fstype: args.extend(["-t", self.fstype]) if self.fstype == "squashfs": args.extend(["-o", "ro"]) rc = call(args) if rc != 0: raise MountError("Failed to mount '%s' to '%s'" % (self.disk.device, self.mountdir)) self.mounted = True
def resize2fs(fs, size=None, minimal=False): if minimal and size is not None: raise ResizeError("Can't specify both minimal and a size for resize!") if not minimal and size is None: raise ResizeError("Must specify either a size or minimal for resize!") e2fsck(fs) logging.info("resizing %s" % (fs,)) args = ["/sbin/resize2fs", fs] if minimal: args.append("-M") else: args.append("%sK" %(size // 1024,)) ret = call(args) if ret != 0: raise ResizeError("resize2fs returned an error (%d)!" % (ret,)) ret = e2fsck(fs) if ret != 0: raise ResizeError("fsck after resize returned an error (%d)!" % (ret,)) return 0
def resize2fs(fs, size=None, minimal=False): if minimal and size is not None: raise ResizeError("Can't specify both minimal and a size for resize!") if not minimal and size is None: raise ResizeError("Must specify either a size or minimal for resize!") e2fsck(fs) logging.info("resizing %s" % (fs,)) args = ["/sbin/resize2fs", fs] if minimal: args.append("-M") else: args.append("%sK" % (size // 1024,)) ret = call(args) if ret != 0: raise ResizeError("resize2fs returned an error (%d)!" % (ret,)) ret = e2fsck(fs) if ret != 0: raise ResizeError("fsck after resize returned an error (%d)!" % (ret,)) return 0
def cleanup(self): if self.device is None: return logging.info("Losetup remove %s" % self.device) rc = call(["/sbin/losetup", "-d", self.device]) self.device = None
def e2fsck(fs): logging.info("Checking filesystem %s" % fs) return call(["/sbin/e2fsck", "-f", "-y", fs])
def lounsetup(self): if self.losetup: rc = call(["/sbin/losetup", "-d", self.loopdev]) self.losetup = False self.loopdev = None