Repository: DieterReuter/image-builder-rpi64 Branch: master Commit: 658f1495d023 Files: 63 Total size: 67.1 KB Directory structure: gitextract_xd0cheqe/ ├── .circleci/ │ └── config.yml ├── .dockerignore ├── .gitignore ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── Vagrantfile └── builder/ ├── build.sh ├── chroot-script.sh ├── files/ │ ├── boot/ │ │ ├── meta-data │ │ └── user-data │ ├── etc/ │ │ ├── apt/ │ │ │ └── preferences.d/ │ │ │ ├── hypriot │ │ │ └── raspberrypi │ │ ├── firstboot.d/ │ │ │ └── 10-resize-rootdisk │ │ ├── skel/ │ │ │ ├── .bash_prompt │ │ │ └── .bashrc │ │ ├── systemd/ │ │ │ └── system/ │ │ │ └── hciuart.service │ │ └── udev/ │ │ └── rules.d/ │ │ ├── 10-wlan-powersave-off.rules │ │ ├── 75-persistent-net-generator.rules │ │ └── 99-com.rules │ ├── lib/ │ │ └── firmware/ │ │ └── brcm/ │ │ ├── brcmfmac43430-sdio.txt │ │ ├── brcmfmac43455-sdio.clm_blob │ │ └── brcmfmac43455-sdio.txt │ └── sbin/ │ └── resizefs ├── test/ │ ├── image_spec.rb │ ├── os-release_spec.rb │ └── spec_helper.rb └── test-integration/ ├── .bundle/ │ └── config ├── .gitignore ├── .rspec ├── .ruby-version ├── Gemfile ├── README.md ├── Rakefile └── spec/ ├── hypriotos-docker/ │ ├── docker-busybox-httpd_spec.rb │ ├── docker-compose_spec.rb.off │ └── docker-node_spec.rb ├── hypriotos-image/ │ ├── base/ │ │ ├── bootfiles_spec.rb │ │ ├── device_tree_spec.rb │ │ ├── kernel_spec.rb │ │ ├── packages_spec.rb │ │ ├── release_spec.rb │ │ ├── rpi3_bluetooth_spec.rb │ │ ├── rpi3_wifi_spec.rb │ │ ├── serial_base.rb │ │ └── users_spec.rb │ ├── cloud-init_spec.rb │ ├── cmdline_kernel_spec.rb │ ├── cmdline_serial_spec.rb │ ├── config_txt_spec.rb │ ├── docker-compose_spec.rb │ ├── docker-machine_spec.rb │ ├── docker_spec.rb │ ├── filesystems_spec.rb │ ├── hypriot-list_spec.rb │ ├── kernel_config_spec.rb │ ├── kernel_modules_spec.rb │ ├── openvswitch_spec.rb │ ├── raspberrypi-list_spec.rb │ ├── serial_spec.rb │ └── udev_spec.rb └── spec_helper.rb ================================================ FILE CONTENTS ================================================ ================================================ FILE: .circleci/config.yml ================================================ version: 2 jobs: build: machine: true steps: - checkout - run: name: Run Shellcheck command: | make shellcheck - run: name: Create SD image command: | VERSION=${CIRCLE_TAG} make sd-image - run: name: Prepare artifacts command: | mkdir -p output cp hypriotos*zip* output/ - store_artifacts: path: /home/circleci/project/output - deploy: name: Deploy command: | if [ "$CIRCLE_TAG" != "" ]; then curl -sSL https://github.com/tcnksm/ghr/releases/download/v0.5.4/ghr_v0.5.4_linux_amd64.zip -o ghr.zip unzip ghr.zip if [[ $CIRCLE_TAG = *"rc"* ]]; then pre=-prerelease fi ./ghr $pre -u hypriot $CIRCLE_TAG output/ fi workflows: version: 2 build_and_deploy: jobs: - build: filters: tags: only: /.*/ ================================================ FILE: .dockerignore ================================================ *.img *.img.zip *.img.zip.sha256 *.tar.gz *.tar.gz.sha256 .vagrant/ resources/ ================================================ FILE: .gitignore ================================================ *.img *.img.zip *.img.zip.sha256 *.tar.gz *.tar.gz.sha256 .vagrant/ resources/ ================================================ FILE: Dockerfile ================================================ FROM hypriot/image-builder:latest ENV HYPRIOT_OS_VERSION=v2.1.0 \ RAW_IMAGE_VERSION=v0.3.1 #Note that the checksums and build timestamps only apply when fetching missing #artifacts remotely is enabled to validate downloaded remote artifacts ENV FETCH_MISSING_ARTIFACTS=true \ ROOT_FS_ARTIFACT=rootfs-arm64-debian-$HYPRIOT_OS_VERSION.tar.gz \ KERNEL_ARTIFACT=4.19.58-hypriotos-v8.tar.gz \ BOOTLOADER_ARTIFACT=rpi-bootloader.tar.gz \ RAW_IMAGE_ARTIFACT=rpi-raw.img.zip \ DOCKER_ENGINE_VERSION="5:18.09.7~3-0~debian-stretch" \ CONTAINERD_IO_VERSION="1.2.6-3" \ DOCKER_COMPOSE_VERSION="1.23.1" \ DOCKER_MACHINE_VERSION="0.16.1" \ KERNEL_VERSION="4.19.58" \ ROOTFS_TAR_CHECKSUM="4437ac3ab8278a4a3994aa9aa36f0f00bc409f80ebdffef23a141dfc0286ecb0" \ RAW_IMAGE_CHECKSUM="ccff10498fb45fb76c6064988fb01b3543adfdb70ee7e5fb04b51885573684a6" \ BOOTLOADER_BUILD="20190713-140339" \ KERNEL_BUILD="20190715-111025" RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install -y \ binfmt-support \ qemu \ qemu-user-static \ --no-install-recommends && \ rm -rf /var/lib/apt/lists/* ADD https://github.com/gruntwork-io/fetch/releases/download/v0.1.0/fetch_linux_amd64 /usr/local/bin/fetch RUN chmod +x /usr/local/bin/fetch COPY builder/ /builder/ # build sd card image CMD /builder/build.sh ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2017-2019 Dieter Reuter Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Makefile ================================================ VERSION ?= dirty default: build build: VERSION=${VERSION} docker build -t image-builder-rpi64 . sd-image: build VERSION=${VERSION} docker run --rm --privileged -v $(shell pwd):/workspace -v /boot:/boot -v /lib/modules:/lib/modules -e CIRCLE_TAG -e VERSION image-builder-rpi64 shell: build VERSION=${VERSION} docker run -ti --privileged -v $(shell pwd):/workspace -v /boot:/boot -v /lib/modules:/lib/modules -e CIRCLE_TAG -e VERSION image-builder-rpi64 bash test: VERSION=${VERSION} docker run --rm --privileged -v $(shell pwd):/workspace -v /boot:/boot -v /lib/modules:/lib/modules -e CIRCLE_TAG -e VERSION image-builder-rpi64 bash -c "unzip /workspace/hypriotos-rpi64-${VERSION}.img.zip && rspec --format documentation --color /workspace/builder/test/*_spec.rb" shellcheck: VERSION=${VERSION} docker run --rm -v $(shell pwd):/workspace koalaman/shellcheck:v0.7.0 /workspace/builder/build.sh /workspace/builder/chroot-script.sh /workspace/builder/files/etc/firstboot.d/10-resize-rootdisk vagrant: vagrant up docker-machine: vagrant docker-machine create -d generic \ --generic-ssh-user $(shell vagrant ssh-config | grep ' User ' | cut -d ' ' -f 4) \ --generic-ssh-key $(shell vagrant ssh-config | grep IdentityFile | cut -d ' ' -f 4) \ --generic-ip-address $(shell vagrant ssh-config | grep HostName | cut -d ' ' -f 4) \ --generic-ssh-port $(shell vagrant ssh-config | grep Port | cut -d ' ' -f 4) \ image-builder-rpi64 test-integration: test-integration-image test-integration-docker test-integration-image: docker run --rm -ti -v $(shell pwd)/builder/test-integration:/serverspec:ro -e BOARD uzyexe/serverspec:2.24.3 bash -c "rspec --format documentation --color spec/hypriotos-image" test-integration-docker: docker run --rm -ti -v $(shell pwd)/builder/test-integration:/serverspec:ro -e BOARD uzyexe/serverspec:2.24.3 bash -c "rspec --format documentation --color spec/hypriotos-docker" tag: git tag ${TAG} git push origin ${TAG} ================================================ FILE: README.md ================================================ # image-builder-rpi64 [![CircleCI](https://circleci.com/gh/DieterReuter/image-builder-rpi64.svg?style=svg)](https://circleci.com/gh/DieterReuter/image-builder-rpi64) **Warning:** This SD image will not work on a Raspberry Pi 4B !!! This repo builds the SD card image with HypriotOS for the Raspberry Pi 3 in 64bit. You can find released versions of the SD card image here in the GitHub releases page. To build this SD card image we have to * take the files for the root filesystem from [`os-rootfs`](https://github.com/hypriot/os-rootfs) * take the empty raw filesystem from [`image-builder-raw`](https://github.com/hypriot/image-builder-raw) with the two partitions * add Hypriot's Debian repos * install the Raspberry Pi kernel from [`rpi64-kernel`](https://github.com/dieterreuter/rpi64-kernel) * install Docker tools Docker Engine, Docker Compose and Docker Machine Here is an example how all the GitHub repos play together: ![Architecture](http://blog.hypriot.com/images/hypriotos-xxx/hypriotos_buildpipeline.jpg) ## Contributing You can contribute to this repo by forking it and sending us pull requests. Feedback is always welcome! You can build the SD card image locally with Vagrant. ### Setting up build environment Make sure you have [vagrant](https://docs.vagrantup.com/v2/installation/) and [docker-machine](https://docs.docker.com/machine/install-machine/) installed. Then run the following command to create the Vagrant box and the Docker Machine connection. The Vagrant box is needed as a vanilla boot2docker VM is not able to run guestfish inside. Use `export VAGRANT_DEFAULT_PROVIDER=virtualbox` to strictly create a VirtualBox VM. ```bash make docker-machine ``` Now set the Docker environments to this new docker machine: ```bash eval $(docker-machine env image-builder-rpi64) ``` ### Build the SD card image From here you can just make the SD card image. The output will be written and compressed to `hypriotos-rpi64-dirty.img.zip`. ```bash make sd-image ``` ### Run Serverspec tests To test the compressed SD card image with [Serverspec](http://serverspec.org) just run the following command. It will expand the SD card image in a Docker container and run the Serverspec tests in `builder/test/` folder against it. ```bash make test ``` ### Run integration tests Now flash the SD card image and boot up a Raspberry Pi. Run the [Serverspec](http://serverspec.org) integration tests in `builder/test-integration/` folder against your Raspberry Pi. Set the environment variable `BOARD` to the IP address or host name of your running Raspberry Pi. ```bash flash hypriotos-rpi64-dirty.img.zip BOARD=black-pearl.local make test-integration ``` This test works with any Docker Machine, so you do not need to create the Vagrant box. ## Deployment For maintainers of this project you can release a new version and deploy the SD card image to GitHub releases with ```bash TAG=v0.0.1 make tag ``` After that open the GitHub release of this version and fill it with relevant changes and links to resolved issues. ## License MIT License Copyright (c) 2017-2019 Dieter Reuter ================================================ FILE: Vagrantfile ================================================ # -*- mode: ruby -*- # vi: set ft=ruby : ENV['VAGRANT_DEFAULT_PROVIDER'] = 'virtualbox' Vagrant.configure(2) do |config| config.vm.box = "bento/ubuntu-16.04" config.vm.network "forwarded_port", guest: 2376, host: 2376, auto_correct: true config.vm.synced_folder ".", "#{`pwd`.chomp}" config.vm.provider "vmware_fusion" do |v| # Customize the amount of memory on the VM: v.memory = "2048" end config.vm.provider "virtualbox" do |vb| # Customize the amount of memory on the VM: vb.memory = "2048" end config.vm.provision "shell", inline: <<-SHELL sudo apt update sudo apt install --yes apt-transport-https ca-certificates curl software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" sudo apt-get update sudo apt-get install -y docker-ce SHELL end ================================================ FILE: builder/build.sh ================================================ #!/bin/bash -e set -x # This script should be run only inside of a Docker container if [ ! -f /.dockerenv ]; then echo "ERROR: script works only in a Docker container!" exit 1 fi ### setting up some important variables to control the build process # place to store our created sd-image file BUILD_RESULT_PATH="/workspace" # place to build our sd-image BUILD_PATH="/build" ROOTFS_TAR=${ROOT_FS_ARTIFACT} ROOTFS_TAR_PATH="${BUILD_RESULT_PATH}/${ROOTFS_TAR}" # Show CIRCLE_TAG in Circle builds echo CIRCLE_TAG="${CIRCLE_TAG}" # name of the sd-image we gonna create HYPRIOT_IMAGE_VERSION=${VERSION:="dirty"} HYPRIOT_IMAGE_NAME="hypriotos-rpi64-${HYPRIOT_IMAGE_VERSION}.img" export HYPRIOT_IMAGE_VERSION # create build directory for assembling our image filesystem rm -rf ${BUILD_PATH} mkdir ${BUILD_PATH} # download our base root file system if [ ! -f "${ROOTFS_TAR_PATH}" ]; then if [ "$FETCH_MISSING_ARTIFACTS" == "true" ]; then wget -q -O "${ROOTFS_TAR_PATH}" "https://github.com/hypriot/os-rootfs/releases/download/${HYPRIOT_OS_VERSION}/${ROOTFS_TAR}" else echo "Missing artifact ${ROOT_FS_ARTIFACT}" exit 255 fi fi if [ "$FETCH_MISSING_ARTIFACTS" == "true" ]; then # verify checksum of our root filesystem echo "${ROOTFS_TAR_CHECKSUM} ${ROOTFS_TAR_PATH}" | sha256sum -c - fi # extract root file system tar xf "${ROOTFS_TAR_PATH}" -C "${BUILD_PATH}" # extract/add additional files FILENAME=/workspace/$BOOTLOADER_ARTIFACT if [ ! -f "$FILENAME" ]; then if [ "$FETCH_MISSING_ARTIFACTS" == "true" ]; then fetch --repo="https://github.com/DieterReuter/rpi-bootloader" --tag="v$BOOTLOADER_BUILD" --release-asset="rpi-bootloader.tar.gz.sha256" /workspace fetch --repo="https://github.com/DieterReuter/rpi-bootloader" --tag="v$BOOTLOADER_BUILD" --release-asset="rpi-bootloader.tar.gz" /workspace else echo "Missing artifact ${BOOTLOADER_ARTIFACT}" exit 255 fi fi tar -xf "$FILENAME" -C "${BUILD_PATH}" FILENAME=/workspace/$KERNEL_ARTIFACT if [ ! -f "$FILENAME" ]; then if [ "$FETCH_MISSING_ARTIFACTS" == "true" ]; then fetch --repo="https://github.com/DieterReuter/rpi64-kernel" --tag="v$KERNEL_BUILD" --release-asset="$KERNEL_VERSION-hypriotos-v8.tar.gz.sha256" /workspace fetch --repo="https://github.com/DieterReuter/rpi64-kernel" --tag="v$KERNEL_BUILD" --release-asset="$KERNEL_VERSION-hypriotos-v8.tar.gz" /workspace else echo "Missing artifact ${KERNEL_ARTIFACT}" exit 255 fi fi tar -xf "$FILENAME" -C "${BUILD_PATH}" # register qemu-aarch64 with binfmt # to ensure that binaries we use in the chroot # are executed via qemu-aarch64 update-binfmts --enable qemu-aarch64 # set up mount points for the pseudo filesystems mkdir -p ${BUILD_PATH}/{proc,sys,dev/pts} mount -o bind /dev ${BUILD_PATH}/dev mount -o bind /dev/pts ${BUILD_PATH}/dev/pts mount -t proc none ${BUILD_PATH}/proc mount -t sysfs none ${BUILD_PATH}/sys # modify/add image files directly # e.g. root partition resize script cp -R /builder/files/* ${BUILD_PATH}/ # make our build directory the current root # and install the Rasberry Pi firmware, kernel packages, # docker tools and some customizations chroot ${BUILD_PATH} /bin/bash < /builder/chroot-script.sh # unmount pseudo filesystems umount -l ${BUILD_PATH}/dev/pts umount -l ${BUILD_PATH}/dev umount -l ${BUILD_PATH}/proc umount -l ${BUILD_PATH}/sys # package image filesytem into two tarballs - one for bootfs and one for rootfs # ensure that there are no leftover artifacts in the pseudo filesystems rm -rf ${BUILD_PATH:?}/{dev,sys,proc}/* tar -czf /image_with_kernel_boot.tar.gz -C ${BUILD_PATH}/boot . du -sh ${BUILD_PATH}/boot rm -Rf ${BUILD_PATH:?}/boot tar -czf /image_with_kernel_root.tar.gz -C ${BUILD_PATH} . du -sh ${BUILD_PATH} ls -alh /image_with_kernel_*.tar.gz RAW_IMAGE=${RAW_IMAGE_ARTIFACT%.*} # download the ready-made raw image for the RPi if [ ! -f "${BUILD_RESULT_PATH}/${RAW_IMAGE_ARTIFACT}" ]; then if [ "$FETCH_MISSING_ARTIFACTS" == "true" ]; then wget -q -O "${BUILD_RESULT_PATH}/${RAW_IMAGE_ARTIFACT}" "https://github.com/hypriot/image-builder-raw/releases/download/${RAW_IMAGE_VERSION}/${RAW_IMAGE}.zip" else echo "Missing artifact ${RAW_IMAGE_ARTIFACT}" exit 255 fi fi if [ "$FETCH_MISSING_ARTIFACTS" == "true" ]; then # verify checksum of the ready-made raw image echo "${RAW_IMAGE_CHECKSUM} ${BUILD_RESULT_PATH}/${RAW_IMAGE_ARTIFACT}" | sha256sum -c - fi unzip -p "${BUILD_RESULT_PATH}/${RAW_IMAGE}" > "/${HYPRIOT_IMAGE_NAME}" # create the image and add root base filesystem guestfish -a "/${HYPRIOT_IMAGE_NAME}"<<_EOF_ run #import filesystem content mount /dev/sda2 / tar-in /image_with_kernel_root.tar.gz / compress:gzip mkdir /boot mount /dev/sda1 /boot tar-in /image_with_kernel_boot.tar.gz /boot compress:gzip _EOF_ # ensure that the travis-ci user can access the sd-card image file umask 0000 # compress image zip "${BUILD_RESULT_PATH}/${HYPRIOT_IMAGE_NAME}.zip" "${HYPRIOT_IMAGE_NAME}" cd ${BUILD_RESULT_PATH} && sha256sum "${HYPRIOT_IMAGE_NAME}.zip" > "${HYPRIOT_IMAGE_NAME}.zip.sha256" && cd - # # test sd-image that we have built # VERSION=${HYPRIOT_IMAGE_VERSION} rspec --format documentation --color ${BUILD_RESULT_PATH}/builder/test ================================================ FILE: builder/chroot-script.sh ================================================ #!/bin/bash set -ex KEYSERVER="ha.pool.sks-keyservers.net" function clean_print(){ local fingerprint="${2}" local func="${1}" nospaces=${fingerprint//[:space:]/} tolowercase=${nospaces,,} KEYID_long=${tolowercase:(-16)} KEYID_short=${tolowercase:(-8)} if [[ "${func}" == "fpr" ]]; then echo "${tolowercase}" elif [[ "${func}" == "long" ]]; then echo "${KEYID_long}" elif [[ "${func}" == "short" ]]; then echo "${KEYID_short}" elif [[ "${func}" == "print" ]]; then if [[ "${fingerprint}" != "${nospaces}" ]]; then printf "%-10s %50s\n" fpr: "${fingerprint}" fi # if [[ "${nospaces}" != "${tolowercase}" ]]; then # printf "%-10s %50s\n" nospaces: $nospaces # fi if [[ "${tolowercase}" != "${KEYID_long}" ]]; then printf "%-10s %50s\n" lower: "${tolowercase}" fi printf "%-10s %50s\n" long: "${KEYID_long}" printf "%-10s %50s\n" short: "${KEYID_short}" echo "" else echo "usage: function {print|fpr|long|short} GPGKEY" fi } function get_gpg(){ GPG_KEY="${1}" KEY_URL="${2}" clean_print print "${GPG_KEY}" GPG_KEY=$(clean_print fpr "${GPG_KEY}") if [[ "${KEY_URL}" =~ ^https?://* ]]; then echo "loading key from url" KEY_FILE=temp.gpg.key wget -q -O "${KEY_FILE}" "${KEY_URL}" elif [[ -z "${KEY_URL}" ]]; then echo "no source given try to load from key server" # gpg --keyserver "${KEYSERVER}" --recv-keys "${GPG_KEY}" apt-key adv --keyserver "${KEYSERVER}" --recv-keys "${GPG_KEY}" return $? else echo "keyfile given" KEY_FILE="${KEY_URL}" fi FINGERPRINT_OF_FILE=$(gpg --with-fingerprint --with-colons "${KEY_FILE}" | grep fpr | rev |cut -d: -f2 | rev) if [[ ${#GPG_KEY} -eq 16 ]]; then echo "compare long keyid" CHECK=$(clean_print long "${FINGERPRINT_OF_FILE}") elif [[ ${#GPG_KEY} -eq 8 ]]; then echo "compare short keyid" CHECK=$(clean_print short "${FINGERPRINT_OF_FILE}") else echo "compare fingerprint" CHECK=$(clean_print fpr "${FINGERPRINT_OF_FILE}") fi if [[ "${GPG_KEY}" == "${CHECK}" ]]; then echo "key OK add to apt" apt-key add "${KEY_FILE}" rm -f "${KEY_FILE}" return 0 else echo "key invalid" exit 1 fi } ## examples: # clean_print {print|fpr|long|short} {GPGKEYID|FINGERPRINT} # get_gpg {GPGKEYID|FINGERPRINT} [URL|FILE] # device specific settings HYPRIOT_DEVICE="Raspberry Pi 3 64bit" # set up /etc/resolv.conf DEST=$(readlink -m /etc/resolv.conf) export DEST mkdir -p "$(dirname "${DEST}")" echo "nameserver 8.8.8.8" > "${DEST}" # # set up hypriot rpi repository for rpi specific kernel- and firmware-packages # PACKAGECLOUD_FPR=418A7F2FB0E1E6E7EABF6FE8C2E73424D59097AB # PACKAGECLOUD_KEY_URL=https://packagecloud.io/gpg.key # get_gpg "${PACKAGECLOUD_FPR}" "${PACKAGECLOUD_KEY_URL}" ###arm64: not used for now # echo 'deb https://packagecloud.io/Hypriot/rpi/debian/ jessie main' > /etc/apt/sources.list.d/hypriot.list # # set up hypriot schatzkiste repository for generic packages # echo 'deb [arch=armhf] https://packagecloud.io/Hypriot/Schatzkiste/debian/ jessie main' >> /etc/apt/sources.list.d/hypriot.list # RPI_ORG_FPR=CF8A1AF502A2AA2D763BAE7E82B129927FA3303E RPI_ORG_KEY_URL=http://archive.raspberrypi.org/debian/raspberrypi.gpg.key # get_gpg "${RPI_ORG_FPR}" "${RPI_ORG_KEY_URL}" # echo 'deb [arch=armhf] http://archive.raspberrypi.org/debian/ jessie main' | tee /etc/apt/sources.list.d/raspberrypi.list # # make sure, we can use dedicated armhf packages # dpkg --add-architecture armhf # sed -i 's/deb http/deb [arch=arm64] http/g' /etc/apt/sources.list # sed -i 's/deb-src http/deb-src [arch=arm64] http/g' /etc/apt/sources.list # reload package sources apt-get update apt-get upgrade -y # # install WiFi firmware packages (same as in Raspbian) # apt-get install -y \ # firmware-atheros \ # firmware-brcm80211 \ # firmware-libertas \ # firmware-ralink \ # firmware-realtek #+++for now copy files statically from ./builder/files/lib/firmware/brcm # # install WiFi firmware for internal RPi3 WiFi module # mkdir -p /lib/firmware/brcm # curl -sSL https://github.com/RPi-Distro/firmware-nonfree/raw/master/brcm/brcmfmac43430-sdio.bin > /lib/firmware/brcm/brcmfmac43430-sdio.bin #--- # install kernel- and firmware-packages # apt-get install -y \ # "raspberrypi-kernel=${KERNEL_BUILD}" \ # "raspberrypi-bootloader=${KERNEL_BUILD}" \ # "libraspberrypi0=${KERNEL_BUILD}" \ # "libraspberrypi-dev=${KERNEL_BUILD}" \ # "libraspberrypi-bin=${KERNEL_BUILD}" # enable serial console printf "# Spawn a getty on Raspberry Pi serial line\nT0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100\n" >> /etc/inittab # boot/cmdline.txt echo "dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 cgroup_enable=cpuset cgroup_enable=memory swapaccount=1 elevator=deadline fsck.repair=yes rootwait console=ttyAMA0,115200 net.ifnames=0" > /boot/cmdline.txt # " net.ifnames=0" is neccessary for Debian Stretch: see https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/ # create a default boot/config.txt file (details see http://elinux.org/RPiconfig) echo " # enable UART console on GPIO pins enable_uart=1 hdmi_force_hotplug=1 " > boot/config.txt # echo "# camera settings, see http://elinux.org/RPiconfig#Camera # start_x=1 # disable_camera_led=1 # gpu_mem=128 # " >> boot/config.txt echo "# setting for maximum memory, gpu_mem to minimum 16M, camera off start_x=0 gpu_mem=16 " >> boot/config.txt # # /etc/modules # echo "snd_bcm2835 # " >> /etc/modules # create /etc/fstab echo " proc /proc proc defaults 0 0 /dev/mmcblk0p1 /boot vfat defaults 0 0 /dev/mmcblk0p2 / ext4 defaults,noatime 0 1 " > /etc/fstab # run resize script on first boot (phase 1) mv /sbin/init /sbin/init.bak ln -s /sbin/resizefs /sbin/init # as the Pi does not have a hardware clock we need a fake one apt-get install -y \ --no-install-recommends \ fake-hwclock # install packages for managing wireless interfaces apt-get install -y \ --no-install-recommends \ wpasupplicant \ wireless-tools \ ethtool \ crda # # add firmware and packages for managing bluetooth devices # apt-get install -y \ # --no-install-recommends \ # bluetooth \ # pi-bluetooth apt-get install -y \ --no-install-recommends \ bluetooth # ensure compatibility with Docker install.sh, so `raspbian` will be detected correctly apt-get install -y \ --no-install-recommends \ lsb-release # install cloud-init and its required dependencies apt-get install -y \ --no-install-recommends \ cloud-init \ dirmngr \ less mkdir -p /var/lib/cloud/seed/nocloud-net ln -s /boot/user-data /var/lib/cloud/seed/nocloud-net/user-data ln -s /boot/meta-data /var/lib/cloud/seed/nocloud-net/meta-data # enable Docker Engine experimental features mkdir -p /etc/docker/ echo '{ "experimental": true } ' > /etc/docker/daemon.json # set up Docker APT repository and install official Docker CE packages # see: https://docs.docker.com/install/linux/docker-ce/debian/ # # Install packages to allow apt to use a repository over HTTPS: apt-get install -y \ --no-install-recommends \ apt-transport-https \ ca-certificates \ curl \ gnupg2 \ software-properties-common # Add Docker’s official GPG key: curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - # Verify fingerprint of Docker’s official GPG key: apt-key fingerprint 0EBFCD88 # Set up set the stable Docker repository: add-apt-repository \ "deb [arch=arm64] https://download.docker.com/linux/debian \ $(lsb_release -cs) \ stable" # Install Docker CE apt-get update apt-get install -y \ --no-install-recommends \ docker-ce="${DOCKER_ENGINE_VERSION}" \ docker-ce-cli="${DOCKER_ENGINE_VERSION}" \ containerd.io="${CONTAINERD_IO_VERSION}" # install Docker Machine directly from GitHub releases curl -sSL "https://github.com/docker/machine/releases/download/v${DOCKER_MACHINE_VERSION}/docker-machine-Linux-aarch64" \ > /usr/local/bin/docker-machine chmod +x /usr/local/bin/docker-machine # install bash completion for Docker Machine curl -sSL "https://raw.githubusercontent.com/docker/machine/v${DOCKER_MACHINE_VERSION}/contrib/completion/bash/docker-machine.bash" -o /etc/bash_completion.d/docker-machine # install Docker Compose via pip apt-get install -y \ --no-install-recommends \ python curl -sSL https://bootstrap.pypa.io/get-pip.py | python pip install docker-compose=="${DOCKER_COMPOSE_VERSION}" # install bash completion for Docker Compose curl -sSL "https://raw.githubusercontent.com/docker/compose/${DOCKER_COMPOSE_VERSION}/contrib/completion/bash/docker-compose" -o /etc/bash_completion.d/docker-compose echo "Installing rpi-serial-console script" wget -q https://raw.githubusercontent.com/lurch/rpi-serial-console/master/rpi-serial-console -O usr/local/bin/rpi-serial-console chmod +x usr/local/bin/rpi-serial-console # cleanup APT cache and lists apt-get clean rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* if [ "$FETCH_MISSING_ARTIFACTS" == "true" ]; then # set device label and version number cat <> /etc/os-release HYPRIOT_BOOTLOADER_BUILD="${BOOTLOADER_BUILD}" HYPRIOT_KERNEL_BUILD="${KERNEL_BUILD}" HYPRIOT_KERNEL_VERSION="${KERNEL_VERSION}" HYPRIOT_DEVICE="$HYPRIOT_DEVICE" HYPRIOT_IMAGE_VERSION="$HYPRIOT_IMAGE_VERSION" EOF else cat <> /etc/os-release HYPRIOT_KERNEL_VERSION="${KERNEL_VERSION}" HYPRIOT_DEVICE="$HYPRIOT_DEVICE" HYPRIOT_IMAGE_VERSION="$HYPRIOT_IMAGE_VERSION" EOF fi cp /etc/os-release /boot/os-release ================================================ FILE: builder/files/boot/meta-data ================================================ ================================================ FILE: builder/files/boot/user-data ================================================ #cloud-config # vim: syntax=yaml # # The current version of cloud-init in the Hypriot rpi-64 is 0.7.9 # When dealing with cloud-init, it is SUPER important to know the version # I have wasted many hours creating servers to find out the module I was trying to use wasn't in the cloud-init version I had # Documentation: http://cloudinit.readthedocs.io/en/0.7.9/index.html # Set your hostname here, the manage_etc_hosts will update the hosts file entries as well hostname: black-pearl manage_etc_hosts: true # You could modify this for your own user information users: - name: pirate gecos: "Hypriot Pirate" sudo: ALL=(ALL) NOPASSWD:ALL shell: /bin/bash groups: users,docker,video plain_text_passwd: hypriot lock_passwd: false ssh_pwauth: true chpasswd: { expire: false } # # Set the locale of the system # locale: "en_US.UTF-8" # # Set the timezone # # Value of 'timezone' must exist in /usr/share/zoneinfo # timezone: "America/Los_Angeles" # # Update apt packages on first boot # package_update: true # package_upgrade: true # package_reboot_if_required: true package_upgrade: false # # Install any additional apt packages you need here # packages: # - ntp # # WiFi connect to HotSpot # # - use `wpa_passphrase SSID PASSWORD` to encrypt the psk # write_files: # - content: | # allow-hotplug wlan0 # iface wlan0 inet dhcp # wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf # iface default inet dhcp # path: /etc/network/interfaces.d/wlan0 # - content: | # ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev # update_config=1 # network={ # ssid="YOUR_WIFI_SSID" # psk="YOUR_WIFI_PASSWORD" # proto=RSN # key_mgmt=WPA-PSK # pairwise=CCMP # auth_alg=OPEN # } # path: /etc/wpa_supplicant/wpa_supplicant.conf # These commands will be ran once on first boot only runcmd: # Pickup the hostname changes - 'systemctl restart avahi-daemon' # # Activate WiFi interface # - 'ifup wlan0' ================================================ FILE: builder/files/etc/apt/preferences.d/hypriot ================================================ # ensure that only Hypriot kernel packages get installed Package: linux-headers-*-hypriotos* Pin: origin packagecloud.io/hypriot/schatzkiste Pin-Priority: 1001 Package: libraspberrypi* Pin: origin packagecloud.io/hypriot/schatzkiste Pin-Priority: 1001 Package: raspberrypi-bootloader Pin: origin packagecloud.io/hypriot/schatzkiste Pin-Priority: 1001 ================================================ FILE: builder/files/etc/apt/preferences.d/raspberrypi ================================================ # ensure that the correct firmware packages from the # Raspberry Pi Foundation get installed # those packages are usually the most recent ones Package: firmware-* Pin: origin archive.raspberrypi.org Pin-Priority: 1001 ================================================ FILE: builder/files/etc/firstboot.d/10-resize-rootdisk ================================================ #!/bin/bash set -ex # resize script phase 2 if ! [ -h /dev/disk/by-label/root ]; then echo "/dev/disk/by-label/root does not exist or is not a symlink. Don't know how to expand" return 0 fi ROOT_PART=$(readlink /dev/disk/by-label/root) /sbin/resize2fs "$ROOT_PART" ================================================ FILE: builder/files/etc/skel/.bash_prompt ================================================ # @gf3’s Sexy Bash Prompt, inspired by “Extravagant Zsh Prompt” # Shamelessly copied from https://github.com/gf3/dotfiles default_username='unknown' OSNAME="HypriotOS: " OSTYPE="Embedded" PROMPTCHAR='\$' # determine OS type if [ "$(uname -s)" = Darwin ]; then OSNAME="OSX: " OSTYPE="Desktop" #PROMPTCHAR="🐳 " elif [ "$(cat /etc/os-release | grep ^NAME= | cut -d\" -f2)" = Ubuntu ]; then OSNAME="Ubuntu: " OSTYPE="Desktop" #PROMPTCHAR="🐳 " elif [ "$(uname -m)" = armv6l ]; then OSNAME="HypriotOS/armv6: " elif [ "$(uname -m)" = armv7l ]; then OSNAME="HypriotOS/armv7: " elif [ "$(uname -m)" = aarch64 ]; then OSNAME="HypriotOS/arm64: " else OSNAME="HypriotOS: " fi if [[ $COLORTERM = gnome-* && $TERM = xterm ]] && infocmp gnome-256color >/dev/null 2>&1; then export TERM=gnome-256color elif infocmp xterm-256color >/dev/null 2>&1; then export TERM=xterm-256color fi if tput setaf 1 &> /dev/null; then tput sgr0 if [[ $(tput colors) -ge 256 ]] 2>/dev/null; then BLUE=$(tput setaf 4) MAGENTA=$(tput setaf 9) ORANGE=$(tput setaf 172) GREEN=$(tput setaf 70) PURPLE=$(tput setaf 141) else BLUE=$(tput setaf 4) MAGENTA=$(tput setaf 5) ORANGE=$(tput setaf 3) GREEN=$(tput setaf 2) PURPLE=$(tput setaf 1) fi BOLD=$(tput bold) RESET=$(tput sgr0) else BLUE="\033[1;34m" MAGENTA="\033[1;31m" ORANGE="\033[1;33m" GREEN="\033[1;32m" PURPLE="\033[1;35m" BOLD="" RESET="\033[m" fi function git_info() { # check if we're in a git repo git rev-parse --is-inside-work-tree &>/dev/null || return # quickest check for what branch we're on branch=$(git symbolic-ref -q HEAD | sed -e 's|^refs/heads/||') # check if it's dirty (via github.com/sindresorhus/pure) dirty=$(test -z "$(git status --porcelain)" || echo -e "*") echo "$RESET$BOLD on $PURPLE$branch$dirty" } # Only show username/host if not default function usernamehost() { if [ "$USER" != $default_username ]; then echo "${BLUE}${OSNAME}${MAGENTA}$USER${RESET}${BOLD}@${ORANGE}$HOSTNAME${RESET}${BOLD} in "; else echo "${BLUE}${OSNAME}"; fi } # iTerm Tab and Title Customization and prompt customization # http://sage.ucsc.edu/xtal/iterm_tab_customization.html # Put the string " [bash] hostname::/full/directory/path" # in the title bar using the command sequence # \[\e]2;[bash] \h::\]$PWD\[\a\] # Put the penultimate and current directory # in the iterm tab # \[\e]1;\]$(basename $(dirname $PWD))/\W\[\a\] # show git info only on macOS/Ubuntu Desktop systems, don't slow down on ARM/Embedded devices if [ "$OSTYPE" = "Desktop" ]; then PS1="\[\e]2;$PWD\[\a\]\[\e]1;\]$(basename "$(dirname "$PWD")")/\W\[\a\]${BOLD}$(usernamehost)\[$GREEN\]\w\$(git_info)\[$RESET\]\[$BOLD\]\n${PROMPTCHAR} \[$RESET\]" else PS1="\[\e]2;$PWD\[\a\]\[\e]1;\]$(basename "$(dirname "$PWD")")/\W\[\a\]${BOLD}$(usernamehost)\[$GREEN\]\w\[$RESET\]\[$BOLD\]\n${PROMPTCHAR} \[$RESET\]" fi ================================================ FILE: builder/files/etc/skel/.bashrc ================================================ # ~/.bashrc: executed by bash(1) for non-login shells. # Note: PS1 and umask are already set in /etc/profile. You should not # need this unless you want different defaults for root. # PS1='${debian_chroot:+($debian_chroot)}\h:\w\$ ' # umask 022 # You may uncomment the following lines if you want `ls' to be colorized: export LS_OPTIONS='--color=auto' eval "`dircolors`" alias ls='ls $LS_OPTIONS' # alias ll='ls $LS_OPTIONS -l' # alias l='ls $LS_OPTIONS -lA' # # Some more alias to avoid making mistakes: # alias rm='rm -i' # alias cp='cp -i' # alias mv='mv -i' ================================================ FILE: builder/files/etc/systemd/system/hciuart.service ================================================ [Unit] Description=Configure Bluetooth Modems connected by UART ConditionPathIsDirectory=/proc/device-tree/soc/gpio@7e200000/bt_pins Before=bluetooth.service After=dev-ttyAMA0.device [Service] Type=forking ExecStart=/usr/bin/hciattach /dev/ttyAMA0 bcm43xx 921600 noflow - [Install] WantedBy=multi-user.target ================================================ FILE: builder/files/etc/udev/rules.d/10-wlan-powersave-off.rules ================================================ KERNEL=="wlan*", ACTION=="add", RUN+="/sbin/iwconfig wlan0 power off" ================================================ FILE: builder/files/etc/udev/rules.d/75-persistent-net-generator.rules ================================================ # These rules generate rules to keep network interface names unchanged # across reboots and write them to /etc/udev/rules.d/70-persistent-net.rules. # variables used to communicate: # MATCHADDR MAC address used for the match # MATCHID bus_id used for the match # MATCHDRV driver name used for the match # MATCHIFTYPE interface type match # COMMENT comment to add to the generated rule # INTERFACE_NAME requested name supplied by external tool # INTERFACE_NEW new interface name returned by rule writer ACTION!="add", GOTO="persistent_net_generator_end" SUBSYSTEM!="net", GOTO="persistent_net_generator_end" # ignore the interface if a name has already been set NAME=="?*", GOTO="persistent_net_generator_end" # new predictable network interface naming scheme # http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/ IMPORT{cmdline}="net.ifnames" ENV{net.ifnames}=="1", GOTO="persistent_net_generator_end" # device name whitelist KERNEL!="ath*|msh*|ra*|sta*|ctc*|lcs*|hsi*", \ GOTO="persistent_net_generator_end" # ignore Xen virtual interfaces SUBSYSTEMS=="xen", GOTO="persistent_net_generator_end" # ignore UML virtual interfaces DRIVERS=="uml-netdev", GOTO="persistent_net_generator_end" # ignore "secondary" raw interfaces of the madwifi driver KERNEL=="ath*", ATTRS{type}=="802", GOTO="persistent_net_generator_end" # ignore "secondary" monitor interfaces of mac80211 drivers KERNEL=="wlan*", ATTRS{type}=="803", GOTO="persistent_net_generator_end" # by default match on the MAC address and interface type ENV{MATCHADDR}="$attr{address}" ENV{MATCHIFTYPE}="$attr{type}" # match interface dev_id ATTR{dev_id}=="?*", ENV{MATCHDEVID}="$attr{dev_id}" # These vendors are known to violate the local MAC address assignment scheme # Interlan, DEC (UNIBUS or QBUS), Apollo, Cisco, Racal-Datacom ENV{MATCHADDR}=="02:07:01:*", GOTO="globally_administered_whitelist" # 3Com ENV{MATCHADDR}=="02:60:60:*", GOTO="globally_administered_whitelist" # 3Com IBM PC; Imagen; Valid; Cisco; Apple ENV{MATCHADDR}=="02:60:8c:*", GOTO="globally_administered_whitelist" # Intel ENV{MATCHADDR}=="02:a0:c9:*", GOTO="globally_administered_whitelist" # Olivetti ENV{MATCHADDR}=="02:aa:3c:*", GOTO="globally_administered_whitelist" # CMC Masscomp; Silicon Graphics; Prime EXL ENV{MATCHADDR}=="02:cf:1f:*", GOTO="globally_administered_whitelist" # Prominet Corporation Gigabit Ethernet Switch ENV{MATCHADDR}=="02:e0:3b:*", GOTO="globally_administered_whitelist" # BTI (Bus-Tech, Inc.) IBM Mainframes ENV{MATCHADDR}=="02:e6:d3:*", GOTO="globally_administered_whitelist" # Novell 2000 ENV{MATCHADDR}=="52:54:4c:*", GOTO="globally_administered_whitelist" # Realtec ENV{MATCHADDR}=="52:54:ab:*", GOTO="globally_administered_whitelist" # Kingston Technologies ENV{MATCHADDR}=="e2:0c:0f:*", GOTO="globally_administered_whitelist" # ignore interfaces with locally administered or null MAC addresses # and VMWare, Hyper-V, KVM, Virtualbox and Xen virtual interfaces ENV{MATCHADDR}=="?[2367abef]:*", ENV{MATCHADDR}="" ENV{MATCHADDR}=="00:00:00:00:00:00", ENV{MATCHADDR}="" ENV{MATCHADDR}=="00:0c:29:*|00:50:56:*|00:05:69:*|00:1C:14:*", \ ENV{MATCHADDR}="" ENV{MATCHADDR}=="00:15:5d:*", ENV{MATCHADDR}="" ENV{MATCHADDR}=="52:54:00:*|54:52:00:*", ENV{MATCHADDR}="" ENV{MATCHADDR}=="08:00:27:*", ENV{MATCHADDR}="" ENV{MATCHADDR}=="00:16:3e:*", ENV{MATCHADDR}="" # ignore Windows Azure Hyper-V virtual interfaces ENV{MATCHADDR}=="00:03:ff:*", ENV{MATCHADDR}="" ENV{MATCHADDR}=="00:0d:3a:*", ENV{MATCHADDR}="" ENV{MATCHADDR}=="00:1d:d8:*", ENV{MATCHADDR}="" ENV{MATCHADDR}=="00:12:5a:*", ENV{MATCHADDR}="" ENV{MATCHADDR}=="00:17:fa:*", ENV{MATCHADDR}="" ENV{MATCHADDR}=="00:22:48:*", ENV{MATCHADDR}="" ENV{MATCHADDR}=="00:25:ae:*", ENV{MATCHADDR}="" ENV{MATCHADDR}=="00:50:f2:*", ENV{MATCHADDR}="" ENV{MATCHADDR}=="28:18:78:*", ENV{MATCHADDR}="" ENV{MATCHADDR}=="50:1a:c5:*", ENV{MATCHADDR}="" ENV{MATCHADDR}=="60:45:bd:*", ENV{MATCHADDR}="" ENV{MATCHADDR}=="7c:1e:52:*", ENV{MATCHADDR}="" ENV{MATCHADDR}=="7c:ed:8d:*", ENV{MATCHADDR}="" ENV{MATCHADDR}=="dc:b4:c4:*", ENV{MATCHADDR}="" # ignore Ravello virtual interfaces ENV{MATCHADDR}=="2c:c2:60:*", ENV{MATCHADDR}="" LABEL="globally_administered_whitelist" # ibmveth interfaces have stable locally administered MAC addresses SUBSYSTEMS=="ibmveth", ENV{MATCHADDR}="$attr{address}" # S/390 interfaces are matched only by id SUBSYSTEMS=="ccwgroup", \ ENV{MATCHDRV}="$driver", ENV{MATCHID}="$id", \ ENV{MATCHADDR}="", ENV{MATCHDEVID}="" # terminate processing if there are not enough conditions to create a rule ENV{MATCHADDR}=="", ENV{MATCHID}=="", ENV{INTERFACE_NAME}=="", \ GOTO="persistent_net_generator_end" # provide nice comments for the generated rules SUBSYSTEMS=="pci", \ ENV{COMMENT}="PCI device $attr{vendor}:$attr{device}" SUBSYSTEMS=="pcmcia", \ ENV{COMMENT}="PCMCIA device $attr{card_id}:$attr{manf_id}" SUBSYSTEMS=="usb", \ ENV{COMMENT}="USB device 0x$attr{idVendor}:0x$attr{idProduct}" SUBSYSTEMS=="ccwgroup", \ ENV{COMMENT}="S/390 device at $id" SUBSYSTEMS=="ibmveth", \ ENV{COMMENT}="LPAR virtual device at $id" SUBSYSTEMS=="ieee1394", \ ENV{COMMENT}="Firewire device $attr{host_id}" ENV{COMMENT}=="", \ ENV{COMMENT}="Unknown $env{SUBSYSTEM} device ($env{DEVPATH})" ATTRS{driver}=="?*", \ ENV{COMMENT}="$env{COMMENT} ($attr{driver})" # ignore interfaces without a driver link like bridges and VLANs, otherwise # generate and write the rule DRIVERS=="?*", IMPORT{program}="write_net_rules" # rename the interface if requested ENV{INTERFACE_NEW}=="?*", NAME="$env{INTERFACE_NEW}" LABEL="persistent_net_generator_end" ================================================ FILE: builder/files/etc/udev/rules.d/99-com.rules ================================================ SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c 'chown -R root:gpio /sys/class/gpio && chmod -R 770 /sys/class/gpio; chown -R root:gpio /sys/devices/virtual/gpio && chmod -R 770 /sys/devices/virtual/gpio; chown -R root:gpio /sys/devices/platform/soc/*.gpio/gpio && chmod -R 770 /sys/devices/platform/soc/*.gpio/gpio'" SUBSYSTEM=="input", GROUP="input", MODE="0660" SUBSYSTEM=="i2c-dev", GROUP="i2c", MODE="0660" SUBSYSTEM=="spidev", GROUP="spi", MODE="0660" SUBSYSTEM=="bcm2835-gpiomem", GROUP="gpio", MODE="0660" ================================================ FILE: builder/files/lib/firmware/brcm/brcmfmac43430-sdio.txt ================================================ # NVRAM file for BCM943430WLSELG # 2.4 GHz, 20 MHz BW mode # The following parameter values are just placeholders, need to be updated. manfid=0x2d0 prodid=0x0726 vendid=0x14e4 devid=0x43e2 boardtype=0x0726 boardrev=0x1202 boardnum=22 macaddr=00:90:4c:c5:12:38 sromrev=11 boardflags=0x00404201 boardflags3=0x08000000 xtalfreq=37400 #xtalfreq=19200 nocrc=1 ag0=255 aa2g=1 ccode=ALL pa0itssit=0x20 extpagain2g=0 #PA parameters for 2.4GHz, measured at CHIP OUTPUT pa2ga0=-168,7161,-820 AvVmid_c0=0x0,0xc8 cckpwroffset0=5 # PPR params maxp2ga0=84 txpwrbckof=6 cckbw202gpo=0 legofdmbw202gpo=0x66111111 mcsbw202gpo=0x77711111 propbw202gpo=0xdd # OFDM IIR : ofdmdigfilttype=18 ofdmdigfilttypebe=18 # PAPD mode: papdmode=1 papdvalidtest=1 pacalidx2g=32 papdepsoffset=-36 papdendidx=61 il0macaddr=00:90:4c:c5:12:38 wl0id=0x431b deadman_to=0xffffffff # muxenab: 0x1 for UART enable, 0x2 for GPIOs, 0x8 for JTAG muxenab=0x1 # CLDO PWM voltage settings - 0x4 - 1.1 volt #cldo_pwm=0x4 #VCO freq 326.4MHz spurconfig=0x3 ================================================ FILE: builder/files/lib/firmware/brcm/brcmfmac43455-sdio.txt ================================================ # Cloned from bcm94345wlpagb_p2xx.txt # NVRAMRev=$Rev: 498373 $ sromrev=11 vendid=0x14e4 devid=0x43ab manfid=0x2d0 prodid=0x06e4 macaddr=00:90:4c:c5:12:38 #macaddr=b8:27:eb:74:f2:6c nocrc=1 boardtype=0x6e4 boardrev=0x1304 #XTAL 37.4MHz xtalfreq=37400 btc_mode=1 #------------------------------------------------------ #boardflags: 5GHz eTR switch by default # 2.4GHz eTR switch by default # bit1 for btcoex boardflags=0x00480201 boardflags2=0x40800000 boardflags3=0x48200100 phycal_tempdelta=15 rxchain=1 txchain=1 aa2g=1 aa5g=1 tssipos5g=1 tssipos2g=1 femctrl=0 AvVmid_c0=1,165,2,100,2,100,2,100,2,100 pa2ga0=-129,6525,-718 pa2ga1=-149,4408,-601 pa5ga0=-185,6836,-815,-186,6838,-815,-184,6859,-815,-184,6882,-818 pa5ga1=-202,4285,-574,-201,4312,-578,-196,4391,-586,-201,4294,-575 itrsw=1 pdoffsetcckma0=2 pdoffset2gperchan=0,-2,1,0,1,0,1,1,1,0,0,-1,-1,0 pdoffset2g40ma0=16 pdoffset40ma0=0x8888 pdoffset80ma0=0x8888 extpagain5g=2 extpagain2g=2 tworangetssi2g=1 tworangetssi5g=1 # LTECX flags # WCI2 ltecxmux=0 ltecxpadnum=0x0504 ltecxfnsel=0x22 ltecxgcigpio=0x32 maxp2ga0=80 ofdmlrbw202gpo=0x0022 dot11agofdmhrbw202gpo=0x4442 mcsbw202gpo=0x98444422 mcsbw402gpo=0x98444422 maxp5ga0=82,82,82,82 mcsbw205glpo=0xb9555000 mcsbw205gmpo=0xb9555000 mcsbw205ghpo=0xb9555000 mcsbw405glpo=0xb9555000 mcsbw405gmpo=0xb9555000 mcsbw405ghpo=0xb9555000 mcsbw805glpo=0xb9555000 mcsbw805gmpo=0xb9555000 mcsbw805ghpo=0xb9555000 swctrlmap_2g=0x00000000,0x00000000,0x00000000,0x010000,0x3ff swctrlmap_5g=0x00100010,0x00200020,0x00200020,0x010000,0x3fe swctrlmapext_5g=0x00000000,0x00000000,0x00000000,0x000000,0x3 swctrlmapext_2g=0x00000000,0x00000000,0x00000000,0x000000,0x3 vcodivmode=1 deadman_to=481500000 ed_thresh2g=-54 ed_thresh5g=-54 eu_edthresh2g=-54 eu_edthresh5g=-54 ldo1=4 rawtempsense=0x1ff cckPwrIdxCorr=3 cckTssiDelay=150 ofdmTssiDelay=150 txpwr2gAdcScale=1 txpwr5gAdcScale=1 dot11b_opts=0x3aa85 cbfilttype=1 fdsslevel_ch11=6 ================================================ FILE: builder/files/sbin/resizefs ================================================ #!/bin/sh mount -t proc proc /proc mount -t sysfs sys /sys mount -t tmpfs tmp /run mount / -o remount,rw PART_START=$(cat /sys/block/mmcblk0/mmcblk0p2/start) echo "Modifying partition table" fdisk -u /dev/mmcblk0 < /proc/sys/kernel/sysrq mount / -o remount,ro sync echo b > /proc/sysrq-trigger ================================================ FILE: builder/test/image_spec.rb ================================================ require_relative 'spec_helper' describe "SD card image" do it "exists" do image_file = file(image_path) expect(image_file).to exist end context "Partition table" do let(:stdout) { run("list-filesystems").stdout } it "has two partitions" do partitions = stdout.split(/\r?\n/) expect(partitions.size).to be 2 end it "has a boot-partition with a vfat filesystem" do expect(stdout).to contain('sda1: vfat') end it "has a root-partition with a ext4 filesystem" do expect(stdout).to contain('sda2: ext4') end end context "Binary dpkg" do let(:stdout) { run_mounted("file-architecture /usr/bin/dpkg").stdout } it "is compiled for ARM aarch64 architecture" do expect(stdout).to contain('aarch64') end end context "/etc/fstab" do let(:stdout) { run_mounted("cat /etc/fstab").stdout } it "has a vfat boot entry" do expect(stdout).to contain('/dev/mmcblk0p1 /boot vfat') end it "has a ext4 root entry" do expect(stdout).to contain('/dev/mmcblk0p2 / ext4') end end context "Docker systemd service file" do let(:stdout) { run_mounted("cat /lib/systemd/system/docker.service").stdout } it "Docker Engine is installed" do expect(stdout).to contain("/usr/bin/dockerd") end end end ================================================ FILE: builder/test/os-release_spec.rb ================================================ require_relative 'spec_helper' describe "Root filesystem" do let(:stdout) { run_mounted("cat /etc/os-release").stdout } it "is based on debian" do expect(stdout).to contain('debian') end it "is debian version stretch" do expect(stdout).to contain('stretch') end it "is a HypriotOS" do expect(stdout).to contain('HypriotOS') end it "has a HYPRIOT_OS= entry" do expect(stdout).to contain('^HYPRIOT_OS=') end it "has a HYPRIOT_OS_VERSION= entry" do expect(stdout).to contain('^HYPRIOT_OS_VERSION=') end it "has a HYPRIOT_DEVICE= entry" do expect(stdout).to contain('^HYPRIOT_DEVICE=') end it "has a HYPRIOT_IMAGE_VERSION= entry" do expect(stdout).to contain('^HYPRIOT_IMAGE_VERSION=') end it "is for architecure 'HYPRIOT_OS=\"HypriotOS/arm64\"'" do expect(stdout).to contain('^HYPRIOT_OS="HypriotOS/arm64"$') end it "is for device 'HYPRIOT_DEVICE=\"Raspberry Pi 3 64bit\"'" do expect(stdout).to contain('^HYPRIOT_DEVICE="Raspberry Pi 3 64bit"$') end it "uses os-rootfs version 'HYPRIOT_OS_VERSION=\"v2.1.0\"'" do expect(stdout).to contain('^HYPRIOT_OS_VERSION="v2.1.0"$') end if ENV.fetch('CIRCLE_TAG','') != '' it "is not dirty" do expect(stdout).not_to contain('dirty') end end end ================================================ FILE: builder/test/spec_helper.rb ================================================ require 'serverspec' set :backend, :exec def image_path return "hypriotos-rpi64-#{ENV['VERSION']}.img" end def run( cmd ) return command("guestfish add #{image_path} : run : #{cmd}") end def run_mounted( cmd ) return run("mount /dev/sda2 / : #{cmd}") end ================================================ FILE: builder/test-integration/.bundle/config ================================================ --- BUNDLE_PATH: vendor/bundle BUNDLE_DISABLE_SHARED_GEMS: '1' BUNDLE_BIN: bin ================================================ FILE: builder/test-integration/.gitignore ================================================ bin/ vendor/ ================================================ FILE: builder/test-integration/.rspec ================================================ --color --format documentation ================================================ FILE: builder/test-integration/.ruby-version ================================================ 2.0.0 ================================================ FILE: builder/test-integration/Gemfile ================================================ # A sample Gemfile source "https://rubygems.org" gem "serverspec" ================================================ FILE: builder/test-integration/README.md ================================================ # HypriotOS serverspec tests To test the SD card image for the Raspberry Pi use this [Serverspec](http://serverspec.org) tests. See the [Serverspec Docs](http://serverspec.org/resource_types.html) for more details what you can test with it. ## Preparation 1. Flash the SD card image 2. Put the SD card into your Raspberry Pi 3. Power on the Raspberry Pi 4. Retrieve the host name or IP address to reach the Pi ## Install Serverspec You need ruby and bundle installed. Then you can install the dependencies locally with ```bash bundle install ``` ## Run tests Set the `BOARD` environment variable to the host name or IP address of your Pi. The user name for the test is `root`. ### Remove previous fingerpint You normally have to remove the fingerprint of a previously tested Hypriot Pi. Use the hostname or the IP address of your Raspberry Pi. ```bash ssh-keygen -R black-pearl.local ``` ### Run basic SD image tests Now run the basic SD card image tests. This tests if docker is up and running and the image has everything as we expect it. ```bash BOARD=black-pearl.local bin/rspec spec/hypriotos-image ``` ### Run full docker test Now run a full docker test. This does a full cycle with `docker pull` and `docker run` to see that everything works fine. ``` BOARD=black-pearl.local bin/rspec spec/hypriotos-docker ``` ================================================ FILE: builder/test-integration/Rakefile ================================================ require 'rake' require 'rspec/core/rake_task' task :spec => 'spec:all' task :default => :spec namespace :spec do targets = [] Dir.glob('./spec/*').each do |dir| next unless File.directory?(dir) targets << File.basename(dir) end task :all => targets task :default => :all targets.each do |target| desc "Run serverspec tests to #{target}" RSpec::Core::RakeTask.new(target.to_sym) do |t| ENV['TARGET_HOST'] = target t.pattern = "spec/#{target}/*_spec.rb" end end end ================================================ FILE: builder/test-integration/spec/hypriotos-docker/docker-busybox-httpd_spec.rb ================================================ require 'spec_helper' describe command('docker pull hypriot/rpi-busybox-httpd:0.1.0') do its(:exit_status) { should eq 0 } end describe command('docker run -t --rm hypriot/rpi-busybox-httpd:0.1.0 busybox') do its(:stdout) { should match /BusyBox v1.20.2/ } its(:exit_status) { should eq 0 } end describe command('docker run -t --rm hypriot/rpi-busybox-httpd:0.1.0 busybox httpd') do its(:exit_status) { should eq 0 } end ================================================ FILE: builder/test-integration/spec/hypriotos-docker/docker-compose_spec.rb.off ================================================ require 'spec_helper' describe command('rm -rf rpi-node-haproxy-example && git clone https://github.com/hypriot/rpi-node-haproxy-example') do its(:exit_status) { should eq 0 } end describe command('cd rpi-node-haproxy-example && docker-compose up -d') do its(:exit_status) { should eq 0 } end describe command('cd rpi-node-haproxy-example && docker-compose ps') do its(:stdout) { should match /rpinodehaproxyexample_haproxy_1 bash \/haproxy-start Up/ } its(:stdout) { should match /rpinodehaproxyexample_weba_1 node index.js Up/ } its(:stdout) { should match /rpinodehaproxyexample_webb_1 node index.js Up/ } its(:stdout) { should match /rpinodehaproxyexample_webc_1 node index.js Up/ } its(:exit_status) { should eq 0 } end describe command('curl http://localhost') do its(:stdout) { should match /Hello from Node.js container/ } its(:exit_status) { should eq 0 } end describe command('cd rpi-node-haproxy-example && docker-compose kill') do its(:exit_status) { should eq 0 } end describe command('cd rpi-node-haproxy-example && docker-compose ps') do its(:stdout) { should match /rpinodehaproxyexample_haproxy_1 bash \/haproxy-start Exit 137/ } its(:stdout) { should match /rpinodehaproxyexample_weba_1 node index.js Exit 137/ } its(:stdout) { should match /rpinodehaproxyexample_webb_1 node index.js Exit 137/ } its(:stdout) { should match /rpinodehaproxyexample_webc_1 node index.js Exit 137/ } its(:exit_status) { should eq 0 } end ================================================ FILE: builder/test-integration/spec/hypriotos-docker/docker-node_spec.rb ================================================ require 'spec_helper' describe command('docker pull hypriot/rpi-node:0.12.0') do its(:exit_status) { should eq 0 } end describe command('docker run -t --rm hypriot/rpi-node:0.12.0 node --version') do its(:stdout) { should match /v0.12.0/ } # its(:stderr) { should match /^$/ } its(:exit_status) { should eq 0 } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/base/bootfiles_spec.rb ================================================ require 'spec_helper' describe file('/boot/bcm2710-rpi-3-b.dtb') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end describe file('/boot/bootcode.bin') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end describe file('/boot/cmdline.txt') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end describe file('/boot/config.txt') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end describe file('/boot/fixup.dat') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end describe file('/boot/kernel8.img') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end describe file('/boot/COPYING.linux') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end describe file('/boot/LICENCE.broadcom') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end describe file('/boot/overlays') do it { should be_directory } it { should be_mode 755 } it { should be_owned_by 'root' } end describe file('/boot/start.elf') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/base/device_tree_spec.rb ================================================ require 'spec_helper' # /proc/device-tree is only present if device-tree works describe file('/proc/device-tree') do it { should be_symlink } it { should be_linked_to '/sys/firmware/devicetree/base' } it { should be_mode 777 } it { should be_owned_by 'root' } end describe file('/proc/device-tree/model') do it { should be_file } it { should be_mode 444 } it { should be_owned_by 'root' } its(:content) { should match /Raspberry Pi 3 Model B/ } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/base/kernel_spec.rb ================================================ require 'spec_helper' describe command('uname -r') do its(:stdout) { should match /4.19.58-hypriotos-v8/ } its(:exit_status) { should eq 0 } end describe file('/lib/modules/4.19.58-hypriotos-v8/kernel') do it { should be_directory } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/base/packages_spec.rb ================================================ describe package('curl') do it { should be_installed } end describe package('wget') do it { should be_installed } end describe package('bash-completion') do it { should be_installed } end describe package('htop') do it { should be_installed } end describe package('occi') do it { should_not be_installed } end describe package('usbutils') do it { should be_installed } end describe package('lsb-release') do it { should be_installed } end describe package('wpasupplicant') do it { should be_installed } end describe package('wireless-tools') do it { should be_installed } end describe 'for bluetooth-support' do describe package('bluetooth') do it { should be_installed } end end ================================================ FILE: builder/test-integration/spec/hypriotos-image/base/release_spec.rb ================================================ describe file('/etc/hypriot_release') do it { should_not be_file } end describe file('/etc/os-release') do it { should be_file } it { should be_owned_by 'root' } its(:content) { should contain /ID=debian/ } its(:content) { should match /HYPRIOT_OS="HypriotOS\/arm64"/ } its(:content) { should match /HYPRIOT_OS_VERSION="v2.1.0"/ } its(:content) { should match /HYPRIOT_DEVICE="Raspberry Pi 3 64bit"/ } its(:content) { should match /HYPRIOT_IMAGE_VERSION=/ } end describe file('/boot/os-release') do it { should be_file } it { should be_owned_by 'root' } its(:content) { should contain /ID=debian/ } its(:content) { should match /HYPRIOT_OS="HypriotOS\/arm64"/ } its(:content) { should match /HYPRIOT_OS_VERSION="v2.1.0"/ } its(:content) { should match /HYPRIOT_DEVICE="Raspberry Pi 3 64bit"/ } its(:content) { should match /HYPRIOT_IMAGE_VERSION=/ } end describe file('/etc/motd') do it { should be_file } it { should be_owned_by 'root' } its(:content) { should match /HypriotOS \(Debian GNU\/Linux 9\)/ } end describe file('/etc/issue') do it { should be_file } it { should be_owned_by 'root' } its(:content) { should match /HypriotOS \(Debian GNU\/Linux 9\)/ } end describe file('/etc/issue.net') do it { should be_file } it { should be_owned_by 'root' } its(:content) { should match /HypriotOS \(Debian GNU\/Linux 9\)/ } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/base/rpi3_bluetooth_spec.rb ================================================ # only test for built-in bluetooth support if we are on the Raspberry Pi 3 cpu_info = command('cat /proc/cpuinfo').stdout if cpu_info.include?('a02082') or cpu_info.include?('a22082') describe "RPi 3: bluetooth support" do describe command('hciconfig') do its(:stdout) { should contain /hci0/ } its(:stdout) { should contain /UP RUNNING/ } end end end ================================================ FILE: builder/test-integration/spec/hypriotos-image/base/rpi3_wifi_spec.rb ================================================ # only test for built-in bluetooth support if we are on the Raspberry Pi 3 cpu_info = command('cat /proc/cpuinfo').stdout if cpu_info.include?('a02082') or cpu_info.include?('a22082') describe "RPi 3B: built-in wifi works" do describe command('ifconfig -a') do its(:stdout) { should contain /wlan0/ } end describe command('ethtool -i wlan0') do its(:stdout) { should contain /driver: brcmfmac/ } its(:stdout) { should contain /version: 7.45.98.38/ } its(:stdout) { should contain /firmware-version: 01-e58d219f/ } end end end describe "RPi 3B: built-in wifi firmware is installed" do describe file('/lib/firmware/brcm/brcmfmac43430-sdio.bin') do it { should be_file } it { should be_mode 644 } it { should be_owned_by 'root' } end describe file('/lib/firmware/brcm/brcmfmac43430-sdio.txt') do it { should be_file } it { should be_mode 644 } it { should be_owned_by 'root' } end end describe "RPi 3B: built-in wifi works" do describe command('ifconfig -a') do its(:stdout) { should contain /wlan0/ } end wifi_info = command('ethtool -i wlan0').stdout if wifi_info.include?('version: 7.45.98.38') describe command('ethtool -i wlan0') do its(:stdout) { should contain /driver: brcmfmac/ } its(:stdout) { should contain /version: 7.45.98.38/ } its(:stdout) { should contain /firmware-version: 01-e58d219f/ } end end end describe "RPi 3B+: built-in wifi firmware is installed" do describe file('/lib/firmware/brcm/brcmfmac43455-sdio.bin') do it { should be_file } it { should be_mode 644 } it { should be_owned_by 'root' } end describe file('/lib/firmware/brcm/brcmfmac43455-sdio.txt') do it { should be_file } it { should be_mode 644 } it { should be_owned_by 'root' } end end describe "RPi 3B+: built-in wifi works" do describe command('ifconfig -a') do its(:stdout) { should contain /wlan0/ } end wifi_info = command('ethtool -i wlan0').stdout if wifi_info.include?('version: 7.45.154') describe command('ethtool -i wlan0') do its(:stdout) { should contain /driver: brcmfmac/ } its(:stdout) { should contain /version: 7.45.154/ } its(:stdout) { should contain /firmware-version: 01-4fbe0b04/ } end end end ================================================ FILE: builder/test-integration/spec/hypriotos-image/base/serial_base.rb ================================================ describe command('ps -ax') do its(:stdout) { should match /getty -L ttyAMA0 115200 vt100/ } end describe file('/etc/inittab') do it { should be_file } it { should be_mode 644 } it { should be_owned_by 'root' } its(:content) { should match /^T0:23:respawn:\/sbin\/getty -L ttyAMA0 115200 vt100/ } end describe file('/usr/bin/rpi-serial-console') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/base/users_spec.rb ================================================ describe user('root') do it { should exist } it { should have_home_directory '/root' } it { should have_login_shell '/bin/bash' } end describe group('docker') do it { should exist } end describe user('pirate') do it { should exist } it { should have_home_directory '/home/pirate' } it { should have_login_shell '/bin/bash' } it { should belong_to_group 'docker' } it { should belong_to_group 'video' } end describe file('/etc/sudoers') do it { should be_file } it { should be_mode 440 } it { should be_owned_by 'root' } end describe file('/etc/sudoers.d') do it { should be_directory } it { should be_mode 750 } it { should be_owned_by 'root' } end describe file('/root/.bashrc') do it { should be_file } it { should be_mode 644 } it { should be_owned_by 'root' } end describe file('/root/.bash_prompt') do it { should be_file } it { should be_mode 644 } it { should be_owned_by 'root' } end describe file('/home/pirate/.bashrc') do it { should be_file } it { should be_mode 644 } it { should be_owned_by 'pirate' } end describe file('/home/pirate/.bash_prompt') do it { should be_file } it { should be_mode 644 } it { should be_owned_by 'pirate' } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/cloud-init_spec.rb ================================================ require 'spec_helper' describe package('cloud-init') do it { should be_installed } end describe file('/boot/user-data') do it { should be_file } its(:content) { should match /hostname: / } end describe file('/boot/meta-data') do it { should be_file } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/cmdline_kernel_spec.rb ================================================ describe file('/boot/cmdline.txt') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } its(:content) { should match /dwc_otg.lpm_enable=0/ } its(:content) { should match /console=tty1/ } its(:content) { should match /root=\/dev\/mmcblk0p2/ } its(:content) { should match /rootfstype=ext4/ } its(:content) { should match /cgroup_enable=cpuset/ } its(:content) { should match /cgroup_enable=memory/ } its(:content) { should match /swapaccount=1/ } its(:content) { should match /elevator=deadline/ } its(:content) { should match /fsck.repair=yes/ } its(:content) { should match /rootwait/ } its(:content) { should match /console=ttyAMA0,115200/ } its(:content) { should match /net.ifnames=0/ } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/cmdline_serial_spec.rb ================================================ describe file('/boot/cmdline.txt') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } its(:content) { should match /console=tty1/ } its(:content) { should match /console=ttyAMA0,115200/ } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/config_txt_spec.rb ================================================ describe file('/boot/config.txt') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } its(:content) { should match /^enable_uart=1/ } its(:content) { should match /^hdmi_force_hotplug=1/ } its(:content) { should match /^start_x=0/ } its(:content) { should match /^gpu_mem=16/ } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/docker-compose_spec.rb ================================================ require 'spec_helper' describe file('/usr/local/bin/docker-compose') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end describe command('docker-compose --version') do its(:stdout) { should match /1.23.1/m } its(:exit_status) { should eq 0 } end describe file('/etc/bash_completion.d/docker-compose') do it { should be_file } it { should be_mode 644 } it { should be_owned_by 'root' } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/docker-machine_spec.rb ================================================ require 'spec_helper' describe file('/usr/local/bin/docker-machine') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end describe command('docker-machine --version') do its(:stdout) { should match /0.16.1/m } its(:exit_status) { should eq 0 } end describe file('/etc/bash_completion.d/docker-machine') do it { should be_file } it { should be_mode 644 } it { should be_owned_by 'root' } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/docker_spec.rb ================================================ require 'spec_helper' describe package('docker-ce') do it { should be_installed } end describe command('dpkg -l docker-ce') do its(:stdout) { should match /ii docker-ce/ } its(:stdout) { should match /5:18.09.7~3-0~debian/ } its(:stdout) { should match /arm64/ } its(:exit_status) { should eq 0 } end describe command('dpkg -l docker-ce-cli') do its(:stdout) { should match /ii docker-ce-cli/ } its(:stdout) { should match /5:18.09.7~3-0~debian/ } its(:stdout) { should match /arm64/ } its(:exit_status) { should eq 0 } end describe command('dpkg -l containerd.io') do its(:stdout) { should match /ii containerd.io/ } its(:stdout) { should match /1.2.6-3/ } its(:stdout) { should match /arm64/ } its(:exit_status) { should eq 0 } end describe file('/usr/bin/docker') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end describe file('/usr/bin/docker-init') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end describe file('/usr/bin/docker-proxy') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end describe file('/usr/bin/dockerd') do it { should be_file } it { should be_owned_by 'root' } end describe file('/usr/bin/dockerd-ce') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end describe file('/usr/bin/containerd') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end describe file('/usr/bin/containerd-shim') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end describe file('/lib/systemd/system/docker.socket') do it { should be_file } it { should be_mode 644 } it { should be_owned_by 'root' } end describe file('/var/run/docker.sock') do it { should be_socket } it { should be_mode 660 } it { should be_owned_by 'root' } it { should be_grouped_into 'docker' } end describe file('/etc/default/docker') do it { should be_file } it { should be_mode 644 } it { should be_owned_by 'root' } end describe file('/var/lib/docker') do it { should be_directory } it { should be_mode 711 } it { should be_owned_by 'root' } end describe file('/var/lib/docker/overlay2') do it { should be_directory } it { should be_mode 700 } it { should be_owned_by 'root' } end describe command('docker -v') do its(:stdout) { should match /Docker version 18.09.7, build/ } its(:exit_status) { should eq 0 } end describe command('docker info') do its(:stdout) { should match /Storage Driver: overlay2/ } its(:exit_status) { should eq 0 } end describe interface('lo') do it { should exist } end describe interface('docker0') do it { should exist } end describe service('docker') do it { should be_enabled } it { should be_running } end describe command('grep docker /var/log/syslog') do its(:stdout) { should match /Daemon has completed initialization/ } its(:exit_status) { should eq 0 } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/filesystems_spec.rb ================================================ Specinfra::Runner.run_command('modprobe btrfs') describe kernel_module('btrfs') do it { should be_loaded } end Specinfra::Runner.run_command('modprobe overlay') describe kernel_module('overlay') do it { should be_loaded } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/hypriot-list_spec.rb ================================================ require 'spec_helper' # describe file('/etc/apt/sources.list.d/hypriot.list') do # it { should be_file } # it { should be_mode 644 } # it { should be_owned_by 'root' } # it { should contain 'deb https://packagecloud.io/Hypriot/Schatzkiste/debian/ jessie main' } # end describe package('apt-transport-https') do it { should be_installed } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/kernel_config_spec.rb ================================================ Specinfra::Runner.run_command('modprobe configs') describe command('zcat /proc/config.gz') do its(:stdout) { should match /CONFIG_KPROBES=y/ } #its(:stdout) { should match /CONFIG_UPROBES=y/ } its(:stdout) { should match /CONFIG_HAVE_KPROBES=y/ } its(:stdout) { should match /CONFIG_EVENT_TRACING=y/ } #its(:stdout) { should match /CONFIG_KPROBE_EVENT=y/ } #its(:stdout) { should match /CONFIG_UPROBE_EVENT=y/ } #its(:stdout) { should match /CONFIG_PROBE_EVENTS=y/ } its(:stdout) { should match /CONFIG_FTRACE=y/ } #its(:stdout) { should match /CONFIG_FTRACE_SYSCALLS=y/ } its(:stdout) { should match /CONFIG_DYNAMIC_FTRACE=y/ } its(:stdout) { should match /CONFIG_HAVE_DYNAMIC_FTRACE=y/ } #its(:stdout) { should match /CONFIG_BCM2708_VCHIQ=y/ } its(:stdout) { should match /CONFIG_HW_RANDOM_BCM2835=y/ } # Docker specific kernel settings (see https://github.com/docker/docker/blob/master/contrib/check-config.sh) ## Generally Necessary: its(:stdout) { should match /CONFIG_NAMESPACES=y/ } its(:stdout) { should match /CONFIG_NET_NS=y/ } its(:stdout) { should match /CONFIG_PID_NS=y/ } its(:stdout) { should match /CONFIG_IPC_NS=y/ } its(:stdout) { should match /CONFIG_UTS_NS=y/ } #its(:stdout) { should match /CONFIG_DEVPTS_MULTIPLE_INSTANCES=y/ } its(:stdout) { should match /CONFIG_CGROUPS=y/ } its(:stdout) { should match /CONFIG_CGROUP_CPUACCT=y/ } its(:stdout) { should match /CONFIG_CGROUP_DEVICE=y/ } its(:stdout) { should match /CONFIG_CGROUP_FREEZER=y/ } its(:stdout) { should match /CONFIG_CGROUP_SCHED=y/ } its(:stdout) { should match /CONFIG_CPUSETS=y/ } its(:stdout) { should match /CONFIG_MEMCG=y/ } its(:stdout) { should match /CONFIG_KEYS=y/ } its(:stdout) { should match /CONFIG_VETH=m/ } its(:stdout) { should match /CONFIG_BRIDGE=m/ } its(:stdout) { should match /CONFIG_BRIDGE_NETFILTER=m/ } its(:stdout) { should match /CONFIG_NF_NAT_IPV4=m/ } its(:stdout) { should match /CONFIG_IP_NF_FILTER=m/ } its(:stdout) { should match /CONFIG_IP_NF_TARGET_MASQUERADE=m/ } its(:stdout) { should match /CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m/ } its(:stdout) { should match /CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m/ } its(:stdout) { should match /CONFIG_NF_NAT=m/ } its(:stdout) { should match /CONFIG_NF_NAT_NEEDED=y/ } its(:stdout) { should match /CONFIG_POSIX_MQUEUE=y/ } ## Optional Features: its(:stdout) { should match /CONFIG_USER_NS=y/ } its(:stdout) { should match /CONFIG_SECCOMP=y/ } its(:stdout) { should match /CONFIG_CGROUP_PIDS=y/ } its(:stdout) { should match /CONFIG_MEMCG_SWAP=y/ } its(:stdout) { should match /CONFIG_MEMCG_SWAP_ENABLED=y/ } #its(:stdout) { should match /CONFIG_MEMCG_KMEM=y/ } its(:stdout) { should match /CONFIG_BLK_CGROUP=y/ } its(:stdout) { should match /CONFIG_BLK_DEV_THROTTLING=y/ } its(:stdout) { should match /CONFIG_IOSCHED_CFQ=y/ } its(:stdout) { should match /CONFIG_CFQ_GROUP_IOSCHED=y/ } its(:stdout) { should match /CONFIG_CGROUP_PERF=y/ } #its(:stdout) { should match /CONFIG_CGROUP_HUGETLB=y/ } its(:stdout) { should match /CONFIG_NET_CLS_CGROUP=m/ } its(:stdout) { should match /CONFIG_CGROUP_NET_PRIO=y/ } its(:stdout) { should match /CONFIG_CFS_BANDWIDTH=y/ } its(:stdout) { should match /CONFIG_FAIR_GROUP_SCHED=y/ } its(:stdout) { should match /CONFIG_RT_GROUP_SCHED=y/ } its(:stdout) { should match /CONFIG_IP_VS=m/ } #its(:stdout) { should match /CONFIG_EXT3_FS=y/ } #its(:stdout) { should match /CONFIG_EXT3_FS_XATTR=y/ } #its(:stdout) { should match /CONFIG_EXT3_FS_POSIX_ACL=y/ } #its(:stdout) { should match /CONFIG_EXT3_FS_SECURITY=y/ } its(:stdout) { should match /CONFIG_EXT4_FS=y/ } its(:stdout) { should match /CONFIG_EXT4_FS_POSIX_ACL=y/ } its(:stdout) { should match /CONFIG_EXT4_FS_SECURITY=y/ } ## Network Drivers: its(:stdout) { should match /CONFIG_VXLAN=m/ } its(:stdout) { should match /CONFIG_XFRM_ALGO=y/ } its(:stdout) { should match /CONFIG_XFRM_USER=y/ } its(:stdout) { should match /CONFIG_IPVLAN=m/ } its(:stdout) { should match /CONFIG_MACVLAN=m/ } its(:stdout) { should match /CONFIG_DUMMY=m/ } ## Storage Drivers: #its(:stdout) { should match /CONFIG_AUFS_FS=m/ } its(:stdout) { should match /CONFIG_BTRFS_FS=m/ } its(:stdout) { should match /CONFIG_BLK_DEV_DM=m/ } its(:stdout) { should match /CONFIG_DM_THIN_PROVISIONING=m/ } its(:stdout) { should match /CONFIG_OVERLAY_FS=m/ } its(:exit_status) { should eq 0 } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/kernel_modules_spec.rb ================================================ Specinfra::Runner.run_command('modprobe snd_bcm2835') # describe kernel_module('snd_bcm2835') do # it { should be_loaded } # end ================================================ FILE: builder/test-integration/spec/hypriotos-image/openvswitch_spec.rb ================================================ Specinfra::Runner.run_command('modprobe openvswitch') Specinfra::Runner.run_command('modprobe vxlan') Specinfra::Runner.run_command('modprobe gre') describe kernel_module('openvswitch') do it { should be_loaded } end describe kernel_module('vxlan') do it { should be_loaded } end describe kernel_module('gre') do it { should be_loaded } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/raspberrypi-list_spec.rb ================================================ require 'spec_helper' # describe file('/etc/apt/sources.list.d/raspberrypi.list') do # it { should be_file } # it { should be_mode 644 } # it { should be_owned_by 'root' } # it { should contain 'deb http://archive.raspberrypi.org/debian/ jessie main' } # end ================================================ FILE: builder/test-integration/spec/hypriotos-image/serial_spec.rb ================================================ require 'spec_helper' describe file('/usr/local/bin/rpi-serial-console') do it { should be_file } it { should be_mode 755 } it { should be_owned_by 'root' } end ================================================ FILE: builder/test-integration/spec/hypriotos-image/udev_spec.rb ================================================ require 'spec_helper' describe file('/etc/udev/rules.d/99-com.rules') do it { should be_file } it { should be_mode 644 } it { should be_owned_by 'root' } end describe file('/etc/udev/rules.d/75-persistent-net-generator.rules') do it { should be_file } it { should be_mode 644 } it { should be_owned_by 'root' } end ================================================ FILE: builder/test-integration/spec/spec_helper.rb ================================================ require 'serverspec' require 'net/ssh' set :backend, :ssh host = ENV['BOARD'] unless host fail "No BOARD env with the target address given!" end port = ENV['PORT'] options = Net::SSH::Config.for(host) options[:user] ||= 'pirate' options[:password] ||= 'hypriot' if port options[:port] = port end set :host, options[:host_name] || host set :ssh_options, options