[Patch 1/5] Author: Frederick Grose <fgr...@sugarlabs.org> Date: Thu Apr 14 09:29:14 2011 -0400
Support Live image mounting. Provide DiskMount with mount options, DeviceMapperSnapshot with a device attribute, and a new LiveImageMount class. diff --git a/imgcreate/fs.py b/imgcreate/fs.py index d5307a2..0871182 100644 --- a/imgcreate/fs.py +++ b/imgcreate/fs.py @@ -324,7 +324,6 @@ class LoopbackDisk(Disk): self.device = None - class SparseLoopbackDisk(LoopbackDisk): """A Disk backed by a sparse file via the loop module.""" def __init__(self, lofile, size): @@ -377,11 +376,12 @@ class Mount: class DiskMount(Mount): """A Mount object that handles mounting of a Disk.""" - def __init__(self, disk, mountdir, fstype = None, rmmountdir = True): + def __init__(self, disk, mountdir, fstype=None, rmmountdir=True, ops=None): Mount.__init__(self, mountdir) self.disk = disk self.fstype = fstype + self.ops = ops self.rmmountdir = rmmountdir self.mounted = False @@ -435,6 +435,8 @@ class DiskMount(Mount): args = [ "/bin/mount", self.disk.device, self.mountdir ] if self.fstype: args.extend(["-t", self.fstype]) + if self.ops: + args.extend(['-o', self.ops]) rc = call(args) if rc != 0: @@ -530,6 +532,7 @@ class ExtDiskMount(DiskMount): self.__resize_filesystem(size) return minsize + class DeviceMapperSnapshot(object): def __init__(self, imgloop, cowloop): self.imgloop = imgloop @@ -541,6 +544,7 @@ class DeviceMapperSnapshot(object): def get_path(self): if self.__name is None: return None + return self.device return os.path.join("/dev/mapper", self.__name) path = property(get_path) @@ -569,6 +573,7 @@ class DeviceMapperSnapshot(object): string.join(args, " ")) self.__created = True + self.device = os.path.join('/dev/mapper', self.__name) def remove(self, ignore_errors = False): if not self.__created: @@ -610,6 +615,89 @@ class DeviceMapperSnapshot(object): except ValueError: raise SnapshotError("Failed to parse dmsetup status: " + out) + +class LiveImageMount(object): + """A class for mounting a LiveOS image installed with an active overlay.""" + + def __init__(self, disk, mountdir, overlay, tmpdir='/tmp'): + self.disk = disk + self.mountdir = mountdir + self.overlay = overlay + self.tmpdir = tmpdir + self.__created = False + self.squashmnt = None + self.homemnt = None + self.mntlive = None + + def __create(self): + if self.__created: + return + self.liveosdevmnt = DiskMount(self.disk, + os.path.join(self.tmpdir, 'device')) + self.liveosdevmnt.mount() + liveosdir = os.path.join(self.liveosdevmnt.mountdir, 'LiveOS') + sqfs_img = os.path.join(liveosdir, 'squashfs.img') + if os.path.exists(sqfs_img): + self.squashloop = LoopbackDisk(sqfs_img, None) + self.squashmnt = DiskMount(self.squashloop, + os.path.join(self.tmpdir, 'squash')) + self.squashmnt.mount() + rootfs_img = os.path.join(self.squashmnt.mountdir, + 'LiveOS', 'ext3fs.img') + else: + rootfs_img = os.path.join(liveosdir, 'ext3fs.img') + if not os.path.exists(rootfs_img): + raise SnapshotError("Failed to find a LiveOS root image.") + self.imgloop = LoopbackDisk(rootfs_img, None) + self.overlay = os.path.join(liveosdir, self.overlay) + self.cowloop = LoopbackDisk(self.overlay, None) + home_img = os.path.join(liveosdir, 'home.img') + self.dm_liveimage = DeviceMapperSnapshot(self.imgloop, self.cowloop) + self.dm_livemount = DiskMount(self.dm_liveimage, self.mountdir) + if os.path.exists(home_img): + homedir = os.path.join(self.mountdir, 'home') + self.homemnt = LoopbackMount(home_img, homedir) + self.__created = True + + def mount(self): + try: + self.__create() + if not self.liveosdevmnt.mounted: + self.liveosdevmnt.mount() + if not self.squashmnt.mounted: + self.squashmnt.mount() + self.dm_livemount.mount() + if self.homemnt: + self.homemnt.mount() + mntlivedir = os.path.join(self.mountdir, 'mnt', 'live') + if not os.path.exists(mntlivedir): + os.makedirs(mntlivedir) + self.mntlive = BindChrootMount(self.liveosdevmnt.mountdir, + '', mntlivedir) + self.mntlive.mount() + except MountError, e: + raise SnapshotError("Failed to mount %s : %s" % (self.disk, e)) + self.cleanup() + + def unmount(self): + if self.mntlive: + self.mntlive.unmount() + if self.homemnt: + self.homemnt.unmount() + self.dm_livemount.unmount() + self.liveosdevmnt.unmount() + + def cleanup(self): + self.unmount() + if self.homemnt: + self.homemnt.cleanup() + self.dm_liveimage.remove() + if self.squashmnt: + self.squashmnt.cleanup() + self.liveosdevmnt.cleanup() + self.__created = False + + def create_image_minimizer(path, image, compress_type, target_size = None, tmpdir = "/tmp"): """
_______________________________________________ SoaS mailing list SoaS@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/soas