virtual-appliance/Makefile
Albert Hopkins 18fdbb86ea Makefile: perform the change-password step in the stage4 phase
This should really happen as late as possibly and possibly not at all.  If
we change (lock) the password too soon, then some build steps can fail.
For example, adduser will fail if root needs to change its password first.
2016-12-08 11:57:41 +00:00

379 lines
12 KiB
Makefile

APPLIANCE ?= base
VABUILDER_OUTPUT := $(CURDIR)
CHROOT = $(VABUILDER_OUTPUT)/build/$(APPLIANCE)
PKGDIR = $(VABUILDER_OUTPUT)/packages
DISTDIR = $(CURDIR)/distfiles
PORTAGE_DIR = $(CURDIR)/portage
HOSTNAME = $(APPLIANCE)
IMAGES = $(VABUILDER_OUTPUT)/images
RAW_IMAGE = $(IMAGES)/$(APPLIANCE).img
QCOW_IMAGE = $(IMAGES)/$(APPLIANCE).qcow
VMDK_IMAGE = $(IMAGES)/$(APPLIANCE).vmdk
XVA_IMAGE = $(IMAGES)/$(APPLIANCE).xva
LST_FILE = $(IMAGES)/$(APPLIANCE)-packages.lst
CHECKSUMS = $(IMAGES)/SHA256SUMS
STAGE3 = $(CHROOT)/var/tmp/stage3
COMPILE_OPTIONS = $(CHROOT)/var/tmp/compile_options
SOFTWARE = $(CHROOT)/var/tmp/software
KERNEL = $(CHROOT)/var/tmp/kernel
GRUB = $(CHROOT)/var/tmp/grub
PREPROOT = $(CHROOT)/var/tmp/preproot
SYSTOOLS = $(CHROOT)/var/tmp/systools
STAGE4_TARBALL = $(VABUILDER_OUTPUT)/images/$(APPLIANCE).tar.xz
VIRTIO = NO
TIMEZONE = UTC
DISK_SIZE = 6.0G
SWAP_SIZE = 30
SWAP_FILE = $(CHROOT)/.swap
ARCH = amd64
KERNEL_CONFIG = configs/kernel.config.$(ARCH)
MAKEOPTS = -j5 -l5.64
ENABLE_SSHD = NO
CHANGE_PASSWORD = YES
HEADLESS = NO
EXTERNAL_KERNEL = NO
PKGLIST = 0
ACCEPT_KEYWORDS = amd64
DASH = NO
LOCALE ?= en_US.utf8
M4 = m4
EMERGE = /usr/bin/emerge --jobs=4
M4_DEFS = -D HOSTNAME=$(HOSTNAME)
M4C = $(M4) $(M4_DEFS)
USEPKG = --usepkg --binpkg-respect-use=y
RSYNC_MIRROR = rsync://rsync.gtlib.gatech.edu/gentoo/
KERNEL_PKG = gentoo-sources
PACKAGE_FILES = $(wildcard appliances/$(APPLIANCE)/package.*)
WORLD = appliances/$(APPLIANCE)/world
EXTRA_WORLD =
# Allow appliance to override variables
-include appliances/$(APPLIANCE)/$(APPLIANCE).cfg
# Allow user to override variables
-include $(profile).cfg
ifneq ($(profile),)
container = $(profile)-$(APPLIANCE)-build
else
container = $(APPLIANCE)-build
endif
inroot := systemd-nspawn --quiet \
--directory=$(CHROOT) \
--machine=$(container) \
--bind=$(PORTAGE_DIR):/usr/portage \
--bind=$(PKGDIR):/usr/portage/packages \
--bind=$(DISTDIR):/usr/portage/distfiles
ifeq ($(ARCH),x86)
inroot := linux32 $(inroot)
endif
stage4-exists := $(wildcard $(STAGE4_TARBALL))
COPY_ARGS = --exclude-from=configs/rsync-excludes
ifeq ($(CHANGE_PASSWORD),YES)
ifdef ROOT_PASSWORD
change_password = $(inroot) usermod -p '$(ROOT_PASSWORD)' root
else
change_password = $(inroot) passwd --delete --expire root
endif
endif
gcc_config = $(inroot) gcc-config 1
export APPLIANCE ACCEPT_KEYWORDS CHROOT EMERGE HEADLESS M4 M4C inroot
export HOSTNAME MAKEOPTS TIMEZONE USEPKG WORLD
export USEPKG RSYNC_MIRROR
unexport PKGDIR ARCH
all: stage4
image: $(RAW_IMAGE)
sync_portage: $(PORTAGE_DIR)
@scripts/echo Grabbing latest portage
git -C $(PORTAGE_DIR) pull
touch $(PORTAGE_DIR)
$(PORTAGE_DIR):
@scripts/echo Grabbing the portage tree
git clone --depth=1 git://github.com/gentoo/gentoo.git $(PORTAGE_DIR)
$(PREPROOT): $(STAGE3) $(PORTAGE_DIR) configs/fstab
mkdir -p $(PKGDIR) $(DISTDIR)
cp configs/fstab $(CHROOT)/etc/fstab
ifeq ($(VIRTIO),YES)
sed -i 's/sda/vda/' $(CHROOT)/etc/fstab
endif
ifneq ($(SWAP_SIZE),0)
@scripts/echo Creating swap file: `basename $(SWAP_FILE)`
dd if=/dev/zero of=$(SWAP_FILE) bs=1M count=$(SWAP_SIZE)
/sbin/mkswap $(SWAP_FILE)
else
sed -i '/swap/d' $(CHROOT)/etc/fstab
endif
rm -f $(CHROOT)/etc/resolv.conf
cp -L /etc/resolv.conf $(CHROOT)/etc/resolv.conf
touch $(PREPROOT)
stage3-$(ARCH).tar.bz2:
@scripts/echo You do not have a stage3 tarball. Consider \"make sync_stage3\"
@exit 1
sync_stage3:
./scripts/fetch-stage3 --specialty=systemd --outfile=stage3-$(ARCH).tar.bz2 $(ARCH)
$(STAGE3): stage3-$(ARCH).tar.bz2
mkdir -p $(CHROOT)
ifdef stage4-exists
@scripts/echo Using stage4 tarball: `basename $(STAGE4_TARBALL)`
tar xpf "$(STAGE4_TARBALL)" -C $(CHROOT)
else
@scripts/echo Using stage3 tarball
tar xpf stage3-$(ARCH).tar.bz2 -C $(CHROOT)
endif
rm -f $(CHROOT)/etc/localtime
touch $(STAGE3)
$(COMPILE_OPTIONS): $(STAGE3) $(PORTAGE_DIR) configs/make.conf.$(ARCH) configs/locale.gen $(PACKAGE_FILES)
cp configs/make.conf.$(ARCH) $(CHROOT)/etc/portage/make.conf
echo ACCEPT_KEYWORDS=$(ACCEPT_KEYWORDS) >> $(CHROOT)/etc/portage/make.conf
-[ -f "appliances/$(APPLIANCE)/make.conf" ] && cat "appliances/$(APPLIANCE)/make.conf" >> $(CHROOT)/etc/portage/make.conf
cp configs/locale.gen $(CHROOT)/etc/locale.gen
$(inroot) locale-gen
for f in $(PACKAGE_FILES); do \
base=`basename $$f` ; \
mkdir -p $(CHROOT)/etc/portage/$$base; \
cp $$f $(CHROOT)/etc/portage/$$base/virtual-appliance-$$base; \
done
touch $(COMPILE_OPTIONS)
$(KERNEL): $(COMPILE_OPTIONS) $(KERNEL_CONFIG) scripts/build-kernel
ifneq ($(EXTERNAL_KERNEL),YES)
@scripts/echo Configuring kernel
cp $(KERNEL_CONFIG) $(CHROOT)/root/kernel.config
cp scripts/build-kernel $(CHROOT)/root/build-kernel
$(inroot) --setenv=KERNEL=$(KERNEL_PKG) \
--setenv=EMERGE="$(EMERGE)" \
--setenv=USEPKG="$(USEPKG)" \
--setenv=MAKEOPTS="$(MAKEOPTS)" \
/root/build-kernel
rm -f $(CHROOT)/root/build-kernel
endif
touch $(KERNEL)
$(SYSTOOLS): $(PREPROOT) $(COMPILE_OPTIONS)
@scripts/echo Installing standard system tools
systemd-firstboot \
--root=$(CHROOT) \
--setup-machine-id \
--timezone=$(TIMEZONE) \
--hostname=$(HOSTNAME) \
--root-password=
$(inroot) eselect locale set $(LOCALE)
ifeq ($(DASH),YES)
if ! test -e "$(STAGE4_TARBALL)"; \
then $(inroot) $(EMERGE) --noreplace $(USEPKG) app-shells/dash; \
echo /bin/dash >> $(CHROOT)/etc/shells; \
$(inroot) chsh -s /bin/sh root; \
fi
$(inroot) ln -sf dash /bin/sh
endif
touch $(SYSTOOLS)
$(GRUB): $(PREPROOT) configs/grub.conf $(KERNEL) scripts/grub-headless.sed
ifneq ($(EXTERNAL_KERNEL),YES)
@scripts/echo Installing Grub
$(inroot) $(EMERGE) -nN $(USEPKG) sys-boot/grub-static
cp configs/grub.conf $(CHROOT)/boot/grub/grub.conf
ifeq ($(VIRTIO),YES)
sed -i 's/sda/vda/' $(CHROOT)/boot/grub/grub.conf
endif
ifeq ($(HEADLESS),YES)
sed -i -f scripts/grub-headless.sed $(CHROOT)/boot/grub/grub.conf
endif
endif
$(inroot) ln -nsf /run/systemd/resolve/resolv.conf /etc/resolv.conf
touch $(GRUB)
$(SOFTWARE): $(STAGE3) $(SYSTOOLS) configs/eth.network configs/issue $(WORLD)
@scripts/echo Building $(APPLIANCE)-specific software
$(MAKE) -C appliances/$(APPLIANCE) preinstall
cp $(WORLD) $(CHROOT)/var/tmp/world
$(inroot) xargs -a/var/tmp/world -d'\n' -r $(EMERGE) $(USEPKG) --update --newuse --deep
-$(gcc_config)
@scripts/echo Running @preserved-rebuild
$(inroot) $(EMERGE) --usepkg=n @preserved-rebuild
cp configs/issue $(CHROOT)/etc/issue
-$(gcc_config)
$(inroot) $(EMERGE) $(USEPKG) --update --newuse --deep world
$(inroot) $(EMERGE) --depclean --with-bdeps=n
-$(gcc_config)
$(inroot) --setenv EDITOR=/usr/bin/nano etc-update
cp configs/eth.network $(CHROOT)/etc/systemd/network/eth.network
$(inroot) systemctl enable systemd-networkd.service
$(inroot) systemctl enable systemd-resolved.service
ifeq ($(ENABLE_SSHD),YES)
$(inroot) systemctl enable sshd.service
endif
ifeq ($(DASH),YES)
$(inroot) $(EMERGE) --depclean app-shells/bash
endif
$(MAKE) -C appliances/$(APPLIANCE) postinstall
ifneq ($(PKGLIST),0)
echo \# > $(LST_FILE)
echo \# Gentoo Virtual Appliance \"$(APPLIANCE)\" package list >> $(LST_FILE)
echo \# Generated `date -u` >> $(LST_FILE)
echo \# >> $(LST_FILE)
(cd "$(CHROOT)"/var/db/pkg ; /bin/ls -1d */* | grep -v '^virtual/') >> $(LST_FILE)
endif
touch $(SOFTWARE)
$(RAW_IMAGE): $(STAGE4_TARBALL) scripts/grub.shell scripts/motd.sh
@scripts/echo Installing files to `basename $(RAW_IMAGE)`
qemu-img create -f raw $(RAW_IMAGE).tmp $(DISK_SIZE)
parted -s $(RAW_IMAGE).tmp mklabel gpt
parted -s $(RAW_IMAGE).tmp mkpart primary 1 $(DISK_SIZE)
parted -s $(RAW_IMAGE).tmp set 1 boot on
sync
losetup --show --find --partscan $(RAW_IMAGE).tmp > partitions
mkfs.ext4 -O sparse_super,^has_journal -L "$(APPLIANCE)"_root -m 0 `cat partitions`p1
mkdir $(CHROOT)
mount -o noatime `cat partitions`p1 $(CHROOT)
tar -xf $(STAGE4_TARBALL) --numeric-owner $(COPY_ARGS) -C $(CHROOT)
scripts/motd.sh $(EXTERNAL_KERNEL) $(VIRTIO) $(DISK_SIZE) $(SWAP_SIZE) $(DASH) $(ARCH) > $(CHROOT)/etc/motd
ifneq ($(EXTERNAL_KERNEL),YES)
echo '(hd0) ' $(RAW_IMAGE).tmp > device-map
$(CHROOT)/sbin/grub --device-map=device-map --no-floppy --batch < scripts/grub.shell
endif
umount $(CHROOT)
rmdir $(CHROOT)
sync
losetup --detach `cat partitions`
rm -f partitions device-map
mv $(RAW_IMAGE).tmp $(RAW_IMAGE)
$(QCOW_IMAGE): $(RAW_IMAGE)
@scripts/echo Creating `basename $(QCOW_IMAGE)`
qemu-img convert -f raw -O qcow2 -c $(RAW_IMAGE) $(QCOW_IMAGE).tmp
mv $(QCOW_IMAGE).tmp $(QCOW_IMAGE)
qcow: $(QCOW_IMAGE)
$(XVA_IMAGE): $(RAW_IMAGE)
@scripts/echo Creating `basename $(XVA_IMAGE)`
xva.py --disk=$(RAW_IMAGE) --is-hvm --memory=256 --vcpus=1 --name=$(APPLIANCE) \
--filename=$(XVA_IMAGE).tmp
mv $(XVA_IMAGE).tmp $(XVA_IMAGE)
xva: $(XVA_IMAGE)
$(VMDK_IMAGE): $(RAW_IMAGE)
@scripts/echo Creating `basename $(VMDK_IMAGE)`
qemu-img convert -f raw -O vmdk $(RAW_IMAGE) $(VMDK_IMAGE).tmp
mv $(VMDK_IMAGE).tmp $(VMDK_IMAGE)
vmdk: $(VMDK_IMAGE)
$(STAGE4_TARBALL): $(PORTAGE_DIR) stage3-$(ARCH).tar.bz2 appliances/$(APPLIANCE) configs/rsync-excludes
$(MAKE) $(STAGE3)
$(MAKE) $(PREPROOT)
$(MAKE) $(SOFTWARE)
$(MAKE) $(KERNEL)
$(MAKE) $(GRUB)
@scripts/echo Creating stage4 tarball: `basename $(STAGE4_TARBALL)`
$(change_password)
mkdir -p $(IMAGES)
tar -acf "$(STAGE4_TARBALL).tmp.xz" --numeric-owner $(COPY_ARGS) -C $(CHROOT) --one-file-system .
mv "$(STAGE4_TARBALL).tmp.xz" "$(STAGE4_TARBALL)"
$(MAKE) clean
stage4: $(STAGE4_TARBALL)
eclean: $(COMPILE_OPTIONS)
$(inroot) $(EMERGE) $(USEPKG) --oneshot --noreplace app-portage/gentoolkit
$(inroot) eclean-pkg
$(inroot) eclean-dist
$(inroot) $(EMERGE) --depclean app-portage/gentoolkit
$(MAKE) clean
clean:
rm -f partitions device-map $(IMAGES)/*.tmp
rm -rf --one-file-system -- $(CHROOT)
realclean: clean
${RM} $(RAW_IMAGE) $(QCOW_IMAGE) $(VMDK_IMAGE)
distclean:
rm -f -- *.qcow *.img *.vmdk
rm -f stage3-*.tar.bz2
rm -f portage-snapshot.tar.bz2
appliance-list:
@scripts/echo 'Available appliances:'
@/bin/ls -1 appliances
checksums:
@scripts/echo 'Calculating checksums'
$(RM) $(CHECKSUMS)
cd $(IMAGES) && sha256sum --binary * > $(CHECKSUMS).tmp
mv $(CHECKSUMS).tmp $(CHECKSUMS)
shell: $(PREPROOT)
@scripts/echo 'Entering interactive shell for the $(APPLIANCE) build.'
@scripts/echo 'Type "exit" or "^D" to leave'
@scripts/echo
@$(inroot)
@rm -f $(CHROOT)/root/.bash_history
help:
@scripts/echo 'Help targets (this is not a comprehensive list)'
@echo
@echo 'sync_portage - Download the latest portage snapshot'
@echo 'sync_stage3 - Download the latest stage3 tarball'
@echo 'stage4 - Build a stage4 tarball'
@echo 'clean - Unmount chroot and clean directory'
@echo 'eclean - Clean outdated packages and distfiles'
@echo 'realclean - Clean and remove image files'
@echo 'shell - Enter a shell in the build environment'
@scripts/echo 'Images'
@echo 'image - Build a raw VM image from stage4'
@echo 'qcow - Build a qcow VM image from a raw image'
@echo 'vmdk - Build a vmdk image from a raw image'
@echo 'xva - Build an xva image from a raw image'
@echo 'appliance-list - List built-in appliances'
@echo 'help - Show this help'
@scripts/echo 'Variables'
@echo 'APPLIANCE= - The appliance to build'
@echo 'HOSTNAME= - Hostname to give appliance'
@echo 'TIMEZONE= - Timezone to set for the appliance'
@echo 'CHROOT= - The directory to build the chroot'
@echo 'DISK_SIZE= - Size of the disk image'
@echo 'SWAP_SIZE= - Size of the swap file'
@echo 'ARCH= - Architecture to build for (x86 or amd64)'
@echo 'VIRTIO=YES - Configure the stage2/image to use virtio'
@echo 'EXTERNAL_KERNEL=YES - Do not build a kernel in the image'
@echo 'HEADLESS=YES - Build a headless (serial console) image.'
@echo 'ENABLE_SSHD=YES - Enable sshd to start automatically in the image'
@echo
@scripts/echo 'Example'
@echo 'make APPLIANCE=mongodb HEADLESS=YES VIRTIO=YES stage4 qcow clean'
.PHONY: qcow vmdk clean realclean distclean stage4 image stage4 help appliance-list eclean sync_portage sync_stage3 checksums