commit 3501e953449d17a53b669bb80bf4e96d8a8e4b25
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"):
"""