help="do not output anything but just errors on console")
parser.add_option("--remove-bootoption", dest="removeoption", action="append",
help="regex for removing existing bootoptions")
+parser.add_option("--rw-blockdev", dest="rwblockdev", action="store_true",
+ help="enforce read-write mode on involved block devices")
parser.add_option("--skip-addons", dest="skipaddons", action="store_true",
help="do not install /boot/addons/ files")
+parser.add_option("--skip-bootflag", dest="skipbootflag", action="store_true",
+ help="do not try to check whether the destination has the bootflag set")
parser.add_option("--skip-grub-config", dest="skipgrubconfig", action="store_true",
help="skip generation of grub configuration files")
parser.add_option("--skip-mbr", dest="skipmbr", action="store_true",
help="do not install a master boot record (MBR) on the device")
parser.add_option("--skip-syslinux-config", dest="skipsyslinuxconfig", action="store_true",
help="skip generation of syslinux configuration files")
+parser.add_option("--skip-usb-check", dest="skipusbcheck", action="store_true",
+ help="skip check to verify whether given device is removable")
parser.add_option("--syslinux", dest="syslinux", action="callback", default=True,
callback=syslinux_warning,
help="install syslinux bootloader (deprecated as it's the default)")
GRML2USB_BASE = os.path.dirname(os.path.realpath(__file__))
+class HodorException(Exception):
+ """Throw exception if the exact error is not known and not fatal.
+
+ @Exception: message"""
+
+
class CriticalException(Exception):
"""Throw critical exception if the exact error is not known but fatal.
return obj.__module__ + '.' + obj.__name__
+def set_rw(device):
+ if not options.rwblockdev:
+ return
+
+ logging.debug("executing: blockdev --setrw %s", device)
+ proc = subprocess.Popen(["blockdev", "--setrw", device])
+ proc.wait()
+ if proc.returncode != 0:
+ raise Exception("error executing blockdev on %s" % device)
+
+
def execute(f, *exec_arguments):
"""Wrapper for executing a command. Either really executes
the command (default) or when using --dry-run commandline option
"""
bootloader_dirs = ['/boot/isolinux/', '/boot/syslinux/']
for directory in bootloader_dirs:
- for name in name, \
- "%s_%s" % (get_flavour_filename(flavour), name):
+ for name in name, "%s_%s" % (get_flavour_filename(flavour), name):
if os.path.isfile(iso_mount + directory + name):
return (directory, name)
return ('', '')
raise CriticalException("please run this script with uid 0 (root).")
+# for usage inside check_boot_flag
+def get_partition_for_path(path):
+ import parted
+
+ boot_dev, x = get_device_from_partition(path)
+
+ d = parted.getDevice(boot_dev)
+ disk = parted.Disk(d)
+ return disk.getPartitionByPath(path)
+
+
def check_boot_flag(device):
boot_dev, x = get_device_from_partition(device)
+ try:
+ import parted
+ part = get_partition_for_path(device)
+ if part is None:
+ raise HodorException("parted could not find partition")
+ if part.getFlag(parted.PARTITION_BOOT):
+ logging.debug("bootflag is enabled on %s" % device)
+ return
+ except HodorException, e:
+ logging.info("%s, falling back to old bootflag detection", e)
+ except ImportError, e:
+ logging.debug("could not import parted, falling back to old bootflag detection")
+
with open(boot_dev, 'r') as image:
data = image.read(520)
bootcode = data[440:]
else:
logging.debug("bootflag is NOT enabled")
raise VerifyException("Device %s does not have the bootflag set. "
- "Please enable it to be able to boot." % boot_dev)
+ "Please enable it to be able to boot." % device)
def mkfs_fat16(device):
logging.info("Installing grub as bootloader")
for opt in ["", "--force"]:
+ set_rw(device)
+ set_rw(grub_device)
logging.debug("grub-install --recheck %s --no-floppy --root-directory=%s %s",
opt, device_mountpoint, grub_device)
- proc = subprocess.Popen([GRUB_INSTALL, "--recheck", opt, "--no-floppy",
+ proc = subprocess.Popen([GRUB_INSTALL, "--recheck", opt,
+ "--no-floppy", "--target=i386-pc",
"--root-directory=%s" % device_mountpoint, grub_device],
stdout=file(os.devnull, "r+"))
proc.wait()
if proc.returncode != 0:
# raise Exception("error executing grub-install")
- logging.critical("Fatal: error executing grub-install "
- + "(please check the grml2usb FAQ or drop the --grub option)")
- logging.critical("Note: if using grub2 consider using "
- + "the --grub-mbr option as grub considers PBR problematic.")
+ logging.critical("Fatal: error executing grub-install " +
+ "(please check the grml2usb FAQ or drop the --grub option)")
+ logging.critical("Note: if using grub2 consider using " +
+ "the --grub-mbr option as grub considers PBR problematic.")
cleanup()
sys.exit(1)
except CriticalException as error:
logging.info("Would install syslinux as bootloader on %s", device)
return 0
+ set_rw(device)
+
# syslinux -d boot/isolinux /dev/sdb1
logging.info("Installing syslinux as bootloader")
logging.debug("syslinux -d boot/syslinux %s", device)
tmpf.file.write(mbrcode)
tmpf.file.close()
+ set_rw(device)
+
logging.debug("executing: dd if='%s' of='%s' bs=512 count=1 conv=notrunc", tmpf.name, device)
proc = subprocess.Popen(["dd", "if=%s" % tmpf.name, "of=%s" % device, "bs=512", "count=1",
"conv=notrunc"], stderr=file(os.devnull, "r+"))
raise Exception("error executing dd (third run)")
del tmpf
+ # make sure we sync filesystems before returning
+ proc = subprocess.Popen(["sync"])
+ proc.wait()
+
+ set_rw(device)
+
def is_writeable(device):
"""Check if the device is writeable for the current user
if not device:
return False
- #raise Exception("no device for checking write permissions")
if not os.path.exists(device):
return False
for x in file('/proc/mounts').readlines():
if x.startswith(source):
- raise CriticalException("Error executing mount: %s already mounted - " % source
- + "please unmount before invoking grml2usb")
+ raise CriticalException("Error executing mount: %s already mounted - " % source +
+ "please unmount before invoking grml2usb")
if os.path.isdir(source):
logging.debug("Source %s is not a device, therefore not mounting.", source)
logging.warning("Warning: Grml releases older than 2011.12 support only one flavour in grub.")
for expr in name, 'distri.cfg', \
- defaults_file, 'grml.png', 'hd.cfg', 'isolinux.cfg', 'isolinux.bin', \
- 'isoprompt.cfg', 'options.cfg', \
- 'prompt.cfg', 'vesamenu.cfg', 'grml.png', '*.c32':
+ defaults_file, 'grml.png', 'hd.cfg', 'isolinux.cfg', 'isolinux.bin', \
+ 'isoprompt.cfg', 'options.cfg', \
+ 'prompt.cfg', 'vesamenu.cfg', 'grml.png', '*.c32':
glob_and_copy(iso_mount + source_dir + expr, syslinux_target)
for filename in glob.glob1(syslinux_target, "*.c32"):
def add_entry_if_not_present(filename, entry):
"""Write entry into filename if entry is not already in the file
- @filanme: name of the file
+ @filename: name of the file
@entry: data to write to the file
"""
data = open(filename, "a+")
remove_device_mountpoint = True
try:
check_for_fat(device)
- check_boot_flag(device)
+ if not options.skipbootflag:
+ check_boot_flag(device)
mount(device, device_mountpoint, ['-o', 'utf8,iocharset=iso8859-1'])
except CriticalException as error:
mount(device, device_mountpoint, "")
logging.critical("Execution failed: %s", error)
sys.exit(1)
+ if options.skipusbcheck:
+ logging.info("Not checking for removable USB device as requested via option --skip-usb-check.")
+ return
+
if not os.path.isdir(device) and not check_for_usbdevice(device) and not options.force:
print("Warning: the specified device %s does not look like a removable usb device." % device)
f = raw_input("Do you really want to continue? y/N ")
if opts.grubmbr and not opts.grub:
raise CriticalException("--grub-mbr requires --grub option.")
+ if opts.copyonly and opts.grub:
+ raise CriticalException("Cannot use --copy-only and --grub at the same time.")
+
def check_programs():
"""check if all needed programs are installed"""
global GRUB_INSTALL
GRUB_INSTALL = which("grub-install") or which("grub2-install")
if not GRUB_INSTALL:
- logging.critical("Fatal: grub-install not available (please install the "
- + "grub package or drop the --grub option)")
+ logging.critical("Fatal: grub-install not available (please install the " +
+ "grub package or drop the --grub option)")
sys.exit(1)
if options.syslinux:
if not which("syslinux"):
- logging.critical("Fatal: syslinux not available (please install the "
- + "syslinux package or use the --grub option)")
+ logging.critical("Fatal: syslinux not available (please install the " +
+ "syslinux package or use the --grub option)")
sys.exit(1)
if not which("rsync"):
if not os.path.isdir(device):
if device[-1:].isdigit():
if int(device[-1:]) > 4 or device[-2:].isdigit():
- logging.critical("Fatal: installation on partition number >4 not supported. (BIOS won't support it.)")
- sys.exit(1)
+ logging.warn("Warning: installing on partition number >4, booting *might* fail depending on your system.")
# provide upgrade path
handle_compat_warning(device)
logging.info("Received KeyboardInterrupt")
cleanup()
-## END OF FILE #################################################################
+# END OF FILE ##################################################################
# vim:foldmethod=indent expandtab ai ft=python tw=120 fileencoding=utf-8