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:
parent
c089b479f1
commit
d6280b9cf0
@ -24,6 +24,7 @@ import os, tempfile
|
|||||||
from os.path import join, dirname
|
from os.path import join, dirname
|
||||||
from pylorax.sysutils import cpfile
|
from pylorax.sysutils import cpfile
|
||||||
from subprocess import *
|
from subprocess import *
|
||||||
|
import traceback
|
||||||
|
|
||||||
######## Functions for making container images (cpio, squashfs) ##########
|
######## Functions for making container images (cpio, squashfs) ##########
|
||||||
|
|
||||||
@ -191,6 +192,69 @@ class Mount(object):
|
|||||||
def __exit__(self, exc_type, exc_value, traceback):
|
def __exit__(self, exc_type, exc_value, traceback):
|
||||||
umount(self.mnt)
|
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 ##########################
|
######## Functions for making filesystem images ##########################
|
||||||
|
|
||||||
def mkfsimage(fstype, rootdir, outfile, size=None, mkfsargs=[], mountargs="", graft={}):
|
def mkfsimage(fstype, rootdir, outfile, size=None, mkfsargs=[], mountargs="", graft={}):
|
||||||
|
@ -127,13 +127,20 @@ class RuntimeBuilder(object):
|
|||||||
check_call(["depmod", "-a", "-F", ksyms, "-b", root, kver])
|
check_call(["depmod", "-a", "-F", ksyms, "-b", root, kver])
|
||||||
generate_module_info(moddir+kver, outfile=moddir+"module-info")
|
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
|
# make live rootfs image - must be named "LiveOS/rootfs.img" for dracut
|
||||||
workdir = joinpaths(os.path.dirname(outfile), "runtime-workdir")
|
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"))
|
os.makedirs(joinpaths(workdir, "LiveOS"))
|
||||||
imgutils.mkext4img(self.vars.root, joinpaths(workdir, "LiveOS/rootfs.img"),
|
imgutils.mkext4img(self.vars.root, joinpaths(workdir, "LiveOS/rootfs.img"),
|
||||||
label="Anaconda", size=fssize)
|
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
|
# squash the live rootfs and clean up workdir
|
||||||
imgutils.mksquashfs(workdir, outfile, compression, compressargs)
|
imgutils.mksquashfs(workdir, outfile, compression, compressargs)
|
||||||
remove(workdir)
|
remove(workdir)
|
||||||
|
Loading…
Reference in New Issue
Block a user