From: JF Ding Date: Wed, 7 Sep 2011 06:03:51 +0000 (+0900) Subject: enhance loop to mount multi-loop imgs at the same time X-Git-Tag: 0.1~146 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=70a7977fbd688afffa1b2c4edf8b19807594b241;p=tools%2Fmic.git enhance loop to mount multi-loop imgs at the same time using new cmdln options like: --extra-loop=/opt:opt.img,/boot:boot.img --- diff --git a/mic/imager/baseimager.py b/mic/imager/baseimager.py index 5cfda0d..2a2c4e5 100644 --- a/mic/imager/baseimager.py +++ b/mic/imager/baseimager.py @@ -654,7 +654,9 @@ class BaseImageCreator(object): self.get_cachedir(cachedir) # bind mount system directories into _instroot - for (f, dest) in [("/sys", None), ("/proc", None), ("/proc/sys/fs/binfmt_misc", None), + for (f, dest) in [("/sys", None), + ("/proc", None), + ("/proc/sys/fs/binfmt_misc", None), ("/dev/pts", None), (self.get_cachedir(), "/var/cache/yum")]: self.__bindmounts.append(fs.BindChrootMount(f, self._instroot, dest)) diff --git a/mic/imager/loop.py b/mic/imager/loop.py index d81c095..d4638d4 100644 --- a/mic/imager/loop.py +++ b/mic/imager/loop.py @@ -22,7 +22,7 @@ import shutil from mic import kickstart, msger from mic.utils.errors import CreatorError, MountError -from mic.utils.fs_related import ExtDiskMount, BtrfsDiskMount, SparseLoopbackDisk +from mic.utils import fs_related as fs from baseimager import BaseImageCreator @@ -37,7 +37,7 @@ class LoopImageCreator(BaseImageCreator): subsequently loopback-mounted. """ - def __init__(self, creatoropts = None, pkgmgr = None): + def __init__(self, creatoropts = None, pkgmgr = None, extra_loop = {}): """Initialize a LoopImageCreator instance. This method takes the same arguments as ImageCreator.__init__() with @@ -50,7 +50,6 @@ class LoopImageCreator(BaseImageCreator): self.__fslabel = None self.fslabel = self.name - self.__minsize_KB = 0 self.__blocksize = 4096 if self.ks: self.__fstype = kickstart.get_image_fstype(self.ks, "ext3") @@ -59,7 +58,7 @@ class LoopImageCreator(BaseImageCreator): self.__fstype = None self.__fsopts = None - self.__instloop = None + self.__instloops = [] # list of dict of image_name:loop_device self.__imgdir = None if self.ks: @@ -70,12 +69,15 @@ class LoopImageCreator(BaseImageCreator): self._img_name = self.name + ".img" + self.extra_loop = extra_loop + def _set_fstype(self, fstype): self.__fstype = fstype def _set_image_size(self, imgsize): self.__image_size = imgsize + # # Properties # @@ -100,7 +102,6 @@ class LoopImageCreator(BaseImageCreator): #silently truncated to FSLABEL_MAXLEN (32) characters. fslabel = property(__get_fslabel, __set_fslabel) - def __get_image(self): if self.__imgdir is None: raise CreatorError("_image is not valid before calling mount()") @@ -115,11 +116,10 @@ class LoopImageCreator(BaseImageCreator): #Note also, this is a read-only attribute. _image = property(__get_image) - def __get_blocksize(self): return self.__blocksize def __set_blocksize(self, val): - if self.__instloop: + if self.__instloops: raise CreatorError("_blocksize must be set before calling mount()") try: self.__blocksize = int(val) @@ -134,7 +134,6 @@ class LoopImageCreator(BaseImageCreator): #Note, this attribute may only be set before calling mount(). _blocksize = property(__get_blocksize, __set_blocksize) - def __get_fstype(self): return self.__fstype def __set_fstype(self, val): @@ -151,7 +150,6 @@ class LoopImageCreator(BaseImageCreator): #Note also, this attribute may only be set before calling mount(). _fstype = property(__get_fstype, __set_fstype) - def __get_fsopts(self): return self.__fsopts def __set_fsopts(self, val): @@ -166,7 +164,7 @@ class LoopImageCreator(BaseImageCreator): # # Helpers for subclasses # - def _resparse(self, size = None): + def _resparse(self, loop, size = None): """Rebuild the filesystem image to be as sparse as possible. This method should be used by subclasses when staging the final image @@ -182,7 +180,7 @@ class LoopImageCreator(BaseImageCreator): causing the original size specified by the kickstart file to be used (or 4GiB if not specified in the kickstart). """ - return self.__instloop.resparse(size) + loop.resparse(size) # base image def _base_on(self, base_on): shutil.copyfile(base_on, self._image) @@ -198,26 +196,51 @@ class LoopImageCreator(BaseImageCreator): self._base_on(base_on) if self.__fstype in ("ext2", "ext3", "ext4"): - MyDiskMount = ExtDiskMount + MyDiskMount = fs.ExtDiskMount elif self.__fstype == "btrfs": - MyDiskMount = BtrfsDiskMount - - self.__instloop = MyDiskMount(SparseLoopbackDisk(self._image, self.__image_size), - self._instroot, - self.__fstype, - self.__blocksize, - self.fslabel) - - try: - self.__instloop.mount() - except MountError, e: - raise CreatorError("Failed to loopback mount '%s' : %s" % - (self._image, e)) + MyDiskMount = fs.BtrfsDiskMount + + self.__instloops.append({ + 'name': self._img_name, + 'loop': MyDiskMount(fs.SparseLoopbackDisk(self._image, self.__image_size), + self._instroot, + self.__fstype, + self.__blocksize, + self.fslabel) + }) + + for point, name in self.extra_loop.iteritems(): + if name != os.path.basename(name): + msger.warning('can not specify path in %s' % name) + name = os.path.basename(name) + imgname = name.rstrip('.img') + '.img' + if point.startswith('/'): + point = point.lstrip('/') + + self.__instloops.append({ + 'name': imgname, + 'loop': MyDiskMount(fs.SparseLoopbackDisk(os.path.join(self.__imgdir, imgname), + self.__image_size), + os.path.join(self._instroot, point), + self.__fstype, + self.__blocksize, + name) + }) + + for item in self.__instloops: + try: + msger.verbose('Mounting image "%s" on "%s"' %(item['name'], item['loop'].mountdir)) + fs.makedirs(item['loop'].mountdir) + item['loop'].mount() + except MountError, e: + raise def _unmount_instroot(self): - if not self.__instloop is None: - self.__instloop.cleanup() + for item in reversed(self.__instloops): + item['loop'].cleanup() def _stage_final_image(self): - self._resparse() - shutil.move(self._image, self._outdir + "/" + self._img_name) + for item in self.__instloops: + self._resparse(item['loop']) + shutil.move(os.path.join(self.__imgdir, item['name']), + os.path.join(self._outdir, item['name'])) diff --git a/mic/utils/misc.py b/mic/utils/misc.py index 4285cd3..e39d804 100644 --- a/mic/utils/misc.py +++ b/mic/utils/misc.py @@ -202,12 +202,10 @@ def get_uncompressed_data_from_url(url, filename, proxies): suffix = None if filename.endswith(".gz"): suffix = ".gz" - gunzip = find_binary_path('gunzip') - runner.show([gunzip, "-f", filename]) + runner.quiet(['gunzip', "-f", filename]) elif filename.endswith(".bz2"): suffix = ".bz2" - bunzip2 = find_binary_path('bunzip2') - runner.show([bunzip2, "-f", filename]) + runner.quiet(['bunzip2', "-f", filename]) if suffix: filename = filename.replace(suffix, "") return filename @@ -297,7 +295,7 @@ def get_metadata_from_repos(repostrs, cachedir): repokey = get_metadata_from_repo(baseurl, proxies, cachedir, reponame, "repodata/repomd.xml.key") except CreatorError: repokey = None - msger.warning("can't get %s/%s" % (baseurl, "repodata/repomd.xml.key")) + msger.warning("\ncan't get %s/%s" % (baseurl, "repodata/repomd.xml.key")) my_repo_metadata.append({"name":reponame, "baseurl":baseurl, "repomd":repomd, "primary":primary, "cachedir":cachedir, "proxies":proxies, "patterns":patterns, "comps":comps, "repokey":repokey}) diff --git a/plugins/imager/loop_plugin.py b/plugins/imager/loop_plugin.py index c2d7ffa..b2fe531 100644 --- a/plugins/imager/loop_plugin.py +++ b/plugins/imager/loop_plugin.py @@ -22,7 +22,7 @@ import shutil import tempfile from mic import configmgr, pluginmgr, chroot, msger -from mic.utils import misc, fs_related, errors +from mic.utils import misc, fs_related, errors, cmdln import mic.imager.loop as loop from mic.pluginbase import ImagerPlugin @@ -30,6 +30,11 @@ class LoopPlugin(ImagerPlugin): name = 'loop' @classmethod + @cmdln.option('-E', '--extra-loop', dest='extra_loop', + help='Extra loop image to be mounted, multiple :name_of_loop_file pairs expected, and ' + 'joined by using "," like the following sample:' + ' --extr-loop=/opt:opt.img,/boot:boot.img' + ) def do_create(self, subcmd, opts, *args): """${cmd_name}: create loop image @@ -45,6 +50,14 @@ class LoopPlugin(ImagerPlugin): else: raise errors.Usage("Extra arguments given") + try: + if opts.extra_loop: + extra_loop = dict([[i.strip() for i in one.split(':')] for one in opts.extra_loop.split(',')]) + else: + extra_loop = {} + except ValueError: + raise errors.Usage("invalid --extra-loop option specified") + cfgmgr = configmgr.getConfigMgr() creatoropts = cfgmgr.create cfgmgr.setProperty("ksconf", ksconf) @@ -59,7 +72,7 @@ class LoopPlugin(ImagerPlugin): if not pkgmgr: raise errors.CreatorError("Can't find package manager: %s" % creatoropts['pkgmgr']) - creator = loop.LoopImageCreator(creatoropts, pkgmgr) + creator = loop.LoopImageCreator(creatoropts, pkgmgr, extra_loop) try: creator.check_depend_tools() creator.mount(None, creatoropts["cachedir"]) @@ -67,6 +80,8 @@ class LoopPlugin(ImagerPlugin): creator.configure(creatoropts["repomd"]) creator.unmount() creator.package(creatoropts["outdir"]) + creator.print_outimage_info() + except errors.CreatorError: raise finally: diff --git a/plugins/imager/raw_plugin.py b/plugins/imager/raw_plugin.py index 914b72a..995d271 100644 --- a/plugins/imager/raw_plugin.py +++ b/plugins/imager/raw_plugin.py @@ -70,7 +70,6 @@ class RawPlugin(ImagerPlugin): creator.configure(creatoropts["repomd"]) creator.unmount() creator.package(creatoropts["outdir"]) - outimage = creator.outimage creator.print_outimage_info() outimage = creator.outimage