imgcreate/creator.py | 17 +-
imgcreate/fs.py | 351 ++++++++++++++++++++++++++++++++++++-------------
imgcreate/kickstart.py | 3
imgcreate/live.py | 6
4 files changed, 278 insertions(+), 99 deletions(-)
New commits:
commit 5a3a91fe44795fb0d5c1f6215081b214d0af3f5b
Merge: 2a57a06... 5279213...
Author: Jeremy Katz <katzj(a)redhat.com>
Date: Tue Aug 5 20:25:23 2008 -0400
Merge branch 'refactor-mount'
diff --cc imgcreate/creator.py
index e63e96d,5fbf554..d9fa711
--- a/imgcreate/creator.py
+++ b/imgcreate/creator.py
@@@ -905,14 -904,14 +909,13 @@@ class LoopImageCreator(ImageCreator)
self.__imgdir = self._mkdtemp()
if not base_on is None:
- self.__base_on(base_on)
- shutil.copyfile(base_on, self._image)
+ self._base_on(base_on)
- self.__instloop = SparseExtLoopbackMount(self._image,
- self._instroot,
- self.__image_size,
- self.__fstype,
- self.__blocksize,
- self.fslabel)
+ self.__instloop = ExtDiskMount(SparseLoopbackDisk(self._image,
self.__image_size),
+ self._instroot,
+ self.__fstype,
+ self.__blocksize,
+ self.fslabel)
try:
self.__instloop.mount()
diff --cc imgcreate/live.py
index 49d524b,abea730..f98f76c
--- a/imgcreate/live.py
+++ b/imgcreate/live.py
@@@ -129,9 -129,9 +129,9 @@@ class LiveImageCreatorBase(LoopImageCre
#
# Actual implementation
#
- def __base_on(self, base_on):
+ def _base_on(self, base_on):
"""helper function to extract ext3 file system from a live CD
ISO"""
- isoloop = LoopbackMount(base_on, self._mkdtemp())
+ isoloop = Mount(LoopbackDisk(base_on), self._mkdtemp())
try:
isoloop.mount()
commit 5279213df3104c32b3cb08afc7e9698dceb1704d
Author: David Huff <dhuff(a)redhat.com>
Date: Tue Jul 22 17:36:52 2008 -0400
Separate out generation of non-disk mounts from other things for /etc/fstab
diff --git a/imgcreate/creator.py b/imgcreate/creator.py
index 64898c5..5fbf554 100644
--- a/imgcreate/creator.py
+++ b/imgcreate/creator.py
@@ -209,7 +209,11 @@ class ImageCreator(object):
"""
s = "/dev/root / %s defaults,noatime 0 0\n"
%(self._fstype)
- s += "devpts /dev/pts devpts gid=5,mode=620 0 0\n"
+ s += self._get_fstab_special()
+ return s
+
+ def _get_fstab_special(self):
+ s = "devpts /dev/pts devpts gid=5,mode=620 0 0\n"
s += "tmpfs /dev/shm tmpfs defaults 0 0\n"
s += "proc /proc proc defaults 0 0\n"
s += "sysfs /sys sysfs defaults 0 0\n"
commit 1f20b4ded9e18257de787c71b28e147f592c09be
Author: David Huff <dhuff(a)redhat.com>
Date: Tue Jul 22 17:36:06 2008 -0400
Switch internal code to use new api
diff --git a/imgcreate/creator.py b/imgcreate/creator.py
index e61f034..64898c5 100644
--- a/imgcreate/creator.py
+++ b/imgcreate/creator.py
@@ -903,12 +903,11 @@ class LoopImageCreator(ImageCreator):
self.__base_on(base_on)
shutil.copyfile(base_on, self._image)
- self.__instloop = SparseExtLoopbackMount(self._image,
- self._instroot,
- self.__image_size,
- self.__fstype,
- self.__blocksize,
- self.fslabel)
+ self.__instloop = ExtDiskMount(SparseLoopbackDisk(self._image,
self.__image_size),
+ self._instroot,
+ self.__fstype,
+ self.__blocksize,
+ self.fslabel)
try:
self.__instloop.mount()
diff --git a/imgcreate/live.py b/imgcreate/live.py
index e0bac09..abea730 100644
--- a/imgcreate/live.py
+++ b/imgcreate/live.py
@@ -131,7 +131,7 @@ class LiveImageCreatorBase(LoopImageCreator):
#
def __base_on(self, base_on):
"""helper function to extract ext3 file system from a live CD
ISO"""
- isoloop = LoopbackMount(base_on, self._mkdtemp())
+ isoloop = Mount(LoopbackDisk(base_on), self._mkdtemp())
try:
isoloop.mount()
@@ -145,10 +145,10 @@ class LiveImageCreatorBase(LoopImageCreator):
else:
squashimg = isoloop.mountdir + "/LiveOS/squashfs.img"
- squashloop = LoopbackMount(squashimg, self._mkdtemp(), "squashfs")
+ squashloop = Mount(LoopbackDisk(squashimg), self._mkdtemp(),
"squashfs")
try:
- if not os.path.exists(squashloop.lofile):
+ if not squashloop.disk.exists():
raise CreatorError("'%s' is not a valid live CD ISO :
"
"squashfs.img doesn't exist" % base_on)
commit 7024f2cc0041d8fd038844c789d869875e4977af
Author: David Huff <dhuff(a)redhat.com>
Date: Mon Jul 28 14:22:00 2008 -0400
Added compat shims in fs.py for old api
Added a compat layer for backwards compatibility. These compat
classes internally create the new Disk objects, switching the old api
(LoopbackMount, SparseLoopbackMount, SparseExtLoopbackMount) types to
the new Disk and Mount classes
diff --git a/imgcreate/fs.py b/imgcreate/fs.py
index 0aca98d..4d8f87a 100644
--- a/imgcreate/fs.py
+++ b/imgcreate/fs.py
@@ -88,32 +88,16 @@ class BindChrootMount:
self.mounted = False
class LoopbackMount:
+ """LoopbackMount compatibility layer for old API"""
def __init__(self, lofile, mountdir, fstype = None):
- self.lofile = lofile
- self.mountdir = mountdir
- self.fstype = fstype
-
- self.mounted = False
+ self.diskmount = DiskMount(LoopbackDisk(lofile,size =
0),mountdir,fstype,rmmountdir = True)
self.losetup = False
- self.rmdir = False
- self.loopdev = None
-
+
def cleanup(self):
- self.unmount()
- self.lounsetup()
+ self.diskmount.cleanup()
def unmount(self):
- if self.mounted:
- rc = subprocess.call(["/bin/umount", self.mountdir])
- if rc == 0:
- self.mounted = False
-
- if self.rmdir and not self.mounted:
- try:
- os.rmdir(self.mountdir)
- except OSError, e:
- pass
- self.rmdir = False
+ self.diskmount.unmount()
def lounsetup(self):
if self.losetup:
@@ -143,152 +127,52 @@ class LoopbackMount:
self.losetup = True
def mount(self):
- if self.mounted:
- return
-
- self.loopsetup()
-
- if not os.path.isdir(self.mountdir):
- os.makedirs(self.mountdir)
- self.rmdir = True
-
- args = [ "/bin/mount", self.loopdev, self.mountdir ]
- if self.fstype:
- args.extend(["-t", self.fstype])
-
- rc = subprocess.call(args)
- if rc != 0:
- raise MountError("Failed to mount '%s' to '%s'" %
- (self.loopdev, self.mountdir))
-
- self.mounted = True
+ self.diskmount.mount()
class SparseLoopbackMount(LoopbackMount):
+ """SparseLoopbackMount compatibility layer for old
API"""
def __init__(self, lofile, mountdir, size, fstype = None):
- LoopbackMount.__init__(self, lofile, mountdir, fstype)
- self.size = size
+ self.diskmount =
DiskMount(SparseLoopbackDisk(lofile,size),mountdir,fstype,rmmountdir = True)
def expand(self, create = False, size = None):
- flags = os.O_WRONLY
- if create:
- flags |= os.O_CREAT
- makedirs(os.path.dirname(self.lofile))
-
- if size is None:
- size = self.size
-
- fd = os.open(self.lofile, flags)
-
- os.lseek(fd, size, 0)
- os.write(fd, '\x00')
- os.close(fd)
+ self.diskmount.disk.expand(create, size)
def truncate(self, size = None):
- if size is None:
- size = self.size
- fd = os.open(self.lofile, os.O_WRONLY)
- os.ftruncate(fd, size)
- os.close(fd)
+ self.diskmount.disk.truncate(size)
def create(self):
- self.expand(create = True)
+ self.diskmount.disk.create()
class SparseExtLoopbackMount(SparseLoopbackMount):
+ """SparseExtLoopbackMount compatibility layer for old
API"""
def __init__(self, lofile, mountdir, size, fstype, blocksize, fslabel):
- SparseLoopbackMount.__init__(self, lofile, mountdir, size, fstype)
- self.blocksize = blocksize
- self.fslabel = fslabel
+ self.diskmount = ExtDiskMount(SparseLoopbackDisk(lofile,size), mountdir, fstype,
blocksize, fslabel, rmmountdir = True)
+
def __format_filesystem(self):
- rc = subprocess.call(["/sbin/mkfs." + self.fstype,
- "-F", "-L", self.fslabel,
- "-m", "1", "-b",
str(self.blocksize),
- self.lofile,
- str(self.size / self.blocksize)])
- if rc != 0:
- raise MountError("Error creating %s filesystem" % (self.fstype,))
- subprocess.call(["/sbin/tune2fs", "-c0", "-i0",
"-Odir_index",
- "-ouser_xattr,acl", self.lofile])
+ self.diskmount.__format_filesystem()
def create(self):
- SparseLoopbackMount.create(self)
- self.__format_filesystem()
+ self.diskmount.disk.create()
def resize(self, size = None):
- current_size = os.stat(self.lofile)[stat.ST_SIZE]
-
- if size is None:
- size = self.size
-
- if size == current_size:
- return
-
- if size > current_size:
- self.expand(size)
-
- self.__fsck()
-
- resize2fs(self.lofile, size)
-
- if size < current_size:
- self.truncate(size)
- return size
+ self.diskmount.__resize_filesystem(size)
def mount(self):
- if not os.path.isfile(self.lofile):
- self.create()
- else:
- self.resize()
- return SparseLoopbackMount.mount(self)
-
+ self.diskmount.mount()
+
def __fsck(self):
- subprocess.call(["/sbin/e2fsck", "-f", "-y",
self.lofile])
+ self.extdiskmount.__fsck()
def __get_size_from_filesystem(self):
- def parse_field(output, field):
- for line in output.split("\n"):
- if line.startswith(field + ":"):
- return line[len(field) + 1:].strip()
-
- raise KeyError("Failed to find field '%s' in output" %
field)
-
- dev_null = os.open("/dev/null", os.O_WRONLY)
- try:
- out = subprocess.Popen(['/sbin/dumpe2fs', '-h',
self.lofile],
- stdout = subprocess.PIPE,
- stderr = dev_null).communicate()[0]
- finally:
- os.close(dev_null)
-
- return int(parse_field(out, "Block count")) * self.blocksize
-
+ self.diskmount.__get_size_from_filesystem()
+
def __resize_to_minimal(self):
- self.__fsck()
-
- #
- # Use a binary search to find the minimal size
- # we can resize the image to
- #
- bot = 0
- top = self.__get_size_from_filesystem()
- while top != (bot + 1):
- t = bot + ((top - bot) / 2)
-
- if not resize2fs(self.lofile, t):
- top = t
- else:
- bot = t
- return top
-
+ self.diskmount.__resize_to_minimal()
+
def resparse(self, size = None):
- self.cleanup()
+ return self.diskmount.resparse(size)
- minsize = self.__resize_to_minimal()
-
- self.truncate(minsize)
- self.resize(size)
- return minsize
-
class Disk:
"""Generic base object for a disk
commit 8d6b5166013b766f0fca163a52ddd0801568a557
Author: Jeremy Katz <katzj(a)redhat.com>
Date: Tue Jul 22 17:15:29 2008 -0400
Clean up pydoc to be with the actual objects
diff --git a/imgcreate/fs.py b/imgcreate/fs.py
index 11348fa..0aca98d 100644
--- a/imgcreate/fs.py
+++ b/imgcreate/fs.py
@@ -290,28 +290,11 @@ class SparseExtLoopbackMount(SparseLoopbackMount):
return minsize
class Disk:
- """
- With the new disk API the image being produced can be partitioned into
- multiple chunks, with many filesystems. Furthermore, not all of them
- require loopback mounts, as the partitions themselves are already
- visible via /dev/mapper/
-
- There are now classes which deal with accessing / creating disks:
-
- Disk - generic base for disks
- RawDisk - a disk backed by a block device
- LoopbackDisk - a disk backed by a file
- SparseLoopbackDisk - a disk backed by a sparse file
+ """Generic base object for a disk
The 'create' method must make the disk visible as a block device - eg
by calling losetup. For RawDisk, this is obviously a no-op. The 'cleanup'
method must undo the 'create' operation.
-
- There are then classes which deal with mounting things:
-
- Mount - generic base for mounts
- DiskMount - able to mount a Disk object
- ExtDiskMount - able to format/resize ext3 filesystems when mounting
"""
def __init__(self, size, device = None):
self._device = device
@@ -335,6 +318,9 @@ class Disk:
class RawDisk(Disk):
+ """A Disk backed by a block device.
+ Note that create() is a no-op.
+ """
def __init__(self, size, device):
Disk.__init__(self, size, device)
@@ -345,6 +331,7 @@ class RawDisk(Disk):
return True
class LoopbackDisk(Disk):
+ """A Disk backed by a file via the loop module."""
def __init__(self, lofile, size):
Disk.__init__(self, size)
self.lofile = lofile
@@ -386,6 +373,7 @@ class LoopbackDisk(Disk):
class SparseLoopbackDisk(LoopbackDisk):
+ """A Disk backed by a sparse file via the loop
module."""
def __init__(self, lofile, size):
LoopbackDisk.__init__(self, lofile, size)
@@ -419,6 +407,7 @@ class SparseLoopbackDisk(LoopbackDisk):
LoopbackDisk.create(self)
class Mount:
+ """A generic base class to deal with mounting
things."""
def __init__(self, mountdir):
self.mountdir = mountdir
@@ -432,6 +421,7 @@ class Mount:
pass
class DiskMount(Mount):
+ """A Mount object that handles mounting of a Disk."""
def __init__(self, disk, mountdir, fstype = None, rmmountdir = True):
Mount.__init__(self, mountdir)
@@ -489,6 +479,7 @@ class DiskMount(Mount):
self.mounted = True
class ExtDiskMount(DiskMount):
+ """A DiskMount object that is able to format/resize ext[23]
filesystems."""
def __init__(self, disk, mountdir, fstype, blocksize, fslabel, rmmountdir=True):
DiskMount.__init__(self, disk, mountdir, fstype, rmmountdir)
self.blocksize = blocksize
commit 129083062fb7b21a49e5f84196d673fa1c37a5bc
Author: David Huff <dhuff(a)redhat.com>
Date: Mon Jul 21 17:26:55 2008 -0400
Re-factor imgcreate/fs.py module
Most of the change here involves re-factoring the imgcreate/fs.py module to
separate the difference between a disk and a mount.
So this patch separates the roles. There are now classes which deal with
accessing / creating disks and classes which deal with mounting things.
Also fixed comments to use the standard pydoc """ format.
Based on a patch by Daniel Berrange <berrange(a)redhat.com>
diff --git a/imgcreate/fs.py b/imgcreate/fs.py
index 98c0db4..11348fa 100644
--- a/imgcreate/fs.py
+++ b/imgcreate/fs.py
@@ -24,6 +24,7 @@ import stat
import subprocess
import random
import string
+import logging
from imgcreate.errors import *
@@ -288,6 +289,303 @@ class SparseExtLoopbackMount(SparseLoopbackMount):
self.resize(size)
return minsize
+class Disk:
+ """
+ With the new disk API the image being produced can be partitioned into
+ multiple chunks, with many filesystems. Furthermore, not all of them
+ require loopback mounts, as the partitions themselves are already
+ visible via /dev/mapper/
+
+ There are now classes which deal with accessing / creating disks:
+
+ Disk - generic base for disks
+ RawDisk - a disk backed by a block device
+ LoopbackDisk - a disk backed by a file
+ SparseLoopbackDisk - a disk backed by a sparse file
+
+ The 'create' method must make the disk visible as a block device - eg
+ by calling losetup. For RawDisk, this is obviously a no-op. The 'cleanup'
+ method must undo the 'create' operation.
+
+ There are then classes which deal with mounting things:
+
+ Mount - generic base for mounts
+ DiskMount - able to mount a Disk object
+ ExtDiskMount - able to format/resize ext3 filesystems when mounting
+ """
+ def __init__(self, size, device = None):
+ self._device = device
+ self._size = size
+
+ def create(self):
+ pass
+
+ def cleanup(self):
+ pass
+
+ def get_device(self):
+ return self._device
+ def set_device(self, path):
+ self._device = path
+ device = property(get_device, set_device)
+
+ def get_size(self):
+ return self._size
+ size = property(get_size)
+
+
+class RawDisk(Disk):
+ def __init__(self, size, device):
+ Disk.__init__(self, size, device)
+
+ def fixed(self):
+ return True
+
+ def exists(self):
+ return True
+
+class LoopbackDisk(Disk):
+ def __init__(self, lofile, size):
+ Disk.__init__(self, size)
+ self.lofile = lofile
+
+ def fixed(self):
+ return False
+
+ def exists(self):
+ return os.path.exists(self.lofile)
+
+ def create(self):
+ if self.device is not None:
+ return
+
+ losetupProc = subprocess.Popen(["/sbin/losetup", "-f"],
+ stdout=subprocess.PIPE)
+ losetupOutput = losetupProc.communicate()[0]
+
+ if losetupProc.returncode:
+ raise MountError("Failed to allocate loop device for '%s'"
%
+ self.lofile)
+
+ device = losetupOutput.split()[0]
+
+ logging.debug("Losetup add %s mapping to %s" % (device, self.lofile))
+ rc = subprocess.call(["/sbin/losetup", device, self.lofile])
+ if rc != 0:
+ raise MountError("Failed to allocate loop device for '%s'"
%
+ self.lofile)
+ self.device = device
+
+ def cleanup(self):
+ if self.device is None:
+ return
+ logging.debug("Losetup remove %s" % self.device)
+ rc = subprocess.call(["/sbin/losetup", "-d", self.device])
+ self.device = None
+
+
+
+class SparseLoopbackDisk(LoopbackDisk):
+ def __init__(self, lofile, size):
+ LoopbackDisk.__init__(self, lofile, size)
+
+ def expand(self, create = False, size = None):
+ flags = os.O_WRONLY
+ if create:
+ flags |= os.O_CREAT
+ makedirs(os.path.dirname(self.lofile))
+
+ if size is None:
+ size = self.size
+
+ logging.debug("Extending sparse file %s to %d" % (self.lofile, size))
+ fd = os.open(self.lofile, flags)
+
+ os.lseek(fd, size, 0)
+ os.write(fd, '\x00')
+ os.close(fd)
+
+ def truncate(self, size = None):
+ if size is None:
+ size = self.size
+
+ logging.debug("Truncating sparse file %s to %d" % (self.lofile, size))
+ fd = os.open(self.lofile, os.O_WRONLY)
+ os.ftruncate(fd, size)
+ os.close(fd)
+
+ def create(self):
+ self.expand(create = True)
+ LoopbackDisk.create(self)
+
+class Mount:
+ def __init__(self, mountdir):
+ self.mountdir = mountdir
+
+ def cleanup(self):
+ self.unmount()
+
+ def mount(self):
+ pass
+
+ def unmount(self):
+ pass
+
+class DiskMount(Mount):
+ def __init__(self, disk, mountdir, fstype = None, rmmountdir = True):
+ Mount.__init__(self, mountdir)
+
+ self.disk = disk
+ self.fstype = fstype
+ self.rmmountdir = rmmountdir
+
+ self.mounted = False
+ self.rmdir = False
+
+ def cleanup(self):
+ Mount.cleanup(self)
+ self.disk.cleanup()
+
+ def unmount(self):
+ if self.mounted:
+ logging.debug("Unmounting directory %s" % self.mountdir)
+ rc = subprocess.call(["/bin/umount", self.mountdir])
+ if rc == 0:
+ self.mounted = False
+
+ if self.rmdir and not self.mounted:
+ try:
+ os.rmdir(self.mountdir)
+ except OSError, e:
+ pass
+ self.rmdir = False
+
+
+ def __create(self):
+ self.disk.create()
+
+
+ def mount(self):
+ if self.mounted:
+ return
+
+ if not os.path.isdir(self.mountdir):
+ logging.debug("Creating mount point %s" % self.mountdir)
+ os.makedirs(self.mountdir)
+ self.rmdir = self.rmmountdir
+
+ self.__create()
+
+ logging.debug("Mounting %s at %s" % (self.disk.device, self.mountdir))
+ args = [ "/bin/mount", self.disk.device, self.mountdir ]
+ if self.fstype:
+ args.extend(["-t", self.fstype])
+
+ rc = subprocess.call(args)
+ if rc != 0:
+ raise MountError("Failed to mount '%s' to '%s'" %
+ (self.disk.device, self.mountdir))
+
+ self.mounted = True
+
+class ExtDiskMount(DiskMount):
+ def __init__(self, disk, mountdir, fstype, blocksize, fslabel, rmmountdir=True):
+ DiskMount.__init__(self, disk, mountdir, fstype, rmmountdir)
+ self.blocksize = blocksize
+ self.fslabel = fslabel
+
+ def __format_filesystem(self):
+ logging.debug("Formating %s filesystem on %s" % (self.fstype,
self.disk.device))
+ rc = subprocess.call(["/sbin/mkfs." + self.fstype,
+ "-F", "-L", self.fslabel,
+ "-m", "1", "-b",
str(self.blocksize),
+ self.disk.device])
+ # str(self.disk.size / self.blocksize)])
+ if rc != 0:
+ raise MountError("Error creating %s filesystem" % (self.fstype,))
+ logging.debug("Tuning filesystem on %s" % self.disk.device)
+ subprocess.call(["/sbin/tune2fs", "-c0", "-i0",
"-Odir_index",
+ "-ouser_xattr,acl", self.disk.device])
+
+ def __resize_filesystem(self, size = None):
+ current_size = os.stat(self.disk.lofile)[stat.ST_SIZE]
+
+ if size is None:
+ size = self.size
+
+ if size == current_size:
+ return
+
+ if size > current_size:
+ self.expand(size)
+
+ self.__fsck()
+
+ resize2fs(self.disk.lofile, size)
+ return size
+
+ def __create(self):
+ resize = False
+ if not self.disk.fixed() and self.disk.exists():
+ resize = True
+
+ self.disk.create()
+
+ if resize:
+ self.__resize_filesystem()
+ else:
+ self.__format_filesystem()
+
+ def mount(self):
+ self.__create()
+ DiskMount.mount(self)
+
+ def __fsck(self):
+ logging.debug("Checking filesystem %s" % self.disk.lofile)
+ subprocess.call(["/sbin/e2fsck", "-f", "-y",
self.disk.lofile])
+
+ def __get_size_from_filesystem(self):
+ def parse_field(output, field):
+ for line in output.split("\n"):
+ if line.startswith(field + ":"):
+ return line[len(field) + 1:].strip()
+
+ raise KeyError("Failed to find field '%s' in output" %
field)
+
+ dev_null = os.open("/dev/null", os.O_WRONLY)
+ try:
+ out = subprocess.Popen(['/sbin/dumpe2fs', '-h',
self.disk.lofile],
+ stdout = subprocess.PIPE,
+ stderr = dev_null).communicate()[0]
+ finally:
+ os.close(dev_null)
+
+ return int(parse_field(out, "Block count")) * self.blocksize
+
+ def __resize_to_minimal(self):
+ self.__fsck()
+
+ #
+ # Use a binary search to find the minimal size
+ # we can resize the image to
+ #
+ bot = 0
+ top = self.__get_size_from_filesystem()
+ while top != (bot + 1):
+ t = bot + ((top - bot) / 2)
+
+ if not resize2fs(self.disk.lofile, t):
+ top = t
+ else:
+ bot = t
+ return top
+
+ def resparse(self, size = None):
+ self.cleanup()
+ minsize = self.__resize_to_minimal()
+ self.disk.truncate(minsize)
+ return minsize
+
class DeviceMapperSnapshot(object):
def __init__(self, imgloop, cowloop):
self.imgloop = imgloop
@@ -306,8 +604,8 @@ class DeviceMapperSnapshot(object):
if self.__created:
return
- self.imgloop.loopsetup()
- self.cowloop.loopsetup()
+ self.imgloop.create()
+ self.cowloop.create()
self.__name = "imgcreate-%d-%d" % (os.getpid(),
random.randint(0, 2**16))
@@ -315,8 +613,8 @@ class DeviceMapperSnapshot(object):
size = os.stat(self.imgloop.lofile)[stat.ST_SIZE]
table = "0 %d snapshot %s %s p 8" % (size / 512,
- self.imgloop.loopdev,
- self.cowloop.loopdev)
+ self.imgloop.device,
+ self.cowloop.device)
args = ["/sbin/dmsetup", "create", self.__name,
"--table", table]
if subprocess.call(args) != 0:
@@ -365,32 +663,31 @@ class DeviceMapperSnapshot(object):
except ValueError:
raise SnapshotError("Failed to parse dmsetup status: " + out)
-#
-# Builds a copy-on-write image which can be used to
-# create a device-mapper snapshot of an image where
-# the image's filesystem is as small as possible
-#
-# The steps taken are:
-# 1) Create a sparse COW
-# 2) Loopback mount the image and the COW
-# 3) Create a device-mapper snapshot of the image
-# using the COW
-# 4) Resize the filesystem to the minimal size
-# 5) Determine the amount of space used in the COW
-# 6) Restroy the device-mapper snapshot
-# 7) Truncate the COW, removing unused space
-# 8) Create a squashfs of the COW
-#
def create_image_minimizer(path, image, minimal_size):
- imgloop = LoopbackMount(image, "None")
+ """
+ Builds a copy-on-write image which can be used to
+ create a device-mapper snapshot of an image where
+ the image's filesystem is as small as possible
+
+ The steps taken are:
+ 1) Create a sparse COW
+ 2) Loopback mount the image and the COW
+ 3) Create a device-mapper snapshot of the image
+ using the COW
+ 4) Resize the filesystem to the minimal size
+ 5) Determine the amount of space used in the COW
+ 6) Restroy the device-mapper snapshot
+ 7) Truncate the COW, removing unused space
+ 8) Create a squashfs of the COW
+ """
+ imgloop = LoopbackDisk(image, None) # Passing bogus size - doesn't matter
- cowloop = SparseLoopbackMount(os.path.join(os.path.dirname(path),
"osmin"),
- None, 64L * 1024L * 1024L)
+ cowloop = SparseLoopbackDisk(os.path.join(os.path.dirname(path), "osmin"),
+ 64L * 1024L * 1024L)
snapshot = DeviceMapperSnapshot(imgloop, cowloop)
try:
- cowloop.create()
snapshot.create()
resize2fs(snapshot.path, minimal_size)
@@ -404,3 +701,4 @@ def create_image_minimizer(path, image, minimal_size):
mksquashfs(cowloop.lofile, path)
os.unlink(cowloop.lofile)
+
commit 8243a268c7791355832ba5efce6fff963a55f3f3
Author: David Huff <dhuff(a)redhat.com>
Date: Thu Jul 10 17:24:52 2008 -0400
Add method to get partitions from kickstart config
diff --git a/imgcreate/kickstart.py b/imgcreate/kickstart.py
index 451b133..e352e98 100644
--- a/imgcreate/kickstart.py
+++ b/imgcreate/kickstart.py
@@ -498,6 +498,9 @@ def get_groups(ks, required = []):
def get_excluded(ks, required = []):
return ks.handler.packages.excludedList + required
+def get_partitions(ks, required = []):
+ return ks.handler.partition.partitions
+
def ignore_missing(ks):
return ks.handler.packages.handleMissing == ksconstants.KS_MISSING_IGNORE