Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build live PXE and ISO images #738

Merged
merged 7 commits into from
Sep 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 44 additions & 12 deletions src/cmd-buildextend-installer
Original file line number Diff line number Diff line change
Expand Up @@ -31,32 +31,38 @@ if not args.build:

print(f"Targeting build: {args.build}")

# Hacky mode switch, until we can drop support for the installer images
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

definitely took me a minute looking at the code sideways :) - any idea how long before we can drop the other images?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For FCOS, hopefully soon. For RHCOS it's more of a policy question.

is_live = os.path.basename(sys.argv[0]).endswith('-live')
image_type = 'live' if is_live else 'installer'
meta_keys = {k: 'live-' + k if is_live else k for k in ('iso', 'kernel', 'initramfs')}

workdir = os.path.abspath(os.getcwd())
builddir = builds.get_build_dir(args.build)
buildmeta_path = os.path.join(builddir, 'meta.json')
with open(buildmeta_path) as f:
buildmeta = json.load(f)

img_qemu = os.path.join(builddir, buildmeta['images']['qemu']['path'])
# Grab the commit hash for this build
buildmeta_commit = buildmeta['ostree-commit']

repo = os.path.join(workdir, 'tmp/repo')

# Don't run if it's already been done, unless forced
if 'iso' in buildmeta['images'] and not args.force:
print(f"Installer has already been built for {args.build}. Skipping.")
if meta_keys['iso'] in buildmeta['images'] and not args.force:
print(f"Image has already been built for {args.build}. Skipping.")
print("You can force a rebuild with '--force'.")
sys.exit(0)

base_name = buildmeta['name']
iso_name = f'{base_name}-{args.build}-installer.iso'
iso_name = f'{base_name}-{args.build}-{image_type}.iso'
name_version = f'{base_name}-{args.build}'

tmpdir = os.environ.get("FORCE_TMPDIR", f"{workdir}/tmp/buildpost-installer")
tmpdir = os.environ.get("FORCE_TMPDIR", f"{workdir}/tmp/buildpost-{image_type}")
if os.path.isdir(tmpdir):
shutil.rmtree(tmpdir)

tmpisoroot = os.path.join(tmpdir, 'installer')
tmpisoroot = os.path.join(tmpdir, image_type)
tmpisoimages = os.path.join(tmpisoroot, 'images')
tmpisoisolinux = os.path.join(tmpisoroot, 'isolinux')

Expand Down Expand Up @@ -85,9 +91,35 @@ def generate_iso():
# initramfs isn't world readable by default so let's open up perms
os.chmod(os.path.join(tmpisoimages, file), 0o755)

if is_live:
initramfs = os.path.join(tmpisoimages, 'initramfs.img')
tmp_squashfs = os.path.join(tmpdir, 'root.squashfs')
tmp_cpio = os.path.join(tmpdir, 'root.cpio')
tmp_initramfs = os.path.join(tmpdir, 'initramfs')

run_verbose(['/usr/lib/coreos-assembler/gf-mksquashfs',
img_qemu, tmp_squashfs])
run_verbose(['cpio', '-o', '-H', 'newc', '-R', 'root:root',
'--quiet', '--reproducible', '--force-local',
'-D', os.path.dirname(tmp_squashfs), '-O', tmp_cpio],
input=os.path.basename(tmp_squashfs).encode())
# Compression is redundant but the kernel requires it
run_verbose(['gzip', '-1', tmp_cpio])

# Append the root cpio to the initramfs.
# The initramfs image is a hardlink to the uncompressed objects
# cache, so we can't modify it in place.
bgilbert marked this conversation as resolved.
Show resolved Hide resolved
with open(tmp_initramfs, 'wb') as fdst:
with open(initramfs, 'rb') as fsrc:
shutil.copyfileobj(fsrc, fdst)
with open(tmp_cpio + '.gz', 'rb') as fsrc:
shutil.copyfileobj(fsrc, fdst)
os.rename(tmp_initramfs, initramfs)
os.unlink(tmp_squashfs)

# TODO ignore EFI dir
# Grab all the contents from the installer dir from the configs
run_verbose(["rsync", "-av", "src/config/installer/", f"{tmpisoroot}/"])
run_verbose(["rsync", "-av", f"src/config/{image_type}/", f"{tmpisoroot}/"])

# These sections are based on lorax templates
# see https://github.com/weldr/lorax/tree/master/share/templates.d/99-generic
Expand Down Expand Up @@ -181,7 +213,7 @@ def generate_iso():
efitarfile = tempfile.NamedTemporaryFile(suffix=".tar")
with tarfile.open(efitarfile.name, "w:", dereference=True) as tar:
tar.add(tmpimageefidir, arcname="/EFI", filter=strip)
tar.add('src/config/installer/EFI/', arcname='/EFI',
tar.add(f'src/config/{image_type}/EFI/', arcname='/EFI',
filter=strip)

# Create the efiboot.img file (a fat filesystem) in the images/ dir
Expand All @@ -203,8 +235,8 @@ def generate_iso():
if arch == "x86_64":
run_verbose(['/usr/bin/isohybrid', tmpisofile])

kernel_name = f'{base_name}-{args.build}-installer-kernel'
initramfs_name = f'{base_name}-{args.build}-installer-initramfs.img'
kernel_name = f'{base_name}-{args.build}-{image_type}-kernel'
initramfs_name = f'{base_name}-{args.build}-{image_type}-initramfs.img'
kernel_file = os.path.join(builddir, kernel_name)
initramfs_file = os.path.join(builddir, initramfs_name)
shutil.copyfile(os.path.join(tmpisoimages, "vmlinuz"), kernel_file)
Expand All @@ -215,15 +247,15 @@ def generate_iso():
checksum = sha256sum_file(tmpisofile)

buildmeta['images'].update({
'iso': {
meta_keys['iso']: {
'path': iso_name,
'sha256': checksum
},
'kernel': {
meta_keys['kernel']: {
'path': kernel_name,
'sha256': kernel_checksum
},
'initramfs': {
meta_keys['initramfs']: {
'path': initramfs_name,
'sha256': initramfs_checksum
}
Expand Down
1 change: 1 addition & 0 deletions src/cmd-buildextend-live
2 changes: 1 addition & 1 deletion src/cmd-compress
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ else:
print(f"Targeting build: {build}")

# Don't compress certain images
imgs_to_skip = ["iso", "vmware", "initramfs", "kernel"]
imgs_to_skip = ["iso", "live-iso", "vmware", "initramfs", "live-initramfs", "kernel", "live-kernel"]


def get_cpu_param(param):
Expand Down
43 changes: 43 additions & 0 deletions src/gf-mksquashfs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
set -euo pipefail

dn=$(dirname "$0")
# shellcheck source=src/cmdlib.sh
. "${dn}"/cmdlib.sh
# shellcheck source=src/libguestfish.sh
. "${dn}"/libguestfish.sh

# Usage: gf-mksquashfs <input image> <output image>
# Example: gf-mksquashfs fedora-coreos.qcow2 fedora-coreos.squashfs
#
# This will generate a squashfs from the contents of the root partition.

src="$1"
dest="$2"

if [[ $src == *.gz || $src == *.xz ]]; then
img="$(basename "$src")"
fatal "Cannot generate squashfs from $img; not an uncompressed image"
fi

set -x
# Work in a tmpdir on the destination so that we don't inherit some MCS labeling
# from the /tmp dir in the container. This also ensures that the final move is a
# pure `rename()`.
# See also:
# https://github.com/coreos/coreos-assembler/issues/292
# https://github.com/coreos/coreos-assembler/pull/394
tmpd=$(mktemp -tdp "$(dirname "${dest}")" gf-mksquashfs.XXXXXX)
tmp_dest=${tmpd}/image.squashfs

coreos_gf_run "${src}" --ro

root=$(coreos_gf findfs-label root)
coreos_gf mount "${root}" /
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know /boot/ won't be used but wondering if we should include it for completeness? Is that was is causing this message:

[core@localhost ~]$ ostree admin status 
error: Unexpected state: /run/ostree-booted found and in / sysroot but not in a booted deployment

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't include the kernel and initramfs. We could include everything else, if that's the right way to proceed. Filed as ostreedev/ostree#1921, and let's not block this PR for it.


coreos_gf mksquashfs / "${tmp_dest}" compress:zstd
dustymabe marked this conversation as resolved.
Show resolved Hide resolved

coreos_gf_shutdown

mv "${tmp_dest}" "${dest}"
rm "${tmpd}" -rf
6 changes: 4 additions & 2 deletions src/gf-platformid
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ src="$1"
dest="$2"
platformid="$3"

if [[ $src == *.gz ]]; then
if [[ $src == *.gz || $src == *.xz ]]; then
img="$(basename "$src")"
fatal "Cannot change ignition.platform.id on $img; not an uncompressed image"
fi
Expand All @@ -27,7 +27,9 @@ set -x
# Work in a tmpdir on the destination so that we don't inherit some MCS labeling
# from the /tmp dir in the container. This also ensures that the final move is a
# pure `rename()`.
# See also: https://github.com/coreos/coreos-assembler/issues/292
# See also:
# https://github.com/coreos/coreos-assembler/issues/292
# https://github.com/coreos/coreos-assembler/pull/394
tmpd=$(mktemp -tdp "$(dirname "${dest}")" gf-platformid.XXXXXX)
tmp_dest=${tmpd}/box.img

Expand Down
10 changes: 1 addition & 9 deletions src/libguestfish.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,7 @@ coreos_gf_launch() {
if [ -n "$GUESTFISH_PID" ]; then
return
fi
local src=$1
shift
local guestfish
guestfish[0]="guestfish"
guestfish[1]="--listen"
guestfish[3]="-a"
guestfish[4]="${src}"

eval "$("${guestfish[@]}")"
eval "$(guestfish --listen -a "$@")"
if [ -z "$GUESTFISH_PID" ]; then
fatal "guestfish didn't start up, see error messages above"
fi
Expand Down