PageRenderTime 83ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/scripts/lib/mic/plugins/imager/loop_plugin.py

https://github.com/dlazzari/oe-core
Python | 255 lines | 192 code | 36 blank | 27 comment | 45 complexity | cf42fbec18fcf69571738849b9f6d3cc MD5 | raw file
  1. #!/usr/bin/python -tt
  2. #
  3. # Copyright (c) 2011 Intel, Inc.
  4. #
  5. # This program is free software; you can redistribute it and/or modify it
  6. # under the terms of the GNU General Public License as published by the Free
  7. # Software Foundation; version 2 of the License
  8. #
  9. # This program is distributed in the hope that it will be useful, but
  10. # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  11. # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  12. # for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License along
  15. # with this program; if not, write to the Free Software Foundation, Inc., 59
  16. # Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. import os
  18. import shutil
  19. import tempfile
  20. from mic import chroot, msger
  21. from mic.utils import misc, fs_related, errors, cmdln
  22. from mic.conf import configmgr
  23. from mic.plugin import pluginmgr
  24. from mic.imager.loop import LoopImageCreator, load_mountpoints
  25. from mic.pluginbase import ImagerPlugin
  26. class LoopPlugin(ImagerPlugin):
  27. name = 'loop'
  28. @classmethod
  29. @cmdln.option("--compress-disk-image", dest="compress_image",
  30. type='choice', choices=("gz", "bz2"), default=None,
  31. help="Same with --compress-image")
  32. # alias to compress-image for compatibility
  33. @cmdln.option("--compress-image", dest="compress_image",
  34. type='choice', choices=("gz", "bz2"), default=None,
  35. help="Compress all loop images with 'gz' or 'bz2'")
  36. @cmdln.option("--shrink", action='store_true', default=False,
  37. help="Whether to shrink loop images to minimal size")
  38. def do_create(self, subcmd, opts, *args):
  39. """${cmd_name}: create loop image
  40. Usage:
  41. ${name} ${cmd_name} <ksfile> [OPTS]
  42. ${cmd_option_list}
  43. """
  44. if len(args) != 1:
  45. raise errors.Usage("Extra arguments given")
  46. creatoropts = configmgr.create
  47. ksconf = args[0]
  48. if creatoropts['runtime'] == "bootstrap":
  49. configmgr._ksconf = ksconf
  50. rt_util.bootstrap_mic()
  51. recording_pkgs = []
  52. if len(creatoropts['record_pkgs']) > 0:
  53. recording_pkgs = creatoropts['record_pkgs']
  54. if creatoropts['release'] is not None:
  55. if 'name' not in recording_pkgs:
  56. recording_pkgs.append('name')
  57. if 'vcs' not in recording_pkgs:
  58. recording_pkgs.append('vcs')
  59. configmgr._ksconf = ksconf
  60. # Called After setting the configmgr._ksconf
  61. # as the creatoropts['name'] is reset there.
  62. if creatoropts['release'] is not None:
  63. creatoropts['outdir'] = "%s/%s/images/%s/" % (creatoropts['outdir'],
  64. creatoropts['release'],
  65. creatoropts['name'])
  66. # try to find the pkgmgr
  67. pkgmgr = None
  68. backends = pluginmgr.get_plugins('backend')
  69. if 'auto' == creatoropts['pkgmgr']:
  70. for key in configmgr.prefer_backends:
  71. if key in backends:
  72. pkgmgr = backends[key]
  73. break
  74. else:
  75. for key in backends.keys():
  76. if key == creatoropts['pkgmgr']:
  77. pkgmgr = backends[key]
  78. break
  79. if not pkgmgr:
  80. raise errors.CreatorError("Can't find backend: %s, "
  81. "available choices: %s" %
  82. (creatoropts['pkgmgr'],
  83. ','.join(backends.keys())))
  84. creator = LoopImageCreator(creatoropts,
  85. pkgmgr,
  86. opts.compress_image,
  87. opts.shrink)
  88. if len(recording_pkgs) > 0:
  89. creator._recording_pkgs = recording_pkgs
  90. image_names = [creator.name + ".img"]
  91. image_names.extend(creator.get_image_names())
  92. self.check_image_exists(creator.destdir,
  93. creator.pack_to,
  94. image_names,
  95. creatoropts['release'])
  96. try:
  97. creator.check_depend_tools()
  98. creator.mount(None, creatoropts["cachedir"])
  99. creator.install()
  100. creator.configure(creatoropts["repomd"])
  101. creator.copy_kernel()
  102. creator.unmount()
  103. creator.package(creatoropts["outdir"])
  104. if creatoropts['release'] is not None:
  105. creator.release_output(ksconf,
  106. creatoropts['outdir'],
  107. creatoropts['release'])
  108. creator.print_outimage_info()
  109. except errors.CreatorError:
  110. raise
  111. finally:
  112. creator.cleanup()
  113. msger.info("Finished.")
  114. return 0
  115. @classmethod
  116. def _do_chroot_tar(cls, target, cmd=[]):
  117. mountfp_xml = os.path.splitext(target)[0] + '.xml'
  118. if not os.path.exists(mountfp_xml):
  119. raise errors.CreatorError("No mount point file found for this tar "
  120. "image, please check %s" % mountfp_xml)
  121. import tarfile
  122. tar = tarfile.open(target, 'r')
  123. tmpdir = misc.mkdtemp()
  124. tar.extractall(path=tmpdir)
  125. tar.close()
  126. mntdir = misc.mkdtemp()
  127. loops = []
  128. for (mp, label, name, size, fstype) in load_mountpoints(mountfp_xml):
  129. if fstype in ("ext2", "ext3", "ext4"):
  130. myDiskMount = fs_related.ExtDiskMount
  131. elif fstype == "btrfs":
  132. myDiskMount = fs_related.BtrfsDiskMount
  133. elif fstype in ("vfat", "msdos"):
  134. myDiskMount = fs_related.VfatDiskMount
  135. else:
  136. msger.error("Cannot support fstype: %s" % fstype)
  137. name = os.path.join(tmpdir, name)
  138. size = size * 1024L * 1024L
  139. loop = myDiskMount(fs_related.SparseLoopbackDisk(name, size),
  140. os.path.join(mntdir, mp.lstrip('/')),
  141. fstype, size, label)
  142. try:
  143. msger.verbose("Mount %s to %s" % (mp, mntdir + mp))
  144. fs_related.makedirs(os.path.join(mntdir, mp.lstrip('/')))
  145. loop.mount()
  146. except:
  147. loop.cleanup()
  148. for lp in reversed(loops):
  149. chroot.cleanup_after_chroot("img", lp, None, mntdir)
  150. shutil.rmtree(tmpdir, ignore_errors=True)
  151. raise
  152. loops.append(loop)
  153. try:
  154. if len(cmd) != 0:
  155. cmdline = "/usr/bin/env HOME=/root " + ' '.join(cmd)
  156. else:
  157. cmdline = "/usr/bin/env HOME=/root /bin/bash"
  158. chroot.chroot(mntdir, None, cmdline)
  159. except:
  160. raise errors.CreatorError("Failed to chroot to %s." % target)
  161. finally:
  162. for loop in reversed(loops):
  163. chroot.cleanup_after_chroot("img", loop, None, mntdir)
  164. shutil.rmtree(tmpdir, ignore_errors=True)
  165. @classmethod
  166. def do_chroot(cls, target, cmd=[]):
  167. if target.endswith('.tar'):
  168. import tarfile
  169. if tarfile.is_tarfile(target):
  170. LoopPlugin._do_chroot_tar(target, cmd)
  171. return
  172. else:
  173. raise errors.CreatorError("damaged tarball for loop images")
  174. img = target
  175. imgsize = misc.get_file_size(img) * 1024L * 1024L
  176. imgtype = misc.get_image_type(img)
  177. if imgtype == "btrfsimg":
  178. fstype = "btrfs"
  179. myDiskMount = fs_related.BtrfsDiskMount
  180. elif imgtype in ("ext3fsimg", "ext4fsimg"):
  181. fstype = imgtype[:4]
  182. myDiskMount = fs_related.ExtDiskMount
  183. else:
  184. raise errors.CreatorError("Unsupported filesystem type: %s" \
  185. % imgtype)
  186. extmnt = misc.mkdtemp()
  187. extloop = myDiskMount(fs_related.SparseLoopbackDisk(img, imgsize),
  188. extmnt,
  189. fstype,
  190. 4096,
  191. "%s label" % fstype)
  192. try:
  193. extloop.mount()
  194. except errors.MountError:
  195. extloop.cleanup()
  196. shutil.rmtree(extmnt, ignore_errors=True)
  197. raise
  198. try:
  199. if len(cmd) != 0:
  200. cmdline = ' '.join(cmd)
  201. else:
  202. cmdline = "/bin/bash"
  203. envcmd = fs_related.find_binary_inchroot("env", extmnt)
  204. if envcmd:
  205. cmdline = "%s HOME=/root %s" % (envcmd, cmdline)
  206. chroot.chroot(extmnt, None, cmdline)
  207. except:
  208. raise errors.CreatorError("Failed to chroot to %s." % img)
  209. finally:
  210. chroot.cleanup_after_chroot("img", extloop, None, extmnt)
  211. @classmethod
  212. def do_unpack(cls, srcimg):
  213. image = os.path.join(tempfile.mkdtemp(dir="/var/tmp", prefix="tmp"),
  214. "target.img")
  215. msger.info("Copying file system ...")
  216. shutil.copyfile(srcimg, image)
  217. return image