from mic.conf import configmgr
from mic.utils import misc, errors, runner, fs_related
+#####################################################################
+### GLOBAL CONSTANTS
+#####################################################################
+
+chroot_bindmounts = None
chroot_lockfd = -1
chroot_lock = ""
BIND_MOUNTS = (
"/sys",
"/dev",
"/dev/pts",
- "/dev/shm",
"/var/lib/dbus",
"/var/run/dbus",
"/var/lock",
)
-def cleanup_after_chroot(targettype,imgmount,tmpdir,tmpmnt):
- if imgmount and targettype == "img":
- imgmount.cleanup()
+#####################################################################
+### GLOBAL ROUTINE
+#####################################################################
- if tmpdir:
- shutil.rmtree(tmpdir, ignore_errors = True)
+def get_bindmounts(chrootdir, bindmounts):
+ global chroot_bindmounts
- if tmpmnt:
- shutil.rmtree(tmpmnt, ignore_errors = True)
+ if chroot_bindmounts:
+ return chroot_bindmounts
-def check_bind_mounts(chrootdir, bindmounts):
chrootmounts = []
+ bindmounts = bindmounts or ""
+
for mount in bindmounts.split(";"):
if not 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]):
- return False
+ # if some bindmount is not existed, but it's created inside
+ # chroot, this is not expected
+ if not os.path.exists(srcdst[0]):
+ os.makedirs(srcdst[0])
- if srcdst[1] == "" or srcdst[1] == "none":
- srcdst[1] = None
-
- if srcdst[0] in BIND_MOUNTS or srcdst[0] == '/':
+ if not os.path.isdir(srcdst[0]):
continue
- if chrootdir:
- if not srcdst[1]:
- srcdst[1] = os.path.abspath(os.path.expanduser(srcdst[0]))
- else:
- srcdst[1] = os.path.abspath(os.path.expanduser(srcdst[1]))
-
- tmpdir = chrootdir + "/" + srcdst[1]
- if os.path.isdir(tmpdir):
- msger.warning("Warning: dir %s has existed." % tmpdir)
-
- return True
-
-def cleanup_mounts(chrootdir):
- umountcmd = misc.find_binary_path("umount")
- abs_chrootdir = os.path.abspath(chrootdir)
- mounts = open('/proc/mounts').readlines()
- for line in reversed(mounts):
- if abs_chrootdir not in line:
+ if srcdst[0] in BIND_MOUNTS or srcdst[0] == '/':
+ msger.verbose("%s will be mounted by default." % srcdst[0])
continue
- point = line.split()[1]
-
- # '/' to avoid common name prefix
- if abs_chrootdir == point or point.startswith(abs_chrootdir + '/'):
- args = [ umountcmd, "-l", point ]
- ret = runner.quiet(args)
- if ret != 0:
- msger.warning("failed to unmount %s" % point)
-
- return 0
-
-def setup_chrootenv(chrootdir, bindmounts = None, mountparent = True):
- global chroot_lockfd, chroot_lock
-
- def get_bind_mounts(chrootdir, bindmounts, mountparent = True):
- chrootmounts = []
- if bindmounts in ("", None):
- bindmounts = ""
-
- for mount in bindmounts.split(";"):
- if not mount:
- continue
-
- srcdst = mount.split(":")
- srcdst[0] = os.path.abspath(os.path.expanduser(srcdst[0]))
- if len(srcdst) == 1:
- srcdst.append("none")
-
- # if some bindmount is not existed, but it's created inside
- # chroot, this is not expected
- if not os.path.exists(srcdst[0]):
- os.makedirs(srcdst[0])
-
- if not os.path.isdir(srcdst[0]):
- continue
-
- if srcdst[0] in BIND_MOUNTS or srcdst[0] == '/':
- msger.verbose("%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]):
- msger.warning("%s has existed in %s , skip it."\
- % (srcdst[1], chrootdir))
- continue
-
- chrootmounts.append(fs_related.BindChrootMount(srcdst[0],
- chrootdir,
- srcdst[1]))
-
- """Default bind mounts"""
- for pt in BIND_MOUNTS:
- if not os.path.exists(pt):
+ 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]):
+ msger.warning("%s has existed in %s , skip it."\
+ % (srcdst[1], chrootdir))
continue
- chrootmounts.append(fs_related.BindChrootMount(pt,
- chrootdir,
- None))
-
- if mountparent:
- 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:
- msger.verbose("bind_mount: %s -> %s" % (b.src, b.dest))
- b.mount()
-
- def setup_resolv(chrootdir):
- try:
- shutil.copyfile("/etc/resolv.conf", chrootdir + "/etc/resolv.conf")
- except:
- pass
- globalmounts = get_bind_mounts(chrootdir, bindmounts, mountparent)
- bind_mount(globalmounts)
+ chrootmounts.append(fs_related.BindChrootMount(srcdst[0],
+ chrootdir,
+ srcdst[1]))
- setup_resolv(chrootdir)
+ """Default bind mounts"""
+ for pt in BIND_MOUNTS:
+ if not os.path.exists(pt):
+ continue
+ chrootmounts.append(fs_related.BindChrootMount(pt,
+ chrootdir,
+ None))
+
+ for kernel in os.listdir("/lib/modules"):
+ chrootmounts.append(fs_related.BindChrootMount(
+ "/lib/modules/"+kernel,
+ chrootdir,
+ None,
+ "ro"))
+ chroot_bindmounts = chrootmounts
+ return chroot_bindmounts
+
+#####################################################################
+### SETUP CHROOT ENVIRONMENT
+#####################################################################
+
+def bind_mount(chrootmounts):
+ for b in chrootmounts:
+ msger.verbose("bind_mount: %s -> %s" % (b.src, b.dest))
+ b.mount()
+
+def setup_resolv(chrootdir):
+ try:
+ shutil.copyfile("/etc/resolv.conf", chrootdir + "/etc/resolv.conf")
+ except:
+ pass
+def setup_mtab(chrootdir):
mtab = "/etc/mtab"
dstmtab = chrootdir + mtab
if not os.path.islink(dstmtab):
shutil.copyfile(mtab, dstmtab)
+def setup_chrootenv(chrootdir, bindmounts = None):
+ # bind mounting
+ bind_mount(get_bindmounts(chrootdir, bindmounts))
+ # setup resolv.conf
+ setup_resolv(chrootdir)
+ # update /etc/mtab
+ setup_mtab(chrootdir)
+
+ # lock
chroot_lock = os.path.join(chrootdir, ".chroot.lock")
chroot_lockfd = open(chroot_lock, "w")
- return globalmounts
+ return None
-def cleanup_chrootenv(chrootdir, bindmounts=None, globalmounts=()):
- global chroot_lockfd, chroot_lock
+######################################################################
+### CLEANUP CHROOT ENVIRONMENT
+######################################################################
- def bind_unmount(chrootmounts):
- for b in reversed(chrootmounts):
- msger.verbose("bind_unmount: %s -> %s" % (b.src, b.dest))
- b.unmount()
+def bind_unmount(chrootmounts):
+ for b in reversed(chrootmounts):
+ msger.verbose("bind_unmount: %s -> %s" % (b.src, b.dest))
+ b.unmount()
- def cleanup_resolv(chrootdir):
+def cleanup_resolv(chrootdir):
+ try:
+ fd = open(chrootdir + "/etc/resolv.conf", "w")
+ fd.truncate(0)
+ fd.close()
+ except:
+ pass
+
+def kill_processes(chrootdir):
+ import glob
+ for fp in glob.glob("/proc/*/root"):
try:
- fd = open(chrootdir + "/etc/resolv.conf", "w")
- fd.truncate(0)
- fd.close()
+ if os.readlink(fp) == chrootdir:
+ pid = int(fp.split("/")[2])
+ os.kill(pid, 9)
except:
pass
- def kill_processes(chrootdir):
- import glob
- for fp in glob.glob("/proc/*/root"):
- try:
- if os.readlink(fp) == chrootdir:
- pid = int(fp.split("/")[2])
- os.kill(pid, 9)
- except:
- pass
-
- def cleanup_mountdir(chrootdir, bindmounts):
- if bindmounts == "" or bindmounts == None:
- return
- chrootmounts = []
- for mount in bindmounts.split(";"):
- if not mount:
- continue
-
- srcdst = mount.split(":")
-
- if len(srcdst) == 1:
- srcdst.append("none")
+def cleanup_mtab(chrootdir):
+ if os.path.exists(chrootdir + "/etc/mtab"):
+ os.unlink(chrootdir + "/etc/mtab")
- if srcdst[0] == "/":
- continue
+def cleanup_mounts(chrootdir):
+ umountcmd = misc.find_binary_path("umount")
+ mounts = open('/proc/mounts').readlines()
+ for line in reversed(mounts):
+ if chrootdir not in line:
+ continue
- if srcdst[1] == "" or srcdst[1] == "none":
- srcdst[1] = srcdst[0]
+ point = line.split()[1]
- 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:
- msger.warning("Warning: dir %s isn't empty." % tmpdir)
+ # '/' to avoid common name prefix
+ if chrootdir == point or point.startswith(chrootdir + '/'):
+ args = [ umountcmd, "-l", point ]
+ ret = runner.quiet(args)
+ if ret != 0:
+ msger.warning("failed to unmount %s" % point)
+ if os.path.isdir(point) and len(os.listdir(point)) == 0:
+ shutil.rmtree(point)
+ else:
+ msger.warning("%s is not directory or is not empty" % point)
+def cleanup_chrootenv(chrootdir, bindmounts=None, globalmounts=()):
+ # unlock
chroot_lockfd.close()
- bind_unmount(globalmounts)
-
- if not fs_related.my_fuser(chroot_lock):
- tmpdir = chrootdir + "/parentroot"
- if os.path.exists(tmpdir) and 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
+ kill_processes(chrootdir)
+ # clean mtab
+ cleanup_mtab(chrootdir)
+ # clean resolv.conf
+ cleanup_resolv(chrootdir)
+ # bind umounting
+ bind_unmount(get_bindmounts(chrootdir, bindmounts))
+ # clean up mounts
+ cleanup_mounts(chrootdir)
+
+ return None
+
+#####################################################################
+### CHROOT STUFF
+#####################################################################
+
+def cleanup_after_chroot(targettype, imgmount, tmpdir, tmpmnt):
+ if imgmount and targettype == "img":
+ imgmount.cleanup()
- kill_processes(chrootdir)
+ if tmpdir:
+ shutil.rmtree(tmpdir, ignore_errors = True)
- cleanup_mountdir(chrootdir, bindmounts)
+ if tmpmnt:
+ shutil.rmtree(tmpmnt, ignore_errors = True)
def chroot(chrootdir, bindmounts = None, execute = "/bin/bash"):
def mychroot():
else:
msger.warning(wrnmsg)
- dev_null = os.open("/dev/null", os.O_WRONLY)
files_to_check = ["/bin/bash", "/sbin/init"]
architecture_found = False
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." \