Patch 1b of 2 substitute patches to replace an earlier patch with new features:
commit 3501e953449d17a53b669bb80bf4e96d8a8e4b25 Author: Frederick Grose <fgr...@sugarlabs.org> Date: Sat Sep 17 17:29:03 2011 -0400 Provide a new LiveImageMount class for mounting a LiveOS filesystem. Mount the LiveOS filesystem with its own or a substitute overlay. Provide mounting options for read-write or read-only overlays. This supports image customization. diff --git a/imgcreate/fs.py b/imgcreate/fs.py index e71032e..6d04c4a 100644 --- a/imgcreate/fs.py +++ b/imgcreate/fs.py @@ -684,6 +684,103 @@ 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=None, tmpdir='/tmp', ops=None): + self.disk = disk + self.mountdir = mountdir + self.overlay = overlay + self.tmpdir = tmpdir + self.ops = ops + self.__created = False + self.squashmnt = None + self.homemnt = None + self.mntlive = None + + def __create(self, ops=None): + if self.__created: + return + self.liveosdevmnt = DiskMount(self.disk, + os.path.join(self.tmpdir, 'device'), ops=ops) + self.liveosdevmnt.mount(ops) + 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, ['-r']) + self.squashmnt = DiskMount(self.squashloop, + os.path.join(self.tmpdir, 'squash'), ops='ro') + self.squashmnt.mount('ro') + 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, ['-r']) + if not self.overlay: + for f in os.listdir(liveosdir): + if f.find('overlay-') == 0: + self.overlay = os.path.join(liveosdir, f) + break + self.cowloop = LoopbackDisk(self.overlay, None, ops) + self.dm_liveimage = DeviceMapperSnapshot(self.imgloop, self.cowloop, + ops) + self.dm_livemount = DiskMount(self.dm_liveimage, self.mountdir, + ops=ops) + home_img = os.path.join(liveosdir, 'home.img') + if os.path.exists(home_img): + homedir = os.path.join(self.mountdir, 'home') + self.homemnt = LoopbackMount(home_img, homedir, ops=ops) + self.__created = True + + def mount(self, ops=None): + if ops is None: + ops = self.ops + try: + self.__create(ops) + if not self.liveosdevmnt.mounted: + self.liveosdevmnt.mount(ops) + if self.squashmnt and not self.squashmnt.mounted: + self.squashmnt.mount('ro') + self.dm_livemount.mount(ops) + if self.homemnt: + self.homemnt.mount(ops) + mntlivedir = os.path.join(self.mountdir, 'mnt', 'live') + if not os.path.exists(mntlivedir): + os.makedirs(mntlivedir) + self.mntlive = BindChrootMount(self.liveosdevmnt.mountdir, + '', mntlivedir, ops) + self.mntlive.mount(ops) + except MountError, e: + self.cleanup() + raise SnapshotError("Failed to mount %s : %s" % (self.disk, e)) + + def remount(self, ops): + try: + self.liveosdevmnt.remount(ops) + if self.homemnt: + self.homemnt.remount(ops) + self.mntlive.reremount(ops) + except MountError, e: + self.cleanup() + raise SnapshotError("Failed to remount %s as %s : %s" % + (self.disk, ops, e)) + + def cleanup(self): + if self.mntlive: + self.mntlive.unmount() + if self.homemnt: + self.homemnt.cleanup() + self.dm_livemount.unmount() + 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"): """ On Thu, Apr 14, 2011 at 12:02 PM, Frederick Grose <fgr...@gmail.com> wrote: > [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