<font face="courier new,monospace">[Patch 1/5]</font><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">Author: Frederick Grose <<a href="mailto:fgrose@sugarlabs.org">fgrose@sugarlabs.org</a>></span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">Date:   Thu Apr 14 09:29:14 2011 -0400</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    Support Live image mounting.</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">    </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    Provide DiskMount with mount options, DeviceMapperSnapshot with a</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">    device attribute, and a new LiveImageMount class.</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">diff --git a/imgcreate/fs.py b/imgcreate/fs.py</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">index d5307a2..0871182 100644</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">--- a/imgcreate/fs.py</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+++ b/imgcreate/fs.py</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">@@ -324,7 +324,6 @@ class LoopbackDisk(Disk):</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">         self.device = None</span><br style="font-family: courier new,monospace;"> <br style="font-family: courier new,monospace;"> <br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">-</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> class SparseLoopbackDisk(LoopbackDisk):</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">     """A Disk backed by a sparse file via the loop module."""</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">     def __init__(self, lofile, size):</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">@@ -377,11 +376,12 @@ class Mount:</span><br style="font-family: courier new,monospace;"> <br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> class DiskMount(Mount):</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">     """A Mount object that handles mounting of a Disk."""</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">-    def __init__(self, disk, mountdir, fstype = None, rmmountdir = True):</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+    def __init__(self, disk, mountdir, fstype=None, rmmountdir=True, ops=None):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">         Mount.__init__(self, mountdir)</span><br style="font-family: courier new,monospace;">

 <br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">         self.disk = disk</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">         self.fstype = fstype</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+        self.ops = ops</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">         self.rmmountdir = rmmountdir</span><br style="font-family: courier new,monospace;">

 <br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">         self.mounted = False</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">@@ -435,6 +435,8 @@ class DiskMount(Mount):</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">         args = [ "/bin/mount", self.disk.device, self.mountdir ]</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">         if self.fstype:</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">             args.extend(["-t", self.fstype])</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        if self.ops:</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+            args.extend(['-o', self.ops])</span><br style="font-family: courier new,monospace;"> <br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">         rc = call(args)</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">         if rc != 0:</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">@@ -530,6 +532,7 @@ class ExtDiskMount(DiskMount):</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">         self.__resize_filesystem(size)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">         return minsize</span><br style="font-family: courier new,monospace;">

 <br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> class DeviceMapperSnapshot(object):</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">     def __init__(self, imgloop, cowloop):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">         self.imgloop = imgloop</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">@@ -541,6 +544,7 @@ class DeviceMapperSnapshot(object):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">     def get_path(self):</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">         if self.__name is None:</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">             return None</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+        return self.device</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">         return os.path.join("/dev/mapper", self.__name)</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">     path = property(get_path)</span><br style="font-family: courier new,monospace;"> <br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">@@ -569,6 +573,7 @@ class DeviceMapperSnapshot(object):</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">                                 string.join(args, " "))</span><br style="font-family: courier new,monospace;"> <br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">         self.__created = True</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">+        self.device = os.path.join('/dev/mapper', self.__name)</span><br style="font-family: courier new,monospace;"> <br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">     def remove(self, ignore_errors = False):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">         if not self.__created:</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">@@ -610,6 +615,89 @@ class DeviceMapperSnapshot(object):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">         except ValueError:</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">             raise SnapshotError("Failed to parse dmsetup status: " + out)</span><br style="font-family: courier new,monospace;"> <br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+class LiveImageMount(object):</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+    """A class for mounting a LiveOS image installed with an active overlay."""</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+    def __init__(self, disk, mountdir, overlay, tmpdir='/tmp'):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        self.disk = disk</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+        self.mountdir = mountdir</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        self.overlay = overlay</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+        self.tmpdir = tmpdir</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        self.__created = False</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+        self.squashmnt = None</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        self.homemnt = None</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+        self.mntlive = None</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+    def __create(self):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        if self.__created:</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+            return</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        self.liveosdevmnt = DiskMount(self.disk,</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+                                   os.path.join(self.tmpdir, 'device'))</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        self.liveosdevmnt.mount()</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+        liveosdir = os.path.join(self.liveosdevmnt.mountdir, 'LiveOS')</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        sqfs_img = os.path.join(liveosdir, 'squashfs.img')</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+        if os.path.exists(sqfs_img):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+            self.squashloop = LoopbackDisk(sqfs_img, None)</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+            self.squashmnt = DiskMount(self.squashloop,</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+                                       os.path.join(self.tmpdir, 'squash'))</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+            self.squashmnt.mount()</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+            rootfs_img = os.path.join(self.squashmnt.mountdir,</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+                                      'LiveOS', 'ext3fs.img')</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        else:</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+            rootfs_img = os.path.join(liveosdir, 'ext3fs.img')</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+            if not os.path.exists(rootfs_img):</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+                raise SnapshotError("Failed to find a LiveOS root image.")</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        self.imgloop = LoopbackDisk(rootfs_img, None)</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+        self.overlay = os.path.join(liveosdir, self.overlay)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        self.cowloop = LoopbackDisk(self.overlay, None)</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+        home_img = os.path.join(liveosdir, 'home.img')</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        self.dm_liveimage = DeviceMapperSnapshot(self.imgloop, self.cowloop)</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+        self.dm_livemount = DiskMount(self.dm_liveimage, self.mountdir)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        if os.path.exists(home_img):</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+            homedir = os.path.join(self.mountdir, 'home')</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+            self.homemnt = LoopbackMount(home_img, homedir)</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+        self.__created = True</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+    def mount(self):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        try:</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+            self.__create()</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+            if not self.liveosdevmnt.mounted:</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+                self.liveosdevmnt.mount()</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+            if not self.squashmnt.mounted:</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+                self.squashmnt.mount()</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+            self.dm_livemount.mount()</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+            if self.homemnt:</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+                self.homemnt.mount()</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+            mntlivedir = os.path.join(self.mountdir, 'mnt', 'live')</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+            if not os.path.exists(mntlivedir):</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+                os.makedirs(mntlivedir)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+            self.mntlive = BindChrootMount(self.liveosdevmnt.mountdir,</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+                                           '', mntlivedir)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+            self.mntlive.mount()</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+        except MountError, e:</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+            raise SnapshotError("Failed to mount %s : %s" % (self.disk, e))</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+            self.cleanup()</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+    def unmount(self):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        if self.mntlive:</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+            self.mntlive.unmount()</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        if self.homemnt:</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+            self.homemnt.unmount()</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        self.dm_livemount.unmount()</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+        self.liveosdevmnt.unmount()</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+    def cleanup(self):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        self.unmount()</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+        if self.homemnt:</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+            self.homemnt.cleanup()</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+        self.dm_liveimage.remove()</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        if self.squashmnt:</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+            self.squashmnt.cleanup()</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+        self.liveosdevmnt.cleanup()</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+        self.__created = False</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">+</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">+</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> def create_image_minimizer(path, image, compress_type, target_size = None,</span><br style="font-family: courier new,monospace;">

<span style="font-family: courier new,monospace;">                            tmpdir = "/tmp"):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">     """</span>