From: Zhou Shuangquan Date: Thu, 28 Jul 2011 06:10:46 +0000 (+0800) Subject: Rework interfaces and move some common functions to misc.py X-Git-Tag: 0.1~228 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b80120670d07db5f705bc3094f940b86ebe0bfd4;p=platform%2Fupstream%2Fmic.git Rework interfaces and move some common functions to misc.py Note: remove "pack/unpack" add "_mount_srcimg/_umount_srcimg" for supporting chroot add "_base_on" for supporting convertor Signed-off-by: Zhou Shuangquan --- diff --git a/micng/pluginbase/imager_plugin.py b/micng/pluginbase/imager_plugin.py index fb5aacc..15014d0 100755 --- a/micng/pluginbase/imager_plugin.py +++ b/micng/pluginbase/imager_plugin.py @@ -787,24 +787,28 @@ class ImagerPlugin(PluginBase): self.do_umount() self.do_package() + def _base_on(self, base_on): + """Support Image Convertor, unpack the source image for building the instroot directory. + + Subclass need a actual implementation. + """ + shutil.copyfile(base_on, self._image) + def _mount_srcimg(self, srcimg): """Mount source image. - This method may be used by subclasses to mount source image for convertor/chroot, - e.g. mount a raw image. There is no default implementation. + This method may be used by subclasses to mount source image for Chroot, + There is no default implementation. + e.g. + "livecd": + imgcreate.DiskMount(imgcreate.LoopbackDisk(self.img, 0), self.imgmnt) """ pass def _umount_srcimg(self, srcimg): """Umount source image. - This method may be used by subclasses to umount source image for convertor/chroot, + This method may be used by subclasses to umount source image for Chroot, e.g. umount a raw image. There is no default implementation. """ pass - - def pack(self): - self.do_package() - - def unpack(self, srcimg): - self._mount_srcimg(srcimg) diff --git a/micng/utils/misc.py b/micng/utils/misc.py old mode 100644 new mode 100755 index d36e5e6..b60590e --- a/micng/utils/misc.py +++ b/micng/utils/misc.py @@ -43,9 +43,11 @@ except ImportError: import cElementTree xmlparse = cElementTree.parse -from errors import * -from fs_related import * +import errors as errors +import fs_related as fs_related +chroot_lockfd = -1 +chroot_lock = "" def setlocale(): try: @@ -1144,3 +1146,176 @@ def add_optparser(arg): f.optparser = arg return f return decorate + +def setup_chrootenv(chrootdir, bindmounts = None):##move to mic/utils/misc + global chroot_lockfd, chroot_lock + def get_bind_mounts(chrootdir, bindmounts): + chrootmounts = [] + if bindmounts in ("", None): + bindmounts = "" + mounts = bindmounts.split(";") + for mount in mounts: + if mount == "": + continue + srcdst = mount.split(":") + srcdst[0] = os.path.abspath(os.path.expanduser(srcdst[0])) + if len(srcdst) == 1: + srcdst.append("none") + if not os.path.isdir(srcdst[0]): + continue + if srcdst[0] in ("/proc", "/proc/sys/fs/binfmt_misc", "/", "/sys", "/dev", "/dev/pts", "/dev/shm", "/var/lib/dbus", "/var/run/dbus", "/var/lock"): + pwarning("%s will be mounted by default." % srcdst[0]) + continue + if srcdst[1] == "" or srcdst[1] == "none": + srcdst[1] = None + else: + srcdst[1] = os.path.abspath(os.path.expanduser(srcdst[1])) + if os.path.isdir(chrootdir + "/" + srcdst[1]): + pwarning("%s has existed in %s , skip it." % (srcdst[1], chrootdir)) + continue + chrootmounts.append(fs_related.BindChrootMount(srcdst[0], chrootdir, srcdst[1])) + + """Default bind mounts""" + chrootmounts.append(fs_related.BindChrootMount("/proc", chrootdir, None)) + chrootmounts.append(fs_related.BindChrootMount("/proc/sys/fs/binfmt_misc", chrootdir, None)) + chrootmounts.append(fs_related.BindChrootMount("/sys", chrootdir, None)) + chrootmounts.append(fs_related.BindChrootMount("/dev", chrootdir, None)) + chrootmounts.append(fs_related.BindChrootMount("/dev/pts", chrootdir, None)) + chrootmounts.append(fs_related.BindChrootMount("/dev/shm", chrootdir, None)) + chrootmounts.append(fs_related.BindChrootMount("/var/lib/dbus", chrootdir, None)) + chrootmounts.append(fs_related.BindChrootMount("/var/run/dbus", chrootdir, None)) + chrootmounts.append(fs_related.BindChrootMount("/var/lock", chrootdir, None)) + chrootmounts.append(fs_related.BindChrootMount("/", chrootdir, "/parentroot", "ro")) + for kernel in os.listdir("/lib/modules"): + chrootmounts.append(fs_related.BindChrootMount("/lib/modules/" + kernel, chrootdir, None, "ro")) + + return chrootmounts + + def bind_mount(chrootmounts): + for b in chrootmounts: + print "bind_mount: %s -> %s" % (b.src, b.dest) + b.mount() + + def setup_resolv(chrootdir): + shutil.copyfile("/etc/resolv.conf", chrootdir + "/etc/resolv.conf") + + globalmounts = get_bind_mounts(chrootdir, bindmounts) + bind_mount(globalmounts) + setup_resolv(chrootdir) + mtab = "/etc/mtab" + dstmtab = chrootdir + mtab + if not os.path.islink(dstmtab): + shutil.copyfile(mtab, dstmtab) + chroot_lock = os.path.join(chrootdir, ".chroot.lock") + chroot_lockfd = open(chroot_lock, "w") + return globalmounts + +def cleanup_chrootenv(chrootdir, bindmounts = None, globalmounts = []): + global chroot_lockfd, chroot_lock + def bind_unmount(chrootmounts): + chrootmounts.reverse() + for b in chrootmounts: + print "bind_unmount: %s -> %s" % (b.src, b.dest) + b.unmount() + + def cleanup_resolv(chrootdir): + fd = open(chrootdir + "/etc/resolv.conf", "w") + fd.truncate(0) + fd.close() + + def kill_processes(chrootdir): + for file in glob.glob("/proc/*/root"): + try: + if os.readlink(file) == chrootdir: + pid = int(file.split("/")[2]) + os.kill(pid, 9) + except: + pass + + def cleanup_mountdir(chrootdir, bindmounts): + if bindmounts == "" or bindmounts == None: + return + chrootmounts = [] + mounts = bindmounts.split(";") + for mount in mounts: + if mount == "": + continue + srcdst = mount.split(":") + if len(srcdst) == 1: + srcdst.append("none") + if srcdst[1] == "" or srcdst[1] == "none": + srcdst[1] = srcdst[0] + srcdst[1] = os.path.abspath(os.path.expanduser(srcdst[1])) + tmpdir = chrootdir + "/" + srcdst[1] + if os.path.isdir(tmpdir): + if len(os.listdir(tmpdir)) == 0: + shutil.rmtree(tmpdir, ignore_errors = True) + else: + print "Warning: dir %s isn't empty." % tmpdir + + chroot_lockfd.close() + bind_unmount(globalmounts) + if not fs_releate.my_fuser(chroot_lock): + tmpdir = chrootdir + "/parentroot" + if len(os.listdir(tmpdir)) == 0: + shutil.rmtree(tmpdir, ignore_errors = True) + cleanup_resolv(chrootdir) + if os.path.exists(chrootdir + "/etc/mtab"): + os.unlink(chrootdir + "/etc/mtab") + kill_processes(chrootdir) + cleanup_mountdir(chrootdir, bindmounts) + +def chroot(chrootdir, bindmounts = None, execute = "/bin/bash"): + def mychroot(): + os.chroot(chrootdir) + os.chdir("/") + + dev_null = os.open("/dev/null", os.O_WRONLY) + files_to_check = ["/bin/bash", "/sbin/init"] + + architecture_found = False + + """ Register statically-linked qemu-arm if it is an ARM fs """ + qemu_emulator = None + + for ftc in files_to_check: + ftc = "%s/%s" % (chrootdir,ftc) + + # Return code of 'file' is "almost always" 0 based on some man pages + # so we need to check the file existance first. + if not os.path.exists(ftc): + continue + + filecmd = find_binary_path("file") + initp1 = subprocess.Popen([filecmd, ftc], stdout=subprocess.PIPE, stderr=dev_null) + fileOutput = initp1.communicate()[0].strip().split("\n") + + for i in range(len(fileOutput)): + if fileOutput[i].find("ARM") > 0: + qemu_emulator = setup_qemu_emulator.(chrootdir, "arm") + architecture_found = True + break + if fileOutput[i].find("Intel") > 0: + architecture_found = True + break + + if architecture_found: + break + + os.close(dev_null) + if not architecture_found: + raise errors.CreatorError("Failed to get architecture from any of the following files %s from chroot." % files_to_check) + + try: + print "Launching shell. Exit to continue." + print "----------------------------------" + globalmounts = setup_chrootenv(chrootdir, bindmounts) + args = shlex.split(execute) + subprocess.call(args, preexec_fn = mychroot) + except OSError, (err, msg): + raise errors.CreatorError("Failed to chroot: %s" % msg) + finally: + cleanup_chrootenv(chrootdir, bindmounts, globalmounts) + if qemu_emulator: + os.unlink(chrootdir + qemu_emulator) +