[SoaS] [PATCH 1/5] Support Live image mounting in fs.py
Frederick Grose
fgrose at gmail.com
Thu Apr 14 12:02:01 EDT 2011
[Patch 1/5]
Author: Frederick Grose <fgrose at 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"):
"""
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.sugarlabs.org/archive/soas/attachments/20110414/d3be87d2/attachment-0001.html>
More information about the SoaS
mailing list