Changes needed for livecd creation

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.
This commit is contained in:
Brian C. Lane 2011-08-24 15:07:19 -07:00
parent c089b479f1
commit d6280b9cf0
2 changed files with 73 additions and 2 deletions

View File

@ -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:
logger.debug(traceback.format_exc())
if self.mount_dir:
logger.info("Partition mounted on {0} size={1}".format(self.mount_dir, self.mount_size))
else:
logger.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={}):

View File

@ -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)