diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..7637ea77 --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +# +# Copyright (c) 2017 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# +MK_DIR :=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) + +DISTRO ?= centos +DISTRO_ROOTFS := "$(PWD)/$(DISTRO)_rootfs" +IMG_SIZE=500 + +image: + @echo Creating rootfs based on "$(DISTRO)" + "$(MK_DIR)/rootfs-builder/rootfs.sh" -r "$(DISTRO_ROOTFS)" "$(DISTRO)" + @echo Creating image based on "$(DISTRO_ROOTFS)" + AGENT_BIN="$(AGENT_BIN)" "$(MK_DIR)/image-builder/image_builder.sh" -s "$(IMG_SIZE)" "$(DISTRO_ROOTFS)" diff --git a/README.md b/README.md new file mode 100644 index 00000000..c14208b2 --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +# Overview # + +`Kata Containers runtime` creates a Virtual Machine to isolate a set of +container workloads. The Virtual Machine requires a operating system +operating (`Guest OS`) to boot and create containers inside the guest +environment. + +This repository contains tools to create a `Guest OS` for `Kata +Containers`. + +## Terms ## + +This section describe the terms used as along all this document. + +- `Guest OS` + + It is the collection of a `virtual disk` or `disk image` and `kernel` + that in conjunction work as an operating system and it is different than + the host operating system. + + - `Virtual disk` or `Guest Image` + + It is a virtual disk witch contains a `rootfs` that will be used to boot + a Virtual Machine by for the `Kata Containers runtime`. + + - `rootfs` + + The root filesystem or rootfs is the filesystem that is contained in the + guest root directory. It can be built from any Linux Distribution but + must provide at least the following components: + - Kata agent + - A `init` system (for example `systemd`) witch allow to start + Kata agent at boot time. diff --git a/image-builder/README.md b/image-builder/README.md new file mode 100644 index 00000000..92968197 --- /dev/null +++ b/image-builder/README.md @@ -0,0 +1,25 @@ +# Kata Containers image generation # + +A Kata Containers image is generated by the script `image_builder.sh` +which uses a `rootfs` directory created by the script +`rootfs-builder/rootfs.sh`. + +To create a guest OS image run: + +``` +$ ./image_builder.sh path/to/rootfs +``` + +Where `path/to/rootfs` is the directory pupulated by `rootfs.sh`. The +script will check for following required binaries: + +- `/sbin/init` : The image must contain a `init` binary +- `/bin/kata-agent` : The image contain the Kata [agent] + +More information about usage: + +``` +$ ./image_builder.sh -h +``` + +[agent]: https://github.com/kata-containers/agent "Kata agent" diff --git a/image-builder/image_builder.sh b/image-builder/image_builder.sh new file mode 100755 index 00000000..68d6187e --- /dev/null +++ b/image-builder/image_builder.sh @@ -0,0 +1,130 @@ +#!/bin/bash +# +# Copyright (c) 2017 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +set -e +if [ -n "$DEBUG" ] ; then + set -x +fi + +SCRIPT_NAME="${0##*/}" +IMAGE="${IMAGE:-kata-containers.img}" +AGENT_BIN=${AGENT_BIN:-kata-agent} + +die() +{ + local msg="$*" + echo "ERROR: ${msg}" >&2 + exit 1 +} + +OK() +{ + local msg="$*" + echo "[OK] ${msg}" >&2 +} + +info() +{ + local msg="$*" + echo "INFO: ${msg}" +} + +usage() +{ + error="${1:-0}" + cat < + This script will create a Kata Containers image file based on the + directory. + +Options: + -h Show this help + -o path to generate image file ENV: IMAGE + -s Image size in MB (default $IMG_SIZE) ENV: IMG_SIZE + +Extra environment variables: + AGENT_BIN: use it to change the expected agent binary name" +EOT +exit "${error}" +} + +while getopts "ho:s:" opt +do + case "$opt" in + h) usage ;; + o) IMAGE="${OPTARG}" ;; + s) IMG_SIZE="${OPTARG}" ;; + esac +done + +shift $(( $OPTIND - 1 )) + +ROOTFS="$1" + +[ -n "${ROOTFS}" ] || usage +[ -d "${ROOTFS}" ] || die "${ROOTFS} is not a directory" +# The kata rootfs image expect init and kata-agent to be installed +init="${ROOTFS_DIR}/sbin/init" +[ -x "${init}" ] || [ -L ${init} ] || die "/sbin/init is not installed in ${ROOTFS_DIR}" +OK "init is installed" +[ -x "${ROOTFS}/bin/${AGENT_BIN}" ] || \ + die "/bin/${AGENT_BIN} is not installed in ${ROOTFS_DIR} + use AGENT_BIN env variable to change the expected agent binary name" +OK "Agent installed" +[ "$(id -u)" -eq 0 ] || die "$0: must be run as root" + +BLOCK_SIZE=${BLOCK_SIZE:-4096} +IMG_SIZE=${IMG_SIZE:-80} + +info "Creating raw disk with size ${IMG_SIZE}M" +qemu-img create -q -f raw "${IMAGE}" "${IMG_SIZE}M" +OK "Image file created" + +# Kata runtime expect an image with just one partition +# The partition is the rootfs content + +info "Creating partitions" +parted "${IMAGE}" --script "mklabel gpt" \ +"mkpart ext4 1M -1M" +OK "Partitions created" + +# Get the loop device bound to the image file (requires /dev mounted in the +# image build system and root privileges) +DEVICE=$(losetup -P -f --show "${IMAGE}") + +#Refresh partition table +partprobe "${DEVICE}" + +MOUNT_DIR=$(mktemp -d osbuilder-mount-dir.XXXX) +info "Formating Image using ext4 format" +mkfs.ext4 -q -F -b "${BLOCK_SIZE}" "${DEVICE}p1" +OK "Image formated" + +info "Mounting root paratition" +mount "${DEVICE}p1" "${MOUNT_DIR}" +OK "root paratition mounted" + +RESERVED_BLOCKS_PERCENTAGE=3 +info "Set filesystem reserved blocks percentage to ${RESERVED_BLOCKS_PERCENTAGE}%" +tune2fs -m "${RESERVED_BLOCKS_PERCENTAGE}" "${DEVICE}p1" + +#TODO: Calculate disk size based on rootfs +#FIXME: https://github.com/kata-containers/osbuilder/issues/2 +ROOTFS_SIZE=$(du -B 1MB -s "${ROOTFS}" | awk '{print $1}') +AVAIL_DISK=$(df -B M --output=avail "${DEVICE}p1" | tail -1) +AVAIL_DISK=${AVAIL_DISK/M} +info "Free space root partition ${AVAIL_DISK} MB" +info "rootfs size ${ROOTFS_SIZE} MB" +info "Copying content from rootfs to root partition" +cp -a "${ROOTFS}"/* ${MOUNT_DIR} +OK "rootfs copied" + +# Cleanup +sync +umount -l ${MOUNT_DIR} +fsck -D -y "${DEVICE}p1" +losetup -d "${DEVICE}" +info "Image created" diff --git a/rootfs-builder/README.md b/rootfs-builder/README.md new file mode 100644 index 00000000..c0a61475 --- /dev/null +++ b/rootfs-builder/README.md @@ -0,0 +1,126 @@ +# Building a rootfs for Kata Containers Guest OS # + +The Kata Containers `rootfs` is created using `rootfs.sh`. + +## Supported base OSs ## + +The `rootfs.sh` script builds a `rootfs` based on a particular Linux\* +distribution. To build a `rootfs`for your chosen distribution, run: + +``` +$./rootfs.sh +``` + +To check the supported `rootfs` based OS run `$rootfs-builder/rootfs.sh +-h`, it will show the supported values of `` + + +## Adding support for new base OS ## + +The script `rootfs.sh` will it check for immediate sub-directories +containing the following expected files structure: + +- A `bash(1)` script called `rootfs_lib.sh` + + This file must contain a function called `build_rootfs()` this function + must receive as first argument the path where the `rootfs` will be + populated. Path: `rootfs-builder//rootfs_lib.sh`. + + +- A `bash(1)` file `config.sh` + + This represents the specific configuration for ``. It must + provide configuration specific variables for user to modify as needed. + The `config.sh` file will be loaded before executing `build_rootfs()` to + provide all the needed configuration to the function. Path: + `rootfs-builder//config.sh`. + +To create a directory with the expected file structure run: + +``` +make -f template/Makefile ROOTFS_BASE_NAME=my_new_awesome_rootfs +``` + +After run the command above, a new directory will be created in +`rootfs-builder/my_new_awesome_rootfs/`. To verify it is one of the +options to build a `rootfs` run `./rootfs.sh -h`, it will show +`my_new_awesome` as one of the options to use it for: + +``` +./rootfs.sh +``` + +Now that a new directory structure was created is need to: + +- If needed, add configuration variables to `rootfs-builder/my_new_awesome_rootfs/config.sh` +- Implement the stub `build_rootfs()` function from `rootfs-builder/my_new_awesome_rootfs/rootfs_lib.sh` + +### Expected `rootfs` directory content ### + +After the function `build_rootfs` is called, the script expects the +`rootfs` directory to contain /sbin/init and /sbin/kata-agent binaries. + +### (optional) Customise the `rootfs` ### + +For development uses cases, developers may want to modify the guest OS. +To do that it is possible to use following methods: + +- Use the environment variable `EXTRA_PKG` to provide a list of space + separated packages to be installed. + + *Note: The package names may vary among Linux* distributions, the extra + package names must exist in the base OS flavor you use to build the + `rootfs`* + + Example: + ``` + EXTRA_PKG="vim emacs" ./rootfs-builder/rootfs.sh \ + -r ${PWD}/myrootfs fedora + + ``` + +- In `rootfs-builder//config.sh` modify the variable `PACKAGES`. + This are the minimal set of packages needed. The configuration file must + use the package names from the distro was created for. + +- It is possible to customise the `rootfs` directory before create an + image based in on it. + + +## Build `rootfs` using Docker* ## + +Depending on the base OS to build the `rootfs` guest OS, it is required some +specific programs that probably are not available or installed in the system +that will build the guest image. For this case `rootfs.sh` can use +a Docker\* container to build the `rootfs`. The following requirements +must be met: + +1. Docker 1.12+ installed + +2. `runc` is configured as the default runtime + + To check if `runc` is the default runtime: + + ``` + $ docker info | grep 'Default Runtime: runc' + ``` + + Note: + This requirement is specifically when using Clear Containers runtime + see [issue](https://github.com/clearcontainers/runtime/issues/828) for + more information. + +3. Export `USE_DOCKER` variable + + ``` + $ export USE_DOCKER=true + ``` +4. Use `rootfs.sh: + Example: + ``` + $ export USE_DOCKER=true + $ # build guest O/S rootfs based on fedora + $ ./rootfs-builder/rootfs.sh -r "${PWD}/fedora_rootfs" fedora + $ # build image based rootfs created above + $ ./image-builder/image_builder.sh "${PWD}/fedora_rootfs" + ``` diff --git a/rootfs-builder/centos/Dockerfile b/rootfs-builder/centos/Dockerfile new file mode 100644 index 00000000..fc96ef0a --- /dev/null +++ b/rootfs-builder/centos/Dockerfile @@ -0,0 +1 @@ +FROM centos:7 diff --git a/rootfs-builder/centos/RPM-GPG-KEY-CentOS-7 b/rootfs-builder/centos/RPM-GPG-KEY-CentOS-7 new file mode 100644 index 00000000..47f6d4d6 --- /dev/null +++ b/rootfs-builder/centos/RPM-GPG-KEY-CentOS-7 @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.5 (GNU/Linux) + +mQINBFOn/0sBEADLDyZ+DQHkcTHDQSE0a0B2iYAEXwpPvs67cJ4tmhe/iMOyVMh9 +Yw/vBIF8scm6T/vPN5fopsKiW9UsAhGKg0epC6y5ed+NAUHTEa6pSOdo7CyFDwtn +4HF61Esyb4gzPT6QiSr0zvdTtgYBRZjAEPFVu3Dio0oZ5UQZ7fzdZfeixMQ8VMTQ +4y4x5vik9B+cqmGiq9AW71ixlDYVWasgR093fXiD9NLT4DTtK+KLGYNjJ8eMRqfZ +Ws7g7C+9aEGHfsGZ/SxLOumx/GfiTloal0dnq8TC7XQ/JuNdB9qjoXzRF+faDUsj +WuvNSQEqUXW1dzJjBvroEvgTdfCJfRpIgOrc256qvDMp1SxchMFltPlo5mbSMKu1 +x1p4UkAzx543meMlRXOgx2/hnBm6H6L0FsSyDS6P224yF+30eeODD4Ju4BCyQ0jO +IpUxmUnApo/m0eRelI6TRl7jK6aGqSYUNhFBuFxSPKgKYBpFhVzRM63Jsvib82rY +438q3sIOUdxZY6pvMOWRkdUVoz7WBExTdx5NtGX4kdW5QtcQHM+2kht6sBnJsvcB +JYcYIwAUeA5vdRfwLKuZn6SgAUKdgeOtuf+cPR3/E68LZr784SlokiHLtQkfk98j +NXm6fJjXwJvwiM2IiFyg8aUwEEDX5U+QOCA0wYrgUQ/h8iathvBJKSc9jQARAQAB +tEJDZW50T1MtNyBLZXkgKENlbnRPUyA3IE9mZmljaWFsIFNpZ25pbmcgS2V5KSA8 +c2VjdXJpdHlAY2VudG9zLm9yZz6JAjUEEwECAB8FAlOn/0sCGwMGCwkIBwMCBBUC +CAMDFgIBAh4BAheAAAoJECTGqKf0qA61TN0P/2730Th8cM+d1pEON7n0F1YiyxqG +QzwpC2Fhr2UIsXpi/lWTXIG6AlRvrajjFhw9HktYjlF4oMG032SnI0XPdmrN29lL +F+ee1ANdyvtkw4mMu2yQweVxU7Ku4oATPBvWRv+6pCQPTOMe5xPG0ZPjPGNiJ0xw +4Ns+f5Q6Gqm927oHXpylUQEmuHKsCp3dK/kZaxJOXsmq6syY1gbrLj2Anq0iWWP4 +Tq8WMktUrTcc+zQ2pFR7ovEihK0Rvhmk6/N4+4JwAGijfhejxwNX8T6PCuYs5Jiv +hQvsI9FdIIlTP4XhFZ4N9ndnEwA4AH7tNBsmB3HEbLqUSmu2Rr8hGiT2Plc4Y9AO +aliW1kOMsZFYrX39krfRk2n2NXvieQJ/lw318gSGR67uckkz2ZekbCEpj/0mnHWD +3R6V7m95R6UYqjcw++Q5CtZ2tzmxomZTf42IGIKBbSVmIS75WY+cBULUx3PcZYHD +ZqAbB0Dl4MbdEH61kOI8EbN/TLl1i077r+9LXR1mOnlC3GLD03+XfY8eEBQf7137 +YSMiW5r/5xwQk7xEcKlbZdmUJp3ZDTQBXT06vavvp3jlkqqH9QOE8ViZZ6aKQLqv +pL+4bs52jzuGwTMT7gOR5MzD+vT0fVS7Xm8MjOxvZgbHsAgzyFGlI1ggUQmU7lu3 +uPNL0eRx4S1G4Jn5 +=OGYX +-----END PGP PUBLIC KEY BLOCK----- diff --git a/rootfs-builder/centos/config.sh b/rootfs-builder/centos/config.sh new file mode 100644 index 00000000..8c5cf749 --- /dev/null +++ b/rootfs-builder/centos/config.sh @@ -0,0 +1,15 @@ +# This is a configuration file add extra variables to +# be used by build_rootfs() from rootfs_lib.sh the variables will be +# loaded just before call the function. + +# Here there are a couple of variables you may need. +# Remove them or add more + +# Centos Version +OS_VERSION=${OS_VERSION:-7} + +#Mandatory Packages that must be installed +# systemd: An init system that will start kata-agent +# iptables: Need by Kata agent +# udevlib.so: Need by Kata agent +PACKAGES="systemd iptables" diff --git a/rootfs-builder/centos/rootfs_lib.sh b/rootfs-builder/centos/rootfs_lib.sh new file mode 100644 index 00000000..499b5758 --- /dev/null +++ b/rootfs-builder/centos/rootfs_lib.sh @@ -0,0 +1,134 @@ +#!/bin/bash +# +# Copyright (c) 2017 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +check_program(){ + type "$1" >/dev/null 2>&1 +} + +check_root() +{ + if [ "$(id -u)" != "0" ]; then + echo "Root is needed" + exit 1 + fi +} + +generate_dnf_config() +{ + cat > "${DNF_CONF}" << EOF +[main] +cachedir=/var/cache/centos-osbuilder +keepcache=0 +debuglevel=2 +logfile=/var/log/yum-centos.log +exactarch=1 +obsoletes=1 +gpgcheck=0 +plugins=0 +installonly_limit=3 +#Dont use the default dnf reposdir +#this will prevent to use host repositories +reposdir=/root/mash + +[base] +name=CentOS-7 - Base +mirrorlist=http://mirrorlist.centos.org/?release=7&arch=x86_64&repo=os&container=container +#baseurl=${REPO_URL}/os/x86_64/ +gpgcheck=1 +gpgkey=file://${CONFIG_DIR}/RPM-GPG-KEY-CentOS-7 + +#released updates +[updates] +name=CentOS-7 - Updates +mirrorlist=http://mirrorlist.centos.org/?release=7&arch=x86_64&repo=updates&container=container +#baseurl=${REPO_URL}/updates/x86_64/ +gpgcheck=1 +gpgkey=file://${CONFIG_DIR}/RPM-GPG-KEY-CentOS-7 + +#additional packages that may be useful +[extras] +name=CentOS-7 - Extras +mirrorlist=http://mirrorlist.centos.org/?release=7&arch=x86_64&repo=extras&container=container +#baseurl=${REPO_URL}/extras/x86_64/ +gpgcheck=1 +gpgkey=file://${CONFIG_DIR}/RPM-GPG-KEY-CentOS-7 + +#additional packages that extend functionality of existing packages +[centosplus] +name=CentOS-7 - Plus +mirrorlist=http://mirrorlist.centos.org/?release=7&arch=x86_64&repo=centosplus&container=container +#baseurl=${REPO_URL}/centosplus/x86_64/ +gpgcheck=1 +enabled=0 +gpgkey=file://${CONFIG_DIR}/RPM-GPG-KEY-CentOS-7 +EOF +} + +# - Arguments +# rootfs_dir=$1 +# +# - Optional environment variables +# +# EXTRA_PKGS: Variable to add extra PKGS provided by the user +# +# BIN_AGENT: Name of the Kata-Agent binary +# +# REPO_URL: URL to distribution repository ( should be configured in +# config.sh file) +# +# Any other configuration variable for a specific distro must be added +# and documented on its own config.sh +# +# - Expected result +# +# rootfs_dir populated with rootfs pkgs +# It must provide a binary in /sbin/init +build_rootfs() { + # Mandatory + local ROOTFS_DIR=$1 + + #Name of the Kata-Agent binary + local BIN_AGENT=${BIN_AGENT} + + # In case of support EXTRA packages, use it to allow + # users add more packages to the base rootfs + local EXTRA_PKGS=${EXTRA_PKGS:-} + + #In case rootfs is created usign repositories allow user to modify + # the default URL + local REPO_URL=${REPO_URL:-http://mirror.centos.org/centos/7} + + #PATH where files this script is placed + #Use it to refer to files in the same directory + #Exmaple: ${CONFIG_DIR}/foo + local CONFIG_DIR=${CONFIG_DIR} + + + # Populate ROOTFS_DIR + # Must provide /sbin/init and /bin/${BIN_AGENT} + check_root + if [ ! -f "${DNF_CONF}" ]; then + DNF_CONF="./kata-centos-dnf.conf" + generate_dnf_config + fi + mkdir -p "${ROOTFS_DIR}" + if [ -n "${PKG_MANAGER}" ]; then + info "DNF path provided by user: ${PKG_MANAGER}" + elif check_program "dnf"; then + PKG_MANAGER="dnf" + elif check_program "yum" ; then + PKG_MANAGER="yum" + else + die "neither yum nor dnf is installed" + fi + + info "Using : ${PKG_MANAGER} to pull packages from ${REPO_URL}" + + DNF="${PKG_MANAGER} --config=$DNF_CONF -y --installroot=${ROOTFS_DIR} --noplugins" + $DNF install ${EXTRA_PKGS} ${PACKAGES} + + [ -n "${ROOTFS_DIR}" ] && rm -r "${ROOTFS_DIR}/var/cache/centos-osbuilder" +} diff --git a/rootfs-builder/clearlinux/Dockerfile b/rootfs-builder/clearlinux/Dockerfile new file mode 100644 index 00000000..fe52e95a --- /dev/null +++ b/rootfs-builder/clearlinux/Dockerfile @@ -0,0 +1,3 @@ +From fedora:27 + +RUN dnf -y update && dnf install -y git golang systemd pkgconfig diff --git a/rootfs-builder/clearlinux/config.sh b/rootfs-builder/clearlinux/config.sh new file mode 100644 index 00000000..4401ce24 --- /dev/null +++ b/rootfs-builder/clearlinux/config.sh @@ -0,0 +1,8 @@ +# +# Copyright (c) 2017 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +#Use "latest" to always pull the last Clear Linux Release +OS_VERSION=${OS_VERSION:-latest} +PACKAGES="systemd iptables-bin libudev0-shim" diff --git a/rootfs-builder/clearlinux/rootfs_lib.sh b/rootfs-builder/clearlinux/rootfs_lib.sh new file mode 100755 index 00000000..d656092d --- /dev/null +++ b/rootfs-builder/clearlinux/rootfs_lib.sh @@ -0,0 +1,93 @@ +#!/bin/bash +# +# Copyright (c) 2017 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +set -e + +check_program(){ + type "$1" >/dev/null 2>&1 +} + +generate_dnf_config() +{ + echo "WARNING: using not signed packages" + cat > "${DNF_CONF}" << EOF +[main] +cachedir=/var/cache/dnf-clear +keepcache=0 +debuglevel=2 +logfile=/var/log/dnf.log +exactarch=1 +obsoletes=1 +gpgcheck=0 +plugins=0 +installonly_limit=3 +#Dont use the default dnf reposdir +#this will prevent to use host repositories +reposdir=/root/mash + +[clear] +name=Clear +failovermethod=priority +baseurl=${REPO_URL} +enabled=1 +#Clear Linux based packages security limitations +#Although the Clear Linux rootfs is constructed from rpm packages, Clear Linux +#itself is not an rpm-based Linux distribution (the software installed on a +#Clear Linux system is not managed using rpm). The rpm packages used to +#generate the rootfs are not signed, so there is no way to ensure that +#downloaded packages are trustworthy. +gpgcheck=0 +EOF +} + +build_rootfs() +{ + # Mandatory + local ROOTFS_DIR=$1 + + #In case rootfs is created usig repositories allow user to modify + # the default URL + local REPO_URL=${REPO_URL:-https://download.clearlinux.org/current/x86_64/os/} + # In case of support EXTRA packages, use it to allow + # users add more packages to the base rootfs + local EXTRA_PKGS=${EXTRA_PKGS:-} + + #PATH where files this script is placed + #Use it to refer to files in the same directory + #Exmaple: ${CONFIG_DIR}/foo + #local CONFIG_DIR=${CONFIG_DIR} + + check_root + if [ ! -f "${DNF_CONF}" ]; then + DNF_CONF="./clear-dnf.conf" + generate_dnf_config + fi + mkdir -p "${ROOTFS_DIR}" + if [ -n "${PKG_MANAGER}" ]; then + info "DNF path provided by user: ${PKG_MANAGER}" + elif check_program "dnf"; then + PKG_MANAGER="dnf" + elif check_program "yum" ; then + PKG_MANAGER="yum" + else + die "neither yum nor dnf is installed" + fi + + info "Using : ${PKG_MANAGER} to pull packages from ${REPO_URL}" + + DNF="${PKG_MANAGER} --config=$DNF_CONF -y --installroot=${ROOTFS_DIR} --noplugins" + $DNF install ${EXTRA_PKGS} ${PACKAGES} + + [ -n "${ROOTFS_DIR}" ] && rm -r "${ROOTFS_DIR}/var/cache/dnf-clear" +} + +check_root() +{ + if [ "$(id -u)" != "0" ]; then + echo "Root is needed" + exit 1 + fi +} diff --git a/rootfs-builder/fedora/Dockerfile b/rootfs-builder/fedora/Dockerfile new file mode 100644 index 00000000..fe52e95a --- /dev/null +++ b/rootfs-builder/fedora/Dockerfile @@ -0,0 +1,3 @@ +From fedora:27 + +RUN dnf -y update && dnf install -y git golang systemd pkgconfig diff --git a/rootfs-builder/fedora/config.sh b/rootfs-builder/fedora/config.sh new file mode 100644 index 00000000..58a51f49 --- /dev/null +++ b/rootfs-builder/fedora/config.sh @@ -0,0 +1,8 @@ +# +# Copyright (c) 2017 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +#Fedora version to use +OS_VERSION=${OS_VERSION:-27} +PACKAGES="systemd iptables" diff --git a/rootfs-builder/fedora/rootfs_lib.sh b/rootfs-builder/fedora/rootfs_lib.sh new file mode 100755 index 00000000..4eb7533b --- /dev/null +++ b/rootfs-builder/fedora/rootfs_lib.sh @@ -0,0 +1,88 @@ +#!/bin/bash +# +# Copyright (c) 2017 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +set -e + +check_program(){ + type "$1" >/dev/null 2>&1 +} + +generate_dnf_config() +{ + cat > "${DNF_CONF}" << EOF +[main] +cachedir=/var/cache/dnf/kata/ +keepcache=0 +debuglevel=2 +logfile=/var/log/dnf.log +exactarch=1 +obsoletes=1 +gpgcheck=0 +plugins=0 +installonly_limit=3 +#Dont use the default dnf reposdir +#this will prevent to use host repositories +reposdir=/root/mash + +[kata] +name=fedora +failovermethod=priority +baseurl=${REPO_URL} +enabled=1 +gpgcheck=0 +EOF +} + +build_rootfs() +{ + # Mandatory + local ROOTFS_DIR=$1 + + #In case rootfs is created usig repositories allow user to modify + # the default URL + local REPO_URL=${REPO_URL:-http://mirror.math.princeton.edu/pub/fedora/linux/releases/$OS_VERSION/Everything/x86_64/os/} + + # In case of support EXTRA packages, use it to allow + # users add more packages to the base rootfs + local EXTRA_PKGS=${EXTRA_PKGS:-""} + + #PATH where files this script is placed + #Use it to refer to files in the same directory + #Exmaple: ${CONFIG_DIR}/foo + #local CONFIG_DIR=${CONFIG_DIR} + + check_root + if [ ! -f "${DNF_CONF}" ]; then + DNF_CONF="./kata-fedora-dnf.conf" + generate_dnf_config + fi + mkdir -p "${ROOTFS_DIR}" + if [ -n "${PKG_MANAGER}" ]; then + info "DNF path provided by user: ${PKG_MANAGER}" + elif check_program "dnf"; then + PKG_MANAGER="dnf" + elif check_program "yum" ; then + PKG_MANAGER="yum" + else + die "neither yum nor dnf is installed" + fi + + info "Using : ${PKG_MANAGER} to pull packages from ${REPO_URL}" + + DNF="${PKG_MANAGER} --config=$DNF_CONF -y --installroot=${ROOTFS_DIR} --noplugins" + $DNF install ${EXTRA_PKGS} ${PACKAGES} + + [ -n "${ROOTFS_DIR}" ] && rm -r "${ROOTFS_DIR}/var/cache/dnf" +} + + +check_root() +{ + if [ "$(id -u)" != "0" ]; then + echo "Root is needed" + exit 1 + fi +} diff --git a/rootfs-builder/rootfs.sh b/rootfs-builder/rootfs.sh new file mode 100755 index 00000000..9cd147f6 --- /dev/null +++ b/rootfs-builder/rootfs.sh @@ -0,0 +1,155 @@ +#!/bin/bash +# +# Copyright (c) 2017 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +set -e + +script_name="${0##*/}" +script_dir="$(dirname $(realpath -s $0))" +ROOTFS_DIR=${ROOTFS_DIR:-${PWD}/rootfs} +AGENT_VERSION=${AGENT_VERSION:-master} +GO_AGENT_PKG=${GO_AGENT_PKG:-github.com/kata-containers/agent} +AGENT_BIN=${AGENT_BIN:-kata-agent} +# Name of file that will implement build_rootfs +typeset -r LIB_SH="rootfs_lib.sh" + +if [ -n "$DEBUG" ] ; then + set -x +fi + +#$1: Error code if want to exit differnt to 0 +usage(){ + error="${1:-0}" + cat < + + : Linux distribution to use as base OS. + +Supported Linux distributions: + +$(get_distros) + +Options: +-a : agent version DEFAULT: ${AGENT_VERSION} ENV: AGENT_VERSION +-h : Show this help message +-r : rootfs directory DEFAULT: ${ROOTFS_DIR} ENV: ROOTFS_DIR + +ENV VARIABLES: +GO_AGENT_PKG: Change the golang package url to get the agent source code + DEFAULT: ${GO_AGENT_PKG} +AGENT_BIN : Name of the agent binary (needed to check if agent is installed) +USE_DOCKER: If set will build rootfs in a Docker Container (requries docker) + DEFAULT: not set +EOT +exit "${error}" +} + +die() +{ + msg="$*" + echo "ERROR: ${msg}" >&2 + exit 1 +} + +info() +{ + msg="$*" + echo "INFO: ${msg}" >&2 +} + +OK() +{ + msg="$*" + echo "INFO: [OK] ${msg}" >&2 +} + +get_distros() { + cdirs=$(find "${script_dir}" -maxdepth 1 -type d) + find ${cdirs} -maxdepth 1 -name "${LIB_SH}" -printf '%H\n' | while read dir; do + basename "${dir}" + done +} + + +check_function_exist() { + function_name="$1" + [ "$(type -t ${function_name})" == "function" ] || die "${function_name} function was not defined" +} + + +while getopts c:hr: opt +do + case $opt in + a) AGENT_VERSION="${OPTARG}" ;; + h) usage ;; + r) ROOTFS_DIR="${OPTARG}" ;; + esac +done + +shift $(($OPTIND - 1)) + +distro="$1" + +[ -n "${distro}" ] || usage 1 +distro_config_dir="${script_dir}/${distro}" + +[ -d "${distro_config_dir}" ] || die "Not found configuration directory ${distro_config_dir}" +rootfs_lib="${distro_config_dir}/${LIB_SH}" +source "${rootfs_lib}" +rootfs_config="${distro_config_dir}/config.sh" +source "${rootfs_config}" + +CONFIG_DIR=${distro_config_dir} +check_function_exist "build_rootfs" + +if [ -n "${USE_DOCKER}" ] ; then + image_name="${distro}-rootfs-osbuilder" + + docker build \ + --build-arg http_proxy="${http_proxy}" \ + --build-arg https_proxy="${https_proxy}" \ + -t "${image_name}" "${distro_config_dir}" + + #Make sure we use a compatible runtime to build rootfs + # In case Clear Containers Runtime is installed we dont want to hit issue: + #https://github.com/clearcontainers/runtime/issues/828 + docker run \ + --runtime runc \ + --env https_proxy="${https_proxy}" \ + --env http_proxy="${http_proxy}" \ + --env AGENT_VERSION="${AGENT_VERSION}" \ + --env ROOTFS_DIR="/rootfs" \ + --env GO_AGENT_PKG="${GO_AGENT_PKG}" \ + --env AGENT_BIN="${AGENT_BIN}" \ + --env GOPATH="${GOPATH}" \ + -v "${script_dir}":"/osbuilder" \ + -v "${ROOTFS_DIR}":"/rootfs" \ + -v "${GOPATH}":"${GOPATH}" \ + ${image_name} \ + bash /osbuilder/rootfs.sh "${distro}" + + exit $? +fi + +mkdir -p ${ROOTFS_DIR} +build_rootfs ${ROOTFS_DIR} + +info "Check init is installed" +init="${ROOTFS_DIR}/sbin/init" +[ -x "${init}" ] || [ -L ${init} ] || die "/sbin/init is not installed in ${ROOTFS_DIR}" +OK "init is installed" + +info "Pull Agent source code" +go get -d "${GO_AGENT_PKG}" || true +OK "Pull Agent source code" + +info "Build agent" +pushd "${GOPATH}/src/${GO_AGENT_PKG}" +make INIT=no +make install DESTDIR="${ROOTFS_DIR}" INIT=no +popd +[ -x "${ROOTFS_DIR}/bin/${AGENT_BIN}" ] || die "/bin/${AGENT_BIN} is not installed in ${ROOTFS_DIR}" +OK "Agent installed" diff --git a/rootfs-builder/template/Makefile b/rootfs-builder/template/Makefile new file mode 100644 index 00000000..66e04e32 --- /dev/null +++ b/rootfs-builder/template/Makefile @@ -0,0 +1,15 @@ +# Copyright (c) 2017 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# +# +MK_DIR :=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) +## Default destdir is one level up where is rootfs.sh script +DESTDIR ?= "$(realpath $(MK_DIR)/../)/$(ROOTFS_BASE_NAME)" +all: +ifndef ROOTFS_BASE_NAME + $(error ROOTFS_BASE_NAME is not set, use $ make ROOTFS_BASE_NAME=new_supported_os) +endif + mkdir -p $(DESTDIR) + cp "$(MK_DIR)/rootfs_lib_template.sh" "$(DESTDIR)/rootfs_lib.sh" + cp "$(MK_DIR)/config_template.sh" "$(DESTDIR)/config.sh" diff --git a/rootfs-builder/template/config_template.sh b/rootfs-builder/template/config_template.sh new file mode 100644 index 00000000..48ce6766 --- /dev/null +++ b/rootfs-builder/template/config_template.sh @@ -0,0 +1,15 @@ +# This is a configuration file add extra variables to +# be used by build_rootfs() from rootfs_lib.sh the variables will be +# loaded just before call the function. + +# Here there are a couple of variables you may need. +# Remove them or add more + +#Use it rootfs is based in a system has different versions +OS_VERSION=${OS_VERSION:-DEFAULT_VERSION} + +#Mandatory Packages that must be installed +# systemd: An init system that will start kata-agent +# iptables: Need by Kata agent +# udevlib.so: Need by Kata agent +PACKAGES="systemd iptables udevlib.so" diff --git a/rootfs-builder/template/rootfs_lib_template.sh b/rootfs-builder/template/rootfs_lib_template.sh new file mode 100644 index 00000000..133834bf --- /dev/null +++ b/rootfs-builder/template/rootfs_lib_template.sh @@ -0,0 +1,43 @@ +# - Arguments +# rootfs_dir=$1 +# +# - Optional environment variables +# +# EXTRA_PKGS: Variable to add extra PKGS provided by the user +# +# BIN_AGENT: Name of the Kata-Agent binary +# +# REPO_URL: URL to distribution repository ( should be configured in +# config.sh file) +# +# Any other configuration variable for a specific distro must be added +# and documented on its own config.sh +# +# - Expected result +# +# rootfs_dir populated with rootfs pkgs +# It must provide a binary in /sbin/init +build_rootfs() { + # Mandatory + local ROOTFS_DIR=$1 + + #Name of the Kata-Agent binary + local BIN_AGENT=${BIN_AGENT} + + # In case of support EXTRA packages, use it to allow + # users add more packages to the base rootfs + local EXTRA_PKGS=${EXTRA_PKGS:-} + + #In case rootfs is created usign repositories allow user to modify + # the default URL + local REPO_URL=${REPO_URL:-YOUR_REPO} + + #PATH where files this script is placed + #Use it to refer to files in the same directory + #Exmaple: ${CONFIG_DIR}/foo + local CONFIG_DIR=${CONFIG_DIR} + + + # Populate ROOTFS_DIR + # Must provide /sbin/init and /bin/${BIN_AGENT} +}