mkbiarch.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. #!/usr/bin/python
  2. import os
  3. import sys
  4. import shutil
  5. import parted
  6. import subprocess
  7. import optparse
  8. import tempfile
  9. import re
  10. def main():
  11. def usage():
  12. usage = 'usage: mkbiarch.py <x86 Live ISO File> <x64 Live ISO File> <Target Multi Arch Image File>'
  13. print >> sys.stdout, usage
  14. def mount(src, dst, options=None):
  15. if os.path.exists(src):
  16. if not os.path.exists(dst):
  17. os.makedir(dst)
  18. if options is None:
  19. args = ("/bin/mount", src, dst)
  20. else:
  21. args = ("/bin/mount", options, src, dst)
  22. rc = subprocess.call(args)
  23. return rc
  24. return
  25. def umount(src):
  26. if os.path.exists(src):
  27. args = ("/bin/umount", src)
  28. rc = subprocess.call(args)
  29. return rc
  30. return
  31. def copy(src, dst):
  32. if os.path.exists(src):
  33. if not os.path.exists(dst):
  34. if not os.path.isfile(src):
  35. mkdir(dst)
  36. shutil.copy(src, dst)
  37. def move(src, dst):
  38. if os.path.exists(src):
  39. shutil.move(src, dst)
  40. def mkdir(dir=None):
  41. if dir is None:
  42. tmp = tempfile.mkdtemp()
  43. return tmp
  44. else:
  45. args = ("/bin/mkdir", "-p", dir)
  46. rc = subprocess.call(args)
  47. def losetup(src, dst, offset=None):
  48. if os.path.exists(src):
  49. if os.path.exists(dst):
  50. if offset is None:
  51. args = ("/sbin/losetup", src, dst)
  52. else:
  53. args = ("/sbin/losetup", "-o", str(offset), src, dst)
  54. rc = subprocess.call(args)
  55. return rc
  56. def lounset(device):
  57. args = ("/sbin/losetup", "-d", device)
  58. rc = subprocess.call(args)
  59. def null():
  60. fd = open(os.devnull, 'w')
  61. return fd
  62. def dd(file, target):
  63. args = ("/bin/dd", "if=%s"%file, "of=%s"%target)
  64. rc = subprocess.call(args)
  65. def lo():
  66. args = ("/sbin/losetup", "--find")
  67. rc = subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0].rstrip()
  68. return rc
  69. def lodev(file):
  70. args = ("/sbin/losetup", "-j", file)
  71. rc = subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0].split(":")
  72. return rc[0]
  73. def mkimage(bs, count):
  74. tmp = tempfile.mkstemp()
  75. image = tmp[1]
  76. args = ("/bin/dd", "if=/dev/zero",
  77. "of=%s"%image, "bs=%s"%bs,
  78. "count=%s"%count)
  79. rc = subprocess.call(args)
  80. return image
  81. def size(ent):
  82. if os.path.exists(ent):
  83. return os.stat(ent).st_size
  84. def bs(size):
  85. return size / 2048
  86. def partition(device):
  87. dev = parted.Device(path=device)
  88. disk = parted.freshDisk(dev, 'msdos')
  89. constraint = parted.Constraint(device=dev)
  90. new_geom = parted.Geometry(device=dev,
  91. start=1,
  92. end=(constraint.maxSize - 1))
  93. filesystem = parted.FileSystem(type="ext2",
  94. geometry=new_geom)
  95. partition = parted.Partition(disk=disk,
  96. fs=filesystem,
  97. type=parted.PARTITION_NORMAL,
  98. geometry=new_geom)
  99. constraint = parted.Constraint(exactGeom=new_geom)
  100. partition.setFlag(parted.PARTITION_BOOT)
  101. disk.addPartition(partition=partition,
  102. constraint=constraint)
  103. disk.commit()
  104. def format(partition):
  105. args = ("/sbin/mke2fs", "-j", partition)
  106. rc = subprocess.call(args)
  107. def mbr(target):
  108. mbr = "/usr/share/syslinux/mbr.bin"
  109. dd(mbr, target)
  110. def getuuid(device):
  111. args = ("/sbin/blkid", "-s", "UUID", "-o", "value", device)
  112. rc = subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0].rstrip()
  113. return rc
  114. def syslinux(multitmp, config, **args):
  115. arg = ("/sbin/extlinux", "--install", multitmp + "/extlinux/")
  116. rc = subprocess.call(arg)
  117. content = """
  118. default vesamenu.c32
  119. timeout 100
  120. menu background splash.jpg
  121. menu title Welcome to Fedora 13
  122. menu color border 0 #ffffffff #00000000
  123. menu color sel 7 #ffffffff #ff000000
  124. menu color title 0 #ffffffff #00000000
  125. menu color tabmsg 0 #ffffffff #00000000
  126. menu color unsel 0 #ffffffff #00000000
  127. menu color hotsel 0 #ff000000 #ffffffff
  128. menu color hotkey 7 #ffffffff #ff000000
  129. menu color timeout_msg 0 #ffffffff #00000000
  130. menu color timeout 0 #ffffffff #00000000
  131. menu color cmdline 0 #ffffffff #00000000
  132. menu hidden
  133. menu hiddenrow 5
  134. label Fedora-13-x86
  135. menu label Fedora-13-x86
  136. kernel vmlinuz0
  137. append initrd=initrd0.img root=UUID=%(uuid)s rootfstype=auto ro live_dir=/x86/LiveOS liveimg
  138. label Fedora-13-x64
  139. menu label Fedora-13-x64
  140. kernel vmlinuz1
  141. append initrd=initrd1.img root=UUID=%(uuid)s rootfstype=auto ro live_dir=/x64/LiveOS liveimg
  142. """ % args
  143. fd = open(config, 'w')
  144. fd.write(content)
  145. fd.close()
  146. def verify():
  147. # use md5 module to verify image files
  148. pass
  149. def setup(x86, x64, multi):
  150. sz = size(x86) + size(x64)
  151. count = bs(sz)
  152. blsz = str(2048)
  153. count = count + 102400
  154. multi = mkimage(blsz, count)
  155. losetup(lo(), multi)
  156. mbr(lodev(multi))
  157. partition(lodev(multi))
  158. lounset(lodev(multi))
  159. losetup(lo(), multi, offset=512)
  160. format(lodev(multi))
  161. multitmp = mkdir()
  162. mount(lodev(multi), multitmp)
  163. losetup(lo(), x86)
  164. losetup(lo(), x64)
  165. x86tmp = mkdir()
  166. x64tmp = mkdir()
  167. mount(lodev(x86), x86tmp)
  168. mount(lodev(x64), x64tmp)
  169. dirs = ("/extlinux/", "/x86/", "/x64/")
  170. for dir in dirs:
  171. mkdir(multitmp + dir)
  172. dirs = ("/x86/", "/x64/")
  173. for dir in dirs:
  174. mkdir(multitmp + dir + "/LiveOS/")
  175. intermediate = tempfile.mkdtemp() # loopdev performance is slow
  176. # copy to here first then back
  177. # to multitmp + dir which is looback also
  178. imgs = ("squashfs.img", "osmin.img")
  179. for img in imgs:
  180. copy(x86tmp + "/LiveOS/" + img, intermediate)
  181. copy(intermediate + "/" + img, multitmp + "/x86/LiveOS/")
  182. for img in imgs:
  183. copy(x64tmp + "/LiveOS/" + img, intermediate)
  184. copy(intermediate + "/" + img, multitmp + "/x64/LiveOS/")
  185. for file in os.listdir(x86tmp + "/isolinux/"):
  186. copy(x86tmp + "/isolinux/" + file, multitmp + "/extlinux/")
  187. copy(x64tmp + "/isolinux/vmlinuz0", multitmp + "/extlinux/vmlinuz1")
  188. copy(x64tmp + "/isolinux/initrd0.img", multitmp + "/extlinux/initrd1.img")
  189. uuid = getuuid(lodev(multi))
  190. config = (multitmp + "/extlinux/extlinux.conf")
  191. syslinux(multitmp,
  192. config,
  193. uuid=uuid)
  194. umount(x86tmp)
  195. umount(x64tmp)
  196. umount(multitmp)
  197. lounset(lodev(x86))
  198. lounset(lodev(x64))
  199. lounset(lodev(multi))
  200. shutil.rmtree(x86tmp)
  201. shutil.rmtree(x64tmp)
  202. shutil.rmtree(multitmp)
  203. shutil.rmtree(intermediate)
  204. if os.path.exists(sys.argv[3]):
  205. os.unlink(sys.argv[3])
  206. move(multi, sys.argv[3])
  207. def parse(x86, x64, multi):
  208. for file in x86, x64:
  209. if os.path.exists(file):
  210. pass
  211. else:
  212. usage()
  213. if not multi:
  214. usage()
  215. setup(x86, x64, multi)
  216. try:
  217. parse(sys.argv[1], sys.argv[2], sys.argv[3])
  218. except:
  219. usage()
  220. if __name__ == "__main__":
  221. sys.exit(main())