diff --git a/OpenBSD.md b/OpenBSD.md new file mode 100644 index 0000000..27bb107 --- /dev/null +++ b/OpenBSD.md @@ -0,0 +1,10 @@ +Build OpenBSD 6.6 image +======================= + +```shell +sudo pkg_add coreutils bash gsed flock bash +git clone https://github.com/goneri/pcib +cd pcib +sudo mkdir /var/cache/pcib +sudo ./bin/pcib --config examples/openstack-openbsd66 +``` diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..167d668 --- /dev/null +++ b/build.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# entry-point for the Cloud-Init BSD CI +version=$1 +repo=$2 +ref=$3 +debug=$4 +if [ -z "$version" ]; then + version="12.1" +fi +if [ -z "${repo}" ]; then + repo="canonical/cloud-init" +fi +if [ -z "${ref}" ]; then + ref="master" +fi +if [ -z "${debug}" ]; then + debug="" +fi +set -eux + + +echo "os=openbsd +mirror=https://openbsd.cs.toronto.edu/pub/OpenBSD +arch=amd64 +release=${version} + +plugin=base/bootable +dhcp-interface=vio0 + +plugin=base/raw-image-file +image-basename=openstack-openbsd${version} +image-size=2 + +plugin=partitioner/disklabel +plugin=package/cloud-init +plugin=fs/ffs +plugin=package/sshd" > /tmp/openstack-openbsd + + +mkdir -p ~/builder +sudo mkdir -p /var/cache/pcib +sudo ./bin/pcib --config /tmp/openstack-openbsd +mv /var/cache/pcib/images/openstack-openbsd*.img ~/builder/final.raw diff --git a/examples/openstack-openbsd66 b/examples/openstack-openbsd66 new file mode 100644 index 0000000..ac82aa9 --- /dev/null +++ b/examples/openstack-openbsd66 @@ -0,0 +1,16 @@ +os=openbsd +mirror=http://mirror.csclub.uwaterloo.ca/pub/OpenBSD +arch=amd64 +release=6.6 + +plugin=base/bootable +dhcp-interface=vio0 + +plugin=base/raw-image-file +image-basename=openstack-openbsd66 +image-size=2 + +plugin=partitioner/disklabel +plugin=package/cloud-init +plugin=fs/ffs +plugin=package/sshd diff --git a/plugins/os/openbsd/files/upobsd.sh b/plugins/os/openbsd/files/upobsd.sh new file mode 100755 index 0000000..da3ec50 --- /dev/null +++ b/plugins/os/openbsd/files/upobsd.sh @@ -0,0 +1,298 @@ +#!/bin/ksh +# +# Copyright (c) 2017-2018 Sebastien Marie +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +set -eu +PATH='/sbin:/bin:/usr/sbin:/usr/bin' + +VERBOSE=0 +MIRROR=$(sed -e '/^$/d' -e '/^#/d' -e 'q' /etc/installurl) +ARCH=$(uname -m) +SIGNIFY_KEY='' +AUTO='no' +RESPONSE_FILE='' +OUTPUT="${PWD}/bsd.rd" +PROFILE_FILE='' + +# get kernel version +set -A _KERNV -- $(sysctl -n kern.version | sed 's/^OpenBSD \([0-9]\)\.\([0-9]\)\([^ ]*\).*/\1.\2 \1\2 \3/;q') +if ((${#_KERNV[*]} == 2)) ; then + OS_VERSION=${_KERNV[0]} +else + OS_VERSION='snapshots' +fi +SIGNIFY_VERSION=${_KERNV[1]} + +UID=$(id -u) +WRKDIR='' + +uo_usage() { + echo "usage: ${0##*/} [-v] [-m mirror] [-V version] [-a arch] [-p signify-key] [-i install-response-file] [-u upgrade-response-file] [-P profile-file] [-o output]" >&2 + exit 1 +} + +uo_cleanup() { + trap "" 1 2 3 13 15 ERR + set +e + + if [[ -d "${WRKDIR}" ]]; then + rm -f -- \ + "${WRKDIR}/SHA256.sig" \ + "${WRKDIR}/bsd.rd" \ + "${WRKDIR}/ramdisk" + + [[ -d "${WRKDIR}/ramdisk.d" ]] && \ + rmdir -- "${WRKDIR}/ramdisk.d" + + rmdir -- "${WRKDIR}" || \ + uo_err 1 "cleanup failed: ${WRKDIR}" + fi +} + +uo_err() { + local exitcode=${1} + shift + + echo "error: ${@}" >&2 + uo_cleanup + + exit ${exitcode} +} + +uo_trap() { + uo_cleanup + exit 1 +} +trap "uo_trap" 1 2 3 13 15 ERR + +uo_verbose() { + [[ ${VERBOSE} != 0 ]] && echo "${@}" +} + +uo_ftp() { + local dest=${1} + local url=${2} + + ftp -V -o "${WRKDIR}/${dest}" -- "${url}" +} + +uo_download() { + local url="${MIRROR}/${OS_VERSION}/${ARCH}" + + uo_verbose "downloading bsd.rd (and SHA256.sig): ${url}" + + uo_ftp SHA256.sig "${url}/SHA256.sig" + uo_ftp bsd.rd "${url}/bsd.rd" + + uo_check_signature +} + +uo_check_signature() { + [ -r "${WRKDIR}/SHA256.sig" ] || \ + uo_err 2 "uo_check_signature: no SHA256.sig in WRKDIR" + + if [ -z "${SIGNIFY_KEY}" ]; then + uo_signify \ + "/etc/signify/openbsd-${SIGNIFY_VERSION}-base.pub" \ + "/etc/signify/openbsd-$(( ${SIGNIFY_VERSION} + 1 ))-base.pub" + else + uo_signify "${SIGNIFY_KEY}" + fi +} + +uo_signify() { + local signify_all_keys="$*" + + while [[ $# != 0 ]]; do + local signify_key=${1} + + echo "checking signature: ${signify_key}" + + [ -e "${signify_key}" ] || \ + uo_err 1 "uo_check_signature: file not found: ${signify_key}" + + if ( cd "${WRKDIR}" && \ + signify -qC -p "${signify_key}" -x SHA256.sig bsd.rd ) ; then + break + fi + + shift + done + + if [[ $# = 0 ]]; then + uo_err 1 "invalid signature: ${signify_all_keys}" + else + uo_verbose "signature is valid" + fi +} + +uo_priv() { + /usr/local/bin/sudo "$@" +} + +uo_addfile() { + local dest=${1} + local src=${2} + local vnd_n=0 + + [ -r "${WRKDIR}/bsd.rd" ] || uo_err 2 "uo_addfile: no bsd.rd in WRKDIR" + [ -r "${src}" ] || uo_err 1 "file not found: ${src}" + + uo_verbose "adding response file: ${dest}: ${src}" + + # Since 6.9, bsd.rd is gzipped + gunzip < ${WRKDIR}/bsd.rd > /tmp/bsd.rd2 && mv /tmp/bsd.rd2 ${WRKDIR}/bsd.rd + # extract ramdisk from bsd.rd + rdsetroot -x "${WRKDIR}/bsd.rd" "${WRKDIR}/ramdisk" + + # create mountpoint + mkdir "${WRKDIR}/ramdisk.d" + + # prepare ramdisk for mounting + while ! uo_priv vnconfig "vnd${vnd_n}" "${WRKDIR}/ramdisk"; do + vnd_n=$(( vnd_n + 1 )) + + [[ ${vnd_n} > 4 ]] && \ + uo_err 1 "no more vnd device available" + done + + # mount ramdisk + if ! uo_priv mount -o nodev,nosuid,noexec "/dev/vnd${vnd_n}a" "${WRKDIR}/ramdisk.d"; then + uo_priv vnconfig -u "vnd${vnd_n}" || true + + uo_err 1 "unable to mount: /dev/vnd${vnd_n}a" + fi + + # copy the file + if ! uo_priv install -m 644 -o root -g wheel -- \ + "${src}" "${WRKDIR}/ramdisk.d/${dest}"; then + + uo_priv umount "/dev/vnd${vnd_n}a" || true + uo_priv vnconfig -u "vnd${vnd_n}" || true + + uo_err 1 "unable to copy: ${src}: ramdisk.d/${dest}" + fi + + # umount vndX + if ! uo_priv umount "/dev/vnd${vnd_n}a" ; then + uo_priv vnconfig -u "vnd${vnd_n}" || true + + uo_err 1 "unable to umount: /dev/vnd${vnd_n}a" + fi + + # unconfigure vndX + if ! uo_priv vnconfig -u "vnd${vnd_n}" ; then + uo_err 1 "unable to unconfigure: vnd${vnd_n}" + fi + + # mountpoint cleanup (ensure it is empty) + rmdir "${WRKDIR}/ramdisk.d" + + # put ramdisk back in bsd.rd + rdsetroot "${WRKDIR}/bsd.rd" "${WRKDIR}/ramdisk" + gzip "${WRKDIR}/bsd.rd" + mv "${WRKDIR}/bsd.rd.gz" "${WRKDIR}/bsd.rd" +} + +uo_output() { + [ -r "${WRKDIR}/bsd.rd" ] || uo_err 2 "uo_output: no bsd.rd in WRKDIR" + + uo_verbose "copying bsd.rd: ${OUTPUT}" + mv -- "${WRKDIR}/bsd.rd" "${OUTPUT}" +} + +uo_arch_endianness() { + case "${1}" in + hppa|luna88k|macppc|octeon|sgi) + echo "MSB" ;; + alpha|amd64|arm64|armv7|i386|landisk|loongson) + echo "LSB" ;; + *) + uo_err 1 "unknown arch: ${1}" + echo "---" ;; + esac +} + +uo_check_arch_endianness() { + [[ $(uo_arch_endianness "${1}") != $(uo_arch_endianness "${2}") ]] && \ + uo_err 1 "incompatible endianness for patching: ${1} ${2}" +} + +uo_check_arch_patchable() { + case "${1}" in + alpha|sparc64|hppa) + uo_err 1 "unpatchable arch (stripped): ${_arch}" ;; + + arm64|i386|loongson|macppc|sgi|amd64|armv7|landisk|luna88k|octeon|socppc) + ;; + + *) + echo "warn: unknown arch (could be unpatchable): ${1}" >&2 ;; + esac +} + +# parse command-line +while getopts 'hvm:V:a:p:i:u:o:P:' arg; do + case "${arg}" in + v) VERBOSE=1 ;; + m) MIRROR="${OPTARG}" ;; + V) OS_VERSION="${OPTARG}" ;; + a) ARCH="${OPTARG}" ;; + p) SIGNIFY_KEY="${OPTARG}" ;; + i) AUTO='install'; RESPONSE_FILE="${OPTARG}" ;; + u) AUTO='upgrade'; RESPONSE_FILE="${OPTARG}" ;; + o) OUTPUT="${OPTARG}" ;; + P) PROFILE_FILE="${OPTARG}" ;; + *) uo_usage ;; + esac +done + +shift $(( OPTIND -1 )) +[[ $# -ne 0 ]] && uo_usage + +# update SIGNIFY_VERSION according to OS_VERSION +case "${OS_VERSION}" in +[0-9].[0-9]) SIGNIFY_VERSION="${OS_VERSION%.[0-9]}${OS_VERSION#[0-9].}" ;; +esac + +[[ -n "${RESPONSE_FILE}" && ! -e ${RESPONSE_FILE} ]] && \ + uo_err 1 "file not found: ${RESPONSE_FILE}" + +# check for patchable archs +if [[ ${AUTO} != 'no' ]]; then + uo_check_arch_endianness "$(uname -m)" "${ARCH}" + uo_check_arch_patchable "${ARCH}" +fi + +# create working directory +WRKDIR=$(mktemp -dt upobsd.XXXXXXXXXX) || \ + uo_err 1 "unable to create temporary directory" + +# download and check files +uo_download + +# add response-file if requested +#[[ ${AUTO} != 'no' ]] && \ +# uo_addfile "auto_${AUTO}.conf" "${RESPONSE_FILE}" + +if [ -n ${PROFILE_FILE} ]; then + uo_addfile .profile ${PROFILE_FILE} +fi + +# place bsd.rd where asked +uo_output + +# cleanup +uo_cleanup diff --git a/plugins/os/openbsd/files/usr/src/distrib/amd64/ramdisk_growfs/Makefile b/plugins/os/openbsd/files/usr/src/distrib/amd64/ramdisk_growfs/Makefile index 6d1b420..47bcdf7 100644 --- a/plugins/os/openbsd/files/usr/src/distrib/amd64/ramdisk_growfs/Makefile +++ b/plugins/os/openbsd/files/usr/src/distrib/amd64/ramdisk_growfs/Makefile @@ -12,13 +12,12 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.include "${.CURDIR}/../ramdiskA/Makefile" .PATH: ${.CURDIR}/../ramdisk RAMDISK=RAMDISK_CD -FLOPPYSIZE=6976 -FLOPPYTYPE=mini34 +FSSIZE=69760 +FSDISKTYPE=mini34 XNAME=miniroot LBA=1 -.include "${.CURDIR}/../common/Makefile.inc" - LISTS+= ${.CURDIR}/list.local diff --git a/plugins/os/openbsd/files/usr/src/distrib/amd64/ramdisk_growfs/dot.profile b/plugins/os/openbsd/files/usr/src/distrib/amd64/ramdisk_growfs/dot.profile index 0f0308b..d0b6e83 100644 --- a/plugins/os/openbsd/files/usr/src/distrib/amd64/ramdisk_growfs/dot.profile +++ b/plugins/os/openbsd/files/usr/src/distrib/amd64/ramdisk_growfs/dot.profile @@ -22,7 +22,9 @@ umask 022 # Make sure we can write to /tmp by just mounting / read-write. mount -u /dev/rd0a / -disk=sd0 +for disk in sd0 wd0; do + fdisk -v ${disk} && break +done fpart=3 dpart=a echo "growing filesystem on disk ${disk}" @@ -43,7 +45,8 @@ echo "calculated new partition size: ${size}" # loop. echo -n "removing boot.conf: " mount /dev/"$disk$dpart" /mnt -rm -f /mnt/etc/boot.conf +echo "set tty com0" > /mnt/etc/boot.conf +echo "boot" >> /mnt/etc/boot.conf umount /mnt echo "done." @@ -74,11 +77,11 @@ EOF echo "done." echo -n "growing filesystem: " -growfs -qys "$size" /dev/"$disk$dpart" >/dev/null +growfs -qys "$size" /dev/"$disk$dpart" echo "done." echo -n "checking filesystem: " -fsck -y /dev/"$disk$dpart" >/dev/null +fsck_ffs -y /dev/"$disk$dpart" || sh echo "done." echo "rebooting system..." diff --git a/plugins/os/openbsd/tasks/20-extract-sets.sh b/plugins/os/openbsd/tasks/20-extract-sets.sh index 2c1a05c..0624fe2 100644 --- a/plugins/os/openbsd/tasks/20-extract-sets.sh +++ b/plugins/os/openbsd/tasks/20-extract-sets.sh @@ -16,11 +16,7 @@ for set in $sets; do tar -xzphC "$TARGET" -f "$SETDIR"/"$set" done -# As of OpenBSD 5.7, configuration is provided in tarballs under -# /usr/share/sysmerge in the base set rather than as a separate etc -# set. -if [ "$release" -ge 57 ]; then - for conf in "$TARGET"/usr/share/sysmerge/*etc.tgz; do - tar -xzphC "$TARGET" -f "$conf" - done -fi +for dir in /var/sysmerge /usr/share/sysmerge; do + test -d $dir || continue + find $dir -name '*.tgz' -exec tar -xzphC "$TARGET" -f {} \; +done diff --git a/plugins/os/openbsd/tasks/21-growfs.sh b/plugins/os/openbsd/tasks/21-growfs.sh index d3d627d..d5127f0 100644 --- a/plugins/os/openbsd/tasks/21-growfs.sh +++ b/plugins/os/openbsd/tasks/21-growfs.sh @@ -13,29 +13,9 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # Only one kernel build at a time, thanks. -lock growfs - -rm -rf /usr/src/distrib/amd64/ramdisk_growfs /usr/src/distrib/special/growfs -cp -r \ - "$(plugin_file os/openbsd usr/src/distrib/amd64/ramdisk_growfs)" \ - /usr/src/distrib/amd64/ -cp -r \ - "$(plugin_file os/openbsd usr/src/distrib/special/growfs)" \ - /usr/src/distrib/special/ - -rm -rf /usr/obj/* -(cd /usr/src && make obj 2>&1) | - spin "Populating /usr/obj" - -(cd /usr/src/distrib/special && make 2>&1) | - spin "Installing distribution tools" - -(cd /usr/src/distrib/amd64/ramdisk_growfs && make 2>&1) | - spin "Building growfs ramdisk kernel" - -cp /usr/src/distrib/amd64/ramdisk_growfs/bsd.rd "$TARGET"/bsd.gf -unlock growfs +ksh "$(plugin_file os/openbsd upobsd.sh)" -P "$(plugin_file os/openbsd usr/src/distrib/amd64/ramdisk_growfs/dot.profile)" -o "$TARGET"/bsd.gf cat >"$TARGET"/etc/boot.conf <> $TARGET/etc/boot.conf +echo boot >> $TARGET/etc/boot.conf +sed -i 's,^\(tty00.*\)"/usr.*,\1"/usr/libexec/getty std.9600" xterm on secure,' $TARGET/etc/ttys diff --git a/plugins/os/openbsd/tasks/00-check-os-openbsd-sources.sh b/plugins/os/openbsd/tasks/60-relink.sh similarity index 84% rename from plugins/os/openbsd/tasks/00-check-os-openbsd-sources.sh rename to plugins/os/openbsd/tasks/60-relink.sh index 729bb73..3621093 100644 --- a/plugins/os/openbsd/tasks/00-check-os-openbsd-sources.sh +++ b/plugins/os/openbsd/tasks/60-relink.sh @@ -11,6 +11,4 @@ # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -[ -d /usr/src/distrib/amd64/common -a -f /usr/src/sys/arch/amd64/conf/RAMDISK_CD ] || - fatal "The OpenBSD source tree is not unpacked in /usr/src." +chroot $TARGET sha256 -h /var/db/kernel.SHA256 /bsd diff --git a/plugins/os/openbsd/tasks/80-installurl.sh b/plugins/os/openbsd/tasks/80-installurl.sh new file mode 100644 index 0000000..0f1b725 --- /dev/null +++ b/plugins/os/openbsd/tasks/80-installurl.sh @@ -0,0 +1 @@ +echo "https://cdn.openbsd.org/pub/OpenBSD" > $TARGET/etc/installurl diff --git a/plugins/package/cloud-init/init.sh b/plugins/package/cloud-init/init.sh new file mode 100644 index 0000000..8400eee --- /dev/null +++ b/plugins/package/cloud-init/init.sh @@ -0,0 +1,24 @@ +# Copyright (c) 2019 GonĂri Le bouder +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +cloud_init_plugin_usage() { + usage_section "Cloud-Init instance initialization" + + usage_description \ + "This plugin provides Cloud-Init support for" \ + "configuring an instance for various Cloud providers." + +} + +register_usage cloud_init_plugin_usage diff --git a/plugins/package/cloud-init/tasks/77-cloud-init.sh b/plugins/package/cloud-init/tasks/77-cloud-init.sh new file mode 100644 index 0000000..7759531 --- /dev/null +++ b/plugins/package/cloud-init/tasks/77-cloud-init.sh @@ -0,0 +1,34 @@ +OS_VERSION=$(sysctl -n kern.osrelease) + +git clone -b main http://github.com/goneri/cloud-init $TARGET/tmp/cloud-init + +echo 'nameserver 8.8.8.8' > $TARGET/etc/resolv.conf + +pkgs=" + bash + dmidecode + py3-configobj + py3-jinja2 + py3-jsonschema + py3-oauthlib + py3-requests + py3-setuptools + py3-six + py3-yaml + sudo-- +" +for pkg in ${pkgs}; do + PKG_PATH="https://openbsd.cs.toronto.edu/pub/OpenBSD/${OS_VERSION}/packages/amd64/" chroot $TARGET pkg_add ${pkg} +done +chroot $TARGET ldconfig /usr/local/lib +PKG_PATH="https://openbsd.cs.toronto.edu/pub/OpenBSD/${OS_VERSION}/packages/amd64/" chroot $TARGET sh -c 'cd /tmp/cloud-init; ./tools/build-on-openbsd' + +echo "#!/bin/sh" > $TARGET/etc/rc.local +echo "/usr/local/bin/cloud-init init -l" >> $TARGET/etc/rc.local +echo "/usr/local/bin/cloud-init init" >> $TARGET/etc/rc.local +echo "/usr/local/bin/cloud-init modules --mode config" >> $TARGET/etc/rc.local +echo "/usr/local/bin/cloud-init modules --mode final" >> $TARGET/etc/rc.local +cat /var/log/cloud-init.log > /dev/tty00 +echo "exit 0" >> $TARGET/etc/rc.local + +rm -r $TARGET/tmp/cloud-init