-
-
Save andreztz/44d4c9656193a914dc8e45c2a6a3fd73 to your computer and use it in GitHub Desktop.
A python script for creating a linux virtual disk with a ready to use rootfs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/python3 | |
| import sys | |
| import os | |
| import argparse | |
| from os import path | |
| from pprint import pprint | |
| from tempfile import TemporaryDirectory | |
| from sh import dd, sudo, ls, losetup, parted, kpartx, mke2fs, grub_install, mount, umount, cp, chmod, ln, chown | |
| def showArgs(args): | |
| for i,arg in enumerate(args): | |
| print("{}) {}".format(i, arg)) | |
| def ensureNewFileIsCreated(fileName, func): | |
| if path.isfile(fileName): | |
| os.remove(fileName) | |
| func() | |
| if not path.isfile(fileName): | |
| raise Exception("Error: could not create raw image file:{}".format(fileName)) | |
| def createRawImageFile(fileName, imageSize): | |
| def func(): | |
| dd("if=/dev/zero", "of={}".format(fileName), "bs=1", "count=0", "seek={}".format(imageSize)) | |
| ensureNewFileIsCreated(fileName, func) | |
| def main(): | |
| try: | |
| print("-------CREATE LINUX VIRTUAL DISK WITH ROOTFS--------") | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("imageFileName", help="Path to the output image file") | |
| parser.add_argument("imageFileSize", help="Size of the output image file. You can use suffixes allowed by the dd command.") | |
| parser.add_argument("--kernel", help="Path to a kernel image. This file will be copied to /boot on the primary partition of the disk image") | |
| parser.add_argument("--busybox", help="Path to the busybox executable. This file will be copied to /bin on the primary partition of the disk image. Links to several useful commands will also be created.") | |
| parser.add_argument("--grubcfg", help="Path to a grub.cfg file. A customized version of grub.cfg can be used to boot linux directly and avoid entering commands on the grub prompt.") | |
| args = parser.parse_args() | |
| createRawImageFile(args.imageFileName, args.imageFileSize) | |
| chown('sandeepd:sandeepd', args.imageFileName) | |
| loop0 = losetup('-f', '--show', args.imageFileName).strip() | |
| print("Disk image file looped at:{}".format(loop0)) | |
| try: | |
| print("Creating msdos partition table") | |
| parted(loop0, 'mklabel msdos') | |
| print("Creating primary partition") | |
| parted(loop0, 'mkpart primary 1 100%') | |
| try: | |
| print("Looping primary partition to /dev/mapper") | |
| kpartx('-va', loop0) | |
| try: | |
| loop1 = losetup('-f','--show', "/dev/mapper/{}p1".format(path.basename(loop0))).strip() | |
| print("Primary partition looped at:{}".format(loop1)) | |
| print("Formatting primary partition") | |
| mke2fs(loop1) | |
| with TemporaryDirectory(dir='/mnt') as dirName: | |
| print("Created temporary mount point for primary partion") | |
| print("Mounting partion 1 at:", dirName) | |
| mount(loop1, dirName) | |
| bootDir = path.join(dirName, 'boot') | |
| print("Installing GRUB2") | |
| grub_install('--boot-directory={}'.format(bootDir), '--modules=ext2 part_msdos', loop0) | |
| print(ls('-lh', bootDir)) | |
| if args.kernel: | |
| print("Copying kernel to /boot on primary partition") | |
| cp(args.kernel, bootDir) | |
| print(ls('-lh', bootDir)) | |
| if args.busybox: | |
| print("Installing busybox to /bin") | |
| binDir = path.join(dirName, 'bin') | |
| os.makedirs(binDir) | |
| busboxTargetPath = path.join(binDir,'busybox') | |
| cp(args.busybox, busboxTargetPath) | |
| chmod('+x', busboxTargetPath) | |
| cwd=os.getcwd() | |
| os.chdir(binDir) | |
| for cmd in ['ash', 'sh', 'ls', 'rm', 'mkdir', 'rmdir', 'grep', 'find', 'mount', 'umount']: | |
| #Use relative paths here. | |
| ln('-s', 'busybox', cmd) | |
| os.chdir(cwd) | |
| print(ls('-lh', binDir)) | |
| if args.grubcfg: | |
| print("Copying '{}' to /boot/grub".format(args.grubcfg)) | |
| cp(args.grubcfg, path.join(bootDir, 'grub')) | |
| umount(loop1) | |
| except Exception as e: | |
| print(e) | |
| finally: | |
| losetup('-d', loop1) | |
| except Exception as e: | |
| print(e) | |
| finally: | |
| kpartx('-vd', loop0) | |
| except Exception as e: | |
| print(e) | |
| finally: | |
| losetup('-d', loop0) | |
| except Exception as e: | |
| print(e) | |
| if __name__ == "__main__": | |
| main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # | |
| # DO NOT EDIT THIS FILE | |
| # | |
| # It is automatically generated by grub-mkconfig using templates | |
| # from /etc/grub.d and settings from /etc/default/grub | |
| # | |
| ### BEGIN /etc/grub.d/00_header ### | |
| if [ -s $prefix/grubenv ]; then | |
| set have_grubenv=true | |
| load_env | |
| fi | |
| set default="0" | |
| if [ x"${feature_menuentry_id}" = xy ]; then | |
| menuentry_id_option="--id" | |
| else | |
| menuentry_id_option="" | |
| fi | |
| export menuentry_id_option | |
| if [ "${prev_saved_entry}" ]; then | |
| set saved_entry="${prev_saved_entry}" | |
| save_env saved_entry | |
| set prev_saved_entry= | |
| save_env prev_saved_entry | |
| set boot_once=true | |
| fi | |
| function savedefault { | |
| if [ -z "${boot_once}" ]; then | |
| saved_entry="${chosen}" | |
| save_env saved_entry | |
| fi | |
| } | |
| function recordfail { | |
| set recordfail=1 | |
| if [ -n "${have_grubenv}" ]; then if [ -z "${boot_once}" ]; then save_env recordfail; fi; fi | |
| } | |
| function load_video { | |
| if [ x$feature_all_video_module = xy ]; then | |
| insmod all_video | |
| else | |
| insmod efi_gop | |
| insmod efi_uga | |
| insmod ieee1275_fb | |
| insmod vbe | |
| insmod vga | |
| insmod video_bochs | |
| insmod video_cirrus | |
| fi | |
| } | |
| if [ x$feature_default_font_path = xy ] ; then | |
| font=unicode | |
| else | |
| insmod part_msdos | |
| insmod ext2 | |
| set root='hd1,msdos5' | |
| if [ x$feature_platform_search_hint = xy ]; then | |
| search --no-floppy --fs-uuid --set=root --hint-bios=hd1,msdos5 --hint-efi=hd1,msdos5 --hint-baremetal=ahci1,msdos5 cd80328b-d252-488d-b9e2-ffa808ce5d83 | |
| else | |
| search --no-floppy --fs-uuid --set=root cd80328b-d252-488d-b9e2-ffa808ce5d83 | |
| fi | |
| font="/usr/share/grub/unicode.pf2" | |
| fi | |
| if loadfont $font ; then | |
| set gfxmode=auto | |
| load_video | |
| insmod gfxterm | |
| set locale_dir=$prefix/locale | |
| set lang=en_IN | |
| insmod gettext | |
| fi | |
| terminal_output gfxterm | |
| if [ "${recordfail}" = 1 ]; then | |
| set timeout=-1 | |
| else | |
| set timeout=10 | |
| fi | |
| ### END /etc/grub.d/00_header ### | |
| ### BEGIN /etc/grub.d/05_debian_theme ### | |
| set menu_color_normal=white/black | |
| set menu_color_highlight=black/light-gray | |
| if background_color 44,0,30; then | |
| clear | |
| fi | |
| ### END /etc/grub.d/05_debian_theme ### | |
| ### BEGIN /etc/grub.d/10_linux ### | |
| function gfxmode { | |
| set gfxpayload="${1}" | |
| if [ "${1}" = "keep" ]; then | |
| set vt_handoff=vt.handoff=7 | |
| else | |
| set vt_handoff= | |
| fi | |
| } | |
| if [ "${recordfail}" != 1 ]; then | |
| if [ -e ${prefix}/gfxblacklist.txt ]; then | |
| if hwmatch ${prefix}/gfxblacklist.txt 3; then | |
| if [ ${match} = 0 ]; then | |
| set linux_gfx_mode=keep | |
| else | |
| set linux_gfx_mode=text | |
| fi | |
| else | |
| set linux_gfx_mode=text | |
| fi | |
| else | |
| set linux_gfx_mode=keep | |
| fi | |
| else | |
| set linux_gfx_mode=text | |
| fi | |
| export linux_gfx_mode | |
| if [ "${linux_gfx_mode}" != "text" ]; then load_video; fi | |
| menuentry 'Linux baremetal' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-cd80328b-d252-488d-b9e2-ffa808ce5d83' { | |
| recordfail | |
| gfxmode $linux_gfx_mode | |
| insmod gzio | |
| insmod part_msdos | |
| insmod ext2 | |
| set root='hd0,msdos1' | |
| linux /boot/bzImage root=/dev/sda1 init=/bin/sh rw | |
| #initrd /boot/initrd.img-3.5.0-43-generic | |
| } | |
| ### END /etc/grub.d/10_linux ### | |
| ### BEGIN /etc/grub.d/30_os-prober ### | |
| if [ "x${timeout}" != "x-1" ]; then | |
| if keystatus; then | |
| if keystatus --shift; then | |
| set timeout=-1 | |
| else | |
| set timeout=0 | |
| fi | |
| else | |
| if sleep --interruptible 3 ; then | |
| set timeout=0 | |
| fi | |
| fi | |
| fi | |
| ### END /etc/grub.d/30_os-prober ### | |
| ### BEGIN /etc/grub.d/30_uefi-firmware ### | |
| ### END /etc/grub.d/30_uefi-firmware ### | |
| ### BEGIN /etc/grub.d/40_custom ### | |
| # This file provides an easy way to add custom menu entries. Simply type the | |
| # menu entries you want to add after this comment. Be careful not to change | |
| # the 'exec tail' line above. | |
| ### END /etc/grub.d/40_custom ### | |
| ### BEGIN /etc/grub.d/41_custom ### | |
| if [ -f ${config_directory}/custom.cfg ]; then | |
| source ${config_directory}/custom.cfg | |
| elif [ -z "${config_directory}" -a -f $prefix/custom.cfg ]; then | |
| source $prefix/custom.cfg; | |
| fi | |
| ### END /etc/grub.d/41_custom ### |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/python3 | |
| import sys | |
| import os | |
| import argparse | |
| from os import path | |
| from pprint import pprint | |
| from tempfile import TemporaryDirectory | |
| from sh import dd, sudo, ls, losetup, parted, kpartx, mke2fs, grub_install, mount, umount, cp, chmod, ln | |
| def main(): | |
| try: | |
| print("-------MOUNT VIRTUAL DISK CREATED WITH CREATE_IMG--------") | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("imageFileName", help="Path to the image file") | |
| parser.add_argument("mountPoint", help="The mount point for the primary partition") | |
| #parser.add_argument("-d", help="Delete all existing loopbacks and mounts") | |
| args = parser.parse_args() | |
| loop0 = losetup('-f', '--show', args.imageFileName).strip() | |
| print("Disk image file looped at:{}".format(loop0)) | |
| print("Looping primary partition to /dev/mapper") | |
| kpartx('-va', loop0) | |
| loop1 = losetup('-f','--show', "/dev/mapper/{}p1".format(path.basename(loop0))).strip() | |
| print("Primary partition looped at:{}".format(loop1)) | |
| print("Created temporary mount point for primary partion") | |
| print("Mounting partion 1 at:", args.mountPoint) | |
| mount(loop1, args.mountPoint) | |
| with open("unmount_img", "w") as unmountScript: | |
| print("#!/bin/bash", file=unmountScript) | |
| print("umount {}".format(loop1), file=unmountScript) | |
| print("losetup -d {}".format(loop1), file=unmountScript) | |
| print("kpartx -vd {}".format(loop0), file=unmountScript) | |
| print("losetup -d {}".format(loop0), file=unmountScript) | |
| chmod('+x', "unmount_img") | |
| except Exception as e: | |
| print(e) | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment