diff options
Diffstat (limited to 'scripts/lib/mic/imager/liveusb.py')
-rw-r--r-- | scripts/lib/mic/imager/liveusb.py | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/scripts/lib/mic/imager/liveusb.py b/scripts/lib/mic/imager/liveusb.py new file mode 100644 index 0000000..a909928 --- /dev/null +++ b/scripts/lib/mic/imager/liveusb.py @@ -0,0 +1,308 @@ +#!/usr/bin/python -tt +# +# Copyright (c) 2011 Intel, 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 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 os +import shutil +import re + +from mic import msger +from mic.utils import misc, fs_related, runner +from mic.utils.errors import CreatorError, MountError +from mic.utils.partitionedfs import PartitionedMount +from mic.imager.livecd import LiveCDImageCreator + + +class LiveUSBImageCreator(LiveCDImageCreator): + def __init__(self, *args): + LiveCDImageCreator.__init__(self, *args) + + self._dep_checks.extend(["kpartx", "parted"]) + + # remove dependency of genisoimage in parent class + if "genisoimage" in self._dep_checks: + self._dep_checks.remove("genisoimage") + + def _create_usbimg(self, isodir): + overlaysizemb = 64 #default + #skipcompress = self.skip_compression? + fstype = "vfat" + homesizemb=0 + swapsizemb=0 + homefile="home.img" + plussize=128 + kernelargs=None + + if fstype == 'vfat': + if overlaysizemb > 2047: + raise CreatorError("Can't have an overlay of 2048MB or " + "greater on VFAT") + + if homesizemb > 2047: + raise CreatorError("Can't have an home overlay of 2048MB or " + "greater on VFAT") + + if swapsizemb > 2047: + raise CreatorError("Can't have an swap overlay of 2048MB or " + "greater on VFAT") + + livesize = misc.get_file_size(isodir + "/LiveOS") + + usbimgsize = (overlaysizemb + \ + homesizemb + \ + swapsizemb + \ + livesize + \ + plussize) * 1024L * 1024L + + disk = fs_related.SparseLoopbackDisk("%s/%s.usbimg" \ + % (self._outdir, self.name), + usbimgsize) + usbmnt = self._mkdtemp("usb-mnt") + usbloop = PartitionedMount(usbmnt) + usbloop.add_disk('/dev/sdb', disk) + + usbloop.add_partition(usbimgsize/1024/1024, + "/dev/sdb", + "/", + fstype, + boot=True) + + usbloop.mount() + + try: + fs_related.makedirs(usbmnt + "/LiveOS") + + if os.path.exists(isodir + "/LiveOS/squashfs.img"): + shutil.copyfile(isodir + "/LiveOS/squashfs.img", + usbmnt + "/LiveOS/squashfs.img") + else: + fs_related.mksquashfs(os.path.dirname(self._image), + usbmnt + "/LiveOS/squashfs.img") + + if os.path.exists(isodir + "/LiveOS/osmin.img"): + shutil.copyfile(isodir + "/LiveOS/osmin.img", + usbmnt + "/LiveOS/osmin.img") + + if fstype == "vfat" or fstype == "msdos": + uuid = usbloop.partitions[0]['mount'].uuid + label = usbloop.partitions[0]['mount'].fslabel + usblabel = "UUID=%s-%s" % (uuid[0:4], uuid[4:8]) + overlaysuffix = "-%s-%s-%s" % (label, uuid[0:4], uuid[4:8]) + else: + diskmount = usbloop.partitions[0]['mount'] + usblabel = "UUID=%s" % diskmount.uuid + overlaysuffix = "-%s-%s" % (diskmount.fslabel, diskmount.uuid) + + args = ['cp', "-Rf", isodir + "/isolinux", usbmnt + "/syslinux"] + rc = runner.show(args) + if rc: + raise CreatorError("Can't copy isolinux directory %s" \ + % (isodir + "/isolinux/*")) + + if os.path.isfile("/usr/share/syslinux/isolinux.bin"): + syslinux_path = "/usr/share/syslinux" + elif os.path.isfile("/usr/lib/syslinux/isolinux.bin"): + syslinux_path = "/usr/lib/syslinux" + else: + raise CreatorError("syslinux not installed : " + "cannot find syslinux installation path") + + for f in ("isolinux.bin", "vesamenu.c32"): + path = os.path.join(syslinux_path, f) + if os.path.isfile(path): + args = ['cp', path, usbmnt + "/syslinux/"] + rc = runner.show(args) + if rc: + raise CreatorError("Can't copy syslinux file " + path) + else: + raise CreatorError("syslinux not installed: " + "syslinux file %s not found" % path) + + fd = open(isodir + "/isolinux/isolinux.cfg", "r") + text = fd.read() + fd.close() + pattern = re.compile('CDLABEL=[^ ]*') + text = pattern.sub(usblabel, text) + pattern = re.compile('rootfstype=[^ ]*') + text = pattern.sub("rootfstype=" + fstype, text) + if kernelargs: + text = text.replace("rd.live.image", "rd.live.image " + kernelargs) + + if overlaysizemb > 0: + msger.info("Initializing persistent overlay file") + overfile = "overlay" + overlaysuffix + if fstype == "vfat": + args = ['dd', + "if=/dev/zero", + "of=" + usbmnt + "/LiveOS/" + overfile, + "count=%d" % overlaysizemb, + "bs=1M"] + else: + args = ['dd', + "if=/dev/null", + "of=" + usbmnt + "/LiveOS/" + overfile, + "count=1", + "bs=1M", + "seek=%d" % overlaysizemb] + rc = runner.show(args) + if rc: + raise CreatorError("Can't create overlay file") + text = text.replace("rd.live.image", "rd.live.image rd.live.overlay=" + usblabel) + text = text.replace(" ro ", " rw ") + + if swapsizemb > 0: + msger.info("Initializing swap file") + swapfile = usbmnt + "/LiveOS/" + "swap.img" + args = ['dd', + "if=/dev/zero", + "of=" + swapfile, + "count=%d" % swapsizemb, + "bs=1M"] + rc = runner.show(args) + if rc: + raise CreatorError("Can't create swap file") + args = ["mkswap", "-f", swapfile] + rc = runner.show(args) + if rc: + raise CreatorError("Can't mkswap on swap file") + + if homesizemb > 0: + msger.info("Initializing persistent /home") + homefile = usbmnt + "/LiveOS/" + homefile + if fstype == "vfat": + args = ['dd', + "if=/dev/zero", + "of=" + homefile, + "count=%d" % homesizemb, + "bs=1M"] + else: + args = ['dd', + "if=/dev/null", + "of=" + homefile, + "count=1", + "bs=1M", + "seek=%d" % homesizemb] + rc = runner.show(args) + if rc: + raise CreatorError("Can't create home file") + + mkfscmd = fs_related.find_binary_path("/sbin/mkfs." + fstype) + if fstype == "ext2" or fstype == "ext3": + args = [mkfscmd, "-F", "-j", homefile] + else: + args = [mkfscmd, homefile] + rc = runner.show(args) + if rc: + raise CreatorError("Can't mke2fs home file") + if fstype == "ext2" or fstype == "ext3": + tune2fs = fs_related.find_binary_path("tune2fs") + args = [tune2fs, + "-c0", + "-i0", + "-ouser_xattr,acl", + homefile] + rc = runner.show(args) + if rc: + raise CreatorError("Can't tune2fs home file") + + if fstype == "vfat" or fstype == "msdos": + syslinuxcmd = fs_related.find_binary_path("syslinux") + syslinuxcfg = usbmnt + "/syslinux/syslinux.cfg" + args = [syslinuxcmd, + "-d", + "syslinux", + usbloop.partitions[0]["device"]] + + elif fstype == "ext2" or fstype == "ext3": + extlinuxcmd = fs_related.find_binary_path("extlinux") + syslinuxcfg = usbmnt + "/syslinux/extlinux.conf" + args = [extlinuxcmd, + "-i", + usbmnt + "/syslinux"] + + else: + raise CreatorError("Invalid file system type: %s" % (fstype)) + + os.unlink(usbmnt + "/syslinux/isolinux.cfg") + fd = open(syslinuxcfg, "w") + fd.write(text) + fd.close() + rc = runner.show(args) + if rc: + raise CreatorError("Can't install boot loader.") + + finally: + usbloop.unmount() + usbloop.cleanup() + + # Need to do this after image is unmounted and device mapper is closed + msger.info("set MBR") + mbrfile = "/usr/lib/syslinux/mbr.bin" + if not os.path.exists(mbrfile): + mbrfile = "/usr/share/syslinux/mbr.bin" + if not os.path.exists(mbrfile): + raise CreatorError("mbr.bin file didn't exist.") + mbrsize = os.path.getsize(mbrfile) + outimg = "%s/%s.usbimg" % (self._outdir, self.name) + + args = ['dd', + "if=" + mbrfile, + "of=" + outimg, + "seek=0", + "conv=notrunc", + "bs=1", + "count=%d" % (mbrsize)] + rc = runner.show(args) + if rc: + raise CreatorError("Can't set MBR.") + + def _stage_final_image(self): + try: + isodir = self._get_isodir() + fs_related.makedirs(isodir + "/LiveOS") + + minimal_size = self._resparse() + + if not self.skip_minimize: + fs_related.create_image_minimizer(isodir + "/LiveOS/osmin.img", + self._image, + minimal_size) + + if self.skip_compression: + shutil.move(self._image, + isodir + "/LiveOS/ext3fs.img") + else: + fs_related.makedirs(os.path.join( + os.path.dirname(self._image), + "LiveOS")) + shutil.move(self._image, + os.path.join(os.path.dirname(self._image), + "LiveOS", "ext3fs.img")) + fs_related.mksquashfs(os.path.dirname(self._image), + isodir + "/LiveOS/squashfs.img") + + self._create_usbimg(isodir) + + if self.pack_to: + usbimg = os.path.join(self._outdir, self.name + ".usbimg") + packimg = os.path.join(self._outdir, self.pack_to) + misc.packing(packimg, usbimg) + os.unlink(usbimg) + + finally: + shutil.rmtree(isodir, ignore_errors = True) + self._set_isodir(None) + |