diff options
author | 2020-10-22 14:58:56 +0900 | |
---|---|---|
committer | 2020-10-22 14:58:56 +0900 | |
commit | 4204309872da5cb401cbb2729d9e2d4869a87f42 (patch) | |
tree | c7415e8600205e40ff7e91e8e5f4c411f30329f2 /external/meta-updater/scripts | |
parent | 5b80bfd7bffd4c20d80b7c70a7130529e9a755dd (diff) |
agl-basesystem 0.1sandbox/ToshikazuOhiwa/master
Diffstat (limited to 'external/meta-updater/scripts')
-rw-r--r-- | external/meta-updater/scripts/ci/Dockerfile.bitbake | 32 | ||||
-rw-r--r-- | external/meta-updater/scripts/ci/Jenkinsfile.bleeding | 87 | ||||
-rw-r--r-- | external/meta-updater/scripts/ci/Jenkinsfile.bleeding-selftest | 91 | ||||
-rw-r--r-- | external/meta-updater/scripts/ci/README.adoc | 14 | ||||
-rwxr-xr-x | external/meta-updater/scripts/ci/build.sh | 3 | ||||
-rwxr-xr-x | external/meta-updater/scripts/ci/configure.sh | 40 | ||||
-rwxr-xr-x | external/meta-updater/scripts/ci/oe-selftest.sh | 14 | ||||
-rwxr-xr-x | external/meta-updater/scripts/envsetup.sh | 35 | ||||
-rwxr-xr-x | external/meta-updater/scripts/find_aktualizr_dependencies.sh | 1 | ||||
-rw-r--r-- | external/meta-updater/scripts/qemucommand.py | 108 | ||||
-rwxr-xr-x | external/meta-updater/scripts/run-qemu-ota | 36 |
11 files changed, 220 insertions, 241 deletions
diff --git a/external/meta-updater/scripts/ci/Dockerfile.bitbake b/external/meta-updater/scripts/ci/Dockerfile.bitbake index c91f94c3..51eaa570 100644 --- a/external/meta-updater/scripts/ci/Dockerfile.bitbake +++ b/external/meta-updater/scripts/ci/Dockerfile.bitbake @@ -1,15 +1,17 @@ -FROM debian:stable +FROM debian:stretch LABEL Description="Image for bitbaking" -RUN sed -i 's#deb http://deb.debian.org/debian stable main#deb http://deb.debian.org/debian stable main contrib#g' /etc/apt/sources.list -RUN sed -i 's#deb http://deb.debian.org/debian stable-updates main#deb http://deb.debian.org/debian stable-updates main contrib#g' /etc/apt/sources.list -RUN apt-get update -q && apt-get install -qy \ +RUN sed -i 's#deb http://deb.debian.org/debian stretch main#deb http://deb.debian.org/debian stretch main contrib#g' /etc/apt/sources.list +RUN sed -i 's#deb http://deb.debian.org/debian stretch-updates main#deb http://deb.debian.org/debian stretch-updates main contrib#g' /etc/apt/sources.list +RUN apt-get update -q && apt-get install --no-install-suggests --no-install-recommends -qy \ + awscli \ build-essential \ bzip2 \ chrpath \ cpio \ default-jre \ diffstat \ + file \ gawk \ gcc-multilib \ git-core \ @@ -17,26 +19,40 @@ RUN apt-get update -q && apt-get install -qy \ iproute \ libpython-dev \ libsdl1.2-dev \ + libvirt-clients \ + libvirt-daemon-system \ locales \ ovmf \ + openssh-client \ procps \ python \ python3 \ python3-pexpect \ - qemu \ + qemu-kvm \ socat \ + sudo \ texinfo \ unzip \ wget \ xterm \ xz-utils -ARG uid=1000 -ARG gid=1000 +ARG uid=4321 +ARG gid=4321 RUN groupadd -g $gid bitbake -RUN useradd -m -u $uid -g $gid bitbake +RUN useradd -m -u $uid -g $gid -s /bin/bash bitbake RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && locale-gen ENV LC_ALL="en_US.UTF-8" ENV LANG="en_US.UTF-8" ENV LANGUAGE="en_US.UTF-8" + +# script to mirror kvm group id with host +RUN echo "bitbake ALL=NOPASSWD: /usr/local/bin/setup_kvm.sh" >> /etc/sudoers +COPY ./docker/setup_kvm.sh /usr/local/bin/setup_kvm.sh + +# other ci scripts +RUN mkdir /scripts +COPY configure.sh build.sh oe-selftest.sh /scripts/ + +USER "bitbake" diff --git a/external/meta-updater/scripts/ci/Jenkinsfile.bleeding b/external/meta-updater/scripts/ci/Jenkinsfile.bleeding deleted file mode 100644 index 6d340fde..00000000 --- a/external/meta-updater/scripts/ci/Jenkinsfile.bleeding +++ /dev/null @@ -1,87 +0,0 @@ -// This CI setup checks out aktualizr, meta-updater and updater-repo and builds -// master branches whenever a change is pushed to any of these - -// define these for docker image creation -node { - // might cause some problems: - // https://stackoverflow.com/questions/44805076/setting-build-args-for-dockerfile-agent-using-a-jenkins-declarative-pipeline - JENKINS_UID = sh(returnStdout: true, script: 'id -u').trim() - JENKINS_GID = sh(returnStdout: true, script: 'id -g').trim() -} - -pipeline { - agent any - environment { - TEST_AKTUALIZR_REMOTE = 'aktualizr' - TEST_AKTUALIZR_DIR = 'aktualizr' - TEST_AKTUALIZR_BRANCH = 'master' - TEST_BITBAKE_COMMON_DIR = "/opt/jenkins/bitbake-common" - } - stages { - stage('checkout') { - steps { - - checkout([$class: 'GitSCM', - userRemoteConfigs: [ - [url: 'https://github.com/advancedtelematic/aktualizr', name: 'aktualizr'] - ], - branches: [[name: 'refs/heads/master']], - extensions: [ - [$class: 'DisableRemotePoll'], - [$class: 'PruneStaleBranch'], - [$class: 'RelativeTargetDirectory', - relativeTargetDir: 'aktualizr' - ] - ], - ]) - - checkout([$class: 'RepoScm', - manifestRepositoryUrl: 'https://github.com/advancedtelematic/updater-repo', - manifestBranch: null, - manifestFile: 'master.xml', - manifestGroup: null, - mirrorDir: null, - jobs: 0, - depth: 0, - localManifest: null, - destinationDir: 'updater-repo', - repoUrl: null, - currentBranch: false, - resetFirst: true, - quiet: false, - trace: false, - showAllChanges: false, - ]) - - // ignore bitbake build directories in docker - sh 'echo \'build*\' > .dockerignore' - - // override meta-updater commit with currently tested branch - sh ''' - META_UPDATER_COMMIT=$(git rev-parse HEAD) - cd updater-repo/meta-updater - git checkout $META_UPDATER_COMMIT - ''' - } - } - stage('build-core-image-minimal') { - agent { - dockerfile { - filename 'scripts/ci/Dockerfile.bitbake' - args '-v /opt/jenkins/bitbake-common:/opt/jenkins/bitbake-common' - additionalBuildArgs "--build-arg uid=${JENKINS_UID} --build-arg gid=${JENKINS_GID}" - reuseNode true - } - } - environment { - TEST_AKTUALIZR_CREDENTIALS = credentials('garage-credentials') - } - steps { - sh 'scripts/ci/configure.sh' - - sh 'scripts/ci/build.sh core-image-minimal' - } - } - } -} -// vim: set ft=groovy tabstop=2 shiftwidth=2 expandtab: diff --git a/external/meta-updater/scripts/ci/Jenkinsfile.bleeding-selftest b/external/meta-updater/scripts/ci/Jenkinsfile.bleeding-selftest deleted file mode 100644 index 8c2d1de6..00000000 --- a/external/meta-updater/scripts/ci/Jenkinsfile.bleeding-selftest +++ /dev/null @@ -1,91 +0,0 @@ -// This CI setup checks out aktualizr, meta-updater and updater-repo and builds -// master branches whenever a change is pushed to any of these - -// define these for docker image creation -node { - // might cause some problems: - // https://stackoverflow.com/questions/44805076/setting-build-args-for-dockerfile-agent-using-a-jenkins-declarative-pipeline - JENKINS_UID = sh(returnStdout: true, script: 'id -u').trim() - JENKINS_GID = sh(returnStdout: true, script: 'id -g').trim() -} - -pipeline { - agent { - node { label 'bitbake' } - } - environment { - TEST_AKTUALIZR_REMOTE = 'aktualizr' - TEST_AKTUALIZR_DIR = 'aktualizr' - TEST_AKTUALIZR_BRANCH = 'master' - TEST_BITBAKE_COMMON_DIR = "/opt/jenkins/bitbake-common" - } - stages { - stage('checkout') { - steps { - - checkout([$class: 'GitSCM', - userRemoteConfigs: [ - [url: 'https://github.com/advancedtelematic/aktualizr', name: 'aktualizr'] - ], - branches: [[name: 'refs/heads/master']], - extensions: [ - [$class: 'DisableRemotePoll'], - [$class: 'PruneStaleBranch'], - [$class: 'RelativeTargetDirectory', - relativeTargetDir: 'aktualizr' - ] - ], - ]) - - checkout([$class: 'RepoScm', - manifestRepositoryUrl: 'https://github.com/advancedtelematic/updater-repo', - manifestBranch: null, - manifestFile: 'master.xml', - manifestGroup: null, - mirrorDir: null, - jobs: 0, - depth: 0, - localManifest: null, - destinationDir: 'updater-repo', - repoUrl: null, - currentBranch: false, - resetFirst: true, - quiet: false, - trace: false, - showAllChanges: false, - ]) - - // ignore bitbake build directories in docker - sh 'echo \'build*\' > .dockerignore' - - // override meta-updater commit with currently tested branch - sh ''' - META_UPDATER_COMMIT=$(git rev-parse HEAD) - cd updater-repo/meta-updater - git checkout $META_UPDATER_COMMIT - ''' - } - } - stage('build-core-image-minimal+oe-selftest') { - agent { - dockerfile { - filename 'scripts/ci/Dockerfile.bitbake' - args '-v /opt/jenkins/bitbake-common:/opt/jenkins/bitbake-common' - additionalBuildArgs "--build-arg uid=${JENKINS_UID} --build-arg gid=${JENKINS_GID}" - reuseNode true - } - } - environment { - TEST_AKTUALIZR_CREDENTIALS = credentials('garage-credentials') - } - steps { - sh 'scripts/ci/configure.sh' - - sh 'scripts/ci/build.sh core-image-minimal' - - sh 'scripts/ci/oe-selftest.sh' - } - } - } -} -// vim: set ft=groovy tabstop=2 shiftwidth=2 expandtab: diff --git a/external/meta-updater/scripts/ci/README.adoc b/external/meta-updater/scripts/ci/README.adoc deleted file mode 100644 index 222982b1..00000000 --- a/external/meta-updater/scripts/ci/README.adoc +++ /dev/null @@ -1,14 +0,0 @@ -= Jenkins setup for running meta-updater CI - -As bitbake is quite resource-hungry, there are some special steps that are -needed to run Jenkins CI tasks: - -- docker should be installed and the `jenkins` unix user should belong to - the `docker` group -- `/opt/jenkins` should exist and have `jenkins:jenkins` permissions, it - will be mapped as a volume on the same location in the docker build - container - -Note that for nodes running Jenkins slaves as a docker container, the -`/opt/jenkins` directory must exist on the host system as well, with -permissions matching the user and groupd ids in Jenkins' docker diff --git a/external/meta-updater/scripts/ci/build.sh b/external/meta-updater/scripts/ci/build.sh index 62354289..9fbae989 100755 --- a/external/meta-updater/scripts/ci/build.sh +++ b/external/meta-updater/scripts/ci/build.sh @@ -12,7 +12,10 @@ IMAGE_NAME=${1:-core-image-minimal} ( set +euo pipefail set +x +METADIR=$(realpath "$TEST_REPO_DIR") +export METADIR . "${TEST_REPO_DIR}/meta-updater/scripts/envsetup.sh" "${TEST_MACHINE}" "${TEST_BUILD_DIR}" +set -x bitbake "${IMAGE_NAME}" ) diff --git a/external/meta-updater/scripts/ci/configure.sh b/external/meta-updater/scripts/ci/configure.sh index 960a0cc9..ae78f066 100755 --- a/external/meta-updater/scripts/ci/configure.sh +++ b/external/meta-updater/scripts/ci/configure.sh @@ -8,9 +8,19 @@ TEST_BUILD_DIR=${TEST_BUILD_DIR:-build} TEST_REPO_DIR=${TEST_REPO_DIR:-updater-repo} TEST_BITBAKE_COMMON_DIR=${TEST_BITBAKE_COMMON_DIR:-} -TEST_AKTUALIZR_DIR=${TEST_AKTUALIZR_DIR:-.} -TEST_AKTUALIZR_BRANCH=${TEST_AKTUALIZR_BRANCH:-master} -TEST_AKTUALIZR_REV=${TEST_AKTUALIZR_REV:-$(GIT_DIR="$TEST_AKTUALIZR_DIR/.git" git rev-parse "$TEST_AKTUALIZR_REMOTE/$TEST_AKTUALIZR_BRANCH")} +TEST_AKTUALIZR_REMOTE=${TEST_AKTUALIZR_REMOTE:-} +TEST_AKTUALIZR_TAG=${TEST_AKTUALIZR_TAG:-} +if [ -n "$TEST_AKTUALIZR_REMOTE" ]; then + if [ -n "$TEST_AKTUALIZR_TAG" ]; then + TEST_AKTUALIZR_BRANCH="" + TEST_AKTUALIZR_REV="" + else + TEST_AKTUALIZR_DIR=${TEST_AKTUALIZR_DIR:-.} + TEST_AKTUALIZR_BRANCH=${TEST_AKTUALIZR_BRANCH:-master} + TEST_AKTUALIZR_REV=${TEST_AKTUALIZR_REV:-$(GIT_DIR="$TEST_AKTUALIZR_DIR/.git" git rev-parse "$TEST_AKTUALIZR_REMOTE/$TEST_AKTUALIZR_BRANCH")} + fi +fi + TEST_AKTUALIZR_CREDENTIALS=${TEST_AKTUALIZR_CREDENTIALS:-} # move existing conf directory to backup, before generating a new one @@ -21,6 +31,8 @@ mv "$TEST_BUILD_DIR/conf" "$TEST_BUILD_DIR/conf.old" || true set +euo pipefail set +x echo ">> Running envsetup.sh" +METADIR=$(realpath "$TEST_REPO_DIR") +export METADIR . "$TEST_REPO_DIR/meta-updater/scripts/envsetup.sh" "$TEST_MACHINE" "$TEST_BUILD_DIR" ) @@ -31,19 +43,30 @@ SITE_CONF="$TEST_BUILD_DIR/conf/site.conf" echo ">> Set common bitbake config options" cat << EOF > "$SITE_CONF" SANITY_TESTED_DISTROS = "" -SSTATE_MIRRORS ?= "file://.* https://bitbake-cache.atsgarage.com/PATH;downloadfilename=PATH" IMAGE_FEATURES += "ssh-server-openssh" EOF -echo ">> Set aktualizr branch in bitbake's config" -cat << EOF >> "$SITE_CONF" +if [ -n "$TEST_AKTUALIZR_REMOTE" ]; then + echo ">> Set aktualizr branch in bitbake's config" + if [ -n "$TEST_AKTUALIZR_TAG" ]; then + # tag case + cat << EOF >> "$SITE_CONF" +SRCREV_pn-aktualizr = "" +SRCREV_pn-aktualizr-native = "" +BRANCH_pn-aktualizr = ";nobranch=1;tag=$TEST_AKTUALIZR_TAG" +BRANCH_pn-aktualizr-native = "\${BRANCH_pn-aktualizr}" +EOF + else + # branch case + cat << EOF >> "$SITE_CONF" SRCREV_pn-aktualizr = "$TEST_AKTUALIZR_REV" SRCREV_pn-aktualizr-native = "\${SRCREV_pn-aktualizr}" BRANCH_pn-aktualizr = "$TEST_AKTUALIZR_BRANCH" BRANCH_pn-aktualizr-native = "\${BRANCH_pn-aktualizr}" - EOF + fi +fi if [[ -n $TEST_AKTUALIZR_CREDENTIALS ]]; then echo ">> Set aktualizr credentials" @@ -63,3 +86,6 @@ SSTATE_DIR = "$SSTATE_DIR" DL_DIR = "$DL_DIR" EOF fi + +echo -e ">> Final configuration (site.conf):\\n" +cat "$SITE_CONF" diff --git a/external/meta-updater/scripts/ci/oe-selftest.sh b/external/meta-updater/scripts/ci/oe-selftest.sh index 3124cce1..d441d027 100755 --- a/external/meta-updater/scripts/ci/oe-selftest.sh +++ b/external/meta-updater/scripts/ci/oe-selftest.sh @@ -12,7 +12,19 @@ TEST_REPO_DIR=${TEST_REPO_DIR:-updater-repo} ( set +euo pipefail set +x +METADIR=$(realpath "$TEST_REPO_DIR") +export METADIR . "${TEST_REPO_DIR}/meta-updater/scripts/envsetup.sh" "${TEST_MACHINE}" "${TEST_BUILD_DIR}" -oe-selftest -r updater +set -x + +# work poky around bug on sumo and thud +# see https://git.yoctoproject.org/cgit/cgit.cgi/poky/commit/?id=d3a94e5b9b3c107cf54d5639071cc6609c002f67 +mkdir -p "tmp/log" + +# This is apparently required here now as well. +git config --global user.email "meta-updater-ci@example.org" +git config --global user.name "meta-updater-ci" + +oe-selftest -r "$@" ) diff --git a/external/meta-updater/scripts/envsetup.sh b/external/meta-updater/scripts/envsetup.sh index 5827bc2a..a7ee877d 100755 --- a/external/meta-updater/scripts/envsetup.sh +++ b/external/meta-updater/scripts/envsetup.sh @@ -3,15 +3,26 @@ SCRIPT="envsetup.sh" MACHINE="$1" BUILDDIR="build" +DISTRO="poky-sota-systemd" +BASE_CONF="local.conf.base.append" -[[ "$#" -lt 1 ]] && { echo "Usage: ${SCRIPT} <machine> [builddir]"; return 1; } -[[ "$#" -eq 2 ]] && { BUILDDIR="$2"; } +# A definition of a dictionary with a list of configuration files that must be appended +# to resulting conf/local.conf file for each particular distribution. +declare -A supported_distros=( + ["poky-sota-systemd"]="local.conf.systemd.append" + ["poky-sota"]="local.conf.base.append" + ["poky"]="local.conf.systemd.append local.conf.nonostree.append" +) + +[[ "$#" -lt 1 ]] && { echo "Usage: ${SCRIPT} <machine> [builddir] [distro=< poky-sota-systemd | poky-sota | poky >]"; return 1; } +[[ "$#" -ge 2 ]] && { BUILDDIR="$2"; } +[[ "$#" -eq 3 ]] && { DISTRO="$3"; } # detect if this script is sourced: see http://stackoverflow.com/a/38128348/6255594 SOURCED=0 -if [ -n "$ZSH_EVAL_CONTEXT" ]; then +if [[ -n "$ZSH_EVAL_CONTEXT" ]]; then [[ "$ZSH_EVAL_CONTEXT" =~ :file$ ]] && { SOURCED=1; SOURCEDIR=$(cd "$(dirname -- "$0")" && pwd -P); } -elif [ -n "$BASH_VERSION" ]; then +elif [[ -n "$BASH_VERSION" ]]; then [[ "$0" != "${BASH_SOURCE[0]}" ]] && { SOURCED=1; SOURCEDIR=$(cd "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P); } fi @@ -24,13 +35,23 @@ fi METADIR=${METADIR:-${SOURCEDIR}/../..} if [[ ! -f "${BUILDDIR}/conf/local.conf" ]]; then + declare -a DISTRO_CONFIGS=${supported_distros[$DISTRO]} + [[ -n ${DISTRO_CONFIGS[@]} ]] && { echo "Using (${DISTRO_CONFIGS[*]}) for the specified distro '$DISTRO'"; } || { echo "The specified distro $DISTRO is not supported"; return 1; } + source "$METADIR/poky/oe-init-build-env" "$BUILDDIR" echo "METADIR := \"\${@os.path.abspath('${METADIR}')}\"" >> conf/bblayers.conf cat "${METADIR}/meta-updater/conf/include/bblayers/sota.inc" >> conf/bblayers.conf cat "${METADIR}/meta-updater/conf/include/bblayers/sota_${MACHINE}.inc" >> conf/bblayers.conf - - sed "s/##MACHINE##/$MACHINE/g" "${METADIR}/meta-updater/conf/local.conf.sample.append" >> conf/local.conf + sed -e "s/##MACHINE##/$MACHINE/g" \ + -e "s/##DISTRO##/$DISTRO/g" \ + "${METADIR}/meta-updater/conf/$BASE_CONF" >> conf/local.conf + + for config in ${DISTRO_CONFIGS[@]}; do + if [[ "$BASE_CONF" != "$config" ]]; then + cat "${METADIR}/meta-updater/conf/$config" >> conf/local.conf + fi + done else source "$METADIR/poky/oe-init-build-env" "$BUILDDIR" -fi +fi
\ No newline at end of file diff --git a/external/meta-updater/scripts/find_aktualizr_dependencies.sh b/external/meta-updater/scripts/find_aktualizr_dependencies.sh index 493df800..fcb2f97e 100755 --- a/external/meta-updater/scripts/find_aktualizr_dependencies.sh +++ b/external/meta-updater/scripts/find_aktualizr_dependencies.sh @@ -13,7 +13,6 @@ ${parentdir}/find_dependencies.py aktualizr ${parentdir}/find_dependencies.py aktualizr-shared-prov ${parentdir}/find_dependencies.py aktualizr-shared-prov-creds ${parentdir}/find_dependencies.py aktualizr-device-prov -${parentdir}/find_dependencies.py aktualizr-device-prov-creds ${parentdir}/find_dependencies.py aktualizr-device-prov-hsm ${parentdir}/find_dependencies.py aktualizr-auto-reboot ${parentdir}/find_dependencies.py aktualizr-disable-send-ip diff --git a/external/meta-updater/scripts/qemucommand.py b/external/meta-updater/scripts/qemucommand.py index 3045b454..30929acc 100644 --- a/external/meta-updater/scripts/qemucommand.py +++ b/external/meta-updater/scripts/qemucommand.py @@ -1,7 +1,8 @@ -from os.path import exists, join, realpath, abspath +from os.path import exists, isdir, join, realpath, abspath from os import listdir import random import socket +from shutil import copyfile from subprocess import check_output EXTENSIONS = { @@ -39,29 +40,84 @@ def random_mac(): class QemuCommand(object): def __init__(self, args): + self.enable_u_boot = True + self.dry_run = args.dry_run + self.overlay = args.overlay + self.host_fwd = None + self.kernel = None + self.drive_interface = "ide" + + if hasattr(args, 'uboot_enable'): + self.enable_u_boot = args.uboot_enable.lower() in ("yes", "true", "1") + + # Rise an exception if U-Boot is disabled and overlay option is used + if not self.enable_u_boot and self.overlay: + raise EnvironmentError("An overlay option is currently supported only with U-Boot loader!") + + # If booting with u-boot is disabled we use "ext4" root fs instead of custom one "ota-ext4" + if not self.enable_u_boot: + self.drive_interface = "virtio" + EXTENSIONS['qemux86-64'] = 'ext4' + if args.machine: self.machine = args.machine else: + if not isdir(args.dir): + raise ValueError("Directory %s does not exist, please specify a --machine or a valid images directory" % args.dir) machines = listdir(args.dir) if len(machines) == 1: self.machine = machines[0] else: raise ValueError("Could not autodetect machine type. More than one entry in %s. Maybe --machine qemux86-64?" % args.dir) + + # If using an overlay with U-Boot, copy the rom when we create the + # overlay so that we can keep it around just in case. if args.efi: self.bios = 'OVMF.fd' + elif self.enable_u_boot: + uboot_path = abspath(join(args.dir, self.machine, 'u-boot-qemux86-64.rom')) + if self.overlay: + new_uboot_path = self.overlay + '.u-boot.rom' + if not exists(self.overlay): + if not exists(uboot_path): + raise ValueError("U-Boot image %s does not exist" % uboot_path) + if not exists(new_uboot_path): + if self.dry_run: + print("cp %s %s" % (uboot_path, new_uboot_path)) + else: + copyfile(uboot_path, new_uboot_path) + uboot_path = new_uboot_path + if not exists(uboot_path) and not (self.dry_run and not exists(self.overlay)): + raise ValueError("U-Boot image %s does not exist" % uboot_path) + self.bios = uboot_path else: - uboot = abspath(join(args.dir, self.machine, 'u-boot-qemux86-64.rom')) - if not exists(uboot): - raise ValueError("U-Boot image %s does not exist" % uboot) - self.bios = uboot + self.kernel = abspath(join(args.dir, self.machine, 'bzImage-qemux86-64.bin')) + + # If using an overlay, we need to keep the "backing" image around, as + # bitbake will often clean it up, and the overlay silently depends on + # the hardcoded path. The easiest solution is to keep the file and use + # a relative path to it. if exists(args.imagename): - image = args.imagename + image = realpath(args.imagename) else: ext = EXTENSIONS.get(self.machine, 'wic') image = join(args.dir, self.machine, '%s-%s.%s' % (args.imagename, self.machine, ext)) - self.image = realpath(image) - if not exists(self.image): + if self.overlay: + new_image_path = self.overlay + '.img' + if not exists(self.overlay): + if not exists(image): + raise ValueError("OS image %s does not exist" % image) + if not exists(new_image_path): + if self.dry_run: + print("cp %s %s" % (image, new_image_path)) + else: + copyfile(image, new_image_path) + self.image = new_image_path + else: + self.image = realpath(image) + if not exists(self.image) and not (self.dry_run and not exists(self.overlay)): raise ValueError("OS image %s does not exist" % self.image) + if args.mac: self.mac_address = args.mac else: @@ -84,28 +140,34 @@ class QemuCommand(object): self.gui = not args.no_gui self.gdb = args.gdb self.pcap = args.pcap - self.overlay = args.overlay self.secondary_network = args.secondary_network + # Append additional port forwarding to QEMU command line. + if hasattr(args, 'host_forward'): + self.host_fwd = args.host_forward + def command_line(self): netuser = 'user,hostfwd=tcp:0.0.0.0:%d-:22,restrict=off' % self.ssh_port if self.gdb: netuser += ',hostfwd=tcp:0.0.0.0:2159-:2159' + if self.host_fwd: + netuser += ",hostfwd=" + self.host_fwd + cmdline = [ "qemu-system-x86_64", - "-bios", self.bios ] + if self.enable_u_boot: + cmdline += ["-bios", self.bios] + else: + cmdline += ["-kernel", self.kernel] + if not self.overlay: - cmdline += ["-drive", "file=%s,if=ide,format=raw,snapshot=on" % self.image] + cmdline += ["-drive", "file=%s,if=%s,format=raw,snapshot=on" % (self.image, self.drive_interface)] cmdline += [ "-serial", "tcp:127.0.0.1:%d,server,nowait" % self.serial_port, "-m", self.mem, - "-usb", "-object", "rng-random,id=rng0,filename=/dev/urandom", "-device", "virtio-rng-pci,rng=rng0", - "-device", "usb-tablet", - "-show-cursor", - "-vga", "std", "-net", netuser, "-net", "nic,macaddr=%s" % self.mac_address ] @@ -117,15 +179,27 @@ class QemuCommand(object): '-device', 'e1000,netdev=vlan1,mac='+random_mac(), ] if self.gui: - cmdline += ["-serial", "stdio"] + cmdline += [ + "-usb", + "-device", "usb-tablet", + "-show-cursor", + "-vga", "std" + ] else: - cmdline.append('-nographic') + cmdline += [ + "-nographic", + "-monitor", "null", + ] if self.kvm: cmdline += ['-enable-kvm', '-cpu', 'host'] else: cmdline += ['-cpu', 'Haswell'] if self.overlay: cmdline.append(self.overlay) + + # If booting with u-boot is disabled, add kernel command line arguments through qemu -append option + if not self.enable_u_boot: + cmdline += ["-append", "root=/dev/vda rw highres=off console=ttyS0 ip=dhcp"] return cmdline def img_command_line(self): diff --git a/external/meta-updater/scripts/run-qemu-ota b/external/meta-updater/scripts/run-qemu-ota index de632970..59301a43 100755 --- a/external/meta-updater/scripts/run-qemu-ota +++ b/external/meta-updater/scripts/run-qemu-ota @@ -2,7 +2,7 @@ from argparse import ArgumentParser from subprocess import Popen -from os.path import exists +from os.path import exists, dirname import sys from qemucommand import QemuCommand @@ -13,6 +13,9 @@ def main(): parser = ArgumentParser(description='Run meta-updater image in qemu') parser.add_argument('imagename', default='core-image-minimal', nargs='?', help="Either the name of the bitbake image target, or a path to the image to run") + parser.add_argument('--uboot-enable', default='yes', + help='(yes/no). Determines whether or not to use U-Boot loader for running image, ' + 'if yes then u-boot binary file will be passed as -bios option into QEMU cmd line.') parser.add_argument('mac', default=None, nargs='?') parser.add_argument('--dir', default=DEFAULT_DIR, help='Path to build directory containing the image and u-boot-qemux86-64.rom') @@ -20,6 +23,7 @@ def main(): help='Boot using UEFI rather than U-Boot. This requires the image to be built with ' + 'OSTREE_BOOTLOADER = "grub" and OVMF.fd firmware to be installed (try "apt install ovmf")', action='store_true') + parser.add_argument('--bootloader', default=None, help="Path to bootloader, e.g. a u-boot ROM") parser.add_argument('--machine', default=None, help="Target MACHINE") kvm_group = parser.add_argument_group() kvm_group.add_argument('--force-kvm', help='Force use of KVM (default is to autodetect)', @@ -38,28 +42,44 @@ def main(): help='Give the image a second network card connected to a virtual network. ' + 'This can be used to test Uptane Primary/Secondary communication.') parser.add_argument('-n', '--dry-run', help='Print qemu command line rather then run it', action='store_true') + parser.add_argument('--host-forward', + help='Redirect incoming TCP or UDP connections to the host port. ' + 'Example forwarding guest port 10050 to the host port 10555:' + '--host-forward="tcp:0.0.0.0:10556-:10050". ' + 'For more details please refer to QEMU man page, option <hostfwd>. ' + 'https://manpages.debian.org/testing/qemu-system-x86/qemu-system-x86_64.1.en.html') args = parser.parse_args() + + if args.overlay and not exists(args.overlay) and dirname(args.overlay) and not dirname(args.overlay) == '.': + print('Error: please provide a file name in the current working directory. ' + + 'Overlays do not work properly with other directories.') + sys.exit(1) + if args.overlay and exists(args.overlay) and args.imagename != parser.get_default('imagename'): + # qemu-img amend -o <filename> might work, but it has not yet been done + # successfully. + print('Warning: cannot change backing image of overlay after it has been created.') + try: qemu_command = QemuCommand(args) except ValueError as e: print(e.message) sys.exit(1) - print("Launching %s with mac address %s" % (args.imagename, qemu_command.mac_address)) - print("To connect via SSH:") - print(" ssh -o StrictHostKeyChecking=no root@localhost -p %d" % qemu_command.ssh_port) - print("To connect to the serial console:") - print(" nc localhost %d" % qemu_command.serial_port) - cmdline = qemu_command.command_line() if args.overlay and not exists(args.overlay): - print("Image file %s does not yet exist, creating." % args.overlay) + print("Overlay file %s does not yet exist, creating." % args.overlay) img_cmdline = qemu_command.img_command_line() if args.dry_run: print(" ".join(img_cmdline)) else: Popen(img_cmdline).wait() + print("Launching %s with mac address %s" % (args.imagename, qemu_command.mac_address)) + print("To connect via SSH:") + print(" ssh -o StrictHostKeyChecking=no root@localhost -p %d" % qemu_command.ssh_port) + print("To connect to the serial console:") + print(" nc localhost %d" % qemu_command.serial_port) + if args.dry_run: print(" ".join(cmdline)) else: |