From 27a4229d05721968e1be077d2101019de7d545a6 Mon Sep 17 00:00:00 2001 From: Nikos Skalkotos Date: Mon, 10 Dec 2012 20:24:16 +0200 Subject: [PATCH] Futher development for bundle_volume Create a sparse file under /mnt in the size of the root hard disk and copy the mbr into this file. Not yet workable. --- image_creator/bundle_volume.py | 86 ++++++++++++++++++++++++++++++++++++++-- image_creator/disk.py | 2 +- 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/image_creator/bundle_volume.py b/image_creator/bundle_volume.py index 2051738..311dd24 100644 --- a/image_creator/bundle_volume.py +++ b/image_creator/bundle_volume.py @@ -31,10 +31,90 @@ # interpreted as representing official policies, either expressed # or implied, of GRNET S.A. +import os +import re +import parted +import uuid + +from image_creator.util import get_command from image_creator.util import FatalError -def bundle_volume(): - raise FatalError("Creating an image out of a running system is not yet " - "supported.") +findfs = get_command('findfs') +truncate = get_command('truncate') +dd = get_command('dd') + +def get_root_partition(): + if not os.path.isfile('/etc/fstab'): + raise FatalError("Unable to open `/etc/fstab'. File is missing.") + + with open('/etc/fstab') as fstab: + for line in iter(fstab): + entry = line.split('#')[0].strip().split() + if len(entry) != 6: + continue + + if entry[1] == "/": + return entry[0] + + raise FatalError("Unable to find root device in /etc/fstab") + +def mnt_mounted(): + if not os.path.isfile('/etc/mtab'): + raise FatalError("Unable to open `/etc/fstab'. File is missing.") + + with open('/etc/mtab') as mtab: + for line in iter(mtab): + entry = line.split('#')[0].strip().split() + if len(entry) != 6: + continue + + if entry[1] == '/mnt': + return True + + return False + + +def part_to_dev(part): + return re.split('[0-9]', part)[0] + +def part_to_num(part): + return re.split('[^0-9]+', part)[-1] + +def bundle_volume(out): + + if mnt_mounted(): + raise FatalError('The directory /mnt where the image will be hosted' + 'is mounted. Please unmount it and start over again.') + + out.output('Searching for root device...', False) + root_part = get_root_partition() + + if root_part.startswith("UUID=") or root_part.startswith("LABEL="): + root_part = findfs(root_part) + elif not root_part.startswith("/"): + raise FatalError("Unable to find a block device for: %s" % root_dev) + + if not re.match('/dev/[hsv]d[a-z][1-9]*$', root_part): + raise FatalError("Don't know how to handle root device: %s" % root_dev) + + device = parted.Device(part_to_dev(root_part)) + + image = '/mnt/%s.diskdump' % uuid.uuid4().hex + + # Create sparse file to host the image + truncate("-s", "%d" % (device.getLength() * device.sectorSize), image) + + disk = parted.Disk(device) + if disk.type != 'msdos': + raise FatalError('For now we can only handle msdos partition tables') + + # Copy the MBR and the space between the MBR and the first partition. + # In Grub version 1 Stage 1.5 is located there. + first_sector = disk.getPrimaryPartitions()[0].geometry.start + + dd('if=%s' % device.path, 'of=%s' % image, 'bs=%d' % device.sectorSize, + 'count=%d' % first_sector, 'conv=notrunc') + + return image # vim: set sta sts=4 shiftwidth=4 sw=4 et ai : diff --git a/image_creator/disk.py b/image_creator/disk.py index f3df5e8..deafb95 100644 --- a/image_creator/disk.py +++ b/image_creator/disk.py @@ -79,7 +79,7 @@ class Disk(object): def _dir_to_disk(self): if self.source == '/': - return bundle_volume() + return bundle_volume(self.out) raise FatalError("Using a directory as media source is supported") def cleanup(self): -- 1.7.10.4