import StringIO
from image_creator import __version__ as version
-from image_creator.util import MD5
+from image_creator.util import MD5, FatalError
from image_creator.output.dialog import GaugeOutput, InfoBoxOutput
from image_creator.kamaki_wrapper import Kamaki, ClientError
from image_creator.help import get_help_file
try:
image.out.add(infobox)
try:
- image.mount(readonly=False)
- try:
- err = "Unable to execute the system preparation " \
- "tasks. Couldn't mount the media%s."
- title = "System Preparation"
- if not image.mounted:
- d.msgbox(err % "", title=title, width=SMALL_WIDTH)
- return
- elif image.mounted_ro:
- d.msgbox(err % " read-write", title=title,
- width=SMALL_WIDTH)
- return
-
- # The checksum is invalid. We have mounted the image rw
- if 'checksum' in session:
- del session['checksum']
-
- # Monitor the metadata changes during syspreps
- with MetadataMonitor(session, image.os.meta):
+ # The checksum is invalid. We have mounted the image rw
+ if 'checksum' in session:
+ del session['checksum']
+
+ # Monitor the metadata changes during syspreps
+ with MetadataMonitor(session, image.os.meta):
+ try:
image.os.do_sysprep()
infobox.finalize()
-
- finally:
- image.umount()
+ except FatalError as e:
+ title = "System Preparation"
+ d.msgbox("System Preparation failed: %s" % e,
+ title=title, width=SMALL_WIDTH)
finally:
image.out.remove(infobox)
finally:
out.clear()
#Sysprep
- image.mount(False)
- err_msg = "Unable to execute the system preparation tasks."
- if not image.mounted:
- raise FatalError("%s Couldn't mount the media." % err_msg)
- elif image.mounted_ro:
- raise FatalError("%s Couldn't mount the media read-write."
- % err_msg)
image.os.do_sysprep()
metadata = image.os.meta
- image.umount()
#Shrink
size = image.shrink()
self.progress_bar = None
self.guestfs_device = None
self.size = 0
- self.mounted = False
- self.mounted_ro = False
self.g = guestfs.GuestFS()
self.g.add_drive_opts(self.device, readonly=0, format="raw")
if not self.guestfs_enabled:
self.enable()
- if not self.mounted:
- do_unmount = True
- self.mount(readonly=True)
- else:
- do_unmount = False
-
- try:
- cls = os_cls(self.distro, self.ostype)
- self._os = cls(self.root, self.g, self.out)
+ cls = os_cls(self.distro, self.ostype)
+ self._os = cls(self.root, self.g, self.out)
- finally:
- if do_unmount:
- self.umount()
+ self._os.collect_metadata()
return self._os
#
# self.progressbar.goto((position * 100) // total)
- def mount(self, readonly=False):
- """Mount all disk partitions in a correct order."""
-
- msg = "Mounting the media%s ..." % (" read-only" if readonly else "")
- self.out.output(msg, False)
-
- #If something goes wrong when mounting rw, remount the filesystem ro
- remount_ro = False
- rw_mpoints = ('/', '/etc', '/root', '/home', '/var')
-
- # Sort the keys to mount the fs in a correct order.
- # / should be mounted befor /boot, etc
- def compare(a, b):
- if len(a[0]) > len(b[0]):
- return 1
- elif len(a[0]) == len(b[0]):
- return 0
- else:
- return -1
- mps = self.g.inspect_get_mountpoints(self.root)
- mps.sort(compare)
-
- mopts = 'ro' if readonly else 'rw'
- for mp, dev in mps:
- if self.ostype == 'freebsd':
- # libguestfs can't handle correct freebsd partitions on GUID
- # Partition Table. We have to do the translation to linux
- # device names ourselves
- m = re.match('^/dev/((?:ada)|(?:vtbd))(\d+)p(\d+)$', dev)
- if m:
- m2 = int(m.group(2))
- m3 = int(m.group(3))
- dev = '/dev/sd%c%d' % (chr(ord('a') + m2), m3)
- try:
- self.g.mount_options(mopts, dev, mp)
- except RuntimeError as msg:
- if self.ostype == 'freebsd':
- freebsd_mopts = "ufstype=ufs2,%s" % mopts
- try:
- self.g.mount_vfs(freebsd_mopts, 'ufs', dev, mp)
- except RuntimeError as msg:
- if readonly is False and mp in rw_mpoints:
- remount_ro = True
- break
- elif readonly is False and mp in rw_mpoints:
- remount_ro = True
- break
- else:
- self.out.warn("%s (ignored)" % msg)
- if remount_ro:
- self.out.warn("Unable to mount %s read-write. "
- "Remounting everything read-only..." % mp)
- self.umount()
- self.mount(True)
- else:
- self.mounted = True
- self.mounted_ro = readonly
- self.out.success("done")
-
- def umount(self):
- """Umount all mounted filesystems."""
- self.g.umount_all()
- self.mounted = False
-
def _last_partition(self):
"""Return the last partition of the image disk"""
if self.meta['PARTITION_TABLE'] not in 'msdos' 'gpt':
image = disk.get_image(snapshot)
- # If no customization is to be done, the image should be mounted ro
- ro = (not (options.sysprep or options.shrink) or options.print_sysprep)
- image.mount(ro)
- try:
- for sysprep in options.disabled_syspreps:
- image.os.disable_sysprep(image.os.get_sysprep_by_name(sysprep))
+ for sysprep in options.disabled_syspreps:
+ image.os.disable_sysprep(image.os.get_sysprep_by_name(sysprep))
- for sysprep in options.enabled_syspreps:
- image.os.enable_sysprep(image.os.get_sysprep_by_name(sysprep))
+ for sysprep in options.enabled_syspreps:
+ image.os.enable_sysprep(image.os.get_sysprep_by_name(sysprep))
- if options.print_sysprep:
- image.os.print_syspreps()
- out.output()
+ if options.print_sysprep:
+ image.os.print_syspreps()
+ out.output()
+
+ if options.outfile is None and not options.upload:
+ return 0
+
+ if options.sysprep:
+ image.os.do_sysprep()
- if options.outfile is None and not options.upload:
- return 0
-
- if options.sysprep:
- err_msg = "Unable to perform the system preparation tasks. " \
- "Couldn't mount the media%s. Use --no-sysprep if you " \
- "don't won't to perform any system preparation task."
- if not image.mounted:
- raise FatalError(err_msg % "")
- elif image.mounted_ro:
- raise FatalError(err_msg % " read-write")
- image.os.do_sysprep()
-
- metadata = image.os.meta
- finally:
- image.umount()
+ metadata = image.os.meta
size = options.shrink and image.shrink() or image.size
metadata.update(image.meta)
self.root = rootdev
self.g = ghandler
self.out = output
-
- # Collect metadata about the OS
self.meta = {}
+
+ def collect_metadata(self):
+ """Collect metadata about the OS"""
+
+ try:
+ if not self.mount(readonly=True):
+ raise FatalError("Unable to mount the media read-only")
+
+ self.out.output('Collecting image metadata ...', False)
+ self._do_collect_metadata()
+ self.out.success('done')
+ finally:
+ self.umount()
+
+ def _do_collect_metadata(self):
+
self.meta['ROOT_PARTITION'] = "%d" % self.g.part_to_partnum(self.root)
self.meta['OSFAMILY'] = self.g.inspect_get_type(self.root)
self.meta['OS'] = self.g.inspect_get_distro(self.root)
def do_sysprep(self):
"""Prepere system for image creation."""
- self.out.output('Preparing system for image creation:')
+ try:
+ if not self.mount(readonly=False):
+ raise FatalError("Unable to mount the media read-write")
+
+ self.out.output('Preparing system for image creation:')
+
+ tasks = self.list_syspreps()
+ enabled = filter(lambda x: x.enabled, tasks)
+
+ size = len(enabled)
+ cnt = 0
+ for task in enabled:
+ cnt += 1
+ self.out.output(('(%d/%d)' % (cnt, size)).ljust(7), False)
+ task()
+ setattr(task.im_func, 'executed', True)
+ self.out.output()
+ finally:
+ self.umount()
+
+ def _do_mount(self, readonly):
+ try:
+ self.g.mount_options('ro' if readonly else 'rw', self.root, '/')
+ except RuntimeError as msg:
+ self.out.warn("unable to mount the root partition: %s" % msg)
+ return False
+
+ return True
+
+ def mount(self, readonly=False):
+ """Mount image."""
+
+ if getattr(self, "mounted", False):
+ return True
+
+ mount_type = 'read-only' if readonly else 'read-write'
+ self.out.output("Mount the media %s ..." % mount_type, False)
+
+ if not self._do_mount(readonly):
+ return False
- tasks = self.list_syspreps()
- enabled = filter(lambda x: x.enabled, tasks)
+ self.mounted = True
+ self.out.success('done')
+ return True
- size = len(enabled)
- cnt = 0
- for task in enabled:
- cnt += 1
- self.out.output(('(%d/%d)' % (cnt, size)).ljust(7), False)
- task()
- setattr(task.im_func, 'executed', True)
- self.out.output()
+ def umount(self):
+ """Umount all mounted filesystems."""
+ self.g.umount_all()
+ self.mounted = False
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :
def __init__(self, rootdev, ghandler, output):
super(Freebsd, self).__init__(rootdev, ghandler, output)
+ def _do_collect_metadata(self):
+
+ super(Freebsd, self)._do_collect_metadata()
self.meta["USERS"] = " ".join(self._get_passworded_users())
#The original product name key is long and ugly
return users
+ def _do_mount(self, readonly):
+ """Mount partitions in the correct order"""
+
+ critical_mpoints = ('/', '/etc', '/root', '/home', '/var')
+
+ # libguestfs can't handle correct freebsd partitions on GUID
+ # Partition Table. We have to do the translation to linux
+ # device names ourselves
+ guid_device = re.compile('^/dev/((?:ada)|(?:vtbd))(\d+)p(\d+)$')
+
+ mopts = "ufstype=ufs2,%s" % ('ro' if readonly else 'rw')
+ for mp, dev in self._mountpoints():
+ match = guid_device.match(dev)
+ if match:
+ m2 = int(match.group(2))
+ m3 = int(match.group(3))
+ dev = '/dev/sd%c%d' % (chr(ord('a') + m2), m3)
+ try:
+ self.g.mount_vfs(mopts, 'ufs', dev, mp)
+ except RuntimeError as msg:
+ if mp in critical_mpoints:
+ self.out.warn('unable to mount %s. Reason: %s' % (mp, msg))
+ return False
+ else:
+ self.out.warn('%s (ignored)' % msg)
+
+ return True
+
@sysprep()
def cleanup_password(self, print_header=True):
"""Remove all passwords and lock all user accounts"""
self._uuid = dict()
self._persistent = re.compile('/dev/[hsv]d[a-z][1-9]*')
+ def _do_collect_metadata(self):
+ """Collect metadata about the OS"""
+
+ super(Linux, self)._do_collect_metadata()
self.meta["USERS"] = " ".join(self._get_passworded_users())
# Delete the USERS metadata if empty
def __init__(self, rootdev, ghandler, output):
super(Ubuntu, self).__init__(rootdev, ghandler, output)
+ def _do_collect_metadata(self):
+ """Collect metadata about the OS"""
+
+ super(Ubuntu, self)._do_collect_metadata()
apps = self.g.inspect_list_applications(self.root)
for app in apps:
if app['app_name'] == 'kubuntu-desktop':
'.kamaki.history'
]
- def __init__(self, rootdev, ghandler, output):
- super(Unix, self).__init__(rootdev, ghandler, output)
+ def _mountpoints(self):
+ """Return mountpoints in the correct order.
+ / should be mounted before /boot or /usr, /usr befor /usr/bin ...
+ """
+ mps = self.g.inspect_get_mountpoints(self.root)
+
+ def compare(a, b):
+ if len(a[0]) > len(b[0]):
+ return 1
+ elif len(a[0]) == len(b[0]):
+ return 0
+ else:
+ return -1
+ mps.sort(compare)
+
+ for mp in mps:
+ yield mp
+
+ def _do_mount(self, readonly):
+ """Mount partitions in the correct order"""
+
+ critical_mpoints = ('/', '/etc', '/root', '/home', '/var')
+
+ mopts = 'ro' if readonly else 'rw'
+ for mp, dev in self._mountpoints():
+ try:
+ self.g.mount_options(mopts, dev, mp)
+ except RuntimeError as msg:
+ if mp in critical_mpoint:
+ self.out.warn('unable to mount %s. Reason: %s' % (mp, msg))
+ return False
+ else:
+ self.out.warn('%s (ignored)' % msg)
+
+ return True
@sysprep()
def cleanup_cache(self, print_header=True):
__version__ = "0.3next"
__version_info__ = ['0', '3next']
-__version_vcs_info__ = {'branch': 'develop',
- 'revid': '9c060ab',
- 'revno': 297,
- 'toplevel': '/home/skalkoto/src/snf-image-creator'}
+__version_vcs_info__ = {
+ 'branch': 'develop',
+ 'revid': '9c060ab',
+ 'revno': 297,
+ 'toplevel': '/home/skalkoto/src/snf-image-creator'}
__version_user_info__ = "skalkoto@darkstar.admin.grnet.gr"