[Thincrust-devel] [Fwd: [PATCH] import imgcreate.fs refactoring and other changes]
David Huff
dhuff at redhat.com
Tue Jul 22 21:15:37 UTC 2008
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
patch committed to f9 branch.
- -D
- -------- Original Message --------
From: - Tue Jul 22 09:58:18 2008
X-Mozilla-Status: 0001
X-Mozilla-Status2: 00000000
Return-Path: <apevec at redhat.com>
Received: from pobox.corp.redhat.com ([unix socket]) by
pobox.corp.redhat.com (Cyrus v2.2.12-Invoca-RPM-2.2.12-8.1.RHEL4) with
LMTPA; Tue, 22 Jul 2008 09:54:21 -0400
X-Sieve: CMU Sieve 2.2
Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com
[172.16.52.254]) by pobox.corp.redhat.com (8.13.1/8.13.1) with ESMTP
id m6MDsLWK026347 for <dhuff at pobox.corp.redhat.com>; Tue, 22 Jul 2008
09:54:21 -0400
Received: from pobox.stuttgart.redhat.com (pobox.stuttgart.redhat.com
[172.16.2.10]) by int-mx1.corp.redhat.com (8.13.1/8.13.1) with ESMTP
id m6MDsKis005757; Tue, 22 Jul 2008 09:54:20 -0400
Received: from localhost.localdomain (vpn-4-112.str.redhat.com
[10.32.4.112]) by pobox.stuttgart.redhat.com (8.13.1/8.13.1) with
ESMTP id m6MDsH4k021135; Tue, 22 Jul 2008 09:54:17 -0400
From: Alan Pevec <apevec at redhat.com>
To: dhuff at redhat.com
Cc: Alan Pevec <apevec at redhat.com>
Subject: [PATCH] import imgcreate.fs refactoring and other changes
Date: Tue, 22 Jul 2008 15:54:17 +0200
Message-Id: <1216734857-5014-1-git-send-email-apevec at redhat.com>
X-Mailer: git-send-email 1.5.4.1
X-Scanned-By: MIMEDefang 2.58 on 172.16.52.254
make it work with Fedora-9 livecd-tools-0.17.1 w/o Thincrust patches
- ---
~ Makefile | 2 +-
~ README | 20 +-
~ appcreate/__init__.py | 1 -
~ appcreate/appliance.py | 508
+++++++++++++++++++-
~ appliance-tools.spec | 23 +-
~ ...-of-python-logging-API-for-debug-messages.patch | 283 -----------
~ ...isk-mount-classes-to-allow-multi-partitio.patch | 457
- ------------------
~ ...-kickstart.py-chages-for-mulit-partitions.patch | 273 -----------
~ tools/appliance-creator | 2 -
~ 9 files changed, 525 insertions(+), 1044 deletions(-)
~ delete mode 100644
patches/0001-Make-use-of-python-logging-API-for-debug-messages.patch
~ delete mode 100644
patches/0002-Refactor-disk-mount-classes-to-allow-multi-partitio.patch
~ delete mode 100644
patches/0003-fs.py-kickstart.py-chages-for-mulit-partitions.patch
~ mode change 100644 => 100755 tools/appliance-creator
diff --git a/Makefile b/Makefile
index 8809374..d4825de 100644
- --- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
- -VERSION = 001
+VERSION = 002
~ INSTALL = /usr/bin/install -c
~ INSTALL_PROGRAM = ${INSTALL}
diff --git a/README b/README
index 5d6b95c..cf7b3c1 100644
- --- a/README
+++ b/README
@@ -1,9 +1,10 @@
- -This is a first cut the Appliance Creation Tool (ACT) a tool to create
Appliance Images from a kick start file. This tool will use the liveCD
creator API as well as patches to create a multi partitioned disk.
+This is a first cut the Appliance Creation Tool (ACT) a tool to create
+Appliance Images from a kick start file. This tool will use the liveCD
+creator API as well as patches to create a multi partitioned disk.
~ Directory structure:
- -patches -> where patches to livecd creator will go
~ config -> kickstart files that describe the appliance
~ tools -> the tools
~ appcreate -> lib files
@@ -11,7 +12,7 @@ appcreate -> lib files
~ prebuilt installs:
~ rpms are available at thincrust.net
- -make sure you have patched version of livecd-tools
+install livecd-tools rpm 0.17.1-1.fc9 or newer
~ install appliance-tools rpm
@@ -23,16 +24,5 @@ git clone git://git.fedorahosted.org/livecd
~ git clone git://git.et.redhat.com/ace.git
~ git clone git://git.et.redhat.com/aos.git
- -Patch livecd creator
- -cd $TCHOME/livecd
- -patch -p1 <
$TCHOME/act/patches/0001-Make-use-of-python-logging-API-for-debug-messages.patch
- -patch -p1 <
$TCHOME/act/patches/0002-Refactor-disk-mount-classes-to-allow-multi-partition.patch
- -patch -p1 <
$TCHOME/act/patches/0003-fs.py-kickstart.py-chages-for-mulit-partition.patch
- -
- -cp $TCHOME/act/tools/appliance-creator tools/
- -cp $TCHOME/act/appcreate/*.py appcreate/
- -
- -chmod a+x tools/appliance-creator
- -
- -export PYTHONPATH=$TCHOME/livecd
+PYTHONPATH=$TCHOME/act $TCHOME/act/tools/appliance-creator
diff --git a/appcreate/__init__.py b/appcreate/__init__.py
index a6404dc..64a82c6 100644
- --- a/appcreate/__init__.py
+++ b/appcreate/__init__.py
@@ -22,7 +22,6 @@ from imgcreate.creator import *
~ from imgcreate.yuminst import *
~ from imgcreate.kickstart import *
~ from imgcreate.fs import *
- -from imgcreate.debug import *
~ from appcreate.appliance import *
~ """A set of classes for building Fedora applinace images.
diff --git a/appcreate/appliance.py b/appcreate/appliance.py
index a315f9a..0e5753b 100644
- --- a/appcreate/appliance.py
+++ b/appcreate/appliance.py
@@ -28,6 +28,501 @@ from imgcreate.errors import *
~ from imgcreate.fs import *
~ from imgcreate.creator import *
+import stat
+
+class Disk:
+ 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 PartitionedMount:
+ def __init__(self, disks, mountdir):
+ self.mountdir = mountdir
+ self.disks = {}
+ for name in disks.keys():
+ self.disks[name] = { 'disk': disks[name], # Disk object
+ 'mapped': False, # True if kpartx
mapping exists
+ 'numpart': 0, # Number of allocate
partitions
+ 'partitions': [], # indexes to
self.partitions
+ 'extended': 0, # Size of extended
partition
+ 'offset': 0 } # Offset of next partition
+
+ self.partitions = []
+ self.mapped = False
+ self.mountOrder = []
+ self.unmountOrder = []
+
+ def add_partition(self, size, disk, mountpoint, fstype = None):
+ self.partitions.append({'size': size,
+ 'mountpoint': mountpoint, # Mount
relative to chroot
+ 'fstype': fstype,
+ 'disk': disk, # physical disk name
holding partition
+ 'device': None, # kpartx device node
for partition
+ 'mount': None, # Mount object
+ 'num': None}) # Partition number
+
+ def __format_disks(self):
+ logging.debug("Formatting disks")
+ for dev in self.disks.keys():
+ d = self.disks[dev]
+ logging.debug("Initializing partition table for %s" %
(d['disk'].device))
+ rc = subprocess.call(["/sbin/parted", "-s",
d['disk'].device, "mklabel", "msdos"])
+ if rc != 0:
+ raise MountError("Error writing partition table on %s"
% d.device)
+
+ logging.debug("Assigning partitions to disks")
+ for n in range(len(self.partitions)):
+ p = self.partitions[n]
+
+ if not self.disks.has_key(p['disk']):
+ raise MountError("No disk %s for partition %s" %
(p['disk'], p['mountpoint']))
+
+ d = self.disks[p['disk']]
+ d['numpart'] += 1
+ if d['numpart'] > 3:
+ # Increase allocation of extended partition to hold
this partition
+ d['extended'] += p['size']
+ p['type'] = 'logical'
+ p['num'] = d['numpart'] + 1
+ else:
+ p['type'] = 'primary'
+ p['num'] = d['numpart']
+
+ p['start'] = d['offset']
+ d['offset'] += p['size']
+ d['partitions'].append(n)
+ logging.debug("Assigned %s to %s%d at %d at size %d" %
(p['mountpoint'], p['disk'], p['num'], p['start'], p['size']))
+
+ # XXX we should probably work in cylinder units to keep fdisk
happier..
+ start = 0
+ logging.debug("Creating partitions")
+ for p in self.partitions:
+ d = self.disks[p['disk']]
+ if p['num'] == 5:
+ logging.debug("Added extended part at %d of size %d" %
(p['start'], d['extended']))
+ rc = subprocess.call(["/sbin/parted", "-s",
d['disk'].device, "mkpart", "extended",
+ "%dM" % p['start'], "%dM" %
(p['start'] + d['extended'])])
+
+ logging.debug("Add %s part at %d of size %d" % (p['type'],
p['start'], p['size']))
+ rc = subprocess.call(["/sbin/parted", "-s",
d['disk'].device, "mkpart",
+ p['type'], "%dM" % p['start'], "%dM"
% (p['start']+p['size'])])
+
+ # XXX disabled return code check because parted always fails to
+ # reload part table with loop devices. Annoying because we
can't
+ # distinguish this failure from real partition failures :-(
+ if rc != 0 and 1 == 0:
+ raise MountError("Error creating partition on %s" %
d['disk'].device)
+
+ def __map_partitions(self):
+ for dev in self.disks.keys():
+ d = self.disks[dev]
+ if d['mapped']:
+ continue
+
+ kpartx = subprocess.Popen(["/sbin/kpartx", "-l",
d['disk'].device],
+ stdout=subprocess.PIPE)
+
+ kpartxOutput = kpartx.communicate()[0].split("\n")
+ # Strip trailing blank
+ kpartxOutput = kpartxOutput[0:len(kpartxOutput)-1]
+
+ if kpartx.returncode:
+ raise MountError("Failed to query partition mapping for
'%s'" %
+ d.device)
+
+ # Quick sanity check that the number of partitions matches
+ # our expectation. If it doesn't, someone broke the code
+ # further up
+ if len(kpartxOutput) != d['numpart']:
+ raise MountError("Unexpected number of partitions from
kpartx: %d != %d" %
+ (len(kpartxOutput), d['numpart']))
+
+ for i in range(len(kpartxOutput)):
+ line = kpartxOutput[i]
+ newdev = line.split()[0]
+ mapperdev = "/dev/mapper/" + newdev
+ loopdev = d['disk'].device + newdev[-1]
+
+ logging.debug("Dev %s: %s -> %s" % (newdev, loopdev,
mapperdev))
+ pnum = d['partitions'][i]
+ self.partitions[pnum]['device'] = loopdev
+
+ # grub's install wants partitions to be named
+ # to match their parent device + partition num
+ # kpartx doesn't work like this, so we add compat
+ # symlinks to point to /dev/mapper
+ os.symlink(mapperdev, loopdev)
+
+ logging.debug("Adding partx mapping for %s" % d['disk'].device)
+ rc = subprocess.call(["/sbin/kpartx", "-a", d['disk'].device])
+ if rc != 0:
+ raise MountError("Failed to map partitions for '%s'" %
+ d['disk'].device)
+ d['mapped'] = True
+
+
+ def __unmap_partitions(self):
+ for dev in self.disks.keys():
+ d = self.disks[dev]
+ if not d['mapped']:
+ continue
+
+ logging.debug("Removing compat symlinks")
+ for pnum in d['partitions']:
+ if self.partitions[pnum]['device'] != None:
+ os.unlink(self.partitions[pnum]['device'])
+ self.partitions[pnum]['device'] = None
+
+ logging.debug("Unmapping %s" % d['disk'].device)
+ rc = subprocess.call(["/sbin/kpartx", "-d", d['disk'].device])
+ if rc != 0:
+ raise MountError("Failed to unmap partitions for '%s'" %
+ d['disk'].device)
+
+ d['mapped'] = False
+
+
+ def __calculate_mountorder(self):
+ for p in self.partitions:
+ self.mountOrder.append(p['mountpoint'])
+ self.unmountOrder.append(p['mountpoint'])
+
+ self.mountOrder.sort()
+ self.unmountOrder.sort()
+ self.unmountOrder.reverse()
+ print str(self.mountOrder)
+
+ def cleanup(self):
+ self.unmount()
+ self.__unmap_partitions()
+ for dev in self.disks.keys():
+ d = self.disks[dev]
+ try:
+ d['disk'].cleanup()
+ except:
+ pass
+
+ def unmount(self):
+ for mp in self.unmountOrder:
+ if mp == 'swap':
+ continue
+ p = None
+ for p1 in self.partitions:
+ if p1['mountpoint'] == mp:
+ p = p1
+ break
+
+ if p['mount'] != None:
+ try:
+ p['mount'].cleanup()
+ except:
+ pass
+ p['mount'] = None
+
+ def mount(self):
+ for dev in self.disks.keys():
+ d = self.disks[dev]
+ d['disk'].create()
+
+ self.__format_disks()
+ self.__map_partitions()
+ self.__calculate_mountorder()
+
+ for mp in self.mountOrder:
+ p = None
+ for p1 in self.partitions:
+ if p1['mountpoint'] == mp:
+ p = p1
+ break
+
+ if mp == 'swap':
+ subprocess.call(["/sbin/mkswap", p['device']])
+ continue
+
+ rmmountdir = False
+ if p['mountpoint'] == "/":
+ rmmountdir = True
+ pdisk = ExtDiskMount(RawDisk(p['size'] * 1024 * 1024,
p['device']),
+ self.mountdir + p['mountpoint'],
+ p['fstype'],
+ 4096,
+ p['mountpoint'],
+ rmmountdir)
+ pdisk.mount()
+ p['mount'] = pdisk
+
+ def resparse(self, size = None):
+ # Can't re-sparse a disk image - too hard
+ pass
+
+
~ class ApplianceImageCreator(ImageCreator):
~ """Installs a system into a file containing a partitioned disk image.
@@ -68,7 +563,10 @@ class ApplianceImageCreator(ImageCreator):
~ 'mountpoint': p['mountpoint'],
~ 'fstype': p['fstype'] }
- - s += self._get_fstab_special()
+ 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"
~ return s
@@ -95,7 +593,7 @@ class ApplianceImageCreator(ImageCreator):
~ self.__imgdir = self._mkdtemp()
~ #list of partitions from kickstart file
- - parts = kickstart.get_partitions(self.ks)
+ parts = self.ks.handler.partition.partitions
~ #list of disks where a disk is an dict with name: and size
~ disks = []
@@ -143,7 +641,7 @@ class ApplianceImageCreator(ImageCreator):
~ def _create_grub_devices(self):
~ devs = []
- - parts = kickstart.get_partitions(self.ks)
+ parts = self.ks.handler.partition.partitions
~ for p in parts:
~ dev = p.disk
~ if not dev in devs:
@@ -328,7 +826,3 @@ class ApplianceImageCreator(ImageCreator):
~ "-O", self.__format, dst])
~ if rc != 0:
~ raise CreatorError("Unable to convert disk to %s" %
(self.__format))
- -
- -
- -
- -
diff --git a/appliance-tools.spec b/appliance-tools.spec
index ab07c14..4b0e1db 100644
- --- a/appliance-tools.spec
+++ b/appliance-tools.spec
@@ -4,24 +4,25 @@
~ Summary: Tools for building Appliances
~ Name: appliance-tools
- -Version: 001
- -Release: thincrust
+Version: 002
+Release: 1%{?dist}
~ License: GPLv2
~ Group: System Environment/Base
~ URL: http://thincrust.net
~ Source0: %{name}-%{version}.tar.bz2
~ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
- -Requires: livecd-tools >= 017
+Requires: livecd-tools >= 017.1
~ BuildRequires: python
+BuildArch: noarch
- -%description
+%description
~ Tools for generating appliance images on Fedora based systems including
~ derived distributions such as RHEL, CentOS and others. See
~ http://thincrust.net for more details.
~ %prep
- -%setup -q -n act
+%setup -q
~ %build
~ make
@@ -45,6 +46,18 @@ rm -rf $RPM_BUILD_ROOT
~ %{python_sitelib}/appcreate/*.pyc
~ %changelog
+* Wed Jul 09 2008 Alan Pevec <apevec at redhat.com> 002-1
+- import imgcreate.fs refactoring and other changes
+ to make it work with Fedora-9 livecd-tools-0.17.1 w/o Thincrust patches
+
+* Wed Jun 11 2008 David Huff <dhuff at redhat.com> - 001-3
+- fixed dependancys
+
+* Tue Jun 10 2008 David Huff <dhuff at redhat.com> - 001-2
+- Undated opt parser
+- fixed grub issue
+- build aginsted newer livecd-tools for selinux issues
+
~ * Wed May 14 2008 David Huff <dhuff at redhat.com> - 001
~ - Initial build.
diff --git
a/patches/0001-Make-use-of-python-logging-API-for-debug-messages.patch
b/patches/0001-Make-use-of-python-logging-API-for-debug-messages.patch
deleted file mode 100644
index 171fd05..0000000
- --- a/patches/0001-Make-use-of-python-logging-API-for-debug-messages.patch
+++ /dev/null
@@ -1,283 +0,0 @@
- -From c239cc871b67ce86dc984d4beb308b0abea71c95 Mon Sep 17 00:00:00 2001
- -From: huff <dhuff at redhat.com>
- -Date: Tue, 20 May 2008 16:21:11 -0400
- -Subject: [PATCH] -Make-use-of-python-logging-API-for-debug-messages3
- -
- ----
- - imgcreate/__init__.py | 4 ++-
- - imgcreate/creator.py | 5 ++-
- - imgcreate/debug.py | 87
+++++++++++++++++++++++++++++++++++++++++++++++++
- - imgcreate/live.py | 4 +-
- - imgcreate/yuminst.py | 3 +-
- - tools/image-creator | 7 +++-
- - tools/livecd-creator | 7 +++-
- - 7 files changed, 107 insertions(+), 10 deletions(-)
- - create mode 100644 imgcreate/debug.py
- -
- -diff --git a/imgcreate/__init__.py b/imgcreate/__init__.py
- -index e535014..bcfb40e 100644
- ---- a/imgcreate/__init__.py
- -+++ b/imgcreate/__init__.py
- -@@ -21,6 +21,7 @@ from imgcreate.creator import *
- - from imgcreate.yuminst import *
- - from imgcreate.kickstart import *
- - from imgcreate.fs import *
- -+from imgcreate.debug import *
- -
- - """A set of classes for building Fedora system images.
- -
- -@@ -62,5 +63,6 @@ __all__ = (
- - 'LoopImageCreator',
- - 'FSLABEL_MAXLEN',
- - 'read_kickstart',
- -- 'construct_name'
- -+ 'construct_name',
- -+ 'setup_logging',
- - )
- -diff --git a/imgcreate/creator.py b/imgcreate/creator.py
- -index 1028e32..40ce1ef 100644
- ---- a/imgcreate/creator.py
- -+++ b/imgcreate/creator.py
- -@@ -22,6 +22,7 @@ import stat
- - import sys
- - import tempfile
- - import shutil
- -+import logging
- -
- - import yum
- - import rpm
- -@@ -522,7 +523,7 @@ class ImageCreator(object):
- - (pkg, e))
- -
- - for pkg in skipped_pkgs:
- -- print >> sys.stderr, "Skipping missing package '%s'" %
(pkg,)
- -+ logging.warn("Skipping missing package '%s'" % (pkg,))
- -
- - def __select_groups(self, ayum):
- - skipped_groups = []
- -@@ -537,7 +538,7 @@ class ImageCreator(object):
- - skipped_groups.append(group)
- -
- - for group in skipped_groups:
- -- print >> sys.stderr, "Skipping missing group '%s'" %
(group.name,)
- -+ logging.warn("Skipping missing group '%s'" % (group.name,))
- -
- - def __deselect_packages(self, ayum):
- - for pkg in kickstart.get_excluded(self.ks,
- -diff --git a/imgcreate/debug.py b/imgcreate/debug.py
- -new file mode 100644
- -index 0000000..99318f3
- ---- /dev/null
- -+++ b/imgcreate/debug.py
- -@@ -0,0 +1,87 @@
- -+#
- -+# debug.py: Helper routines for debugging
- -+#
- -+# Copyright 2008, Red Hat Inc.
- -+#
- -+# This program is free software; you can redistribute it and/or modify
- -+# it under the terms of the GNU General Public License as published by
- -+# the Free Software Foundation; version 2 of the License.
- -+#
- -+# This program is distributed in the hope that it will be useful,
- -+# but WITHOUT ANY WARRANTY; without even the implied warranty of
- -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- -+# GNU Library General Public License for more details.
- -+#
- -+# You should have received a copy of the GNU General Public License
- -+# along with this program; if not, write to the Free Software
- -+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
- -+#
- -+
- -+import logging
- -+import logging.handlers
- -+import optparse
- -+import sys
- -+
- -+
- -+def handle_logging(option, opt, val, parser, logger, level):
- -+ if level < logger.level:
- -+ logger.setLevel(level)
- -+
- -+def handle_logfile(option, opt, val, parser, logger, stream):
- -+ try:
- -+ logfile = logging.FileHandler(val,"a")
- -+ except IOError, (err, msg):
- -+ raise optparse.OptionValueError("Cannot open file '%s' : %s" %
- -+ (val, msg))
- -+
- -+
- -+ logger.removeHandler(stream)
- -+ logger.addHandler(logfile)
- -+
- -+def setup_logging(parser = None):
- -+ """Set up the root logger and add logging options.
- -+
- -+ Set up the root logger so only warning/error messages are logged
to stderr
- -+ by default.
- -+
- -+ Also, optionally, add --debug, --verbose and --logfile command
line options
- -+ to the supplied option parser, allowing the root logger
configuration to be
- -+ modified by the user.
- -+
- -+ Note, to avoid possible namespace clashes, setup_logging() will
only ever
- -+ add these three options. No new options will be added in the future.
- -+
- -+ parser -- an optparse.OptionParser instance, or None
- -+
- -+ """
- -+ logger = logging.getLogger()
- -+
- -+ logger.setLevel(logging.WARN)
- -+
- -+ stream = logging.StreamHandler(sys.stderr)
- -+
- -+ logger.addHandler(stream)
- -+
- -+ if parser is None:
- -+ return
- -+
- -+ group = optparse.OptionGroup(parser, "Debugging options",
- -+ "These options control the output of
logging information during image creation")
- -+
- -+ group.add_option("-d", "--debug",
- -+ action = "callback", callback = handle_logging,
- -+ callback_args = (logger, logging.DEBUG),
- -+ help = "Output debugging information")
- -+
- -+ group.add_option("-v", "--verbose",
- -+ action = "callback", callback = handle_logging,
- -+ callback_args = (logger, logging.INFO),
- -+ help = "Output verbose progress information")
- -+
- -+ group.add_option("", "--logfile", type="string",
- -+ action = "callback", callback = handle_logfile,
- -+ callback_args = (logger, stream),
- -+ help = "Save debug information to FILE", metavar
= "FILE")
- -+
- -+ parser.add_option_group(group)
- -+
- -diff --git a/imgcreate/live.py b/imgcreate/live.py
- -index c6267f7..130f7fa 100644
- ---- a/imgcreate/live.py
- -+++ b/imgcreate/live.py
- -@@ -21,6 +21,7 @@ import os.path
- - import glob
- - import shutil
- - import subprocess
- -+import logging
- -
- - from imgcreate.errors import *
- - from imgcreate.fs import *
- -@@ -252,8 +253,7 @@ class LiveImageCreatorBase(LoopImageCreator):
- - elif os.path.exists("/usr/lib/anaconda-runtime/implantisomd5"):
- - implantisomd5 = "/usr/lib/anaconda-runtime/implantisomd5"
- - else:
- -- print >> sys.stderr, \
- -- "isomd5sum not installed; not setting up mediacheck"
- -+ logging.warn("isomd5sum not installed; not setting up
mediacheck")
- -
- - subprocess.call([implantisomd5, iso])
- -
- -diff --git a/imgcreate/yuminst.py b/imgcreate/yuminst.py
- -index 80fc514..aebb822 100644
- ---- a/imgcreate/yuminst.py
- -+++ b/imgcreate/yuminst.py
- -@@ -18,6 +18,7 @@
- -
- - import os
- - import sys
- -+import logging
- -
- - import yum
- - import rpmUtils
- -@@ -103,7 +104,7 @@ class LiveCDYum(yum.YumBase):
- - pkgs.remove(x)
- - self.tsInfo.conditionals[req] = pkgs
- - else:
- -- print >> sys.stderr, "No such package %s to remove" %(pkg,)
- -+ logging.warn("No such package %s to remove" %(pkg,))
- -
- - def selectGroup(self, grp, include =
pykickstart.parser.GROUP_DEFAULT):
- - yum.YumBase.selectGroup(self, grp)
- -diff --git a/tools/image-creator b/tools/image-creator
- -index aca9228..6f2604c 100755
- ---- a/tools/image-creator
- -+++ b/tools/image-creator
- -@@ -21,6 +21,7 @@ import os
- - import sys
- - import shutil
- - import optparse
- -+import logging
- -
- - import imgcreate
- -
- -@@ -30,6 +31,8 @@ def parse_options(args):
- - parser.add_option("-n", "--name", type="string", dest="name",
- - help="Image name and filesystem label")
- -
- -+ imgcreate.setup_logging(parser)
- -+
- - (options, args) = parser.parse_args()
- -
- - if len(args) != 1:
- -@@ -48,7 +51,7 @@ def main():
- - try:
- - ks = imgcreate.read_kickstart(kscfg)
- - except imgcreate.CreatorError, e:
- -- print >> sys.stderr, "Error loading kickstart file '%s' : %s"
% (kscfg, e)
- -+ logging.error("Unable to load kickstart file '%s' : %s" %
(kscfg, e))
- - return 1
- -
- - if options.name:
- -@@ -61,7 +64,7 @@ def main():
- - try:
- - creator.create()
- - except imgcreate.CreatorError, e:
- -- print >> sys.stderr, "Error creating image : %s" % e
- -+ logging.error("Unable to create image : %s" % e)
- - return 1
- - finally:
- - creator.cleanup()
- -diff --git a/tools/livecd-creator b/tools/livecd-creator
- -index 7c08323..a3ece16 100755
- ---- a/tools/livecd-creator
- -+++ b/tools/livecd-creator
- -@@ -22,6 +22,7 @@ import os.path
- - import sys
- - import time
- - import optparse
- -+import logging
- -
- - import imgcreate
- -
- -@@ -53,6 +54,8 @@ def parse_options(args):
- - help="Cache directory to use (default: private
cache")
- - parser.add_option_group(sysopt)
- -
- -+ imgcreate.setup_logging(parser)
- -+
- - # debug options not recommended for "production" images
- - # Start a shell in the chroot for post-configuration.
- - parser.add_option("-l", "--shell", action="store_true",
dest="give_shell",
- -@@ -101,7 +104,7 @@ def main():
- - "livecd-",
- - maxlen =
imgcreate.FSLABEL_MAXLEN)
- -
- -- print "Using label '%s' and name '%s'" % (fs_label, name)
- -+ logging.info("Using label '%s' and name '%s'" % (fs_label,
name))
- -
- - ks = imgcreate.read_kickstart(options.kscfg)
- -
- -@@ -121,7 +124,7 @@ def main():
- - creator.unmount()
- - creator.package()
- - except imgcreate.CreatorError, e:
- -- print >> sys.stderr, "Error creating Live CD : %s" % e
- -+ logging.error("Error creating Live CD : %s" % e)
- - return 1
- - finally:
- - creator.cleanup()
- ---
- -1.5.4.1
- -
diff --git
a/patches/0002-Refactor-disk-mount-classes-to-allow-multi-partitio.patch
b/patches/0002-Refactor-disk-mount-classes-to-allow-multi-partitio.patch
deleted file mode 100644
index cf7af67..0000000
- ---
a/patches/0002-Refactor-disk-mount-classes-to-allow-multi-partitio.patch
+++ /dev/null
@@ -1,457 +0,0 @@
- -From 2de5f2bff3572d168db357b36b666f0761dec1ae Mon Sep 17 00:00:00 2001
- -From: huff <dhuff at redhat.com>
- -Date: Mon, 19 May 2008 11:01:48 -0400
- -Subject: [PATCH] -Refactor-disk-mount-classes-to-allow-multi-partitions
- -
- ----
- - imgcreate/creator.py | 17 ++--
- - imgcreate/fs.py | 250
++++++++++++++++++++++++++++++++------------------
- - imgcreate/live.py | 6 +-
- - 3 files changed, 175 insertions(+), 98 deletions(-)
- -
- -diff --git a/imgcreate/creator.py b/imgcreate/creator.py
- -index febb847..7ccbef9 100644
- ---- a/imgcreate/creator.py
- -+++ b/imgcreate/creator.py
- -@@ -208,7 +208,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"
- -@@ -840,12 +844,11 @@ class LoopImageCreator(ImageCreator):
- - if not base_on is None:
- - 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/fs.py b/imgcreate/fs.py
- -index 98c0db4..314a776 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 *
- -
- -@@ -86,42 +87,51 @@ class BindChrootMount:
- - subprocess.call(["/bin/umount", self.dest])
- - self.mounted = False
- -
- --class LoopbackMount:
- -- def __init__(self, lofile, mountdir, fstype = None):
- -- self.lofile = lofile
- -- self.mountdir = mountdir
- -- self.fstype = fstype
- -+class Disk:
- -+ def __init__(self, size, device = None):
- -+ self._device = device
- -+ self._size = size
- -
- -- self.mounted = False
- -- self.losetup = False
- -- self.rmdir = False
- -- self.loopdev = None
- -+ def create(self):
- -+ pass
- -
- - def cleanup(self):
- -- self.unmount()
- -- self.lounsetup()
- -+ pass
- -
- -- def unmount(self):
- -- if self.mounted:
- -- rc = subprocess.call(["/bin/umount", self.mountdir])
- -- if rc == 0:
- -- self.mounted = False
- -+ def get_device(self):
- -+ return self._device
- -+ def set_device(self, path):
- -+ self._device = path
- -+ device = property(get_device, set_device)
- -
- -- if self.rmdir and not self.mounted:
- -- try:
- -- os.rmdir(self.mountdir)
- -- except OSError, e:
- -- pass
- -- self.rmdir = False
- -+ 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 lounsetup(self):
- -- if self.losetup:
- -- rc = subprocess.call(["/sbin/losetup", "-d", self.loopdev])
- -- self.losetup = False
- -- self.loopdev = None
- -+ def exists(self):
- -+ return os.path.exists(self.lofile)
- -
- -- def loopsetup(self):
- -- if self.losetup:
- -+ def create(self):
- -+ if self.device is not None:
- - return
- -
- - losetupProc = subprocess.Popen(["/sbin/losetup", "-f"],
- -@@ -132,40 +142,27 @@ class LoopbackMount:
- - raise MountError("Failed to allocate loop device for '%s'" %
- - self.lofile)
- -
- -- self.loopdev = losetupOutput.split()[0]
- -+ device = losetupOutput.split()[0]
- -
- -- rc = subprocess.call(["/sbin/losetup", self.loopdev,
self.lofile])
- -+ 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
- -
- -- self.losetup = True
- --
- -- def mount(self):
- -- if self.mounted:
- -+ 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
- -
- -- 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
- --
- --class SparseLoopbackMount(LoopbackMount):
- -- def __init__(self, lofile, mountdir, size, fstype = None):
- -- LoopbackMount.__init__(self, lofile, mountdir, fstype)
- -- self.size = size
- -+class SparseLoopbackDisk(LoopbackDisk):
- -+ def __init__(self, lofile, size):
- -+ LoopbackDisk.__init__(self, lofile, size)
- -
- - def expand(self, create = False, size = None):
- - flags = os.O_WRONLY
- -@@ -176,6 +173,7 @@ class SparseLoopbackMount(LoopbackMount):
- - 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)
- -@@ -185,36 +183,107 @@ class SparseLoopbackMount(LoopbackMount):
- - 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()
- -+
- -
- --class SparseExtLoopbackMount(SparseLoopbackMount):
- -- def __init__(self, lofile, mountdir, size, fstype, blocksize,
fslabel):
- -- SparseLoopbackMount.__init__(self, lofile, mountdir, size,
fstype)
- -+ 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.lofile,
- -- str(self.size / 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.lofile])
- --
- -- def create(self):
- -- SparseLoopbackMount.create(self)
- -- self.__format_filesystem()
- -+ "-ouser_xattr,acl", self.disk.device])
- -
- -- def resize(self, size = None):
- -- current_size = os.stat(self.lofile)[stat.ST_SIZE]
- -+ def __resize_filesystem(self, size = None):
- -+ current_size = os.stat(self.disk.lofile)[stat.ST_SIZE]
- -
- - if size is None:
- - size = self.size
- -@@ -227,21 +296,28 @@ class SparseExtLoopbackMount(SparseLoopbackMount):
- -
- - self.__fsck()
- -
- -- resize2fs(self.lofile, size)
- --
- -- if size < current_size:
- -- self.truncate(size)
- -+ resize2fs(self.disk.lofile, size)
- - return size
- -
- -- def mount(self):
- -- if not os.path.isfile(self.lofile):
- -- self.create()
- -+ 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.resize()
- -- return SparseLoopbackMount.mount(self)
- -+ self.__format_filesystem()
- -+
- -+ def mount(self):
- -+ self.__create()
- -+ DiskMount.mount(self)
- -
- - def __fsck(self):
- -- subprocess.call(["/sbin/e2fsck", "-f", "-y", self.lofile])
- -+ 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):
- -@@ -253,7 +329,7 @@ class SparseExtLoopbackMount(SparseLoopbackMount):
- -
- - dev_null = os.open("/dev/null", os.O_WRONLY)
- - try:
- -- out = subprocess.Popen(['/sbin/dumpe2fs', '-h',
self.lofile],
- -+ out = subprocess.Popen(['/sbin/dumpe2fs', '-h',
self.disk.lofile],
- - stdout = subprocess.PIPE,
- - stderr = dev_null).communicate()[0]
- - finally:
- -@@ -273,7 +349,7 @@ class SparseExtLoopbackMount(SparseLoopbackMount):
- - while top != (bot + 1):
- - t = bot + ((top - bot) / 2)
- -
- -- if not resize2fs(self.lofile, t):
- -+ if not resize2fs(self.disk.lofile, t):
- - top = t
- - else:
- - bot = t
- -@@ -284,8 +360,7 @@ class SparseExtLoopbackMount(SparseLoopbackMount):
- -
- - minsize = self.__resize_to_minimal()
- -
- -- self.truncate(minsize)
- -- self.resize(size)
- -+ self.disk.truncate(minsize)
- - return minsize
- -
- - class DeviceMapperSnapshot(object):
- -@@ -306,8 +381,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 +390,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:
- -@@ -382,15 +457,14 @@ class DeviceMapperSnapshot(object):
- - # 8) Create a squashfs of the COW
- - #
- - def create_image_minimizer(path, image, minimal_size):
- -- imgloop = LoopbackMount(image, "None")
- -+ 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)
- -diff --git a/imgcreate/live.py b/imgcreate/live.py
- -index 130f7fa..9ecd3cf 100644
- ---- a/imgcreate/live.py
- -+++ b/imgcreate/live.py
- -@@ -129,7 +129,7 @@ class LiveImageCreatorBase(LoopImageCreator):
- - #
- - def __base_on_iso(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()
- -@@ -143,10 +143,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)
- -
- ---
- -1.5.4.1
- -
diff --git
a/patches/0003-fs.py-kickstart.py-chages-for-mulit-partitions.patch
b/patches/0003-fs.py-kickstart.py-chages-for-mulit-partitions.patch
deleted file mode 100644
index 2f8b4c0..0000000
- --- a/patches/0003-fs.py-kickstart.py-chages-for-mulit-partitions.patch
+++ /dev/null
@@ -1,273 +0,0 @@
- -From 835cb44a7084498a164c06bb54f1b44f8da3d5cd Mon Sep 17 00:00:00 2001
- -From: huff <dhuff at redhat.com>
- -Date: Mon, 19 May 2008 11:10:39 -0400
- -Subject: [PATCH] -fs.py-kickstart.py-chages-for-mulit-partitions
- -
- ----
- - imgcreate/fs.py | 223
+++++++++++++++++++++++++++++++++++++++++++++++-
- - imgcreate/kickstart.py | 4 +
- - 2 files changed, 225 insertions(+), 2 deletions(-)
- -
- -diff --git a/imgcreate/fs.py b/imgcreate/fs.py
- -index 314a776..aaff4c3 100644
- ---- a/imgcreate/fs.py
- -+++ b/imgcreate/fs.py
- -@@ -357,11 +357,229 @@ class ExtDiskMount(DiskMount):
- -
- - def resparse(self, size = None):
- - self.cleanup()
- --
- - minsize = self.__resize_to_minimal()
- --
- - self.disk.truncate(minsize)
- - return minsize
- -+
- -+class PartitionedMount(Mount):
- -+ def __init__(self, disks, mountdir):
- -+ Mount.__init__(self, mountdir)
- -+ self.disks = {}
- -+ for name in disks.keys():
- -+ self.disks[name] = { 'disk': disks[name], # Disk object
- -+ 'mapped': False, # True if kpartx
mapping exists
- -+ 'numpart': 0, # Number of allocate
partitions
- -+ 'partitions': [], # indexes to
self.partitions
- -+ 'extended': 0, # Size of extended
partition
- -+ 'offset': 0 } # Offset of next
partition
- -+
- -+ self.partitions = []
- -+ self.mapped = False
- -+ self.mountOrder = []
- -+ self.unmountOrder = []
- -+
- -+ def add_partition(self, size, disk, mountpoint, fstype = None):
- -+ self.partitions.append({'size': size,
- -+ 'mountpoint': mountpoint, # Mount
relative to chroot
- -+ 'fstype': fstype,
- -+ 'disk': disk, # physical disk name
holding partition
- -+ 'device': None, # kpartx device node
for partition
- -+ 'mount': None, # Mount object
- -+ 'num': None}) # Partition number
- -+
- -+ def __format_disks(self):
- -+ logging.debug("Formatting disks")
- -+ for dev in self.disks.keys():
- -+ d = self.disks[dev]
- -+ logging.debug("Initializing partition table for %s" %
(d['disk'].device))
- -+ rc = subprocess.call(["/sbin/parted", "-s",
d['disk'].device, "mklabel", "msdos"])
- -+ if rc != 0:
- -+ raise MountError("Error writing partition table on %s"
% d.device)
- -+
- -+ logging.debug("Assigning partitions to disks")
- -+ for n in range(len(self.partitions)):
- -+ p = self.partitions[n]
- -+
- -+ if not self.disks.has_key(p['disk']):
- -+ raise MountError("No disk %s for partition %s" %
(p['disk'], p['mountpoint']))
- -+
- -+ d = self.disks[p['disk']]
- -+ d['numpart'] += 1
- -+ if d['numpart'] > 3:
- -+ # Increase allocation of extended partition to hold
this partition
- -+ d['extended'] += p['size']
- -+ p['type'] = 'logical'
- -+ p['num'] = d['numpart'] + 1
- -+ else:
- -+ p['type'] = 'primary'
- -+ p['num'] = d['numpart']
- -+
- -+ p['start'] = d['offset']
- -+ d['offset'] += p['size']
- -+ d['partitions'].append(n)
- -+ logging.debug("Assigned %s to %s%d at %d at size %d" %
(p['mountpoint'], p['disk'], p['num'], p['start'], p['size']))
- -+
- -+ # XXX we should probably work in cylinder units to keep fdisk
happier..
- -+ start = 0
- -+ logging.debug("Creating partitions")
- -+ for p in self.partitions:
- -+ d = self.disks[p['disk']]
- -+ if p['num'] == 5:
- -+ logging.debug("Added extended part at %d of size %d" %
(p['start'], d['extended']))
- -+ rc = subprocess.call(["/sbin/parted", "-s",
d['disk'].device, "mkpart", "extended",
- -+ "%dM" % p['start'], "%dM" %
(p['start'] + d['extended'])])
- -+
- -+ logging.debug("Add %s part at %d of size %d" % (p['type'],
p['start'], p['size']))
- -+ rc = subprocess.call(["/sbin/parted", "-s",
d['disk'].device, "mkpart",
- -+ p['type'], "%dM" % p['start'], "%dM"
% (p['start']+p['size'])])
- -+
- -+ # XXX disabled return code check because parted always
fails to
- -+ # reload part table with loop devices. Annoying because we
can't
- -+ # distinguish this failure from real partition failures :-(
- -+ if rc != 0 and 1 == 0:
- -+ raise MountError("Error creating partition on %s" %
d['disk'].device)
- -+
- -+ def __map_partitions(self):
- -+ for dev in self.disks.keys():
- -+ d = self.disks[dev]
- -+ if d['mapped']:
- -+ continue
- -+
- -+ kpartx = subprocess.Popen(["/sbin/kpartx", "-l",
d['disk'].device],
- -+ stdout=subprocess.PIPE)
- -+
- -+ kpartxOutput = kpartx.communicate()[0].split("\n")
- -+ # Strip trailing blank
- -+ kpartxOutput = kpartxOutput[0:len(kpartxOutput)-1]
- -+
- -+ if kpartx.returncode:
- -+ raise MountError("Failed to query partition mapping
for '%s'" %
- -+ d.device)
- -+
- -+ # Quick sanity check that the number of partitions matches
- -+ # our expectation. If it doesn't, someone broke the code
- -+ # further up
- -+ if len(kpartxOutput) != d['numpart']:
- -+ raise MountError("Unexpected number of partitions from
kpartx: %d != %d" %
- -+ (len(kpartxOutput), d['numpart']))
- -+
- -+ for i in range(len(kpartxOutput)):
- -+ line = kpartxOutput[i]
- -+ newdev = line.split()[0]
- -+ mapperdev = "/dev/mapper/" + newdev
- -+ loopdev = d['disk'].device + newdev[-1]
- -+
- -+ logging.debug("Dev %s: %s -> %s" % (newdev, loopdev,
mapperdev))
- -+ pnum = d['partitions'][i]
- -+ self.partitions[pnum]['device'] = loopdev
- -+
- -+ # grub's install wants partitions to be named
- -+ # to match their parent device + partition num
- -+ # kpartx doesn't work like this, so we add compat
- -+ # symlinks to point to /dev/mapper
- -+ os.symlink(mapperdev, loopdev)
- -+
- -+ logging.debug("Adding partx mapping for %s" %
d['disk'].device)
- -+ rc = subprocess.call(["/sbin/kpartx", "-a",
d['disk'].device])
- -+ if rc != 0:
- -+ raise MountError("Failed to map partitions for '%s'" %
- -+ d['disk'].device)
- -+ d['mapped'] = True
- -+
- -+
- -+ def __unmap_partitions(self):
- -+ for dev in self.disks.keys():
- -+ d = self.disks[dev]
- -+ if not d['mapped']:
- -+ continue
- -+
- -+ logging.debug("Removing compat symlinks")
- -+ for pnum in d['partitions']:
- -+ if self.partitions[pnum]['device'] != None:
- -+ os.unlink(self.partitions[pnum]['device'])
- -+ self.partitions[pnum]['device'] = None
- -+
- -+ logging.debug("Unmapping %s" % d['disk'].device)
- -+ rc = subprocess.call(["/sbin/kpartx", "-d",
d['disk'].device])
- -+ if rc != 0:
- -+ raise MountError("Failed to unmap partitions for '%s'" %
- -+ d['disk'].device)
- -+
- -+ d['mapped'] = False
- -+
- -+
- -+ def __calculate_mountorder(self):
- -+ for p in self.partitions:
- -+ self.mountOrder.append(p['mountpoint'])
- -+ self.unmountOrder.append(p['mountpoint'])
- -+
- -+ self.mountOrder.sort()
- -+ self.unmountOrder.sort()
- -+ self.unmountOrder.reverse()
- -+ print str(self.mountOrder)
- -+
- -+ def cleanup(self):
- -+ Mount.cleanup(self)
- -+ self.__unmap_partitions()
- -+ for dev in self.disks.keys():
- -+ d = self.disks[dev]
- -+ try:
- -+ d['disk'].cleanup()
- -+ except:
- -+ pass
- -+
- -+ def unmount(self):
- -+ for mp in self.unmountOrder:
- -+ if mp == 'swap':
- -+ continue
- -+ p = None
- -+ for p1 in self.partitions:
- -+ if p1['mountpoint'] == mp:
- -+ p = p1
- -+ break
- -+
- -+ if p['mount'] != None:
- -+ try:
- -+ p['mount'].cleanup()
- -+ except:
- -+ pass
- -+ p['mount'] = None
- -+
- -+ def mount(self):
- -+ for dev in self.disks.keys():
- -+ d = self.disks[dev]
- -+ d['disk'].create()
- -+
- -+ self.__format_disks()
- -+ self.__map_partitions()
- -+ self.__calculate_mountorder()
- -+
- -+ for mp in self.mountOrder:
- -+ p = None
- -+ for p1 in self.partitions:
- -+ if p1['mountpoint'] == mp:
- -+ p = p1
- -+ break
- -+
- -+ if mp == 'swap':
- -+ subprocess.call(["/sbin/mkswap", p['device']])
- -+ continue
- -+
- -+ rmmountdir = False
- -+ if p['mountpoint'] == "/":
- -+ rmmountdir = True
- -+ pdisk = ExtDiskMount(RawDisk(p['size'] * 1024 * 1024,
p['device']),
- -+ self.mountdir + p['mountpoint'],
- -+ p['fstype'],
- -+ 4096,
- -+ p['mountpoint'],
- -+ rmmountdir)
- -+ pdisk.mount()
- -+ p['mount'] = pdisk
- -+
- -+ def resparse(self, size = None):
- -+ # Can't re-sparse a disk image - too hard
- -+ pass
- -
- - class DeviceMapperSnapshot(object):
- - def __init__(self, imgloop, cowloop):
- -@@ -478,3 +696,4 @@ def create_image_minimizer(path, image,
minimal_size):
- - mksquashfs(cowloop.lofile, path)
- -
- - os.unlink(cowloop.lofile)
- -+
- -diff --git a/imgcreate/kickstart.py b/imgcreate/kickstart.py
- -index ef7b9e4..eff28bb 100644
- ---- a/imgcreate/kickstart.py
- -+++ b/imgcreate/kickstart.py
- -@@ -474,6 +474,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
- -
- -@@ -490,3 +493,4 @@ def get_post_scripts(ks):
- -
- - def selinux_enabled(ks):
- - return ks.handler.selinux.selinux == ksconstants.SELINUX_ENFORCING
- -+
- ---
- -1.5.4.1
- -
diff --git a/tools/appliance-creator b/tools/appliance-creator
old mode 100644
new mode 100755
index e65d2c0..61d6f26
- --- a/tools/appliance-creator
+++ b/tools/appliance-creator
@@ -61,8 +61,6 @@ def parse_options(args):
~ parser.add_option_group(sysopt)
- - imgcreate.setup_logging(parser)
- -
~ (options, args) = parser.parse_args()
- --
1.5.4.1
- --
David Huff
Red Hat, Raleigh, NC
Mobile: 919-796-3553
Office: 919-754-4129
GPG Key ID: 6A20BBF7
GPG Fingerprint: FE13 8AF6 0E58 D92E A4E1 2D0A 71C1 CADF 6A20 BBF7
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org
iD8DBQFIhk34ccHK32ogu/cRAg57AJ9E3dX214mZs4jNVbcwQpoDAc3FLwCcC5cM
ISWnz+pK9OA8fIqgpJj1q+c=
=qorA
-----END PGP SIGNATURE-----
More information about the Thincrust-devel
mailing list