diff --git a/doc/source/building/build_oem_disk.rst b/doc/source/building/build_oem_disk.rst index 722d7c61..0476c094 100644 --- a/doc/source/building/build_oem_disk.rst +++ b/doc/source/building/build_oem_disk.rst @@ -1,3 +1,5 @@ +.. _oem: + Build an OEM Expandable Disk Image ================================== diff --git a/doc/source/building/working_with_images.rst b/doc/source/building/working_with_images.rst index bbb34c46..53749ec2 100644 --- a/doc/source/building/working_with_images.rst +++ b/doc/source/building/working_with_images.rst @@ -18,3 +18,4 @@ different image types. working_with_images/uninstall_package_requests working_with_images/vagrant_setup working_with_images/pxe_live_iso_boot + working_with_images/oem_ramdisk_deployment diff --git a/doc/source/building/working_with_images/oem_ramdisk_deployment.rst b/doc/source/building/working_with_images/oem_ramdisk_deployment.rst new file mode 100644 index 00000000..12d8896c --- /dev/null +++ b/doc/source/building/working_with_images/oem_ramdisk_deployment.rst @@ -0,0 +1,86 @@ +.. _ramdisk_deployment: + +Deploy and Run System in a RamDisk +================================== + +.. sidebar:: Abstract + + This page provides further information for handling + oem images built with KIWI and references the following + articles: + + * :ref:`oem` + +If a machine should run the OS completely in memory without +the need for any persistent storage, the approach to deploy +the image into a ramdisk serves this purpose. KIWI allows +to create a bootable ISO image which deploys the image +into a ramdisk and activates that image with the following +oem type definition: + +.. code:: xml + + + + true + true + /dev/ram1 + false + false + + + +The type specification above builds an installation ISO image +which deploys the System Image into the specified ramdisk +device (/dev/ram1). The setup of the ISO image boots with a +short boot timeout of 1sec and just runs through the process +without asking any questions. In a ramdisk deployment the +optional target verification, swap space and multipath targets +are out of scope and therefore disabled. + +The configured size of the ramdisk specifies the size of the +OS disk and must be at least of the size of the System Image. +The disk size can be configured with the following value in +the kernelcmdline attribute: + +* ramdisk_size=kbyte-value" + +An image built with the above setup can be tested in QEMU as +follows: + +.. code:: bash + + $ qemu -cdrom LimeJeOS-Leap-42.3.x86_64-1.42.3.install.iso + +.. note:: Enough Main Memory + + The machine, no matter if it's a virtual machine like QEMU + or a real machine, must provide enough RAM to hold the image + in the ramdisk as well as have enough RAM available to operate + the OS and its applications. The KIWI build image with the + extension .raw provides the System Image which gets deployed + into the RAM space. Substract the size of the System Image + from the RAM space the machine offers and make sure the result + is still big enough for the use case of the appliance. In + case of a virtual machine, attach enough main memory to fit + this calculation. In case of QEMU this can be done with + the `-m` option + +Like all other oem KIWI images, also the ramdisk setup supports +all the deployments methods as explained in :ref:`deployment_methods` +This means it's also possible to dump the ISO image on a USB +stick let the system boot from it and unplug the stick from +the machine because the system was deployed into RAM + +.. note:: Limitations Of RamDisk Deployments + + Only standard images which can be booted by a simple root mount + and root switch can be used. Usually KIWI calls kexec after deployment + such that the correct, for the image created dracut initrd, will boot + the image. In case of a RAM only system kexec does not work because + it would loose the ramdisk contents. Thus the dracut initrd driving + the deployment is also the environment to boot the system. + There are cases where this environment is not suitable to boot + the system. One example would be luks encrypted images which requires + to run unlock code inside of the initrd which is not present in the + initrd created for deployment. diff --git a/dracut/modules.d/90kiwi-dump/kiwi-dump-image.sh b/dracut/modules.d/90kiwi-dump/kiwi-dump-image.sh index a4f05827..22d20c9b 100755 --- a/dracut/modules.d/90kiwi-dump/kiwi-dump-image.sh +++ b/dracut/modules.d/90kiwi-dump/kiwi-dump-image.sh @@ -36,14 +36,29 @@ function get_disk_list { local disk_meta local item_status=on local list_items + local blk_opts if [ ! -z "${kiwi_devicepersistency}" ];then disk_id=${kiwi_devicepersistency} fi - if [ ! -z "${kiwi_oemmultipath_scan}" ];then + if getargbool 0 rd.kiwi.ramdisk; then + # target should be a ramdisk on request. Thus actively + # load the ramdisk block driver and support custom sizes + local rd_size + local modfile=/etc/modprobe.d/99-brd.conf + rd_size=$(getarg ramdisk_size=) + if [ ! -z "${rd_size}" ];then + echo "options brd rd_size=${rd_size}" > ${modfile} + fi + modprobe brd + udev_pending + # target should be a ramdisk on request. Thus instruct + # lsblk to list only ramdisk devices (Major=1) + blk_opts="-I 1" + elif [ ! -z "${kiwi_oemmultipath_scan}" ];then scan_multipath_devices fi for disk_meta in $( - lsblk -p -n -r -o NAME,SIZE,TYPE | grep disk | tr ' ' ":" + lsblk "${blk_opts}" -p -n -r -o NAME,SIZE,TYPE | grep disk | tr ' ' ":" );do disk_device="$(echo "${disk_meta}" | cut -f1 -d:)" if [ "$(blkid "${disk_device}" -s LABEL -o value)" = \ @@ -373,6 +388,14 @@ fi check_image_integrity "${image_target}" -boot_installed_system - -exit 0 +if getargbool 0 rd.kiwi.ramdisk; then + # For ramdisk deployment a kexec boot is not possible as it + # will wipe the contents of the ramdisk. Therefore we prepare + # the switch_root from this deployment initrd. Also see the + # unit generator: dracut-kiwi-ramdisk-generator + kpartx -s -a "${image_target}" +else + # Standard deployment will use kexec to activate and boot the + # deployed system + boot_installed_system +fi diff --git a/dracut/modules.d/90kiwi-dump/kiwi-ramdisk-deployment-generator.sh b/dracut/modules.d/90kiwi-dump/kiwi-ramdisk-deployment-generator.sh new file mode 100755 index 00000000..44f17632 --- /dev/null +++ b/dracut/modules.d/90kiwi-dump/kiwi-ramdisk-deployment-generator.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh + +GENERATOR_DIR="$1" +[ -z "${GENERATOR_DIR}" ] && exit 1 +[ -d "${GENERATOR_DIR}" ] || mkdir -p "${GENERATOR_DIR}" + +root_uuid=$( + while read -r -d ' ' opt; do echo "${opt}";done < /config.bootoptions |\ + grep root= | cut -f2- -d= +) + +{ + echo "[Unit]" + echo "Before=initrd-root-fs.target" + echo "[Mount]" + echo "Where=/sysroot" + echo "What=${root_uuid}" + _dev=RamDisk_rootfs +} > "$GENERATOR_DIR"/sysroot.mount + +if [ ! -e "$GENERATOR_DIR/initrd-root-fs.target.requires/sysroot.mount" ]; then + mkdir -p "$GENERATOR_DIR"/initrd-root-fs.target.requires + ln -s "$GENERATOR_DIR"/sysroot.mount \ + "$GENERATOR_DIR"/initrd-root-fs.target.requires/sysroot.mount +fi + +mkdir -p "$GENERATOR_DIR/$_dev.device.d" +{ + echo "[Unit]" + echo "JobTimeoutSec=60" +} > "$GENERATOR_DIR/$_dev.device.d/timeout.conf" diff --git a/dracut/modules.d/90kiwi-dump/module-setup.sh b/dracut/modules.d/90kiwi-dump/module-setup.sh index 21e15d3e..3241e1d4 100755 --- a/dracut/modules.d/90kiwi-dump/module-setup.sh +++ b/dracut/modules.d/90kiwi-dump/module-setup.sh @@ -14,8 +14,9 @@ installkernel() { # called by dracut install() { declare moddir=${moddir} + declare systemdutildir=${systemdutildir} inst_multiple \ - tr lsblk dd md5sum head pv kexec basename awk + tr lsblk dd md5sum head pv kexec basename awk kpartx inst_hook pre-udev 30 "${moddir}/kiwi-installer-genrules.sh" inst_hook pre-udev 60 "${moddir}/kiwi-dump-net-genrules.sh" @@ -25,6 +26,10 @@ install() { inst_hook cmdline 30 "${moddir}/parse-kiwi-install.sh" inst_hook pre-mount 30 "${moddir}/kiwi-dump-image.sh" + + inst_script "${moddir}/kiwi-ramdisk-deployment-generator.sh" \ + "${systemdutildir}/system-generators/dracut-kiwi-ramdisk-generator" + inst_rules 60-cdrom_id.rules dracut_need_initqueue }