From: "Brian C. Lane" <bcl@xxxxxxxxxx> Allow passing of size to create_runtime, add PartitionMount context to use kpartx to mount partitioned file images. Add resetting the selinux context on the newly created rootfs. --- src/pylorax/imgutils.py | 64 ++++++++++++++++++++++++++++++++++++++++++++ src/pylorax/treebuilder.py | 11 ++++++- 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/src/pylorax/imgutils.py b/src/pylorax/imgutils.py index e7526b0..3dd6460 100644 --- a/src/pylorax/imgutils.py +++ b/src/pylorax/imgutils.py @@ -24,6 +24,7 @@ import os, tempfile from os.path import join, dirname from pylorax.sysutils import cpfile from subprocess import * +import traceback ######## Functions for making container images (cpio, squashfs) ########## @@ -191,6 +192,69 @@ class Mount(object): def __exit__(self, exc_type, exc_value, traceback): umount(self.mnt) +class PartitionMount(object): + """ Mount a partitioned image file using kpartx """ + def __init__(self, disk_img, mount_ok=None): + """ + disk_img is the full path to a partitioned disk image + mount_ok is a function that is passed the mount point and + returns True if it should be mounted. + """ + self.mount_dir = None + self.disk_img = disk_img + self.mount_ok = mount_ok + + # Default is to mount partition with /etc/passwd + if not self.mount_ok: + self.mount_ok = lambda mount_dir: os.path.isfile(mount_dir+"/etc/passwd") + + # Example kpartx output + # kpartx -p p -v -a /tmp/diskV2DiCW.im + # add map loop2p1 (253:2): 0 3481600 linear /dev/loop2 2048 + # add map loop2p2 (253:3): 0 614400 linear /dev/loop2 3483648 + cmd = [ "kpartx", "-v", "-p", "p", "-a", self.disk_img ] + logger.debug(cmd) + kpartx_output = check_output(cmd) + logger.debug(kpartx_output) + + # list of (deviceName, sizeInBytes) + self.loop_devices = [] + for line in kpartx_output.splitlines(): + # add map loop2p3 (253:4): 0 7139328 linear /dev/loop2 528384 + # 3rd element is size in 512 byte blocks + if line.startswith("add map "): + fields = line[8:].split() + self.loop_devices.append( (fields[0], int(fields[3])*512) ) + + def __enter__(self): + # Mount the device selected by mount_ok, if possible + mount_dir = tempfile.mkdtemp() + for dev, size in self.loop_devices: + try: + mount( "/dev/mapper/"+dev, mnt=mount_dir ) + if self.mount_ok(mount_dir): + self.mount_dir = mount_dir + self.mount_dev = dev + self.mount_size = size + break + umount( mount_dir ) + except CalledProcessError: + logging.debug(traceback.format_exc()) + if self.mount_dir: + logging.info("Partition mounted on {0} size={1}".format(self.mount_dir, self.mount_size)) + else: + logging.debug("Unable to mount anything from {0}".format(self.disk_img)) + os.rmdir(mount_dir) + return self + + def __exit__(self, exc_type, exc_value, traceback): + if self.mount_dir: + umount( self.mount_dir ) + os.rmdir(self.mount_dir) + self.mount_dir = None + call(["kpartx", "-d", self.disk_img]) + + ######## Functions for making filesystem images ########################## def mkfsimage(fstype, rootdir, outfile, size=None, mkfsargs=[], mountargs="", graft={}): diff --git a/src/pylorax/treebuilder.py b/src/pylorax/treebuilder.py index 57cf530..b1b5b0c 100644 --- a/src/pylorax/treebuilder.py +++ b/src/pylorax/treebuilder.py @@ -127,13 +127,20 @@ class RuntimeBuilder(object): check_call(["depmod", "-a", "-F", ksyms, "-b", root, kver]) generate_module_info(moddir+kver, outfile=moddir+"module-info") - def create_runtime(self, outfile="/tmp/squashfs.img", compression="xz", compressargs=[]): + def create_runtime(self, outfile="/tmp/squashfs.img", compression="xz", compressargs=[], size=2): # make live rootfs image - must be named "LiveOS/rootfs.img" for dracut workdir = joinpaths(os.path.dirname(outfile), "runtime-workdir") - fssize = 2 * (1024*1024*1024) # 2GB sparse file compresses down to nothin' + fssize = size * (1024*1024*1024) # 2GB sparse file compresses down to nothin' os.makedirs(joinpaths(workdir, "LiveOS")) imgutils.mkext4img(self.vars.root, joinpaths(workdir, "LiveOS/rootfs.img"), label="Anaconda", size=fssize) + + # Reset selinux context on new rootfs + with imgutils.LoopDev( joinpaths(workdir, "LiveOS/rootfs.img") ) as loopdev: + with imgutils.Mount(loopdev) as mnt: + cmd = ["chroot", mnt, "setfiles", "-e", "/proc", "-e", "/sys", "-e", "/dev", "-e", "/selinux", "/etc/selinux/targeted/contexts/files/file_contexts", "/"] + check_call(cmd) + # squash the live rootfs and clean up workdir imgutils.mksquashfs(workdir, outfile, compression, compressargs) remove(workdir) -- 1.7.6.4 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list