2013-07-24 20:41:03 +00:00
|
|
|
#!/usr/bin/python
|
2011-09-24 00:36:09 +00:00
|
|
|
#
|
|
|
|
# Live Media Creator
|
|
|
|
#
|
2014-04-04 21:38:51 +00:00
|
|
|
# Copyright (C) 2011-2014 Red Hat, Inc.
|
2011-09-24 00:36:09 +00:00
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#
|
|
|
|
import logging
|
|
|
|
log = logging.getLogger("livemedia-creator")
|
|
|
|
program_log = logging.getLogger("program")
|
|
|
|
pylorax_log = logging.getLogger("pylorax")
|
|
|
|
|
2017-10-02 23:50:01 +00:00
|
|
|
import argparse
|
2011-09-24 00:36:09 +00:00
|
|
|
import os
|
2017-10-02 23:50:01 +00:00
|
|
|
import shutil
|
2011-09-24 00:36:09 +00:00
|
|
|
import sys
|
|
|
|
import tempfile
|
|
|
|
|
|
|
|
# Use pykickstart to calculate disk image size
|
|
|
|
from pykickstart.parser import KickstartParser
|
2014-09-22 23:24:42 +00:00
|
|
|
from pykickstart.version import makeVersion, RHEL7
|
2011-09-24 00:36:09 +00:00
|
|
|
|
2017-10-02 23:50:01 +00:00
|
|
|
from pylorax import vernum
|
|
|
|
from pylorax.creator import DRACUT_DEFAULT, mount_boot_part_over_root
|
|
|
|
from pylorax.creator import make_appliance, make_image, make_livecd, make_live_images
|
|
|
|
from pylorax.creator import make_runtime, make_squashfs
|
2016-08-01 21:12:02 +00:00
|
|
|
from pylorax.imgutils import copytree
|
2017-10-02 23:50:01 +00:00
|
|
|
from pylorax.imgutils import Mount, PartitionMount, umount
|
|
|
|
from pylorax.installer import InstallError
|
|
|
|
from pylorax.sysutils import joinpaths
|
|
|
|
|
|
|
|
VERSION = "{0}-{1}".format(os.path.basename(sys.argv[0]), vernum)
|
|
|
|
|
2011-09-24 00:36:09 +00:00
|
|
|
|
2012-05-10 21:21:42 +00:00
|
|
|
# no-virt mode doesn't need libvirt, so make it optional
|
|
|
|
try:
|
|
|
|
import libvirt
|
|
|
|
except ImportError:
|
|
|
|
libvirt = None
|
2011-09-24 00:36:09 +00:00
|
|
|
|
2017-10-02 23:50:01 +00:00
|
|
|
def lorax_parser():
|
|
|
|
""" Return the ArgumentParser for lorax"""
|
2016-07-28 21:11:37 +00:00
|
|
|
|
2011-09-24 00:36:09 +00:00
|
|
|
parser = argparse.ArgumentParser( description="Create Live Install Media",
|
|
|
|
fromfile_prefix_chars="@" )
|
|
|
|
|
2011-12-09 01:12:06 +00:00
|
|
|
# These are mutually exclusive, one is required
|
2011-09-24 00:36:09 +00:00
|
|
|
action = parser.add_mutually_exclusive_group( required=True )
|
|
|
|
action.add_argument( "--make-iso", action="store_true",
|
|
|
|
help="Build a live iso" )
|
|
|
|
action.add_argument( "--make-disk", action="store_true",
|
2013-01-30 22:16:25 +00:00
|
|
|
help="Build a partitioned disk image" )
|
|
|
|
action.add_argument( "--make-fsimage", action="store_true",
|
|
|
|
help="Build a filesystem image" )
|
2011-09-24 00:36:09 +00:00
|
|
|
action.add_argument( "--make-appliance", action="store_true",
|
|
|
|
help="Build an appliance image and XML description" )
|
|
|
|
action.add_argument( "--make-ami", action="store_true",
|
|
|
|
help="Build an ami image" )
|
2014-04-04 21:38:51 +00:00
|
|
|
action.add_argument( "--make-tar", action="store_true",
|
|
|
|
help="Build a tar of the root filesystem" )
|
2014-07-30 15:59:27 +00:00
|
|
|
action.add_argument( "--make-pxe-live", action="store_true",
|
|
|
|
help="Build a live pxe boot squashfs image" )
|
|
|
|
action.add_argument( "--make-ostree-live", action="store_true",
|
|
|
|
help="Build a live pxe boot squashfs image of Atomic Host" )
|
|
|
|
|
2011-09-24 00:36:09 +00:00
|
|
|
|
2011-12-09 01:12:06 +00:00
|
|
|
parser.add_argument( "--iso", type=os.path.abspath,
|
2011-09-24 00:36:09 +00:00
|
|
|
help="Anaconda installation .iso path to use for virt-install" )
|
2014-04-02 23:56:28 +00:00
|
|
|
parser.add_argument( "--fs-label", default="Anaconda",
|
|
|
|
help="Label to set on fsimage, default is 'Anaconda'")
|
2014-04-04 21:38:51 +00:00
|
|
|
parser.add_argument("--compression", default="xz",
|
|
|
|
help="Compression binary for make-tar. xz, lzma, gzip, and bzip2 are supported. xz is the default.")
|
|
|
|
parser.add_argument("--compress-arg", action="append", dest="compress_args", default=[],
|
|
|
|
help="Arguments to pass to compression. Pass once for each argument")
|
2011-09-24 00:36:09 +00:00
|
|
|
|
|
|
|
parser.add_argument( "--ks", action="append", type=os.path.abspath,
|
|
|
|
help="Kickstart file defining the install." )
|
|
|
|
parser.add_argument( "--image-only", action="store_true",
|
2013-01-30 22:16:25 +00:00
|
|
|
help="Exit after creating fs/disk image." )
|
2014-03-08 02:43:14 +00:00
|
|
|
|
2011-09-24 00:36:09 +00:00
|
|
|
parser.add_argument( "--no-virt", action="store_true",
|
|
|
|
help="Use Anaconda's image install instead of virt-install" )
|
2011-12-09 01:12:06 +00:00
|
|
|
parser.add_argument( "--proxy",
|
|
|
|
help="proxy URL to use for the install" )
|
|
|
|
parser.add_argument( "--anaconda-arg", action="append", dest="anaconda_args",
|
|
|
|
help="Additional argument to pass to anaconda (no-virt "
|
|
|
|
"mode). Pass once for each argument" )
|
2012-08-15 17:08:24 +00:00
|
|
|
parser.add_argument( "--armplatform",
|
|
|
|
help="the platform to use when creating images for ARM, "
|
|
|
|
"i.e., highbank, mvebu, omap, tegra, etc." )
|
2012-08-16 22:03:58 +00:00
|
|
|
parser.add_argument( "--location", default=None, type=os.path.abspath,
|
|
|
|
help="location of iso directory tree with initrd.img "
|
|
|
|
"and vmlinuz. Used to run virt-install with a "
|
|
|
|
"newer initrd than the iso." )
|
2011-09-24 00:36:09 +00:00
|
|
|
|
|
|
|
parser.add_argument( "--logfile", default="./livemedia.log",
|
|
|
|
type=os.path.abspath,
|
|
|
|
help="Path to logfile" )
|
|
|
|
parser.add_argument( "--lorax-templates", default="/usr/share/lorax/",
|
|
|
|
type=os.path.abspath,
|
|
|
|
help="Path to mako templates for lorax" )
|
2012-05-11 20:12:17 +00:00
|
|
|
parser.add_argument( "--tmp", default="/var/tmp", type=os.path.abspath,
|
2011-09-24 00:36:09 +00:00
|
|
|
help="Top level temporary directory" )
|
|
|
|
parser.add_argument( "--resultdir", default=None, dest="result_dir",
|
|
|
|
type=os.path.abspath,
|
|
|
|
help="Directory to copy the resulting images and iso into. "
|
|
|
|
"Defaults to the temporary working directory")
|
|
|
|
|
2013-09-26 23:57:09 +00:00
|
|
|
parser.add_argument( "--macboot", action="store_true",
|
2013-09-26 23:47:05 +00:00
|
|
|
dest="domacboot")
|
2013-09-26 23:57:09 +00:00
|
|
|
parser.add_argument( "--nomacboot", action="store_false", default=False,
|
2013-09-26 23:47:05 +00:00
|
|
|
dest="domacboot")
|
|
|
|
|
2014-03-08 02:43:14 +00:00
|
|
|
image_group = parser.add_argument_group("disk/fs image arguments")
|
|
|
|
image_group.add_argument( "--disk-image", type=os.path.abspath,
|
|
|
|
help="Path to disk image to use for creating final image" )
|
|
|
|
image_group.add_argument( "--keep-image", action="store_true",
|
|
|
|
help="Keep raw disk image after .iso creation" )
|
|
|
|
image_group.add_argument( "--fs-image", type=os.path.abspath,
|
|
|
|
help="Path to filesystem image to use for creating final image" )
|
|
|
|
image_group.add_argument( "--image-name", default=None,
|
|
|
|
help="Name of fs/disk image to create. Default is a random name." )
|
|
|
|
image_group.add_argument("--qcow2", action="store_true",
|
|
|
|
help="create qcow2 image instead of raw sparse image")
|
|
|
|
image_group.add_argument("--qcow2-arg", action="append", dest="qcow2_args", default=[],
|
|
|
|
help="Arguments to pass to qemu-img. Pass once for each argument")
|
|
|
|
|
2012-05-24 22:55:46 +00:00
|
|
|
# Group of arguments for appliance creation
|
|
|
|
app_group = parser.add_argument_group("appliance arguments")
|
|
|
|
app_group.add_argument( "--app-name", default=None,
|
|
|
|
help="Name of appliance to pass to template")
|
|
|
|
app_group.add_argument( "--app-template", default=None,
|
|
|
|
help="Path to template to use for appliance data.")
|
|
|
|
app_group.add_argument( "--app-file", default="appliance.xml",
|
|
|
|
help="Appliance template results file.")
|
|
|
|
|
2011-09-24 00:36:09 +00:00
|
|
|
# Group of arguments to pass to virt-install
|
2012-05-10 21:21:42 +00:00
|
|
|
if not libvirt:
|
|
|
|
virt_group = parser.add_argument_group("virt-install arguments (DISABLED -- no libvirt)")
|
|
|
|
else:
|
|
|
|
virt_group = parser.add_argument_group("virt-install arguments")
|
2018-06-11 20:49:28 +00:00
|
|
|
virt_group.add_argument("--ram", metavar="MEMORY", type=int, default=2048,
|
2011-09-24 00:36:09 +00:00
|
|
|
help="Memory to allocate for installer in megabytes." )
|
|
|
|
virt_group.add_argument("--vcpus", default=1,
|
|
|
|
help="Passed to --vcpus command" )
|
|
|
|
virt_group.add_argument("--vnc",
|
|
|
|
help="Passed to --graphics command" )
|
2012-05-29 18:21:15 +00:00
|
|
|
virt_group.add_argument("--arch", default=None,
|
2015-11-04 02:03:09 +00:00
|
|
|
help="Passed to --arch command")
|
|
|
|
virt_group.add_argument("--kernel-args",
|
|
|
|
help="Additional argument to pass to the installation kernel")
|
|
|
|
virt_group.add_argument("--ovmf-path", default="/usr/share/OVMF/",
|
|
|
|
help="Path to OVMF firmware. Requires OVMF_CODE.fd and OVMF_VARS.fd")
|
|
|
|
virt_group.add_argument("--virt-uefi", action="store_true", default=False,
|
|
|
|
help="Use OVMF firmware to boot the VM in UEFI mode")
|
2011-09-24 00:36:09 +00:00
|
|
|
|
|
|
|
# dracut arguments
|
|
|
|
dracut_group = parser.add_argument_group( "dracut arguments" )
|
|
|
|
dracut_group.add_argument( "--dracut-arg", action="append", dest="dracut_args",
|
|
|
|
help="Argument to pass to dracut when "
|
|
|
|
"rebuilding the initramfs. Pass this "
|
|
|
|
"once for each argument. NOTE: this "
|
|
|
|
"overrides the default. (default: %s)" % (DRACUT_DEFAULT,) )
|
|
|
|
|
2015-01-15 10:22:30 +00:00
|
|
|
# pxe to live arguments
|
|
|
|
pxelive_group = parser.add_argument_group( "pxe to live arguments" )
|
|
|
|
pxelive_group.add_argument( "--live-rootfs-size", type=int, default=0,
|
|
|
|
help="Size of root filesystem of live image in GiB" )
|
2015-01-15 10:26:44 +00:00
|
|
|
pxelive_group.add_argument( "--live-rootfs-keep-size", action="store_true",
|
|
|
|
help="Keep the original size of root filesystem in live image " )
|
|
|
|
|
2015-01-15 10:22:30 +00:00
|
|
|
|
2011-09-24 00:36:09 +00:00
|
|
|
parser.add_argument( "--title", default="Linux Live Media",
|
|
|
|
help="Substituted for @TITLE@ in bootloader config files" )
|
2013-10-31 19:30:22 +00:00
|
|
|
parser.add_argument( "--project", default="Red Hat Enterprise Linux",
|
2011-09-24 00:36:09 +00:00
|
|
|
help="substituted for @PROJECT@ in bootloader config files" )
|
2015-08-13 16:01:40 +00:00
|
|
|
parser.add_argument( "--releasever", default="7",
|
2011-09-24 00:36:09 +00:00
|
|
|
help="substituted for @VERSION@ in bootloader config files" )
|
2012-03-08 01:29:31 +00:00
|
|
|
parser.add_argument( "--volid", default=None, help="volume id")
|
2011-09-24 00:36:09 +00:00
|
|
|
parser.add_argument( "--squashfs_args",
|
|
|
|
help="additional squashfs args" )
|
|
|
|
|
2017-08-08 23:12:21 +00:00
|
|
|
# add the show version option
|
|
|
|
parser.add_argument("-V", help="show program's version number and exit",
|
|
|
|
action="version", version=VERSION)
|
|
|
|
|
2017-10-02 23:50:01 +00:00
|
|
|
return parser
|
|
|
|
|
|
|
|
|
|
|
|
def setup_logging(opts):
|
|
|
|
# Setup logging to console and to logfile
|
|
|
|
log.setLevel(logging.DEBUG)
|
|
|
|
pylorax_log.setLevel(logging.DEBUG)
|
|
|
|
|
|
|
|
sh = logging.StreamHandler()
|
|
|
|
sh.setLevel(logging.INFO)
|
|
|
|
fmt = logging.Formatter("%(asctime)s: %(message)s")
|
|
|
|
sh.setFormatter(fmt)
|
|
|
|
log.addHandler(sh)
|
|
|
|
pylorax_log.addHandler(sh)
|
|
|
|
|
|
|
|
fh = logging.FileHandler(filename=opts.logfile, mode="w")
|
|
|
|
fh.setLevel(logging.DEBUG)
|
|
|
|
fmt = logging.Formatter("%(asctime)s %(levelname)s %(name)s: %(message)s")
|
|
|
|
fh.setFormatter(fmt)
|
|
|
|
log.addHandler(fh)
|
|
|
|
pylorax_log.addHandler(fh)
|
|
|
|
|
|
|
|
# External program output log
|
|
|
|
program_log.setLevel(logging.DEBUG)
|
|
|
|
logfile = os.path.abspath(os.path.dirname(opts.logfile))+"/program.log"
|
|
|
|
fh = logging.FileHandler(filename=logfile, mode="w")
|
|
|
|
fh.setLevel(logging.DEBUG)
|
|
|
|
program_log.addHandler(fh)
|
|
|
|
|
|
|
|
|
|
|
|
def default_image_name(compression, basename):
|
|
|
|
""" Return a default image name with the correct suffix for the compression type.
|
|
|
|
|
|
|
|
:param str compression: Compression type
|
|
|
|
:param str basename: Base filename
|
|
|
|
:returns: basename with compression suffix
|
|
|
|
|
|
|
|
If the compression is unknown it defaults to xz
|
|
|
|
"""
|
|
|
|
SUFFIXES = {"xz": ".xz", "gzip": ".gz", "bzip2": ".bz2", "lzma": ".lzma"}
|
|
|
|
return basename + SUFFIXES.get(compression, ".xz")
|
|
|
|
|
|
|
|
|
2017-10-12 12:55:55 +00:00
|
|
|
def main():
|
2017-08-08 23:12:21 +00:00
|
|
|
# parse the arguments
|
2017-10-02 23:50:01 +00:00
|
|
|
parser = lorax_parser()
|
2011-09-24 00:36:09 +00:00
|
|
|
opts = parser.parse_args()
|
|
|
|
|
2012-07-26 20:57:25 +00:00
|
|
|
setup_logging(opts)
|
2011-09-24 00:36:09 +00:00
|
|
|
|
2017-08-08 23:12:21 +00:00
|
|
|
log.info("livemedia-creator %s", vernum)
|
2011-09-24 00:36:09 +00:00
|
|
|
log.debug( opts )
|
|
|
|
|
|
|
|
if os.getuid() != 0:
|
|
|
|
log.error("You need to run this as root")
|
|
|
|
sys.exit( 1 )
|
|
|
|
|
2012-02-28 21:57:17 +00:00
|
|
|
if opts.make_iso and not os.path.exists( opts.lorax_templates ):
|
2017-10-12 12:18:32 +00:00
|
|
|
log.error( "The lorax templates directory (%s) doesn't"
|
|
|
|
" exist.", opts.lorax_templates)
|
2011-09-24 00:36:09 +00:00
|
|
|
sys.exit( 1 )
|
|
|
|
|
|
|
|
if opts.result_dir and os.path.exists(opts.result_dir):
|
2017-10-12 12:18:32 +00:00
|
|
|
log.error( "The results_dir (%s) should not exist, please delete or "
|
|
|
|
"move its contents", opts.result_dir)
|
2011-09-24 00:36:09 +00:00
|
|
|
sys.exit( 1 )
|
|
|
|
|
2015-03-20 00:22:16 +00:00
|
|
|
# Default to putting results into tmp
|
|
|
|
if not opts.result_dir:
|
|
|
|
opts.result_dir = opts.tmp
|
|
|
|
else:
|
|
|
|
os.makedirs(opts.result_dir)
|
|
|
|
|
2011-09-24 00:36:09 +00:00
|
|
|
if opts.iso and not os.path.exists( opts.iso ):
|
2017-10-12 12:18:32 +00:00
|
|
|
log.error( "The iso %s is missing.", opts.iso)
|
2011-09-24 00:36:09 +00:00
|
|
|
sys.exit( 1 )
|
|
|
|
|
|
|
|
if opts.disk_image and not os.path.exists( opts.disk_image ):
|
2017-10-12 12:18:32 +00:00
|
|
|
log.error( "The disk image %s is missing.", opts.disk_image)
|
2011-09-24 00:36:09 +00:00
|
|
|
sys.exit( 1 )
|
|
|
|
|
2013-01-30 22:16:25 +00:00
|
|
|
if opts.fs_image and not os.path.exists( opts.fs_image ):
|
2017-10-12 12:18:32 +00:00
|
|
|
log.error( "The filesystem image %s is missing.", opts.fs_image)
|
2013-01-30 22:16:25 +00:00
|
|
|
sys.exit( 1 )
|
|
|
|
|
|
|
|
is_install = not (opts.disk_image or opts.fs_image)
|
|
|
|
if is_install and not opts.no_virt and not opts.iso:
|
2013-07-17 17:34:11 +00:00
|
|
|
log.error( "virt install needs an install iso." )
|
2011-12-09 01:12:06 +00:00
|
|
|
sys.exit( 1 )
|
2011-09-24 00:36:09 +00:00
|
|
|
|
2012-03-08 01:29:31 +00:00
|
|
|
if opts.volid and len(opts.volid) > 32:
|
2013-01-30 22:16:25 +00:00
|
|
|
log.fatal("the volume id cannot be longer than 32 characters")
|
2012-03-08 01:29:31 +00:00
|
|
|
sys.exit(1)
|
|
|
|
|
2013-01-30 22:16:25 +00:00
|
|
|
if is_install and not opts.no_virt and not libvirt:
|
2013-07-17 17:34:11 +00:00
|
|
|
log.error("virt install requires libvirt-python to be installed.")
|
2012-07-21 00:44:30 +00:00
|
|
|
sys.exit(1)
|
|
|
|
|
2013-01-30 22:16:25 +00:00
|
|
|
if is_install and not opts.no_virt \
|
|
|
|
and not os.path.exists("/usr/bin/virt-install"):
|
2013-07-17 17:34:11 +00:00
|
|
|
log.error("virt-install needs to be installed.")
|
2012-05-10 21:21:42 +00:00
|
|
|
sys.exit(1)
|
|
|
|
|
2013-05-24 19:20:56 +00:00
|
|
|
if is_install and opts.no_virt \
|
2013-01-30 22:16:25 +00:00
|
|
|
and not os.path.exists("/usr/sbin/anaconda"):
|
2012-05-24 22:55:46 +00:00
|
|
|
log.error("no-virt requires anaconda to be installed.")
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if opts.make_appliance and not opts.app_template:
|
|
|
|
opts.app_template = joinpaths(opts.lorax_templates,
|
|
|
|
"appliance/libvirt.tmpl")
|
|
|
|
|
|
|
|
if opts.make_appliance and not os.path.exists(opts.app_template):
|
2017-10-12 12:18:32 +00:00
|
|
|
log.error("The appliance template (%s) doesn't "
|
|
|
|
"exist", opts.app_template)
|
2012-05-24 22:55:46 +00:00
|
|
|
sys.exit(1)
|
|
|
|
|
2015-03-20 00:22:16 +00:00
|
|
|
if opts.image_name and os.path.exists(joinpaths(opts.result_dir, opts.image_name)):
|
2012-05-24 22:55:46 +00:00
|
|
|
log.error("The disk image to be created should not exist.")
|
|
|
|
sys.exit(1)
|
|
|
|
|
2014-03-08 02:43:14 +00:00
|
|
|
if opts.qcow2 and not os.path.exists("/usr/bin/qemu-img"):
|
|
|
|
log.error("qcow2 requires the qemu-img utility to be installed.")
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if opts.qcow2 and opts.make_iso:
|
|
|
|
log.error("qcow2 cannot be used to make a bootable iso.")
|
|
|
|
sys.exit(1)
|
|
|
|
|
2015-11-04 02:03:09 +00:00
|
|
|
if opts.virt_uefi:
|
|
|
|
if not os.path.isdir(opts.ovmf_path):
|
|
|
|
log.error("The OVMF firmware is missing from %s", opts.ovmf_path)
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
for f in ["OVMF_CODE.fd", "OVMF_VARS.fd"]:
|
|
|
|
if not os.path.exists(joinpaths(opts.ovmf_path, f)):
|
|
|
|
log.error("OVMF firmware file %s is missing from %s", f, opts.ovmf_path)
|
|
|
|
sys.exit(1)
|
|
|
|
|
2014-04-02 23:56:28 +00:00
|
|
|
# AMI image is just a fsimage with an AMI label
|
|
|
|
if opts.make_ami:
|
|
|
|
opts.make_fsimage = True
|
|
|
|
if not opts.image_name:
|
|
|
|
opts.image_name = "ami-root.img"
|
|
|
|
if opts.fs_label == "Anaconda":
|
|
|
|
opts.fs_label = "AMI"
|
2014-04-04 21:38:51 +00:00
|
|
|
elif opts.make_tar:
|
|
|
|
if not opts.image_name:
|
2016-03-29 00:20:49 +00:00
|
|
|
opts.image_name = default_image_name(opts.compression, "root.tar")
|
2014-04-04 21:38:51 +00:00
|
|
|
if opts.compression == "xz" and not opts.compress_args:
|
|
|
|
opts.compress_args = ["-9"]
|
2014-04-02 23:56:28 +00:00
|
|
|
|
2012-05-24 22:55:46 +00:00
|
|
|
if opts.app_file:
|
2015-03-20 00:22:16 +00:00
|
|
|
opts.app_file = joinpaths(opts.result_dir, opts.app_file)
|
2012-05-24 22:55:46 +00:00
|
|
|
|
2014-07-30 15:59:27 +00:00
|
|
|
if opts.make_ostree_live:
|
|
|
|
opts.make_pxe_live = True
|
|
|
|
opts.ostree = True
|
|
|
|
else:
|
|
|
|
opts.ostree = False
|
|
|
|
|
2012-05-11 20:12:17 +00:00
|
|
|
tempfile.tempdir = opts.tmp
|
2012-05-24 22:55:46 +00:00
|
|
|
disk_img = None
|
2012-05-11 20:12:17 +00:00
|
|
|
|
2012-05-24 22:55:46 +00:00
|
|
|
# Parse the kickstart
|
|
|
|
if opts.ks:
|
2014-09-22 23:24:42 +00:00
|
|
|
ks_version = makeVersion(RHEL7)
|
2011-09-24 00:36:09 +00:00
|
|
|
ks = KickstartParser( ks_version, errorsAreFatal=False, missingIncludeIsFatal=False )
|
|
|
|
ks.readKickstart( opts.ks[0] )
|
2012-05-24 22:55:46 +00:00
|
|
|
|
2013-01-30 22:16:25 +00:00
|
|
|
# Make the disk or filesystem image
|
|
|
|
if not opts.disk_image and not opts.fs_image:
|
2012-05-24 22:55:46 +00:00
|
|
|
if not opts.ks:
|
|
|
|
log.error("Image creation requires a kickstart file")
|
|
|
|
sys.exit(1)
|
|
|
|
|
2013-01-30 22:16:25 +00:00
|
|
|
errors = []
|
2014-07-03 20:41:28 +00:00
|
|
|
if ks.handler.method.method != "url" and opts.no_virt:
|
2013-01-30 22:16:25 +00:00
|
|
|
errors.append("Only url install method is currently supported. Please "
|
|
|
|
"fix your kickstart file." )
|
2011-09-24 00:36:09 +00:00
|
|
|
|
2013-01-30 22:16:25 +00:00
|
|
|
if ks.handler.displaymode.displayMode is not None:
|
|
|
|
errors.append("The kickstart must not set a display mode (text, cmdline, "
|
|
|
|
"graphical), this will interfere with livemedia-creator.")
|
2011-09-24 00:36:09 +00:00
|
|
|
|
2014-04-03 17:45:06 +00:00
|
|
|
if opts.make_fsimage:
|
|
|
|
# Make sure the kickstart isn't using autopart and only has a / mountpoint
|
|
|
|
part_ok = not any(p for p in ks.handler.partition.partitions
|
|
|
|
if p.mountpoint not in ["/", "swap"])
|
|
|
|
if not part_ok or ks.handler.autopart.seen:
|
|
|
|
errors.append("Filesystem images must use a single / part, not autopart or "
|
|
|
|
"multiple partitions. swap is allowed but not used.")
|
2014-04-02 23:56:28 +00:00
|
|
|
|
2013-01-30 22:16:25 +00:00
|
|
|
if errors:
|
2017-10-12 12:55:55 +00:00
|
|
|
for _e in errors:
|
|
|
|
log.error(_e)
|
2013-01-30 22:16:25 +00:00
|
|
|
sys.exit(1)
|
2011-12-09 01:12:06 +00:00
|
|
|
|
2013-01-30 22:16:25 +00:00
|
|
|
# Make the image. Output of this is either a partitioned disk image or a fsimage
|
|
|
|
try:
|
|
|
|
disk_img = make_image(opts, ks)
|
|
|
|
except InstallError as e:
|
2017-10-12 12:18:32 +00:00
|
|
|
log.error("ERROR: Image creation failed: %s", e)
|
2013-01-30 22:16:25 +00:00
|
|
|
sys.exit(1)
|
2012-05-12 00:35:16 +00:00
|
|
|
|
2013-01-30 22:16:25 +00:00
|
|
|
if not opts.image_only:
|
|
|
|
result_dir = None
|
|
|
|
if opts.make_iso:
|
|
|
|
work_dir = tempfile.mkdtemp()
|
2017-10-12 12:18:32 +00:00
|
|
|
log.info("working dir is %s", work_dir)
|
2013-01-30 22:16:25 +00:00
|
|
|
|
|
|
|
if (opts.fs_image or opts.no_virt) and not opts.disk_image:
|
|
|
|
# Create iso from a filesystem image
|
|
|
|
disk_img = opts.fs_image or disk_img
|
|
|
|
|
|
|
|
make_squashfs(disk_img, work_dir)
|
|
|
|
with Mount(disk_img, opts="loop") as mount_dir:
|
|
|
|
result_dir = make_livecd(opts, mount_dir, work_dir)
|
|
|
|
else:
|
|
|
|
# Create iso from a partitioned disk image
|
|
|
|
disk_img = opts.disk_image or disk_img
|
|
|
|
with PartitionMount(disk_img) as img_mount:
|
|
|
|
if img_mount and img_mount.mount_dir:
|
|
|
|
make_runtime(opts, img_mount.mount_dir, work_dir)
|
|
|
|
result_dir = make_livecd(opts, img_mount.mount_dir, work_dir)
|
|
|
|
|
|
|
|
# cleanup the mess
|
|
|
|
# cleanup work_dir?
|
|
|
|
if disk_img and not (opts.keep_image or opts.disk_image or opts.fs_image):
|
|
|
|
os.unlink(disk_img)
|
|
|
|
log.info("Disk image erased")
|
|
|
|
disk_img = None
|
|
|
|
elif opts.make_appliance:
|
|
|
|
if not opts.ks:
|
|
|
|
networks = []
|
|
|
|
else:
|
|
|
|
networks = ks.handler.network.network
|
|
|
|
make_appliance(opts.disk_image or disk_img, opts.app_name,
|
|
|
|
opts.app_template, opts.app_file, networks, opts.ram,
|
|
|
|
opts.vcpus, opts.arch, opts.title, opts.project, opts.releasever)
|
2014-07-30 15:59:27 +00:00
|
|
|
elif opts.make_pxe_live:
|
|
|
|
work_dir = tempfile.mkdtemp()
|
2017-10-12 12:18:32 +00:00
|
|
|
log.info("working dir is %s", work_dir)
|
2014-07-30 15:59:27 +00:00
|
|
|
|
|
|
|
if (opts.fs_image or opts.no_virt) and not opts.disk_image:
|
|
|
|
# Create pxe live images from a filesystem image
|
|
|
|
disk_img = opts.fs_image or disk_img
|
|
|
|
with Mount(disk_img, opts="loop") as mnt_dir:
|
|
|
|
result_dir = make_live_images(opts, work_dir, mnt_dir, rootfs_image=disk_img)
|
|
|
|
else:
|
|
|
|
# Create pxe live images from a partitioned disk image
|
|
|
|
disk_img = opts.disk_image or disk_img
|
|
|
|
is_root_part = None
|
|
|
|
if opts.ostree:
|
|
|
|
is_root_part = lambda dir: os.path.exists(dir+"/ostree/deploy")
|
|
|
|
with PartitionMount(disk_img, mount_ok=is_root_part) as img_mount:
|
|
|
|
if img_mount and img_mount.mount_dir:
|
|
|
|
try:
|
|
|
|
mounted_sysroot_boot_dir = None
|
|
|
|
if opts.ostree:
|
|
|
|
mounted_sysroot_boot_dir = mount_boot_part_over_root(img_mount)
|
2015-01-15 10:26:44 +00:00
|
|
|
if opts.live_rootfs_keep_size:
|
|
|
|
size = img_mount.mount_size / 1024**3
|
|
|
|
else:
|
|
|
|
size = opts.live_rootfs_size or None
|
2015-01-15 10:22:30 +00:00
|
|
|
result_dir = make_live_images(opts, work_dir, img_mount.mount_dir, size=size)
|
2014-07-30 15:59:27 +00:00
|
|
|
finally:
|
|
|
|
if mounted_sysroot_boot_dir:
|
|
|
|
umount(mounted_sysroot_boot_dir)
|
2013-01-30 22:16:25 +00:00
|
|
|
|
2015-03-20 00:22:16 +00:00
|
|
|
if opts.result_dir != opts.tmp and result_dir:
|
2016-08-01 21:12:02 +00:00
|
|
|
copytree(result_dir, opts.result_dir, preserve=False)
|
2013-01-30 22:16:25 +00:00
|
|
|
shutil.rmtree( result_dir )
|
2011-09-24 00:36:09 +00:00
|
|
|
|
|
|
|
log.info("SUMMARY")
|
|
|
|
log.info("-------")
|
2017-10-12 12:18:32 +00:00
|
|
|
log.info("Logs are in %s", os.path.abspath(os.path.dirname(opts.logfile)))
|
2012-05-24 22:55:46 +00:00
|
|
|
if disk_img:
|
2017-10-12 12:18:32 +00:00
|
|
|
log.info("Disk image is at %s", disk_img)
|
2012-05-24 22:55:46 +00:00
|
|
|
if opts.make_appliance:
|
2017-10-12 12:18:32 +00:00
|
|
|
log.info("Appliance description is in %s", opts.app_file)
|
|
|
|
log.info("Results are in %s", opts.result_dir or result_dir)
|
2011-09-24 00:36:09 +00:00
|
|
|
|
|
|
|
sys.exit( 0 )
|
2017-10-12 12:55:55 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|