Add docker image for vagrant-libvirt (#1149)

Provide a docker image that supports execution of vagrant-libvirt
provided the host system has docker and libvirt installed. This can help
side step many of the library compatibility issues experienced by users
by providing an alternative way to run the latest code should their
distribution not have a natively packaged vagrant.
This commit is contained in:
Darragh Bailey
2020-10-03 17:16:00 +01:00
committed by GitHub
parent d7debb68c6
commit d4d82d9773
5 changed files with 346 additions and 48 deletions

2
.dockerignore Normal file
View File

@@ -0,0 +1,2 @@
Gemfile.Lock
pkg

82
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,82 @@
name: ci
on:
push:
branches:
- '**'
tags:
- 'v*'
pull_request:
jobs:
main:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Prepare
id: prep
run: |
DOCKER_IMAGE=vagrantlibvirt/vagrant-libvirt
VERSION=noop
if [ "${{ github.event_name }}" = "schedule" ]; then
VERSION=nightly
elif [[ $GITHUB_REF == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/}
elif [[ $GITHUB_REF == refs/heads/* ]]; then
VERSION=$(echo ${GITHUB_REF#refs/heads/} | sed -r 's#/+#-#g')
if [ "${{ github.event.repository.default_branch }}" = "$VERSION" ]; then
VERSION=edge
fi
elif [[ $GITHUB_REF == refs/pull/* ]]; then
VERSION=pr-${{ github.event.number }}
fi
TAGS="${DOCKER_IMAGE}:${VERSION}"
if [[ $VERSION =~ ^v[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
MINOR=${VERSION%.*}
MAJOR=${MINOR%.*}
TAGS="$TAGS,${DOCKER_IMAGE}:${MINOR},${DOCKER_IMAGE}:${MAJOR},${DOCKER_IMAGE}:latest"
elif [ "${{ github.event_name }}" = "push" ]; then
TAGS="$TAGS,${DOCKER_IMAGE}:sha-${GITHUB_SHA::8}"
fi
echo ::set-output name=version::${VERSION}
echo ::set-output name=tags::${TAGS}
echo ::set-output name=created::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
with:
driver-opts: image=moby/buildkit:master
-
name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
platforms: linux/amd64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.prep.outputs.tags }}
labels: |
org.opencontainers.image.title=${{ github.event.repository.name }}
org.opencontainers.image.description=${{ github.event.repository.description }}
org.opencontainers.image.url=${{ github.event.repository.html_url }}
org.opencontainers.image.source=${{ github.event.repository.clone_url }}
org.opencontainers.image.version=${{ steps.prep.outputs.version }}
org.opencontainers.image.created=${{ steps.prep.outputs.created }}
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.licenses=${{ github.event.repository.license.spdx_id }}
-
name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}

72
Dockerfile Normal file
View File

@@ -0,0 +1,72 @@
# syntax = docker/dockerfile:1.0-experimental
ARG VAGRANT_VERSION=2.2.10
FROM ubuntu:bionic as base
RUN apt update \
&& apt install -y --no-install-recommends \
bash \
ca-certificates \
curl \
git \
gosu \
kmod \
openssh-client \
libvirt-bin \
&& rm -rf /var/lib/apt/lists \
;
RUN mkdir /vagrant
ENV VAGRANT_HOME /vagrant
ARG VAGRANT_VERSION
ENV VAGRANT_VERSION ${VAGRANT_VERSION}
RUN set -e \
&& curl https://releases.hashicorp.com/vagrant/${VAGRANT_VERSION}/vagrant_${VAGRANT_VERSION}_x86_64.deb -o vagrant.deb \
&& apt update \
&& apt install -y ./vagrant.deb \
&& rm -rf /var/lib/apt/lists/* \
&& rm -f vagrant.deb \
;
FROM base as build
# allow caching of packages for build
RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
RUN sed -i '/deb-src/s/^# //' /etc/apt/sources.list
RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/apt \
apt update \
&& apt build-dep -y \
vagrant \
ruby-libvirt \
&& apt install -y --no-install-recommends \
libxslt-dev \
libxml2-dev \
libvirt-dev \
ruby-bundler \
ruby-dev \
zlib1g-dev \
;
WORKDIR /build
COPY . .
RUN rake build
RUN vagrant plugin install ./pkg/vagrant-libvirt*.gem
RUN for dir in boxes data tmp; \
do \
rm -rf /vagrant/${dir} && ln -s /.vagrant.d/${dir} /vagrant/${dir}; \
done \
;
FROM base as final
COPY --from=build /vagrant /vagrant
COPY entrypoint.sh /usr/local/bin/
ENTRYPOINT ["entrypoint.sh"]
# vim: set expandtab sw=4:

130
README.md
View File

@@ -16,54 +16,55 @@ can help a lot :-)
<!-- note in vim set "let g:vmt_list_item_char='-'" to generate the correct output -->
<!-- vim-markdown-toc GFM -->
- [Features](#features)
- [Future work](#future-work)
- [Installation](#installation)
- [Possible problems with plugin installation on Linux](#possible-problems-with-plugin-installation-on-linux)
- [Vagrant Project Preparation](#vagrant-project-preparation)
- [Add Box](#add-box)
- [Create Vagrantfile](#create-vagrantfile)
- [Start VM](#start-vm)
- [How Project Is Created](#how-project-is-created)
- [Libvirt Configuration](#libvirt-configuration)
- [Provider Options](#provider-options)
- [Domain Specific Options](#domain-specific-options)
- [Reload behavior](#reload-behavior)
- [Networks](#networks)
- [Private Network Options](#private-network-options)
- [Public Network Options](#public-network-options)
- [Management Network](#management-network)
- [Additional Disks](#additional-disks)
- [Reload behavior](#reload-behavior-1)
- [CDROMs](#cdroms)
- [Input](#input)
- [PCI device passthrough](#pci-device-passthrough)
- [Using USB Devices](#using-usb-devices)
- [USB Controller Configuration](#usb-controller-configuration)
- [USB Device Passthrough](#usb-device-passthrough)
- [USB Redirector Devices](#usb-redirector-devices)
- [Filter for USB Redirector Devices](#filter-for-usb-redirector-devices)
- [Random number generator passthrough](#random-number-generator-passthrough)
- [Watchdog device](#watchdog-device)
- [Smartcard device](#smartcard-device)
- [Hypervisor Features](#hypervisor-features)
- [CPU features](#cpu-features)
- [Memory Backing](#memory-backing)
- [No box and PXE boot](#no-box-and-pxe-boot)
- [SSH Access To VM](#ssh-access-to-vm)
- [Forwarded Ports](#forwarded-ports)
- [Synced Folders](#synced-folders)
- [QEMU Session Support](#qemu-session-support)
- [Customized Graphics](#customized-graphics)
- [TPM Devices](#tpm-devices)
- [Libvirt communication channels](#libvirt-communication-channels)
- [Custom command line arguments and environment variables](#custom-command-line-arguments-and-environment-variables)
- [Box Format](#box-format)
- [Create Box](#create-box)
- [Package Box from VM](#package-box-from-vm)
- [Troubleshooting VMs](#troubleshooting-vms)
- [Development](#development)
- [Contributing](#contributing)
* [Features](#features)
* [Future work](#future-work)
* [Using Docker based Installation](#using-docker-based-installation)
* [Installation](#installation)
* [Possible problems with plugin installation on Linux](#possible-problems-with-plugin-installation-on-linux)
* [Vagrant Project Preparation](#vagrant-project-preparation)
* [Add Box](#add-box)
* [Create Vagrantfile](#create-vagrantfile)
* [Start VM](#start-vm)
* [How Project Is Created](#how-project-is-created)
* [Libvirt Configuration](#libvirt-configuration)
* [Provider Options](#provider-options)
* [Domain Specific Options](#domain-specific-options)
* [Reload behavior](#reload-behavior)
* [Networks](#networks)
* [Private Network Options](#private-network-options)
* [Public Network Options](#public-network-options)
* [Management Network](#management-network)
* [Additional Disks](#additional-disks)
* [Reload behavior](#reload-behavior-1)
* [CDROMs](#cdroms)
* [Input](#input)
* [PCI device passthrough](#pci-device-passthrough)
* [Using USB Devices](#using-usb-devices)
* [USB Controller Configuration](#usb-controller-configuration)
* [USB Device Passthrough](#usb-device-passthrough)
* [USB Redirector Devices](#usb-redirector-devices)
* [Filter for USB Redirector Devices](#filter-for-usb-redirector-devices)
* [Random number generator passthrough](#random-number-generator-passthrough)
* [Watchdog device](#watchdog-device)
* [Smartcard device](#smartcard-device)
* [Hypervisor Features](#hypervisor-features)
* [CPU features](#cpu-features)
* [Memory Backing](#memory-backing)
* [No box and PXE boot](#no-box-and-pxe-boot)
* [SSH Access To VM](#ssh-access-to-vm)
* [Forwarded Ports](#forwarded-ports)
* [Synced Folders](#synced-folders)
* [QEMU Session Support](#qemu-session-support)
* [Customized Graphics](#customized-graphics)
* [TPM Devices](#tpm-devices)
* [Libvirt communication channels](#libvirt-communication-channels)
* [Custom command line arguments and environment variables](#custom-command-line-arguments-and-environment-variables)
* [Box Format](#box-format)
* [Create Box](#create-box)
* [Package Box from VM](#package-box-from-vm)
* [Troubleshooting VMs](#troubleshooting-vms)
* [Development](#development)
* [Contributing](#contributing)
<!-- vim-markdown-toc -->
@@ -92,6 +93,39 @@ can help a lot :-)
* Take a look at [open
issues](https://github.com/vagrant-libvirt/vagrant-libvirt/issues?state=open).
## Using Docker based Installation
Due to the number of issues encountered around compatibility between the ruby runtime environment
that is part of the upstream vagrant installation and the library dependencies of libvirt that
this project requires to communicate with libvirt, there is a docker image build and published.
This should allow users to execute vagrant with vagrant-libvirt without needing to deal with
the compatibility issues, though you may need to extend the image for your own needs should
you make use of additional plugins.
To get the image:
```bash
docker pull vagrantlibvirt/vagrant-libvirt:latest
```
Running the image:
```bash
docker run -it -rm \
-e LIBVIRT_DEFAULT_URI \
-v /var/run/libvirt/:/var/run/libvirt/ \
-v ~/.vagrant.d:/.vagrant.d \
-v $(pwd):$(pwd) \
-w $(pwd) \
vagrantlibvirt/vagrant-libvirt:latest \
vagrant status
```
Note that if you are connecting to a remote system libvirt, you may omit the
`-v /var/run/libvirt/:/var/run/libvirt/` mount bind. Some distributions patch the local
vagrant environment to ensure vagrant-libvirt uses `qemu:///session`, which means you
may need to set the environment variable `LIBVIRT_DEFAULT_URI` to the same value if
looking to use this in place of your distribution provided installation.
## Installation
First, you should have both QEMU and Libvirt installed if you plan to run VMs

108
entrypoint.sh Executable file
View File

@@ -0,0 +1,108 @@
#!/bin/bash
set -u -o pipefail
vdir="/.vagrant.d"
if [[ ! -d ${vdir} ]]
then
echo "Require the user ~/.vagrant.d to be bind mounted at ${vdir}"
echo
echo "Typically use '-v ~/.vagrant.d:${vdir}' with the docker run command."
exit 2
fi
vdir_mnt=$(stat -c %m ${vdir})
case "${vdir_mnt%%/}" in
/*)
# user mounted vagrant home is not mounted on /, so
# presumably it is a mount bind or mounted volume and should
# be able to determine suitable uid/gid
;;
*)
echo "${vdir} is not set to a bind mounted volume, will not be able"
echo "to automatically determine suitable uid/gid to execute under."
if [[ -z "${USER_UID:-}" ]] || [[ -z "${USER_GID:-}" ]]
then
echo "USER_UID and USER_GID must be explicitly provided when"
echo "auto-detection is unable to be used"
exit 2
fi
;;
esac
USER_UID=${USER_UID:-$(stat -c %u ${vdir})} || exit 3
USER_GID=${USER_GID:-$(stat -c %g ${vdir})} || exit 3
if [[ ${USER_UID} -eq 0 ]] && [[ -z "${IGNORE_RUN_AS_ROOT:-}" ]]
then
echo "WARNING! Running as root, if this breaks, you get to keep both pieces"
fi
export USER=vagrant
export GROUP=users
export HOME=/home/${USER}
echo "Starting with UID: ${USER_UID}, GID: ${USER_GID}"
if [[ "${USER_GID}" != "0" ]]
then
if getent group ${GROUP} > /dev/null
then
GROUPCMD=groupmod
else
GROUPCMD=groupadd
fi
${GROUPCMD} -g ${USER_GID} ${GROUP} >/dev/null || exit 3
fi
if [[ "${USER_UID}" != "0" ]]
then
if getent passwd ${USER} > /dev/null
then
USERCMD=usermod
else
USERCMD=useradd
fi
${USERCMD} --shell /bin/bash -u ${USER_UID} -g ${USER_GID} -o -c "" -m ${USER} >/dev/null 2>&1 || exit 3
fi
# make sure the directories can be written to by vagrant otherwise will
# get a start up error
find ${VAGRANT_HOME} -maxdepth 1 ! -exec chown -h ${USER}:${GROUP} {} \+
LIBVIRT_SOCK=/var/run/libvirt/libvirt-sock
if [[ ! -S ${LIBVIRT_SOCK} ]]
then
if [[ -z "${IGNORE_MISSING_LIBVIRT_SOCK:-}" ]]
then
echo "Unless you are using this to connect to a remote libvirtd it is"
echo "necessary to mount the libvirt socket in as ${LIBVIRT_SOCK}"
echo
echo "Set IGNORE_MISSING_LIBVIRT_SOCK to silence this warning"
fi
else
LIBVIRT_GID=$(stat -c %g ${LIBVIRT_SOCK})
# only do this if the host uses a non-root group for libvirt
if [[ ${LIBVIRT_GID} -ne 0 ]]
then
if getent group libvirt >/dev/null
then
GROUPCMD=groupmod
else
GROUPCMD=groupadd
fi
${GROUPCMD} -g ${LIBVIRT_GID} libvirt >/dev/null || exit 3
usermod -a -G libvirt ${USER} || exit 3
fi
fi
if [[ $# -eq 0 ]]
then
# if no command provided
exec gosu ${USER} vagrant help
fi
exec gosu ${USER} $*