From 833f5cffddd5d1d0acae38d25f55326f922b9a37 Mon Sep 17 00:00:00 2001 From: Sebastien Luttringer <sebastien.luttringer@smartjog.com> Date: Fri, 21 Oct 2011 15:56:50 +0200 Subject: [PATCH] add chroot command this command is and helper to chroot inside payload mounting /{proc,sys,dev,dev/pts} fs inside the chroot and disable daemon restart --- bin/is | 15 ++++++++++++ installsystems/tools.py | 54 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/bin/is b/bin/is index 3f08269..f84e399 100755 --- a/bin/is +++ b/bin/is @@ -117,6 +117,12 @@ def c_check(parser, args): for reponame in args.repository: repoman[reponame].check() +def c_chroot(parser, args): + ''' + Helper to go cleanly inside a chroot + ''' + istools.chroot(args.path, shell=args.shell, mount=not args.no_mount) + def c_clean(parser, args): ''' Remove unreferenced files from repoistory @@ -366,6 +372,15 @@ p_check = subparsers.add_parser("check", help=c_check.__doc__.lower()) p_check.add_argument("repository", nargs="+", help="repositories to check") p_check.set_defaults(func=c_check) +# chroot command parser +p_chroot = subparsers.add_parser("chroot", help=c_chroot.__doc__.lower()) +p_chroot.add_argument("-m", "--no-mount", action="store_true", default=False, + help="disable mouting of /{proc,dev,sys} inside chroot") +p_chroot.add_argument("-s", "--shell", default="/bin/bash", + help="shell to call inside chroot") +p_chroot.add_argument("path") +p_chroot.set_defaults(func=c_chroot) + # clean command parser p_clean = subparsers.add_parser("clean", help=c_clean.__doc__.lower()) p_clean.add_argument("repository", nargs="+", help="repositories to clean") diff --git a/installsystems/tools.py b/installsystems/tools.py index 6ccf791..826bae6 100644 --- a/installsystems/tools.py +++ b/installsystems/tools.py @@ -13,6 +13,8 @@ import shutil import urllib2 import time +from subprocess import call, check_call, CalledProcessError + from installsystems.progressbar import ProgressBar, Percentage, FileTransferSpeed from installsystems.progressbar import Bar, BouncingBar, ETA, UnknownLength from installsystems.tarball import Tarball @@ -327,3 +329,55 @@ def human_size(num): return "%3.1f%s" % (num, x) num /= 1024.0 return "%3.1f%s" % (num, x) + +def chroot(path, shell="/bin/bash", mount=True): + ''' + Chroot inside a directory and call shell + if mount is true, mount /{proc,dev,sys} inside the chroot + ''' + # try to guest distro + if os.path.exists(os.path.join(path, "etc/debian_version")): + distro="debian" + elif os.path.exists(os.path.join(path, "etc/arch-release")): + distro="archlinux" + else: + distro=None + # try to mount /proc /sys /dev + if mount: + mps = ("proc", "sys", "dev", "dev/pts") + arrow("Mouting filesystems") + for mp in mps: + origin = "/%s" % mp + target = os.path.join(path, mp) + if os.path.ismount(origin) and os.path.isdir(target): + arrow("%s -> %s" % (origin, target), 1) + try: + check_call(["mount", "--bind", origin, target], close_fds=True) + except CalledProcessError as e: + warn("Mount failed: %s.\n" % e) + # in case of debian disable policy + if distro == "debian": + arrow("Creating debian chroot housekeepers") + # create a chroot header + try: open(os.path.join(path, "etc/debian_chroot"), "w").write("CHROOT") + except: pass + # fake policy-d + try: open(os.path.join(path, "usr/sbin/policy-rc.d"), "w").write("#!/bin/bash\nexit 42\n") + except: pass + # chrooting + arrow("Chrooting inside %s and running %s" % (path, shell)) + call(["chroot", path, shell], close_fds=True) + # cleaning debian stuff + if distro == "debian": + arrow("Removing debian chroot housekeepers") + for f in ("etc/debian_chroot", "usr/sbin/policy-rc.d"): + try: os.unlink(os.path.join(path, f)) + except: pass + # unmounting + if mount: + arrow("Unmouting filesystems") + for mp in reversed(mps): + target = os.path.join(path, mp) + if os.path.ismount(target): + arrow(target, 1) + call(["umount", target], close_fds=True) -- GitLab