Commit 833f5cff authored by Sebastien Luttringer's avatar Sebastien Luttringer
Browse files

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
parent a996f3bf
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -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")
+54 −0
Original line number Diff line number Diff line
@@ -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)