tools/livecd-iso-to-disk.sh
by Brian C. Lane
tools/livecd-iso-to-disk.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
New commits:
commit 9bf3a161c44c0d80e3d57d6c33c6dde65e3109d8
Author: Brian C. Lane <bcl(a)redhat.com>
Date: Mon Sep 19 13:16:05 2011 -0700
Only check first match for boot flag (#739411)
If, for some reason, you are installing to a device with
more than 9 partitions the boot flag check could match multiple
lines (eg. /dev/sda1 also matches /dev/sda10). This limits the
check to the first match.
diff --git a/tools/livecd-iso-to-disk.sh b/tools/livecd-iso-to-disk.sh
index 43c825e..9c8c878 100755
--- a/tools/livecd-iso-to-disk.sh
+++ b/tools/livecd-iso-to-disk.sh
@@ -391,7 +391,7 @@ checkPartActive() {
return
fi
- if [ "$(/sbin/fdisk -l $device 2>/dev/null |grep $dev |awk {'print $2;'})" != "*" ]; then
+ if [ "$(/sbin/fdisk -l $device 2>/dev/null |grep -m1 $dev |awk {'print $2;'})" != "*" ]; then
echo "Partition isn't marked bootable!"
echo "You can mark the partition as bootable with "
echo " # /sbin/parted $device"
12 years, 7 months
[PATCH 3a/6] substitute was: [PATCH 3/5] Liveimage-mount within running LiveOS instance
by Frederick Grose
This code is ready for Rawhide testing and comment.
I've used it on Fedora 11 - 15.
commit b9cdca9fb0ab97239bc68d2184ce16818401a0e2
Author: Frederick Grose <fgrose(a)sugarlabs.org>
Date: Sun Sep 18 20:49:01 2011 -0400
Support liveimage mounting from within a booted LiveOS instance.
Provide functions to add loop devices and remove them on exit, a
LiveImageMountError(Exception) class for better error handling,
random device-mapper node names, and the ability to liveimage-mount
an image (in the LiveOS folder) saved in a plain directory.
Provide a yum cache mount point option,
bind mount /etc/resolv.conf to permit Internet updating,
bind mount /dev/mapper to permit device checking,
support dmsetup versions lacking --noudevrules & --noudevsync,
miscellaneous code and whitespace optimizations.
diff --git a/tools/liveimage-mount b/tools/liveimage-mount
index 80d67d1..aed7606 100755
--- a/tools/liveimage-mount
+++ b/tools/liveimage-mount
@@ -1,9 +1,10 @@
#!/usr/bin/python -tt
+# coding: latin-1
+# 2011-09-18 11:47:42 -0400
#
-# liveimage-mount: Mount a LiveOS at the specified point, and log
-# into a shell.
+# liveimage-mount: Mount a LiveOS at the specified point, and log into a
shell.
#
-# Copyright 2011, Red Hat Inc.
+# Copyright 2011, Red Hat Inc., Sugar Labs®
# Code for Live mounting an attached LiveOS device added by Frederick
Grose,
# <fgrose at sugarlabs.org>
#
@@ -23,23 +24,39 @@
import os
import sys
import stat
+import time
import getopt
+import random
import tempfile
import subprocess
+extra_loops = []
def usage(ecode):
print """Usage:
- liveimage-mount [opts] ISO.iso|LiveOSdevice MOUNTPOINT [COMMAND]
[ARGS]
+ liveimage-mount [opts] ISO.iso|LiveOSdev|dir MOUNTPOINT [COMMAND]
[ARGS]
where [opts] = [-h|--help
[--chroot
[--mount-hacks
- [--persist]]]]]
+ [--persist
+ [-y|--yumcache=YUMCACHEPATH]]]]]
and [ARGS] = [arg1[ arg2[ ...]]]\n"""
sys.exit(ecode)
+class LiveImageMountError(Exception):
+ """An exception base class for all liveimage-mount errors."""
+ def __init__(self, msg):
+ Exception.__init__(self, msg)
+ def __str__(self):
+ try:
+ return str(self.message)
+ except UnicodeEncodeError:
+ return repr(self.message)
+
+ def __unicode__(self):
+ return unicode(self.message)
def call(*popenargs, **kwargs):
'''
@@ -62,43 +79,81 @@ def call(*popenargs, **kwargs):
return rc
-def rcall(args, env=None):
- if env:
+def rcall(args, stdin=None, rpterr=True, env=None):
+ '''Return stdout, stderr, & returncode from a subprocess call.'''
+
+ out, err, p, environ = '', '', None, None
+ if env is not None:
environ = os.environ.copy()
environ.update(env)
- else:
- environ = None
try:
- p = subprocess.Popen(args, stdout=subprocess.PIPE,
- stderr=subprocess.PIPE, env=environ)
- out, err = p.communicate()
+ p = subprocess.Popen(args, stdin=subprocess.PIPE, env=environ,
+ stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
+ out, err = p.communicate(stdin)
except OSError, e:
- raise CreatorError(u"Failed to execute:\n'%s'\n'%s'" % (args, e))
+ out, err = out, u'Failed executing:\n%s\nerror: %s' % (args, e)
+ if rpterr:
+ raise LiveImageMountError(u'Failed executing:\n%s\nerror: %s' %
+ (args, e))
except:
- raise CreatorError(u"""Failed to execute:\n'%s'
- \renviron: '%s'\nstdout: '%s'\nstderr: '%s'\nreturncode:
'%s'""" %
- (args, environ, out, err, p.returncode))
+ out, err = (out, u'Failed to execute:\n%s\nenviron: %s' %
+ (args, environ))
+ if rpterr:
+ raise LiveImageMountError(u'''Failed to execute:\n%s
+ \renviron: %s\nstdout: %s\nstderr: %s''' %
+ (args, environ, out, err))
else:
- if p.returncode != 0:
- raise CreatorError(u"""Error in call:\n'%s'\nenviron: '%s'
- \rstdout: '%s'\nstderr: '%s'\nreturncode: '%s'""" %
- (args, environ, out, err, p.returncode))
- return out
+ if p.returncode != 0 and rpterr:
+ raise LiveImageMountError(u'''Error in call:\n%s\nenviron: %s
+ \rstdout: %s\nstderr: %s\nreturncode: %s'''
%
+ (args, environ, out, err, p.returncode))
+ finally:
+ return out, err
+
+
+def get_fsvalue(format=None, tag=None, token=None, filesystem=None):
+ """Return filesystem information based on a blkid tag, token, or
device."""
+
+ dev_null = os.open('/dev/null', os.O_WRONLY)
+ args = ['/sbin/blkid', '-c', '/dev/null']
+ if format:
+ args.extend(['-o', format])
+ if tag:
+ args.extend(['-s', tag])
+ if token:
+ args.extend(['-l', '-t', token])
+ if filesystem:
+ args.extend([filesystem])
+ try:
+ fs_value = subprocess.Popen(args,
+ stdout=subprocess.PIPE,
+ stderr=dev_null).communicate()[0].rstrip()
+ except IOError, e:
+ raise LiveImageMountError("Failed to determine fs %s: %s" % value,
e)
+ finally:
+ os.close(dev_null)
+ return fs_value
-def get_device_mountpoint(path):
- """Return the device and mountpoint for a file or device path."""
+def add_loop(n=8):
+ """Add a loop device."""
- info = list()
- info[0:5] = [None] * 6
- if os.path.exists(path):
- st_mode = os.stat(path).st_mode
- if stat.S_ISBLK(st_mode) or os.path.ismount(path):
- devinfo = rcall(['/bin/df', path]).splitlines()
- info = devinfo[1].split(None)
- if len(info) == 1:
- info.extend(devinfo[2].split(None))
- return [info[0], info[5]]
+ while os.path.exists('/dev/loop%s' % n):
+ n += 1
+ os.mknod('/dev/loop%s' % n, 0660 | stat.S_IFBLK, os.makedev(7, n))
+ extra_loops.extend(['/dev/loop%s' % n])
+ return '/dev/loop%s' % n
+
+
+def loop_setup(path, ops=None):
+ """Make and associate a loop device with an image file or device."""
+
+ loop = add_loop()
+ args = ['/sbin/losetup', loop, path]
+ if ops is not None:
+ args += ops
+ call(args)
+ return loop
def main():
@@ -108,9 +163,8 @@ def main():
return 1
try:
- opts,args = getopt.getopt(sys.argv[1:], 'h', ['help',
- 'chroot', 'persist',
- 'mount-hacks'])
+ opts, args = getopt.getopt(sys.argv[1:], 'hy:', ['help', 'chroot',
+ 'persist', 'mount-hacks', 'yumcache='])
except getopt.GetoptError, e:
usage(1)
@@ -118,7 +172,9 @@ def main():
chroot = False
persist = False
mount_hacks = False
- for o,a in opts:
+ yumcache = None
+ rm_dir = None
+ for o, a in opts:
if o in ('-h', '--help'):
usage(0)
elif o in ('--chroot', ):
@@ -128,49 +184,64 @@ def main():
elif o in ('--persist', ):
"""Option used to run a command in a spawned process."""
persist = True
+ elif o in ('-y', '--yumcache'):
+ yumcache = a
if len(args) < 2:
usage(1)
liveos = args[0]
destmnt = args[1]
-
+ if not os.path.isdir(destmnt):
+ os.makedirs(destmnt)
+ rm_mnt = destmnt
+ if os.path.ismount(destmnt):
+ print """\n Exiting...
+ %s is already in use as a mount point.\n""" % destmnt
+ ecode = 1
+ return
+
if not os.path.exists(liveos):
print """\n Exiting...
%s is not a file, directory, or device.\n""" % liveos
ecode = 1
return
- if stat.S_ISBLK(os.stat(liveos).st_mode):
+ liveos_stat = os.stat(liveos).st_mode
+ if stat.S_ISBLK(liveos_stat):
img_type = 'blk'
- imgloop = None
overlayloop = None
+ liveosmnt = tempfile.mkdtemp(prefix='livemnt-device-')
+ elif stat.S_ISDIR(liveos_stat):
+ img_type = 'dir'
+ liveosmnt = liveos
else:
img_type = 'iso'
-
- if img_type is 'blk':
- liveosmnt = tempfile.mkdtemp(prefix='livemnt-device-')
- if img_type is 'iso':
liveosmnt = tempfile.mkdtemp(prefix='livemnt-iso-')
liveosdir = os.path.join(liveosmnt, 'LiveOS')
homemnt = None
dm_cow = None
mntlive = None
+ rmmntdir = None
+ rm_mnt = None
command = args[2:]
verbose = not command
+ dmsetup_cmd = ['/sbin/dmsetup']
+ if '--noudevsync' in rcall(['/sbin/dmsetup', '-h'])[1]:
+ dmsetup_cmd = ['/sbin/dmsetup', '--noudevrules', '--noudevsync']
+
squashmnt = tempfile.mkdtemp(prefix='livemnt-squash-')
squashloop = None
imgloop = None
- losetup_args = ['/sbin/losetup', '-f', '--show']
try:
- if img_type is 'blk':
+ if img_type == 'blk':
call(['/bin/mount', liveos, liveosmnt])
- elif img_type is 'iso':
- liveosloop = rcall(losetup_args + [liveos]).rstrip()
+ elif img_type == 'iso':
+ liveosloop = loop_setup(liveos)
call(['/bin/mount', '-o', 'ro', liveosloop, liveosmnt])
squash_img = os.path.join(liveosdir, 'squashfs.img')
@@ -182,57 +253,89 @@ def main():
ecode = 1
return
else:
- squashloop = rcall(losetup_args + [squash_img]).rstrip()
+ squashloop = loop_setup(squash_img, ['-r'])
call(['/bin/mount', '-o', 'ro', squashloop, squashmnt])
ext3_img = os.path.join(squashmnt, 'LiveOS', 'ext3fs.img')
- if img_type is 'blk':
- imgloop = rcall(losetup_args + [ext3_img]).rstrip()
- imgsize = rcall(['/sbin/blockdev', '--getsz',
imgloop]).rstrip()
- files = os.listdir(liveosdir)
- overlay = None
- for f in files:
- if f.find('overlay-') == 0:
- overlay = f
- break
- overlayloop = rcall(['/sbin/losetup', '-f']).rstrip()
- if overlay:
- call(['/sbin/losetup', overlayloop, os.path.join(liveosdir,
- overlay)])
- dm_cow = 'live-rw'
- else:
- overlay = tempfile.NamedTemporaryFile(dir='/dev/shm')
- print "\npreparing temporary overlay..."
- call(['/bin/dd', 'if=/dev/null', 'of=%s' % overlay.name,
- 'bs=1024', 'count=1', 'seek=%s' % (512 * 1024)])
- call(['/sbin/losetup', overlayloop, overlay.name])
- dm_cow = 'live-ro'
- call(['/sbin/dmsetup', '--noudevrules', '--noudevsync',
- 'create', dm_cow, '--table=0 %s snapshot %s %s p 8' %
- (imgsize, imgloop, overlayloop)])
- call(['/bin/mount', os.path.join('/dev/mapper', dm_cow),
destmnt])
- home_path = os.path.join(liveosdir, 'home.img')
- if os.path.exists(home_path):
- homemnt = os.path.join(destmnt, 'home')
- homeloop = rcall(losetup_args + [home_path]).rstrip()
- call(['/bin/mount', homeloop, homemnt])
- mntlive = os.path.join(destmnt, 'mnt', 'live')
- if not os.path.exists(mntlive):
- os.makedirs(mntlive)
- call(['/bin/mount', '--bind', liveosmnt, mntlive])
- elif img_type is 'iso':
- imgloop = rcall(losetup_args + [ext3_img]).rstrip()
- call(['/bin/mount', '-o', 'ro', imgloop, destmnt])
+ if img_type in ('blk', 'dir'):
+ imgloop = loop_setup(ext3_img)
+ elif img_type == 'iso':
+ imgloop = loop_setup(ext3_img, ['-r'])
+ imgsize = rcall(['/sbin/blockdev', '--getsz', imgloop])[0].rstrip()
+ overlay = None
+ for f in os.listdir(liveosdir):
+ if f.find('overlay-') == 0:
+ overlay = f
+ break
+ fd, dm_cow = tempfile.mkstemp(prefix='dm-')
+ os.close(fd)
+ os.unlink(dm_cow)
+ dm_cow = os.path.basename(dm_cow)
+ if overlay:
+ overlayloop = loop_setup(os.path.join(liveosdir, overlay))
+ else:
+ overlay = tempfile.NamedTemporaryFile(dir='/dev/shm')
+ print "\npreparing temporary overlay..."
+ call(['/bin/dd', 'if=/dev/null', 'of=%s' % overlay.name,
+ 'bs=1024', 'count=1', 'seek=%s' % (512 * 1024)])
+ overlayloop = loop_setup(overlay.name)
+ call(dmsetup_cmd + ['create', dm_cow,
+ '--table=0 %s snapshot %s %s p 8' %
+ (imgsize, imgloop, overlayloop)])
+ call(['/bin/mount', os.path.join('/dev/mapper', dm_cow), destmnt])
+ home_path = os.path.join(liveosdir, 'home.img')
+ if os.path.exists(home_path):
+ homemnt = os.path.join(destmnt, 'home')
+ homedev = loop_setup(home_path)
+ if get_fsvalue('value', 'TYPE', None,
+ homedev) == 'crypto_LUKS':
+ call(['/sbin/cryptsetup', 'luksOpen', homedev, 'EncHome'])
+ homedev = os.path.join('/dev', 'mapper', 'EncHome')
+ if img_type in ('blk', 'dir'):
+ call(['/bin/mount', homedev, homemnt])
+ elif img_type == 'iso':
+ call(['/bin/mount', '-o', 'ro', homedev, homemnt])
+ mntlive = os.path.join(destmnt, 'mnt', 'live')
+ if not os.path.isdir(mntlive):
+ os.makedirs(mntlive)
+ rmmntdir = True
+ call(['/bin/mount', '--bind', liveosmnt, mntlive])
if mount_hacks:
- subprocess.check_call(['mount', '-t', 'proc', 'proc',
os.path.join(destmnt, 'proc')], stderr=sys.stderr)
- subprocess.check_call(['mount', '-t', 'tmpfs', 'tmpfs',
os.path.join(destmnt, 'var', 'run')], stderr=sys.stderr)
+ subprocess.check_call(['mount', '-t', 'proc', 'proc',
+ os.path.join(destmnt, 'proc')], stderr=sys.stderr)
+ subprocess.check_call(['mount', '-t', 'tmpfs', 'tmpfs',
+ os.path.join(destmnt, 'var', 'run')], stderr=sys.stderr)
+ subprocess.check_call(['mount', '-t', 'sysfs', 'sys',
+ os.path.join(destmnt, 'sys')], stderr=sys.stderr)
+ subprocess.check_call(['mount', '-t', 'devpts', 'devpts',
+ os.path.join(destmnt, 'dev', 'pts')], stderr=sys.stderr)
+ tmpfs = os.path.join(destmnt, 'dev', 'shm')
+ if not os.path.exists(tmpfs):
+ os.makedirs(tmpfs)
+ subprocess.check_call(['mount', '-t', 'tmpfs', 'tmpfs', tmpfs],
+ stderr=sys.stderr)
+ run_dir = os.path.join(destmnt, 'run')
+ if not os.path.exists(run_dir):
+ os.makedirs(run_dir)
+ call(['/bin/mount', '-t', 'tmpfs', 'run', run_dir])
+ if yumcache is not None:
+ call(['/bin/mount', '--bind', yumcache,
+ os.path.join(destmnt, 'var', 'cache', 'yum')])
+ else:
+ subprocess.check_call(['mount', '-t', 'tmpfs',
'varcacheyum',
+ os.path.join(destmnt, 'var', 'cache', 'yum')],
+ stderr=sys.stderr)
+ call(['/bin/mount', '--bind', '/etc/resolv.conf',
+ os.path.join(destmnt, 'etc', 'resolv.conf')])
+ call(['/bin/mount', '--bind', '/dev/mapper',
+ os.path.join(destmnt, 'dev', 'mapper')])
if len(command) > 0 and persist:
args = []
args.extend(command)
live = ''
- if img_type is 'blk':
+ if img_type in ('blk', 'dir'):
live = 'live-'
print """Starting process with this command line:
\r%s\n %s is %smounted.""" % (' '.join(command), liveos, live)
@@ -244,50 +347,68 @@ def main():
args.extend(command)
ecode = subprocess.call(args, stdin=sys.stdin,
stdout=sys.stdout, stderr=sys.stderr)
elif chroot:
- print "Starting subshell in chroot, press Ctrl-D to exit..."
+ print "Starting subshell in chroot, press Ctrl D to exit..."
ecode = subprocess.call(['chroot', destmnt], stdin=sys.stdin,
stdout=sys.stdout, stderr=sys.stderr)
else:
- if dm_cow == 'live-ro':
+ if img_type in ('blk', 'dir') and dm_cow[:7] == 'live-ro':
status = ' with NO LiveOS persistence,'
else:
status = ''
- print "Entering subshell,%s press Ctrl-D to exit..." % status
+ print "Entering subshell,%s press Ctrl D to exit..." % status
ecode = subprocess.call([os.environ['SHELL']], cwd=destmnt,
stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr)
finally:
+ if verbose:
+ print """Cleaning up...
+ Please wait if large files were written."""
call(['/bin/sync'])
if not persist:
- if verbose:
- print """Cleaning up...
- Please wait if large files were written."""
if mount_hacks:
- subprocess.call(['umount', os.path.join(destmnt, 'var',
'run')])
- subprocess.call(['umount', os.path.join(destmnt, 'proc')])
+ call(['umount', os.path.join(destmnt, 'var', 'run')])
+ call(['umount', os.path.join(destmnt, 'proc')])
+ call(['umount', os.path.join(destmnt, 'dev', 'pts')])
+ call(['umount', os.path.join(destmnt, 'sys')])
+ call(['umount', os.path.join(destmnt, 'dev', 'shm')])
+ call(['umount', os.path.join(destmnt, 'run')])
+ call(['umount', os.path.join(destmnt, 'var', 'cache',
'yum')])
+ call(['umount', os.path.join(destmnt, 'etc',
'resolv.conf')])
+ call(['umount', os.path.join(destmnt, 'dev', 'mapper')])
+
if homemnt:
call(['/bin/umount', homemnt])
- call(['/sbin/losetup', '-d', homeloop])
- if img_type is 'blk':
- if mntlive:
- call(['/bin/umount', mntlive])
- os.rmdir(mntlive)
+ if homedev == os.path.join('/dev', 'mapper', 'EncHome'):
+ call(dmsetup_cmd + ['remove', 'EncHome'])
+ else:
+ call(['/sbin/losetup', '-d', homedev])
+ if mntlive:
+ call(['/bin/umount', mntlive])
+ if rmmntdir:
+ time.sleep(2)
+ os.removedirs(mntlive)
if os.path.ismount(destmnt):
+ os.chdir('..')
call(['/bin/umount', destmnt])
- if img_type is 'blk':
- m_cow:
- call(['/sbin/dmsetup', '--noudevrules', '--noudevsync',
- 'remove', dm_cow])
- if overlayloop:
- call(['/sbin/losetup', '-d', overlayloop])
+ if dm_cow:
+ #FIXME -f force option is sometimes needed when there are
+ # multiple invocations of liveimage-mount active.
+ call(dmsetup_cmd + ['remove', '-f', dm_cow])
+ if overlayloop:
+ call(['/sbin/losetup', '-d', overlayloop])
if imgloop:
call(['/sbin/losetup', '-d', imgloop])
if squashloop:
call(['/bin/umount', squashloop])
call(['/sbin/losetup', '-d', squashloop])
- call(['/bin/umount', liveosmnt])
- if not img_type is 'blk':
+ if os.path.ismount(liveosmnt):
+ call(['/bin/umount', liveosmnt])
+ if img_type is 'iso':
call(['/sbin/losetup', '-d', liveosloop])
os.rmdir(squashmnt)
- if not os.path.ismount(liveosmnt):
+ if not os.path.ismount(liveosmnt) and img_type != 'dir':
os.rmdir(liveosmnt)
+ time.sleep(2)
+ [call(['/bin/rm', '-f', loop]) for loop in extra_loops]
+ if rm_mnt is not None:
+ os.removedirs(rm_mnt)
if verbose:
print "Cleanup complete"
On Thu, Apr 14, 2011 at 12:10 PM, Frederick Grose <fgrose(a)gmail.com> wrote:
> [Patch 3/5]
> Author: Frederick Grose <fgrose(a)sugarlabs.org>
> Date: Thu Apr 14 10:37:13 2011 -0400
>
> Support usage within a booted LiveOS instance.
>
> Provide functions to add loop devices and remove then on exit, a
> LiveImageMountError(Exception) class for better error handling, and
> random device mapper names.
>
> diff --git a/tools/liveimage-mount b/tools/liveimage-mount
> index 80d67d1..1ee5b16 100755
> --- a/tools/liveimage-mount
> +++ b/tools/liveimage-mount
> @@ -23,10 +23,13 @@
> import os
> import sys
> import stat
> +import time
> import getopt
> +import random
> import tempfile
> import subprocess
>
> +extra_loops = []
>
> def usage(ecode):
> print """Usage:
> @@ -40,6 +43,18 @@ def usage(ecode):
> and [ARGS] = [arg1[ arg2[ ...]]]\n"""
> sys.exit(ecode)
>
> +class LiveImageMountError(Exception):
> + """An exception base class for all liveimage-mount errors."""
> + def __init__(self, msg):
> + Exception.__init__(self, msg)
> + def __str__(self):
> + try:
> + return str(self.message)
> + except UnicodeEncodeError:
> + return repr(self.message)
> +
> + def __unicode__(self):
> + return unicode(self.message)
>
> def call(*popenargs, **kwargs):
> '''
> @@ -62,43 +77,57 @@ def call(*popenargs, **kwargs):
> return rc
>
>
> -def rcall(args, env=None):
> +def rcall(args, stdin=None, stderr=True, env=None):
> + out, err, p, environ = None, None, None, None
> if env:
> environ = os.environ.copy()
> environ.update(env)
> - else:
> - environ = None
> try:
> - p = subprocess.Popen(args, stdout=subprocess.PIPE,
> - stderr=subprocess.PIPE, env=environ)
> - out, err = p.communicate()
> + p = subprocess.Popen(args, stdin=subprocess.PIPE, env=environ,
> + stdout=subprocess.PIPE,
> stderr=subprocess.PIPE)
> + out, err = p.communicate(stdin)
> except OSError, e:
> - raise CreatorError(u"Failed to execute:\n'%s'\n'%s'" % (args, e))
> + raise LiveImageMountError(u"Failed executing:\n'%s'\n'%s'" %
> (args, e))
> except:
> - raise CreatorError(u"""Failed to execute:\n'%s'
> - \renviron: '%s'\nstdout: '%s'\nstderr: '%s'\nreturncode:
> '%s'""" %
> - (args, environ, out, err, p.returncode))
> + raise LiveImageMountError(u"""Failed to execute:\n'%s'
> + \renviron: '%s'\nstdout: '%s'\nstderr:
> '%s'""" %
> + (args, environ, out, err))
> else:
> - if p.returncode != 0:
> - raise CreatorError(u"""Error in call:\n'%s'\nenviron: '%s'
> - \rstdout: '%s'\nstderr: '%s'\nreturncode: '%s'""" %
> - (args, environ, out, err, p.returncode))
> + if p.returncode != 0 and stderr:
> + raise LiveImageMountError(u'''Error in call:\n'%s'\nenviron:
> '%s'
> + \rstdout: %s\nstderr: %sreturncode: %s''' %
> + (args, environ, out, err, p.returncode))
> return out
>
>
> -def get_device_mountpoint(path):
> - """Return the device and mountpoint for a file or device path."""
> +def get_loop(path):
> + """Return the loop device for a given mount point path."""
> +
> + loopdevice = None
> + for loop in rcall(['/sbin/losetup', '-a']).splitlines():
> + info = loop.split()
> + if path == info[2].strip('()'):
> + loopdevice = info[0].rstrip(':')
> + break
> + return loopdevice
> +
> +
> +def add_loop(n=8):
> + """Add a loop device."""
> +
> + while os.path.exists('/dev/loop%s' % n):
> + n += 1
> + os.mknod('/dev/loop%s' % n, 0660 | stat.S_IFBLK, os.makedev(7, n))
> + extra_loops.extend(['/dev/loop%s' % n])
> + return '/dev/loop%s' % n
>
> - info = list()
> - info[0:5] = [None] * 6
> - if os.path.exists(path):
> - st_mode = os.stat(path).st_mode
> - if stat.S_ISBLK(st_mode) or os.path.ismount(path):
> - devinfo = rcall(['/bin/df', path]).splitlines()
> - info = devinfo[1].split(None)
> - if len(info) == 1:
> - info.extend(devinfo[2].split(None))
> - return [info[0], info[5]]
> +
> +def loop_setup(path):
> + """Make and associate a loop device with an image file or device."""
> +
> + loop = add_loop()
> + call(['/sbin/losetup', loop, path])
> + return loop
>
>
> def main():
> @@ -145,18 +174,16 @@ def main():
> img_type = 'blk'
> imgloop = None
> overlayloop = None
> + liveosmnt = tempfile.mkdtemp(prefix='livemnt-device-')
> else:
> img_type = 'iso'
> -
> - if img_type is 'blk':
> - liveosmnt = tempfile.mkdtemp(prefix='livemnt-device-')
> - if img_type is 'iso':
> liveosmnt = tempfile.mkdtemp(prefix='livemnt-iso-')
>
> liveosdir = os.path.join(liveosmnt, 'LiveOS')
> homemnt = None
> dm_cow = None
> mntlive = None
> + rmmntdir = None
>
> command = args[2:]
> verbose = not command
> @@ -164,13 +191,12 @@ def main():
> squashmnt = tempfile.mkdtemp(prefix='livemnt-squash-')
> squashloop = None
> imgloop = None
> - losetup_args = ['/sbin/losetup', '-f', '--show']
>
> try:
> - if img_type is 'blk':
> + if img_type == 'blk':
> call(['/bin/mount', liveos, liveosmnt])
> - elif img_type is 'iso':
> - liveosloop = rcall(losetup_args + [liveos]).rstrip()
> + elif img_type == 'iso':
> + liveosloop = loop_setup(liveos)
> call(['/bin/mount', '-o', 'ro', liveosloop, liveosmnt])
>
> squash_img = os.path.join(liveosdir, 'squashfs.img')
> @@ -182,12 +208,12 @@ def main():
> ecode = 1
> return
> else:
> - squashloop = rcall(losetup_args + [squash_img]).rstrip()
> + squashloop = loop_setup(squash_img)
> call(['/bin/mount', '-o', 'ro', squashloop, squashmnt])
> ext3_img = os.path.join(squashmnt, 'LiveOS', 'ext3fs.img')
>
> - if img_type is 'blk':
> - imgloop = rcall(losetup_args + [ext3_img]).rstrip()
> + if img_type == 'blk':
> + imgloop = loop_setup(ext3_img)
> imgsize = rcall(['/sbin/blockdev', '--getsz',
> imgloop]).rstrip()
> files = os.listdir(liveosdir)
> overlay = None
> @@ -195,18 +221,19 @@ def main():
> if f.find('overlay-') == 0:
> overlay = f
> break
> - overlayloop = rcall(['/sbin/losetup', '-f']).rstrip()
> if overlay:
> - call(['/sbin/losetup', overlayloop,
> os.path.join(liveosdir,
> -
> overlay)])
> - dm_cow = 'live-rw'
> + overlayloop = loop_setup(os.path.join(liveosdir, overlay))
> + dm_cow = "live-rw-%d-%d" % (os.getpid(),
> + random.randint(0, 2**16))
> +
> else:
> overlay = tempfile.NamedTemporaryFile(dir='/dev/shm')
> print "\npreparing temporary overlay..."
> call(['/bin/dd', 'if=/dev/null', 'of=%s' % overlay.name,
> 'bs=1024', 'count=1', 'seek=%s' % (512 * 1024)])
> - call(['/sbin/losetup', overlayloop, overlay.name])
> - dm_cow = 'live-ro'
> + overlayloop = loop_setup(overlay.name)
> + dm_cow = "live-ro-%d-%d" % (os.getpid(),
> + random.randint(0, 2**16))
> call(['/sbin/dmsetup', '--noudevrules', '--noudevsync',
> 'create', dm_cow, '--table=0 %s snapshot %s %s p 8' %
> (imgsize, imgloop, overlayloop)])
> @@ -214,14 +241,15 @@ def main():
> home_path = os.path.join(liveosdir, 'home.img')
> if os.path.exists(home_path):
> homemnt = os.path.join(destmnt, 'home')
> - homeloop = rcall(losetup_args + [home_path]).rstrip()
> + homeloop = loop_setup(home_path)
> call(['/bin/mount', homeloop, homemnt])
> mntlive = os.path.join(destmnt, 'mnt', 'live')
> if not os.path.exists(mntlive):
> os.makedirs(mntlive)
> + rmmntdir = True
> call(['/bin/mount', '--bind', liveosmnt, mntlive])
> - elif img_type is 'iso':
> - imgloop = rcall(losetup_args + [ext3_img]).rstrip()
> + elif img_type == 'iso':
> + imgloop = loop_setup(ext3_img)
> call(['/bin/mount', '-o', 'ro', imgloop, destmnt])
>
> if mount_hacks:
> @@ -232,7 +260,7 @@ def main():
> args = []
> args.extend(command)
> live = ''
> - if img_type is 'blk':
> + if img_type == 'blk':
> live = 'live-'
> print """Starting process with this command line:
> \r%s\n %s is %smounted.""" % (' '.join(command), liveos,
> live)
> @@ -247,7 +275,7 @@ def main():
> print "Starting subshell in chroot, press Ctrl-D to exit..."
> ecode = subprocess.call(['chroot', destmnt], stdin=sys.stdin,
> stdout=sys.stdout, stderr=sys.stderr)
> else:
> - if dm_cow == 'live-ro':
> + if img_type == 'blk' and dm_cow[:7] == 'live-ro':
> status = ' with NO LiveOS persistence,'
> else:
> status = ''
> @@ -268,11 +296,13 @@ def main():
> if img_type is 'blk':
> if mntlive:
> call(['/bin/umount', mntlive])
> - os.rmdir(mntlive)
> + if rmmntdir:
> + time.sleep(2)
> + os.rmdir(mntlive)
> if os.path.ismount(destmnt):
> call(['/bin/umount', destmnt])
> if img_type is 'blk':
> - m_cow:
> + if dm_cow:
> call(['/sbin/dmsetup', '--noudevrules',
> '--noudevsync',
> 'remove', dm_cow])
> if overlayloop:
> @@ -288,6 +318,10 @@ def main():
> os.rmdir(squashmnt)
> if not os.path.ismount(liveosmnt):
> os.rmdir(liveosmnt)
> + time.sleep(2)
> + for loop in extra_loops:
> + if loop:
> + call(['/bin/rm', '-f', loop])
> if verbose:
> print "Cleanup complete"
12 years, 7 months
[PATCH 1b] substitute was: [PATCH 1/5] Support Live image mounting in fs.py
by Frederick Grose
Patch 1b of 2 substitute patches to replace an earlier patch with new
features:
commit 3501e953449d17a53b669bb80bf4e96d8a8e4b25
Author: Frederick Grose <fgrose(a)sugarlabs.org>
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"):
"""
On Thu, Apr 14, 2011 at 12:02 PM, Frederick Grose <fgrose(a)gmail.com> wrote:
> [Patch 1/5]
> Author: Frederick Grose <fgrose(a)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"):
> """
12 years, 7 months
[PATCH 1a] substitutes was: [PATCH 1/5] Support Live image mounting in fs.py
by Frederick Grose
Patch 1a of 2 substitute patches to replace an earlier patch with new
features:
commit 7389913c708d3f19ca029cf3f150bbfb08a768d3
Author: Frederick Grose <fgrose(a)sugarlabs.org>
Date: Sat Sep 17 17:05:17 2011 -0400
Enable mount options, particularly 'read-only', for greater safety.
Provide parameters for mounting options, and code to recognize and
implement various 'read-only' flag possibilities.
diff --git a/imgcreate/fs.py b/imgcreate/fs.py
index 69fb5f1..e71032e 100644
--- a/imgcreate/fs.py
+++ b/imgcreate/fs.py
@@ -122,9 +122,10 @@ def e2fsck(fs):
class BindChrootMount:
"""Represents a bind mount of a directory into a chroot."""
- def __init__(self, src, chroot, dest = None):
+ def __init__(self, src, chroot, dest=None, ops=None):
self.src = src
self.root = chroot
+ self.ops = ops
if not dest:
dest = src
@@ -132,17 +133,35 @@ class BindChrootMount:
self.mounted = False
- def mount(self):
+ def mount(self, ops=None):
if self.mounted:
return
makedirs(self.dest)
- rc = call(["/bin/mount", "--bind", self.src, self.dest])
+ args = ['/bin/mount', '--bind', self.src, self.dest]
+ rc = call(args)
if rc != 0:
raise MountError("Bind-mounting '%s' to '%s' failed" %
(self.src, self.dest))
+ if ops is None:
+ ops = self.ops
+ if ops in (['-o', 'remount,ro'], 'remount,ro,bind', 'remount,ro',
+ ['-o', 'ro'], ['ro'], ['-r'], 'ro', '-r'):
+ self.remount('ro')
+
self.mounted = True
+ def remount(self, ops):
+ if not self.mounted:
+ return
+
+ remount_ops = ''.join(('remount,', ops))
+ args = ['/bin/mount', '-o', remount_ops, self.dest]
+ rc = call(args)
+ if rc != 0:
+ raise MountError("%s of '%s' to '%s' failed." %
+ (remount_ops, self.src, self.dest))
+
def unmount(self):
if not self.mounted:
return
@@ -161,9 +180,11 @@ class BindChrootMount:
class LoopbackMount:
"""LoopbackMount compatibility layer for old API"""
- def __init__(self, lofile, mountdir, fstype = None):
- self.diskmount = DiskMount(LoopbackDisk(lofile,size =
0),mountdir,fstype,rmmountdir = True)
+ def __init__(self, lofile, mountdir, fstype=None, ops=None):
+ self.diskmount = DiskMount(LoopbackDisk(lofile, size=0), mountdir,
+ fstype, rmmountdir=True, ops=None)
self.losetup = False
+ self.ops = ops
def cleanup(self):
self.diskmount.cleanup()
@@ -177,7 +198,7 @@ class LoopbackMount:
self.losetup = False
self.loopdev = None
- def loopsetup(self):
+ def loopsetup(self, ops=None):
if self.losetup:
return
@@ -191,15 +212,22 @@ class LoopbackMount:
self.loopdev = losetupOutput.split()[0]
- rc = call(["/sbin/losetup", self.loopdev, self.lofile])
+ args = ['/sbin/losetup', self.loopdev, self.lofile]
+ if ops is None:
+ ops = self.ops
+ if ops in (['-o', 'ro'], ['ro'], ['-r'], 'ro', '-r'):
+ ops = ['-r']
+ # This is the only additional option supported, so far.
+ args += ops
+ rc = call(args)
if rc != 0:
raise MountError("Failed to allocate loop device for '%s'" %
self.lofile)
self.losetup = True
- def mount(self):
- self.diskmount.mount()
+ def mount(self, ops=None):
+ self.diskmount.mount(ops)
class SparseLoopbackMount(LoopbackMount):
"""SparseLoopbackMount compatibility layer for old API"""
@@ -290,9 +318,10 @@ class RawDisk(Disk):
class LoopbackDisk(Disk):
"""A Disk backed by a file via the loop module."""
- def __init__(self, lofile, size):
+ def __init__(self, lofile, size, ops=None):
Disk.__init__(self, size)
self.lofile = lofile
+ self.ops = ops
def fixed(self):
return False
@@ -300,7 +329,7 @@ class LoopbackDisk(Disk):
def exists(self):
return os.path.exists(self.lofile)
- def create(self):
+ def create(self, ops=None):
if self.device is not None:
return
@@ -313,9 +342,16 @@ class LoopbackDisk(Disk):
self.lofile)
device = losetupOutput.split()[0]
+ args = ['/sbin/losetup', device, self.lofile]
+ if ops is None:
+ ops = self.ops
+ if ops in (['-o', 'ro'], ['ro'], ['-r'], 'ro', '-r'):
+ ops = ['-r']
+ # This is the only additional option supported, so far.
+ args += ops
logging.info("Losetup add %s mapping to %s" % (device,
self.lofile))
- rc = call(["/sbin/losetup", device, self.lofile])
+ rc = call(args)
if rc != 0:
raise MountError("Failed to allocate loop device for '%s'" %
self.lofile)
@@ -329,11 +365,10 @@ 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):
- LoopbackDisk.__init__(self, lofile, size)
+ def __init__(self, lofile, size, ops=None):
+ LoopbackDisk.__init__(self, lofile, size, ops=None)
def expand(self, create = False, size = None):
flags = os.O_WRONLY
@@ -362,9 +397,9 @@ class SparseLoopbackDisk(LoopbackDisk):
os.ftruncate(fd, size)
os.close(fd)
- def create(self):
+ def create(self, ops=None):
self.expand(create = True)
- LoopbackDisk.create(self)
+ LoopbackDisk.create(self, ops=None)
class Mount:
"""A generic base class to deal with mounting things."""
@@ -382,15 +417,17 @@ 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
self.rmdir = False
+ self.created = False
def cleanup(self):
Mount.cleanup(self)
@@ -420,12 +457,12 @@ class DiskMount(Mount):
pass
self.rmdir = False
-
def __create(self):
- self.disk.create()
-
+ if not self.created:
+ self.disk.create()
+ self.created = True
- def mount(self):
+ def mount(self, ops=None):
if self.mounted:
return
@@ -440,6 +477,10 @@ class DiskMount(Mount):
args = [ "/bin/mount", self.disk.device, self.mountdir ]
if self.fstype:
args.extend(["-t", self.fstype])
+ if ops is None:
+ ops = self.ops
+ if ops is not None:
+ args.extend(['-o', ops])
rc = call(args)
if rc != 0:
@@ -448,6 +489,17 @@ class DiskMount(Mount):
self.mounted = True
+ def remount(self, ops):
+ if not self.mounted:
+ return
+
+ remount_ops = ''.join(('remount,', ops))
+ args = ['/bin/mount', '-o', remount_ops, self.mountdir]
+ rc = call(args)
+ if rc != 0:
+ raise MountError("%s of '%s' to '%s' failed." %
+ (remount_ops, self.disk.device,
self.mountdir))
+
class ExtDiskMount(DiskMount):
"""A DiskMount object that is able to format/resize ext[23]
filesystems."""
def __init__(self, disk, mountdir, fstype, blocksize, fslabel,
@@ -456,6 +508,7 @@ class ExtDiskMount(DiskMount):
self.blocksize = blocksize
self.fslabel = "_" + fslabel
self.tmpdir = tmpdir
+ self.created = False
def __format_filesystem(self):
logging.info("Formating %s filesystem on %s" % (self.fstype,
self.disk.device))
@@ -487,6 +540,8 @@ class ExtDiskMount(DiskMount):
return size
def __create(self):
+ if self.created:
+ return
resize = False
if not self.disk.fixed() and self.disk.exists():
resize = True
@@ -498,6 +553,8 @@ class ExtDiskMount(DiskMount):
else:
self.__format_filesystem()
+ self.created = True
+
def mount(self):
self.__create()
DiskMount.mount(self)
@@ -535,10 +592,12 @@ class ExtDiskMount(DiskMount):
self.__resize_filesystem(size)
return minsize
+
class DeviceMapperSnapshot(object):
- def __init__(self, imgloop, cowloop):
+ def __init__(self, imgloop, cowloop, ops=None):
self.imgloop = imgloop
self.cowloop = cowloop
+ self.ops = ops
self.__created = False
self.__name = None
@@ -546,15 +605,16 @@ 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)
- def create(self):
+ def create(self, ops=None):
if self.__created:
return
- self.imgloop.create()
- self.cowloop.create()
+ self.imgloop.create(self.ops)
+ self.cowloop.create(self.ops)
self.__name = "imgcreate-%d-%d" % (os.getpid(),
random.randint(0, 2**16))
@@ -567,13 +627,22 @@ class DeviceMapperSnapshot(object):
args = ["/sbin/dmsetup", "create", self.__name,
"--uuid", "LIVECD-%s" % self.__name, "--table", table]
+ if ops is None:
+ ops = self.ops
+ if ops in (['-o', 'ro'], ['ro'], ['-r'], 'ro', '-r',
+ ['--readonly'], '--readonly'):
+ ops = ['--readonly']
+ # This is the only additional option supported, so far.
+ args += ops
if call(args) != 0:
+ time.sleep(1)
self.cowloop.cleanup()
self.imgloop.cleanup()
raise SnapshotError("Could not create snapshot device using: "
+
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:
On Thu, Apr 14, 2011 at 12:02 PM, Frederick Grose <fgrose(a)gmail.com> wrote:
> [Patch 1/5]
> Author: Frederick Grose <fgrose(a)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"):
> """
12 years, 7 months
[PATCH] Enable resize and squashing progress reporting option.
by Frederick Grose
The following patch will support better user feedback for
customization scripts, such as edit-livecd.
commit 44cdc19b436008f03af3c1c4f5c82fa0ce8a26e6
Author: Frederick Grose <fgrose(a)sugarlabs.org>
Date: Sat Sep 17 12:35:03 2011 -0400
Enable resize and squashing progress reporting option.
Provide optional parameter to package(), _stage_final_image(), and
mksquashfs() and 'show-squashing' code to mksquashfs() to permit
progress reporting to the terminal.
Insert the '-p' option for percentage completion reporting in the
resize2fs call arguments.
diff --git a/imgcreate/creator.py b/imgcreate/creator.py
index deb9d95..a6a1b39 100644
--- a/imgcreate/creator.py
+++ b/imgcreate/creator.py
@@ -729,7 +729,7 @@ class ImageCreator(object):
"""
subprocess.call(["/bin/bash"], preexec_fn = self._chroot)
- def package(self, destdir = "."):
+ def package(self, destdir = ".", ops=None):
"""Prepares the created image for final delivery.
In its simplest form, this method merely copies the install root to
the
@@ -740,8 +740,11 @@ class ImageCreator(object):
destdir -- the directory into which the final image should be
moved;
this defaults to the current directory.
+ ops -- options, e.g., 'show-squashing', passed to subsequent
+ procedures.
+
"""
- self._stage_final_image()
+ self._stage_final_image(ops)
for f in os.listdir(self._outdir):
shutil.move(os.path.join(self._outdir, f),
diff --git a/imgcreate/fs.py b/imgcreate/fs.py
index a387f51..69fb5f1 100644
--- a/imgcreate/fs.py
+++ b/imgcreate/fs.py
@@ -70,7 +70,7 @@ def squashfs_compression_type(sqfs_img):
break
return compress_type
-def mksquashfs(in_img, out_img, compress_type):
+def mksquashfs(in_img, out_img, compress_type, ops=None):
# Allow gzip to work for older versions of mksquashfs
if compress_type == "gzip":
args = ["/sbin/mksquashfs", in_img, out_img]
@@ -80,11 +80,18 @@ def mksquashfs(in_img, out_img, compress_type):
if not sys.stdout.isatty():
args.append("-no-progress")
- ret = call(args)
+ if ops == 'show-squashing':
+ p = subprocess.Popen(args, stdout=None, stderr=subprocess.STDOUT)
+ p.wait()
+ ret = p.returncode
+ else:
+ ret = call(args)
+
if ret != 0:
raise SquashfsError("'%s' exited with error (%d)" %
(string.join(args, " "), ret))
+
def resize2fs(fs, size = None, minimal = False, tmpdir = "/tmp"):
if minimal and size is not None:
raise ResizeError("Can't specify both minimal and a size for
resize!")
@@ -94,7 +101,7 @@ def resize2fs(fs, size = None, minimal = False, tmpdir =
"/tmp"):
e2fsck(fs)
logging.info("resizing %s" % (fs,))
- args = ["/sbin/resize2fs", fs]
+ args = ["/sbin/resize2fs", '-p', fs]
if minimal:
args.append("-M")
else:
diff --git a/imgcreate/live.py b/imgcreate/live.py
index 721b609..7aff50d 100755
--- a/imgcreate/live.py
+++ b/imgcreate/live.py
@@ -320,7 +320,7 @@ class LiveImageCreatorBase(LoopImageCreator):
subprocess.call([implantisomd5, iso])
- def _stage_final_image(self):
+ def _stage_final_image(self, ops=None):
try:
makedirs(self.__ensure_isodir() + "/LiveOS")
@@ -343,7 +343,7 @@ class LiveImageCreatorBase(LoopImageCreator):
"LiveOS", "ext3fs.img"))
mksquashfs(os.path.dirname(self._image),
self.__isodir + "/LiveOS/squashfs.img",
- self.compress_type)
+ self.compress_type, ops)
if os.stat(self.__isodir + "/LiveOS/squashfs.img").st_size
>= 4*1024*1024*1024:
self._isofstype = "udf"
logging.warn("Switching to UDF due to size of
LiveOS/squashfs.img")
12 years, 7 months
Changes to 'refs/tags/livecd-tools-16.6'
by Brian C. Lane
Tag 'livecd-tools-16.6' created by Brian C. Lane <bcl(a)redhat.com> at 2011-09-14 17:56 +0000
Tag as livecd-tools-16.6
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
iQEVAwUATnDquRF+jBaO/jp/AQIdnQf/cqek3pusf0TRUHF44bRRty71Y5DN2P2A
zg2Mf4AYkatsKyAiSK5fLnFmw0R8Fazrcha7xewSEnxUzs+blRuqjDIf7OBquQbu
4AvOZJc+ditE2ATKBBptyHy0bjoUbvWGalXy1G4SFyaBiFaSqQLMbB90qxU9TGyE
BCd6Gk7dORRmVLdwzzA3LLwDFN4MJr5HFaYKkjGl6U7tVmKGrHeRemzVeo+iYRmc
AZKZPY5PDYtP7KdV+1owX4VQ54zq57d54nkWsmcLSUuFCcjFh5p204kgnqGEw8vI
cBpGqiEppmkJIvgKlPO6XiYkhruA8FPXax8ZMm3HgAHLrRv/gQGxkw==
=RL/c
-----END PGP SIGNATURE-----
Changes since livecd-tools-16.5:
Brian C. Lane (4):
splash is now png (#738381)
Correct some syslinux typos (#738381)
Stop creating backup image before resizing (#737243)
Version 16.6
---
Makefile | 2 +-
imgcreate/fs.py | 16 +++++++---------
imgcreate/live.py | 33 +++++++++++++++------------------
3 files changed, 23 insertions(+), 28 deletions(-)
---
12 years, 7 months
Branch 'f16-branch' - 4 commits - imgcreate/fs.py imgcreate/live.py Makefile
by Brian C. Lane
Makefile | 2 +-
imgcreate/fs.py | 16 +++++++---------
imgcreate/live.py | 33 +++++++++++++++------------------
3 files changed, 23 insertions(+), 28 deletions(-)
New commits:
commit d457ef30d52d35d7633d887b6103c93f587855e1
Author: Brian C. Lane <bcl(a)redhat.com>
Date: Wed Sep 14 10:55:45 2011 -0700
Version 16.6
diff --git a/Makefile b/Makefile
index 14ffbd7..b64ecd7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
-VERSION = 16.5
+VERSION = 16.6
INSTALL = /usr/bin/install -c
INSTALL_PROGRAM = ${INSTALL}
commit ba41cae95d4cf0fc5abc439cbc6096819a277fd7
Author: Brian C. Lane <bcl(a)redhat.com>
Date: Tue Sep 13 14:55:00 2011 -0700
Stop creating backup image before resizing (#737243)
diff --git a/imgcreate/fs.py b/imgcreate/fs.py
index d5307a2..a387f51 100644
--- a/imgcreate/fs.py
+++ b/imgcreate/fs.py
@@ -92,10 +92,8 @@ def resize2fs(fs, size = None, minimal = False, tmpdir = "/tmp"):
raise ResizeError("Must specify either a size or minimal for resize!")
e2fsck(fs)
- (fd, saved_image) = tempfile.mkstemp("", "resize-image-", tmpdir)
- os.close(fd)
- call(["/sbin/e2image", "-r", fs, saved_image])
+ logging.info("resizing %s" % (fs,))
args = ["/sbin/resize2fs", fs]
if minimal:
args.append("-M")
@@ -103,17 +101,17 @@ def resize2fs(fs, size = None, minimal = False, tmpdir = "/tmp"):
args.append("%sK" %(size / 1024,))
ret = call(args)
if ret != 0:
- raise ResizeError("resize2fs returned an error (%d)! image to debug at %s" %(ret, saved_image))
+ raise ResizeError("resize2fs returned an error (%d)!" % (ret,))
+
+ ret = e2fsck(fs)
+ if ret != 0:
+ raise ResizeError("fsck after resize returned an error (%d)!", (ret,))
- if e2fsck(fs) != 0:
- raise ResizeError("fsck after resize returned an error! image to debug at %s" %(saved_image,))
- os.unlink(saved_image)
return 0
def e2fsck(fs):
logging.info("Checking filesystem %s" % fs)
- rc = call(["/sbin/e2fsck", "-f", "-y", fs])
- return rc
+ return call(["/sbin/e2fsck", "-f", "-y", fs])
class BindChrootMount:
"""Represents a bind mount of a directory into a chroot."""
commit 7db0bde27d07905e067723cce21085c7c53cd0f7
Author: Brian C. Lane <bcl(a)redhat.com>
Date: Wed Sep 14 10:23:55 2011 -0700
Correct some syslinux typos (#738381)
diff --git a/imgcreate/live.py b/imgcreate/live.py
index 87151c2..2aa8ab6 100755
--- a/imgcreate/live.py
+++ b/imgcreate/live.py
@@ -570,7 +570,7 @@ menu separator
long = "Start " + long + " in ^basic graphics mode.",
short = "basic" + index,
extra = "xdriver=vesa nomodeset",
- help = "Try this option out if you're having trouble starting.",
+ help = "Try this option out if you're having trouble installing " + long + ".",
index = index))
if checkisomd5:
@@ -600,7 +600,7 @@ menu separator
return """label memtest
menu label Run a ^memory test.
text help
- If your system is having issues, an problem with your
+ If your system is having issues, a problem with your
system's memory may be the cause. Use this utility to
see if the memory is working correctly.
endtext
commit a3c11ee33ca60c525d16c35247060730124d2b50
Author: Brian C. Lane <bcl(a)redhat.com>
Date: Wed Sep 14 10:02:37 2011 -0700
splash is now png (#738381)
Search for the new background image first, falling back to the previous
locations if it isn't found.
diff --git a/imgcreate/live.py b/imgcreate/live.py
index 721b609..87151c2 100755
--- a/imgcreate/live.py
+++ b/imgcreate/live.py
@@ -402,21 +402,20 @@ class x86LiveImageCreator(LiveImageCreatorBase):
shutil.copy(path, isodir + "/isolinux/")
- def __copy_syslinux_background(self, isodest):
- background_path = self._instroot + \
- "/usr/share/anaconda/boot/syslinux-vesa-splash.jpg"
-
- if not os.path.exists(background_path):
- # fallback to F13 location
- background_path = self._instroot + \
- "/usr/lib/anaconda-runtime/syslinux-vesa-splash.jpg"
-
- if not os.path.exists(background_path):
- return False
+ def __copy_syslinux_background(self, isodir):
+ """ Find the correct splash image, copy it to the destination and
+ return the name of the file.
+ """
+ bg_list = [ ("/usr/share/anaconda/boot/splash.png", "splash.png"),
+ ("/usr/share/anaconda/boot/syslinux-vesa-splash.jpg", "splash.jpg"),
+ ("/usr/lib/anaconda-runtime/syslinux-vesa-splash.jpg", "splash.jpg")]
- shutil.copyfile(background_path, isodest)
+ for bg_path, bg_name in bg_list:
+ if os.path.exists(bg_path):
+ shutil.copyfile(bg_path, isodir + bg_name)
+ return bg_name
- return True
+ return ""
def __copy_kernel_and_initramfs(self, isodir, version, index):
bootdir = self._instroot + "/boot"
@@ -623,9 +622,7 @@ menu separator
self.__copy_syslinux_files(isodir, menu,
self.__find_syslinux_mboot())
- background = ""
- if self.__copy_syslinux_background(isodir + "/isolinux/splash.jpg"):
- background = "splash.jpg"
+ background = self.__copy_syslinux_background(isodir + "/isolinux/")
cfg = self.__get_basic_syslinux_config(menu = menu,
background = background,
12 years, 7 months
imgcreate/fs.py
by Brian C. Lane
imgcreate/fs.py | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
New commits:
commit f5477c71b3c362ed1ba28d2739e7c4cae93523da
Author: Brian C. Lane <bcl(a)redhat.com>
Date: Tue Sep 13 14:55:00 2011 -0700
Stop creating backup image before resizing (#737243)
diff --git a/imgcreate/fs.py b/imgcreate/fs.py
index d5307a2..a387f51 100644
--- a/imgcreate/fs.py
+++ b/imgcreate/fs.py
@@ -92,10 +92,8 @@ def resize2fs(fs, size = None, minimal = False, tmpdir = "/tmp"):
raise ResizeError("Must specify either a size or minimal for resize!")
e2fsck(fs)
- (fd, saved_image) = tempfile.mkstemp("", "resize-image-", tmpdir)
- os.close(fd)
- call(["/sbin/e2image", "-r", fs, saved_image])
+ logging.info("resizing %s" % (fs,))
args = ["/sbin/resize2fs", fs]
if minimal:
args.append("-M")
@@ -103,17 +101,17 @@ def resize2fs(fs, size = None, minimal = False, tmpdir = "/tmp"):
args.append("%sK" %(size / 1024,))
ret = call(args)
if ret != 0:
- raise ResizeError("resize2fs returned an error (%d)! image to debug at %s" %(ret, saved_image))
+ raise ResizeError("resize2fs returned an error (%d)!" % (ret,))
+
+ ret = e2fsck(fs)
+ if ret != 0:
+ raise ResizeError("fsck after resize returned an error (%d)!", (ret,))
- if e2fsck(fs) != 0:
- raise ResizeError("fsck after resize returned an error! image to debug at %s" %(saved_image,))
- os.unlink(saved_image)
return 0
def e2fsck(fs):
logging.info("Checking filesystem %s" % fs)
- rc = call(["/sbin/e2fsck", "-f", "-y", fs])
- return rc
+ return call(["/sbin/e2fsck", "-f", "-y", fs])
class BindChrootMount:
"""Represents a bind mount of a directory into a chroot."""
12 years, 7 months
Changes to 'refs/tags/livecd-tools-16.5'
by Brian C. Lane
Tag 'livecd-tools-16.5' created by Brian C. Lane <bcl(a)redhat.com> at 2011-09-01 18:58 +0000
Tag as livecd-tools-16.5
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
iQEVAwUATl/VvxF+jBaO/jp/AQJKxwf/bJOb4Ed2gtmobE0abnL0YNqLkDTUyXGh
2FGxeHQ6Aj7xZhtCATIFBGw3l/sEpfvYTSA3LzC2YLkoWywcN0DO8c/i4/4ex33d
Bq3MpCBbK+o91Hu/baGKVilHAs3R/RMtb4WN6Gb5mTvrEM5EuVrG2xkyu36HYUt0
Sb8FKOiuDexpdKHWqW1f9S/CDSzoSSc8UKAQpm1uqdzlehg0xsF8wHPCHsRbluPY
9cXk4f20U8nWk6dIUQFc1HxZkjT5aJrjgpEcjt5LCfAAP322afc2hMOQFl8MQZLV
liBqXb23sBRt3duh8ZCwJh8CpsrzgWpCoWZsDFRoPJHq7NDfAPfkxw==
=JGj5
-----END PGP SIGNATURE-----
Changes since livecd-tools-16.3:
Brian C. Lane (13):
Copy updates and product image files
Modify pxeboot script to work with F16
Ensure previous filesystems are wiped when formatting (#712553)
Make MBR replacement message more clear
Don't ask about replacing MBR when formatting
Turn on the legacy_boot flag for EFI (#680563)
Use rsync to copy if available
Use copyFile on the iso
Version 16.4
Add new syslinux.cfg template (#734173)
Skip bind mounts when source isn't there
Add title and product args (#669120)
Version 16.5
Bruno Wolff III (1):
Quote $SRC so iso's with spaces will work (#694915)
Daniel Walsh (1):
Handle move to /sys/fs/selinux (#728576)
Martin Langhoff (1):
Add initial support for ARM architectures
---
Makefile | 2
imgcreate/creator.py | 75 ++++++-------------
imgcreate/kickstart.py | 3
imgcreate/live.py | 154 +++++++++++++++++++++++++++--------------
tools/livecd-creator | 25 ++++++
tools/livecd-iso-to-disk.sh | 44 +++++++----
tools/livecd-iso-to-pxeboot.sh | 20 +++--
7 files changed, 197 insertions(+), 126 deletions(-)
---
12 years, 8 months
Branch 'f16-branch' - Makefile
by Brian C. Lane
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
New commits:
commit 2d73993f3604107ef50da17423a39fc2be497b0e
Author: Brian C. Lane <bcl(a)redhat.com>
Date: Thu Sep 1 11:57:47 2011 -0700
Version 16.5
diff --git a/Makefile b/Makefile
index 7cc3d23..14ffbd7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
-VERSION = 16.4
+VERSION = 16.5
INSTALL = /usr/bin/install -c
INSTALL_PROGRAM = ${INSTALL}
12 years, 8 months