Migrate documentation to github pages (#1523)

Switch from having all documentation contained within the README to
publishing a jekyll static site of documentation under github pages.

This allows for configuration and installation guides to be handled
separately to make for the relevant pieces to be in smaller chunks and
therefore easier to follow for users. Additionally a table of contents
can now be included in a left navigation section that ensures it should
be possible to quickly jump from the start to any section and back
again.

Include support for publishing previews and releases under separate
directories to allow for them to exist at the same time as the other
latest version of the documents.

The navigation section also includes support for accessing any of the
other versions published so that it easier to see what configuration
options exist for a given release. These will be published automatically
when releases are added.
This commit is contained in:
Darragh Bailey 2022-07-19 14:48:02 +01:00 committed by GitHub
parent 206a9244a8
commit 82202945ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 3353 additions and 2072 deletions

View File

@ -0,0 +1,25 @@
name: Deploy Docs Preview Requires Label
on:
pull_request_target:
types:
- opened
- reopened
- synchronized
paths:
- 'docs/**'
permissions:
pull-requests: write
jobs:
notify-label-required:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'preview-docs') }}
runs-on: ubuntu-latest
steps:
- name: Comment on label required for docs preview deploy
uses: marocchino/sticky-pull-request-comment@v2
with:
recreate: true
header: notify-label-required
message: |-
Maintainers: This PR updates the documentation, please review and apply
the label 'preview-docs' if satisfied it is safe to publish.

View File

@ -0,0 +1,72 @@
name: Deploy Docs Preview
on:
pull_request_target:
types:
- closed
- labeled
paths:
- 'docs/**'
permissions:
contents: write
pull-requests: write
jobs:
build-and-deploy:
if: ${{ github.event.action == 'closed' || (github.event.action == 'labeled' && github.event.label.name == 'preview-docs') }}
concurrency: publish-gh-pages
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Set up Ruby
if: ${{ github.event.action == 'labeled' }}
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6
- name: Install and Build 🔧
# don't allow a close to execute anything from the source code
if: ${{ github.event.action == 'labeled' }}
run: |
PR_NUMBER=$(jq -r ".number" "$GITHUB_EVENT_PATH")
REPO_NAME=$(jq -r ".repository.name" "$GITHUB_EVENT_PATH")
# TODO find a way for jekyll to perform this automatically
convert docs/_assets/images/logo.png -define icon:auto-resize=256,64,48,32,16 docs/favicon.ico
# avoid look up of API as it doesn't work from within actions without exposing the GITHUB_TOKEN here which is a security risk
cat <<EOF >> docs/_config.yml
repository_nwo: vagrant-libvirt/vagrant-libvirt
EOF
BUNDLE_GEMFILE=./docs/Gemfile bundle install
BUNDLE_GEMFILE=./docs/Gemfile bundle exec jekyll build --source docs/ --baseurl="/${REPO_NAME}/pr-preview/pr-${PR_NUMBER}" --destination build
- name: Set action
run: |
event_type=$(jq -r ".action" "$GITHUB_EVENT_PATH")
echo "event_type is $event_type"
case $event_type in
"labeled")
echo "action=deploy" >> "$GITHUB_ENV"
;;
"closed")
echo "action=remove" >> "$GITHUB_ENV"
;;
*)
echo "unknown event type $event_type; no action to take"
echo "action=none" >> "$GITHUB_ENV"
;;
esac
- name: Deploy preview
uses: rossjrw/pr-preview-action@v1
with:
source-dir: ./build/
preview-branch: gh-pages
umbrella-dir: pr-preview
- name: Remove label
uses: actions-ecosystem/action-remove-labels@v1
if: ${{ always() }}
with:
labels: preview-docs

View File

@ -0,0 +1,46 @@
name: Deploy Docs Release
on:
push:
tags:
- '*.*.*'
permissions:
contents: write
jobs:
build-and-deploy:
concurrency: ci-${{ github.ref }}
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6
- name: Install and Build 🔧
run: |
VERSION={{ github.ref_name }}
REPO_NAME=$(jq -r ".repository.name" "$GITHUB_EVENT_PATH")
# TODO find a way for jekyll to perform this automatically
convert docs/_assets/images/logo.png -define icon:auto-resize=256,64,48,32,16 docs/favicon.ico
# avoid look up of API as it doesn't work from within actions without exposing the GITHUB_TOKEN here which is a security risk
cat <<EOF >> docs/_config.yml
repository_nwo: vagrant-libvirt/vagrant-libvirt
EOF
BUNDLE_GEMFILE=./docs/Gemfile bundle install
BUNDLE_GEMFILE=./docs/Gemfile bundle exec jekyll build --source docs/ --baseurl="/${REPO_NAME}/version/${VERSION}" --destination build
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@v4.3.3
with:
branch: gh-pages
folder: build
clean: true
force: false
target-folder: version/{{ github.ref_name }}
clean-exclude: |
pr-preview/
version/

View File

@ -0,0 +1,43 @@
name: Deploy Docs
on:
push:
branches:
- main
paths:
- 'docs/**'
permissions:
contents: write
jobs:
build-and-deploy:
concurrency: ci-${{ github.ref }}
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6
- name: Install and Build 🔧
run: |
# TODO find a way for jekyll to perform this automatically
convert docs/_assets/images/logo.png -define icon:auto-resize=256,64,48,32,16 docs/favicon.ico
# avoid look up of API as it doesn't work from within actions without exposing the GITHUB_TOKEN here which is a security risk
cat <<EOF >> docs/_config.yml
repository_nwo: vagrant-libvirt/vagrant-libvirt
EOF
BUNDLE_GEMFILE=./docs/Gemfile bundle install
BUNDLE_GEMFILE=./docs/Gemfile bundle exec jekyll build --source docs/ --destination build
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@v4.3.3
with:
branch: gh-pages
folder: build
clean: true
clean-exclude: |
pr-preview/
version/

1
.gitignore vendored
View File

@ -20,6 +20,7 @@ tmp
.vagrant
*.swp
.deps
docs/favicon.ico
# don't commit the generated version
lib/vagrant-libvirt/version

2102
README.md

File diff suppressed because it is too large Load Diff

5
docs/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
_site
.sass-cache
.jekyll-cache
.jekyll-metadata
vendor

25
docs/404.html Normal file
View File

@ -0,0 +1,25 @@
---
permalink: /404.html
layout: default
---
<style type="text/css" media="screen">
.container {
margin: 10px auto;
max-width: 600px;
text-align: center;
}
h1 {
margin: 30px 0;
font-size: 4em;
line-height: 1;
letter-spacing: -1px;
}
</style>
<div class="container">
<h1>404</h1>
<p><strong>Page not found :(</strong></p>
<p>The requested page could not be found.</p>
</div>

34
docs/Gemfile Normal file
View File

@ -0,0 +1,34 @@
source "https://rubygems.org"
# Hello! This is where you manage which Jekyll version is used to run.
# When you want to use a different version, change it below, save the
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
#
# bundle exec jekyll serve
#
# This will help ensure the proper Jekyll version is running.
# Happy Jekylling!
gem "github-pages", "~> 226", group: :jekyll_plugins
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
# gem "github-pages", group: :jekyll_plugins
# If you have any plugins, put them here!
group :jekyll_plugins do
gem "jekyll-assets", "~> 3.0.12"
gem "jekyll-feed", "~> 0.12"
gem "jekyll-toc", "~> 0.17"
end
# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
# and associated library.
platforms :mingw, :x64_mingw, :mswin, :jruby do
gem "tzinfo", "~> 1.2"
gem "tzinfo-data"
end
# Performance-booster for watching directories on Windows
gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin]
gem "sprockets", "~> 3.7.2"
# Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem
# do not have a Java counterpart.
gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby]

296
docs/Gemfile.lock Normal file
View File

@ -0,0 +1,296 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (5.2.8)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.11.1)
colorator (1.1.0)
commonmarker (0.23.5)
concurrent-ruby (1.1.10)
dnsruby (1.61.9)
simpleidn (~> 0.1)
em-websocket (0.5.3)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
ethon (0.15.0)
ffi (>= 1.15.0)
eventmachine (1.2.7)
execjs (2.8.1)
extras (0.3.0)
forwardable-extended (~> 2.5)
faraday (2.3.0)
faraday-net_http (~> 2.0)
ruby2_keywords (>= 0.0.4)
faraday-net_http (2.0.3)
fastimage (2.2.6)
ffi (1.15.5)
forwardable-extended (2.6.0)
gemoji (3.0.1)
github-pages (226)
github-pages-health-check (= 1.17.9)
jekyll (= 3.9.2)
jekyll-avatar (= 0.7.0)
jekyll-coffeescript (= 1.1.1)
jekyll-commonmark-ghpages (= 0.2.0)
jekyll-default-layout (= 0.1.4)
jekyll-feed (= 0.15.1)
jekyll-gist (= 1.5.0)
jekyll-github-metadata (= 2.13.0)
jekyll-include-cache (= 0.2.1)
jekyll-mentions (= 1.6.0)
jekyll-optional-front-matter (= 0.3.2)
jekyll-paginate (= 1.1.0)
jekyll-readme-index (= 0.3.0)
jekyll-redirect-from (= 0.16.0)
jekyll-relative-links (= 0.6.1)
jekyll-remote-theme (= 0.4.3)
jekyll-sass-converter (= 1.5.2)
jekyll-seo-tag (= 2.8.0)
jekyll-sitemap (= 1.4.0)
jekyll-swiss (= 1.0.0)
jekyll-theme-architect (= 0.2.0)
jekyll-theme-cayman (= 0.2.0)
jekyll-theme-dinky (= 0.2.0)
jekyll-theme-hacker (= 0.2.0)
jekyll-theme-leap-day (= 0.2.0)
jekyll-theme-merlot (= 0.2.0)
jekyll-theme-midnight (= 0.2.0)
jekyll-theme-minimal (= 0.2.0)
jekyll-theme-modernist (= 0.2.0)
jekyll-theme-primer (= 0.6.0)
jekyll-theme-slate (= 0.2.0)
jekyll-theme-tactile (= 0.2.0)
jekyll-theme-time-machine (= 0.2.0)
jekyll-titles-from-headings (= 0.5.3)
jemoji (= 0.12.0)
kramdown (= 2.3.2)
kramdown-parser-gfm (= 1.1.0)
liquid (= 4.0.3)
mercenary (~> 0.3)
minima (= 2.5.1)
nokogiri (>= 1.13.4, < 2.0)
rouge (= 3.26.0)
terminal-table (~> 1.4)
github-pages-health-check (1.17.9)
addressable (~> 2.3)
dnsruby (~> 1.60)
octokit (~> 4.0)
public_suffix (>= 3.0, < 5.0)
typhoeus (~> 1.3)
html-pipeline (2.14.2)
activesupport (>= 2)
nokogiri (>= 1.4)
http_parser.rb (0.8.0)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
jekyll (3.9.2)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (~> 0.7)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 2.0)
kramdown (>= 1.17, < 3)
liquid (~> 4.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (>= 1.7, < 4)
safe_yaml (~> 1.0)
jekyll-assets (3.0.12)
activesupport (~> 5.0)
execjs (~> 2.7)
extras (~> 0.2)
fastimage (~> 2.0, >= 1.8)
jekyll (>= 3.5, < 4.0)
jekyll-sanity (~> 1.2)
liquid-tag-parser (~> 1.0)
nokogiri (~> 1.8)
pathutil (~> 0.16)
sprockets (>= 3.3, < 4.1.beta)
jekyll-avatar (0.7.0)
jekyll (>= 3.0, < 5.0)
jekyll-coffeescript (1.1.1)
coffee-script (~> 2.2)
coffee-script-source (~> 1.11.1)
jekyll-commonmark (1.4.0)
commonmarker (~> 0.22)
jekyll-commonmark-ghpages (0.2.0)
commonmarker (~> 0.23.4)
jekyll (~> 3.9.0)
jekyll-commonmark (~> 1.4.0)
rouge (>= 2.0, < 4.0)
jekyll-default-layout (0.1.4)
jekyll (~> 3.0)
jekyll-feed (0.15.1)
jekyll (>= 3.7, < 5.0)
jekyll-gist (1.5.0)
octokit (~> 4.2)
jekyll-github-metadata (2.13.0)
jekyll (>= 3.4, < 5.0)
octokit (~> 4.0, != 4.4.0)
jekyll-include-cache (0.2.1)
jekyll (>= 3.7, < 5.0)
jekyll-mentions (1.6.0)
html-pipeline (~> 2.3)
jekyll (>= 3.7, < 5.0)
jekyll-optional-front-matter (0.3.2)
jekyll (>= 3.0, < 5.0)
jekyll-paginate (1.1.0)
jekyll-readme-index (0.3.0)
jekyll (>= 3.0, < 5.0)
jekyll-redirect-from (0.16.0)
jekyll (>= 3.3, < 5.0)
jekyll-relative-links (0.6.1)
jekyll (>= 3.3, < 5.0)
jekyll-remote-theme (0.4.3)
addressable (~> 2.0)
jekyll (>= 3.5, < 5.0)
jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0)
rubyzip (>= 1.3.0, < 3.0)
jekyll-sanity (1.6.0)
jekyll (>= 3.1, < 5.0)
pathutil (~> 0.16)
jekyll-sass-converter (1.5.2)
sass (~> 3.4)
jekyll-seo-tag (2.8.0)
jekyll (>= 3.8, < 5.0)
jekyll-sitemap (1.4.0)
jekyll (>= 3.7, < 5.0)
jekyll-swiss (1.0.0)
jekyll-theme-architect (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-cayman (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-dinky (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-hacker (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-leap-day (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-merlot (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-midnight (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-minimal (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-modernist (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-primer (0.6.0)
jekyll (> 3.5, < 5.0)
jekyll-github-metadata (~> 2.9)
jekyll-seo-tag (~> 2.0)
jekyll-theme-slate (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-tactile (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-time-machine (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-titles-from-headings (0.5.3)
jekyll (>= 3.3, < 5.0)
jekyll-toc (0.17.1)
jekyll (>= 3.9)
nokogiri (~> 1.11)
jekyll-watch (2.2.1)
listen (~> 3.0)
jemoji (0.12.0)
gemoji (~> 3.0)
html-pipeline (~> 2.2)
jekyll (>= 3.0, < 5.0)
kramdown (2.3.2)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.3)
liquid-tag-parser (1.9.0)
extras (~> 0.3)
liquid (>= 3.0, < 5.0)
listen (3.7.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.3.6)
mini_portile2 (2.8.0)
minima (2.5.1)
jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
minitest (5.16.1)
nokogiri (1.13.6)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
octokit (4.25.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (4.0.7)
racc (1.6.0)
rack (2.2.4)
rb-fsevent (0.11.1)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.2.5)
rouge (3.26.0)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
safe_yaml (1.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sawyer (0.9.2)
addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3)
simpleidn (0.2.1)
unf (~> 0.1.4)
sprockets (3.7.2)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thread_safe (0.3.6)
typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (1.2.9)
thread_safe (~> 0.1)
unf (0.1.4)
unf_ext
unf_ext (0.0.8.2)
unicode-display_width (1.8.0)
PLATFORMS
ruby
DEPENDENCIES
github-pages (~> 226)
http_parser.rb (~> 0.6.0)
jekyll-assets (~> 3.0.12)
jekyll-feed (~> 0.12)
jekyll-toc (~> 0.17)
sprockets (~> 3.7.2)
tzinfo (~> 1.2)
tzinfo-data
wdm (~> 0.1.1)
BUNDLED WITH
1.17.3

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

@ -0,0 +1,81 @@
changeVersion = function handleVersionedDocs() {
{%- comment %}handle development serving site on root{% endcomment %}
{%- if site.baseurl.size == 0 %}
const basePath = '';
{%- else %}
const basePath = '/{{ site.github.repository_name }}';
{%- endif %}
async function loadOptions(select) {
const defaultBranchPromise = axios.get(
'https://api.github.com/repos/{{ site.repository_nwo or site.github.repository_nwo }}',
).then(res => {
return res.data.default_branch;
});
const versionDir = await axios.get(
'https://api.github.com/repos/{{ site.repository_nwo or site.github.repository_nwo }}/git/trees/gh-pages',
).then(res => {
return res.data.tree.find(t => {
return t.path.toLowerCase() === 'version';
});
}).catch(e => {
if (e.response.status == "404") {
return null;
}
throw(e);
});
if (versionDir === undefined || versionDir === null) {
var options = [];
} else {
res = await axios.get(versionDir.url);
var options = res.data.tree.map(t => {
return {value: t.path, text: t.path};
});
};
options = options.sort( (a, b) => b.value.localeCompare(a.value, undefined, { numeric:true }) );
const defaultBranch = await defaultBranchPromise;
options.unshift({ value: 'latest', text: defaultBranch });
options.forEach( item => {
var opt = document.createElement('option');
opt.value = item.value;
opt.innerHTML = item.text;
select.appendChild(opt);
});
const path = window.location.pathname.toLowerCase();
const versionPath = `${basePath}/version/`;
if (path.startsWith(versionPath)) {
const start = versionPath.length;
const end = path.indexOf('/', start);
select.value = path.substring(start, end);
} else {
select.value = 'latest';
}
};
function changeVersion(selectElement) {
const targetVersionPath =
selectElement.value === 'latest' ? '' : `/version/${selectElement.value}`;
const path = window.location.pathname.toLowerCase();
const versionPath = `${basePath}/version/`;
const startIdx = path.startsWith(`${basePath}/version/`) ? versionPath.length : basePath.length;
const endIdx = path.indexOf('/', startIdx);
const targetPath =
basePath + targetVersionPath + window.location.pathname.substring(endIdx);
window.location.pathname = targetPath;
};
loadOptions(document.getElementById("docs-version"));
return changeVersion;
}();

85
docs/_config.yml Normal file
View File

@ -0,0 +1,85 @@
# Welcome to Jekyll!
#
# This config file is meant for settings that affect your whole blog, values
# which you are expected to set up once and rarely edit after that. If you find
# yourself editing this file very often, consider using Jekyll's data files
# feature for the data you need to update frequently.
#
# For technical reasons, this file is *NOT* reloaded automatically when you use
# 'bundle exec jekyll serve'. If you change this file, please restart the server process.
#
# If you need help with YAML syntax, here are some quick references for you:
# https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml
# https://learnxinyminutes.com/docs/yaml/
#
# Site settings
# These are used to personalize your new site. If you look in the HTML files,
# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
# You can create any custom variable you would like, and they will be accessible
# in the templates via {{ site.myvariable }}.
title: Vagrant Libvirt Documentation
description: >- # this means to ignore newlines until "baseurl:"
Create and manage Vagrant machines using Libvirt/QEMU
baseurl: "/vagrant-libvirt" # the subpath of your site, e.g. /blog
url: "https://vagrant-libvirt.github.io" # the base hostname & protocol for your site, e.g. http://example.com
logo: "/assets/images/logo.png"
# Footer last edited timestamp
last_edit_timestamp: true # show or hide edit time - page must have `last_modified_date` defined in the frontmatter
last_edit_time_format: "%b %e %Y at %I:%M %p" # uses ruby's time format: https://ruby-doc.org/stdlib-2.7.0/libdoc/time/rdoc/Time.html
# Footer "Edit this page on GitHub" link text
gh_edit_link: true # show or hide edit this page link
gh_edit_link_text: "Edit this page on GitHub"
gh_edit_repository: "https://github.com/vagrant-libvirt/vagrant-libvirt" # the github URL for your repo
gh_edit_branch: "main" # the branch that your docs is served from
# gh_edit_source: docs # the source that your files originate from
gh_edit_view_mode: "tree" # "tree" or "edit" if you want the user to jump into the editor immediately
# default theme is empty to skip using the default style sheet and instead load both light
# and dark using media queries to select based on whether the user prefers light or dark mode.
#color_scheme: "default"
# Build settings
remote_theme: just-the-docs/just-the-docs@v0.3.3
#theme: just-the-docs
plugins:
- jekyll-assets
- jekyll-feed
- jekyll-remote-theme
- jekyll-toc
assets:
raw_precompile: [
"images/logo.png",
]
sources:
- _assets
toc:
max_level: 3
# Exclude from processing.
# The following items will not be processed, by default.
# Any item listed under the `exclude:` key here will be automatically added to
# the internal "default list".
#
# Excluded items can be processed by explicitly listing the directories or
# their entries' file path in the `include:` list.
#
# exclude:
# - .sass-cache/
# - .jekyll-cache/
# - gemfiles/
# - Gemfile
# - Gemfile.lock
# - node_modules/
# - vendor/bundle/
# - vendor/cache/
# - vendor/gems/
# - vendor/ruby/
keep_files:
- .nojekyll
- .git
- favicon.ico

View File

@ -0,0 +1,3 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.27.2/axios.min.js"></script>
<link rel="stylesheet" href="{{ '/assets/css/just-the-docs-light.css' | relative_url }}" media="(prefers-color-scheme: light)">
<link rel="stylesheet" href="{{ '/assets/css/just-the-docs-dark.css' | relative_url }}" media="(prefers-color-scheme: dark)">

View File

@ -0,0 +1,6 @@
<div class="site-footer">
Plugin Version:
<select id="docs-version" onChange="changeVersion(this)">
</select>
</div>
<script src="{% asset "js/version_switcher.js" @path %}"></script>

111
docs/_includes/nav.html Normal file
View File

@ -0,0 +1,111 @@
{%- comment -%}
Original taken from https://github.com/just-the-docs/just-the-docs/blob/10388ed8b09eeae132a56c2b931e642b5ae2719d/_includes/nav.html
{%- endcomment -%}
<ul class="nav-list">
{%- assign titled_pages = include.pages
| where_exp:"item", "item.title != nil" -%}
{%- comment -%}
The values of `title` and `nav_order` can be numbers or strings.
Jekyll gives build failures when sorting on mixtures of different types,
so numbers and strings need to be sorted separately.
Here, numbers are sorted by their values, and come before all strings.
An omitted `nav_order` value is equivalent to the page's `title` value
(except that a numerical `title` value is treated as a string).
The case-sensitivity of string sorting is determined by `site.nav_sort`.
{%- endcomment -%}
{%- assign string_ordered_pages = titled_pages
| where_exp:"item", "item.nav_order == nil" -%}
{%- assign nav_ordered_pages = titled_pages
| where_exp:"item", "item.nav_order != nil" -%}
{%- comment -%}
The nav_ordered_pages have to be added to number_ordered_pages and
string_ordered_pages, depending on the nav_order value.
The first character of the jsonify result is `"` only for strings.
{%- endcomment -%}
{%- assign nav_ordered_groups = nav_ordered_pages
| group_by_exp:"item", "item.nav_order | jsonify | slice: 0" -%}
{%- assign number_ordered_pages = "" | split:"X" -%}
{%- for group in nav_ordered_groups -%}
{%- if group.name == '"' -%}
{%- assign string_ordered_pages = string_ordered_pages | concat: group.items -%}
{%- else -%}
{%- assign number_ordered_pages = number_ordered_pages | concat: group.items -%}
{%- endif -%}
{%- endfor -%}
{%- assign sorted_number_ordered_pages = number_ordered_pages | sort:"nav_order" -%}
{%- comment -%}
The string_ordered_pages have to be sorted by nav_order, and otherwise title
(where appending the empty string to a numeric title converts it to a string).
After grouping them by those values, the groups are sorted, then the items
of each group are concatenated.
{%- endcomment -%}
{%- assign string_ordered_groups = string_ordered_pages
| group_by_exp:"item", "item.nav_order | default: item.title | append:''" -%}
{%- if site.nav_sort == 'case_insensitive' -%}
{%- assign sorted_string_ordered_groups = string_ordered_groups | sort_natural:"name" -%}
{%- else -%}
{%- assign sorted_string_ordered_groups = string_ordered_groups | sort:"name" -%}
{%- endif -%}
{%- assign sorted_string_ordered_pages = "" | split:"X" -%}
{%- for group in sorted_string_ordered_groups -%}
{%- assign sorted_string_ordered_pages = sorted_string_ordered_pages | concat: group.items -%}
{%- endfor -%}
{%- assign pages_list = sorted_number_ordered_pages | concat: sorted_string_ordered_pages -%}
{%- for node in pages_list -%}
{%- if node.parent == nil -%}
{%- unless node.nav_exclude -%}
<li class="nav-list-item{% if page.url == node.url or page.parent == node.title or page.grand_parent == node.title %} active{% endif %}">
{%- if node.has_children -%}
<a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a>
{%- endif -%}
<a href="{{ node.url | absolute_url }}" class="nav-list-link{% if page.url == node.url %} active{% endif %}">{{ node.title }}</a>
{% if page.url == node.url %}
{{ content | toc_only }}
{% endif %}
{%- if node.has_children -%}
{%- assign children_list = pages_list | where: "parent", node.title -%}
<ul class="nav-list ">
{%- for child in children_list -%}
{%- unless child.nav_exclude -%}
<li class="nav-list-item {% if page.url == child.url or page.parent == child.title %} active{% endif %}">
{%- if child.has_children -%}
<a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a>
{%- endif -%}
<a href="{{ child.url | absolute_url }}" class="nav-list-link{% if page.url == child.url %} active{% endif %}">{{ child.title }}</a>
{% if page.url == child.url %}
{{ content | toc_only }}
{% endif %}
{%- if child.has_children -%}
{%- assign grand_children_list = pages_list | where: "parent", child.title | where: "grand_parent", node.title -%}
<ul class="nav-list">
{%- for grand_child in grand_children_list -%}
{%- unless grand_child.nav_exclude -%}
<li class="nav-list-item {% if page.url == grand_child.url %} active{% endif %}">
<a href="{{ grand_child.url | absolute_url }}" class="nav-list-link{% if page.url == grand_child.url %} active{% endif %}">{{ grand_child.title }}</a>
{% if page.url == grand_child.url %}
{{ content | toc_only }}
{% endif %}
</li>
{%- endunless -%}
{%- endfor -%}
</ul>
{%- endif -%}
</li>
{%- endunless -%}
{%- endfor -%}
</ul>
{%- endif -%}
</li>
{%- endunless -%}
{%- endif -%}
{%- endfor -%}
</ul>

View File

@ -0,0 +1,97 @@
libssh issue:
```
/opt/vagrant/embedded/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require': /opt/vagrant/embedded/lib64/libcrypto.so.1.1: version `OPENSSL_1_1_1b' not found (required by /lib64/libssh.so.4) - /home/xxx/.vagrant.d/gems/2.4.6/gems/ruby-libvirt-0.7.1/lib/_libvirt.so (LoadError)
```
Solution identified thanks to James Reynolds (see [https://github.com/hashicorp/vagrant/issues/11020#issuecomment-540043472](https://github.com/hashicorp/vagrant/issues/11020#issuecomment-540043472)).
libk5crypto issue:
```
/opt/vagrant/embedded/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require': /usr/lib64/libk5crypto.so.3: undefined symbol: EVP_KDF_ctrl, version OPENSSL_1_1_1b - /home/rbelgrave/.vagrant.d/gems/2.4.9/gems/ruby-libvirt-0.7.1/lib/_libvirt.so (LoadError)
```
Solution identified thanks to Marco Bevc (see [https://github.com/hashicorp/vagrant/issues/11020#issuecomment-625801983](https://github.com/hashicorp/vagrant/issues/11020#issuecomment-625801983)).
Compile libraries to replaced those bundled with Vagrant to allow linking ruby-libvirt against
vagrant's embedded ruby and the system libvirt (updated originals to be generic):
```bash
mkdir patches
pushd patches
{%- if include.distro == "centos" or include.distro == "rhel" %}
[[ ! -d centos-git-common ]] && git clone https://git.centos.org/centos-git-common
export PATH=$(readlink -f ./centos-git-common):$PATH
chmod a+x ./centos-git-common/*.sh
git clone https://git.centos.org/rpms/libssh
{%- else %}
mkdir libssh
{%- endif %}
pushd libssh
nvr=$(rpm -q --queryformat "libssh-%{version}-%{release}" libssh)
nv=$(rpm -q --queryformat "libssh-%{version}" libssh)
{%- if include.distro == "fedora" %}
dnf download --source libssh
rpm2cpio ${nvr}.src.rpm | cpio -imdV
rm -rf ${nv}
tar xf ${nv}.tar.*z
{%- elsif include.distro == "centos" %}
git checkout $(git tag -l | grep "${nvr}\$" | tail -n1)
into_srpm.sh -d c8s
pushd BUILD
tar xf ../SOURCES/${nv}.tar.*z
{%- elsif include.distro == "opensuse" %}
{%- else %}
*******Missing the correct distro for patch commands********
{%- endif %}
mkdir libssh-build
pushd libssh-build
cmake ../${nv} -DOPENSSL_ROOT_DIR=/opt/vagrant/embedded/
make
sudo cp lib/libssh* /opt/vagrant/embedded/lib64
popd
popd
{%- if include.distro == "centos" %}
popd
{%- endif %}
{%- if include.distro == "centos" or include.distro == "rhel" %}
git clone https://git.centos.org/rpms/krb5
{%- else %}
mkdir krb5
{%- endif %}
pushd krb5
nvr=$(rpm -q --queryformat "krb5-%{version}-%{release}" krb5-libs)
nv=$(rpm -q --queryformat "krb5-%{version}" krb5-libs)
{%- if include.distro == "fedora" %}
dnf download --source krb5-libs
rpm2cpio ${nvr}.src.rpm | cpio -imdV
tar xf ${nv}.tar.*z
{%- elsif include.distro == "centos" %}
git checkout $(git tag -l | grep "${nvr}\$" | tail -n1)
into_srpm.sh -d c8s
pushd BUILD
tar xf ../SOURCES/${nv}.tar.*z
{%- elsif include.distro == "opensuse" %}
{%- else %}
*******Missing the correct distro for patch commands********
{%- endif %}
pushd ${nv}/src
./configure
make
sudo cp -P lib/crypto/libk5crypto.* /opt/vagrant/embedded/lib64/
popd
popd
{%- if include.distro == "centos" %}
popd
{%- endif %}
popd
```

View File

@ -0,0 +1,4 @@
{% if site.logo %}
<div class="site-logo"></div>
{% endif %}
{{ site.title }}

View File

@ -0,0 +1,42 @@
* Upstream Vagrant Install<br />
Download and execute the vagrant-libvirt-qa install script (installs latest vagrant by default):
```shell
curl -O https://github.com/vagrant-libvirt/vagrant-libvirt-qa/blob/main/scripts/install.bash
chmod a+x ./install.bash
./install.bash
```
* Alternatively install vagrant following [https://www.vagrantup.com/downloads](https://www.vagrantup.com/downloads):
{% if include.distro == "debian" or include.distro == "ubuntu" -%}
```shell
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install vagrant
```
{% elsif include.distro == "fedora" -%}
```shell
sudo dnf install -y dnf-plugins-core
sudo dnf config-manager --add-repo https://rpm.releases.hashicorp.com/fedora/hashicorp.repo
sudo dnf -y install vagrant
```
{% elsif include.distro == "centos" or include.distro == "rhel" -%}
```shell
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo yum -y install vagrant
```
{% elsif include.distro == "opensuse" %}
As there is no upstream repository this will not be kept up to date automatically.
{: .warn }
```shell
version="$(
wget -qO - https://checkpoint-api.hashicorp.com/v1/check/vagrant 2>/dev/null | \
tr ',' '\n' | grep current_version | cut -d: -f2 | tr -d '"'
)"
wget --no-verbose -O vagrant.rpm \
https://releases.hashicorp.com/vagrant/${version}/vagrant_${version}_x86_64.rpm
sudo zypper install --allow-unsigned-rpm --no-confirm vagrant.rpm
```
{% else -%}
Missing the correct distro for vagrant install in site generation
{% endif -%}

View File

@ -0,0 +1,84 @@
$callouts: (
info: ($blue-000, rgba($blue-200, .2), 'INFO'),
warn: ($yellow-300, rgba($yellow-200, .2), 'WARNING'),
danger: ($red-300, rgba($red-000, .2), 'DANGER')
);
@each $class, $props in $callouts {
.#{$class} {
background: nth($props, 2);
border-left: $border-radius solid nth($props, 1);
border-radius: $border-radius;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), 0 3px 10px rgba(0, 0, 0, 0.08);
padding: .8rem;
&::before {
color: nth($props, 1);
content: nth($props, 3);
display: block;
font-weight: bold;
font-size: .75em;
padding-bottom: .125rem;
}
}
}
// override site-title padding to ensure logo is better sized
.site-title {
padding-top: 0.125rem;
padding-bottom: 0.125rem;
}
@media (min-width: 50rem) { .site-title { padding-right: 1rem; padding-left: 1rem; } }
// override search style for dark to ensure default text is readable
@media (prefers-color-scheme: dark) {
input#search-input {
color: white;
&:focus {
color: white;
}
}
#search-input::placeholder {
color: $body-text-color;
opacity: 0.6;
}
}
// tweak the toc plugin styles to keep toc in nav more left aligned
ul#toc ul {
padding-left: 0.6rem;
}
ul#toc {
padding-left: 2.75rem;
}
ul#toc li {
margin-bottom: 0px;
margin-top: 0px;
}
.toc-entry a {
/*
background: initial;
padding-top: 0.1rem;
padding-bottom: 0.1rem;
display: block;
padding-right: $gutter-spacing-sm;
line-height: 1.5rem;
text-decoration: none;
&.active {
font-weight: 600;
text-decoration: none;
}
&:hover {
background-image: linear-gradient(
-90deg,
rgba($feedback-color, 1) 20% 40%,
rgba($feedback-color, 0.8) 80%,
rgba($feedback-color, 0) 100%
);
}
*/
}

61
docs/about.markdown Normal file
View File

@ -0,0 +1,61 @@
---
layout: page
title: About
permalink: /about/
---
Vagrant-libvirt is a [Vagrant](http://www.vagrantup.com) plugin that adds a
[Libvirt](http://libvirt.org) provider to Vagrant, allowing Vagrant to
control and provision machines via Libvirt toolkit.
{: .info }
Actual version is still a development one. Feedback is welcome and
can help a lot :-)
You can find the source code for Vagrant Libvirt plugin at GitHub:
[https://github.com/vagrant-libvirt/vagrant-libvirt](https://github.com/vagrant-libvirt/vagrant-libvirt)
You can find the source code for Vagrant Libvirt QA testing of install instructions at GitHub:
[https://github.com/vagrant-libvirt/vagrant-libvirt-qa](https://github.com/vagrant-libvirt/vagrant-libvirt-qa)
Creating issues can be done via GitHub:
[https://github.com/vagrant-libvirt/vagrant-libvirt/issues](https://github.com/vagrant-libvirt/vagrant-libvirt/issues)
To ask questions or discuss a problem ahead of logging an issue you can use:
* Gitter [https://gitter.im/vagrant-libvirt/vagrant-libvirt](https://gitter.im/vagrant-libvirt/vagrant-libvirt)
* Github Discussions [https://github.com/vagrant-libvirt/vagrant-libvirt/discussions](https://github.com/vagrant-libvirt/vagrant-libvirt/discussions)
## Features
* Control local Libvirt hypervisors.
* Vagrant `up`, `destroy`, `suspend`, `resume`, `halt`, `ssh`, `reload`,
`package` and `provision` commands.
* Upload box image (qcow2 format) to Libvirt storage pool.
* Create volume as COW diff image for domains.
* Create private networks.
* Create and boot Libvirt domains.
* SSH into domains.
* Setup hostname and network interfaces.
* Provision domains with any built-in Vagrant provisioner.
* Synced folder support via `rsync`, `nfs`, `9p` or `virtiofs`.
* Snapshots
* Package caching via
[vagrant-cachier](http://fgrehm.viewdocs.io/vagrant-cachier/).
* Use boxes from other Vagrant providers via
[vagrant-mutate](https://github.com/sciurus/vagrant-mutate).
* Support VMs with no box for PXE boot purposes (Vagrant 1.6 and up)
## How a Machine Is Created
Vagrant goes through steps below when creating new project:
1. Connect to Libvirt locally or remotely via SSH.
2. Check if box image is available in Libvirt storage pool. If not, upload it
to remote Libvirt storage pool as new volume.
3. Create COW diff image of base box image for new Libvirt domain.
4. Create and start new domain on Libvirt host.
5. Check for DHCP lease from dnsmasq server.
6. Wait till SSH is available.
7. Sync folders and run Vagrant provisioner on new domain if setup in
Vagrantfile.

150
docs/boxes.markdown Normal file
View File

@ -0,0 +1,150 @@
---
title: Boxes
nav_order: 4
toc: true
---
## Existing Boxes
Libvirt ready boxes can be downloaded at
[Vagrant Cloud](https://app.vagrantup.com/boxes/search?provider=libvirt).
## Creating Boxes
It's possible to also create custom boxes using existing boxes as the initial
starting point.
<div class="info">
If creating a box from a modified vagrant-libvirt machine, ensure that you have set the
<code class="language-plaintext highlighter-rouge">config.ssh.insert_key = false</code>
in the original Vagrantfile as otherwise Vagrant will replace the default connection
key-pair that is required on first boot with one specific to the machine and prevent
the default key from working on the exported result.
{% highlight ruby %}
Vagrant.configure("2") do |config|
# this setting is only recommended if planning to export the
# resulting machine
config.ssh.insert_key = false
config.vm.define :test_vm do |test_vm|
test_vm.vm.box = "fedora/32-cloud-base"
end
end
{% endhighlight %}
</div>
### Using Vagrant Package
vagrant-libvirt has native support for [`vagrant
package`](https://www.vagrantup.com/docs/cli/package.html) via
libguestfs [virt-sysprep](http://libguestfs.org/virt-sysprep.1.html).
virt-sysprep operations can be customized via the
`VAGRANT_LIBVIRT_VIRT_SYSPREP_OPERATIONS` environment variable; see the
[upstream
documentation](http://libguestfs.org/virt-sysprep.1.html#operations) for
further details especially on default sysprep operations enabled for
your system.
Options to the virt-sysprep command call can be passed via
`VAGRANT_LIBVIRT_VIRT_SYSPREP_OPTIONS` environment variable.
```shell
$ export VAGRANT_LIBVIRT_VIRT_SYSPREP_OPTIONS="--delete /etc/hostname"
$ vagrant package
```
For example, on Chef [bento](https://github.com/chef/bento) VMs that
require SSH hostkeys already set (e.g. bento/debian-7) as well as leave
existing LVM UUIDs untouched (e.g. bento/ubuntu-18.04), these can be
packaged into vagrant-libvirt boxes like so:
```shell
$ export VAGRANT_LIBVIRT_VIRT_SYSPREP_OPERATIONS="defaults,-ssh-userdir,-ssh-hostkeys,-lvm-uuids"
$ vagrant package
```
### From qcow2 Image
To create a vagrant-libvirt box from a qcow2 image, run `create_box.sh`
(located in the tools directory):
```shell
$ create_box.sh ubuntu14.qcow2
```
### Packer
You can also create a box by using [Packer](https://packer.io). Packer
templates for use with vagrant-libvirt are available at
https://github.com/jakobadam/packer-qemu-templates. After cloning that project
you can build a vagrant-libvirt box by running:
```shell
$ cd packer-qemu-templates
$ packer build ubuntu-14.04-server-amd64-vagrant.json
```
## Box Formats
### Version 1
This is the original format that most boxes currently use.
You can view an example box in the
[`example_box/directory`](https://github.com/vagrant-libvirt/vagrant-libvirt/tree/main/example_box).
That directory also contains instructions on how to build a box.
The box is a tarball containing:
* qcow2 image file named `box.img`
* `metadata.json` file describing box image (`provider`, `virtual_size`,
`format`)
* `Vagrantfile` that does default settings for the provider-specific
configuration for this provider
### Version 2 (Experimental)
Due to the limitation of only being able to handle a single disk with the version 1 format, a new
format was added to support boxes that need to specify multiple disks. This is still currently
experimental and as such is not the default format. Packaging support is in place and will automatically
alert you if attempting to package a machine with additional disks attached. To enable the new format
to verify ahead of it becoming the default, export the variable `VAGRANT_LIBVIRT_BOX_FORMAT_VERSION=v2`
before running `vagrant package`
Additionally there is a script in the tools folder
([`tools/create_box_with_two_disks.sh`](https://github.com/vagrant-libvirt/vagrant-libvirt/blob/main/tools/create_box_with_two_disks.sh))
that provides a guideline on how to create such a box from qcow2 images should it not be practical use
a vagrant machine with additional storage as a starting point.
At it's most basic, it expects an array of disks to allow a specific order to be presented. Disks
will be attached in this order and as such assume device names base on this within the VM. The
'path' attribute is required, and is expected to be relative to the base of the box. This should
allow placing the disk images within a nested directory within the box if it useful for those
with a larger number of disks. The name allows overriding the target volume name that will be
used in the libvirt storage pool. Note that vagrant-libvirt will still prefix the volume name
with `#{box_name}_vagrant_box_image_#{box_version}_` to avoid accidental clashes with other boxes.
Format and virtual size need no longer be specified as they are now retrieved directly from the
provided image using `qemu-img info ...`.
Example format:
```json
{
"disks": [
{
"path": "disk1.img"
},
{
"path": "disk2.img",
"name": "secondary_disk"
},
{
"path": "disk3.img"
}
],
"provider": "libvirt"
}
```

1034
docs/configuration.markdown Normal file

File diff suppressed because it is too large Load Diff

472
docs/examples.markdown Normal file
View File

@ -0,0 +1,472 @@
---
title: Examples
nav_order: 5
toc: true
---
Examples of specific use cases, and/or in-depth configuration for special behaviour.
## No box and PXE boot
There is support for PXE booting VMs with no disks as well as PXE booting VMs
with blank disks. There are some limitations:
* Requires Vagrant 1.6.0 or newer
* No provisioning scripts are ran
* No network configuration is being applied to the VM
* No SSH connection can be made
* `vagrant halt` will only work cleanly if the VM handles ACPI shutdown signals
In short, VMs without a box can be created, halted and destroyed but all other
functionality cannot be used.
An example for a PXE booted VM with no disks whatsoever:
```ruby
Vagrant.configure("2") do |config|
config.vm.define :pxeclient do |pxeclient|
pxeclient.vm.provider :libvirt do |domain|
domain.boot 'network'
end
end
end
```
And an example for a PXE booted VM with no box but a blank disk which will boot from this HD if the NICs fail to PXE boot:
```ruby
Vagrant.configure("2") do |config|
config.vm.define :pxeclient do |pxeclient|
pxeclient.vm.provider :libvirt do |domain|
domain.storage :file, :size => '100G', :type => 'qcow2'
domain.boot 'network'
domain.boot 'hd'
end
end
end
```
Example for vm with 2 networks and only 1 is bootable and has dhcp server in this subnet, for example foreman with dhcp server
Name of network "foreman_managed" is key for define boot order
```ruby
config.vm.define :pxeclient do |pxeclient|
pxeclient.vm.network :private_network,ip: '10.0.0.5',
libvirt__network_name: "foreman_managed",
libvirt__dhcp_enabled: false,
libvirt__host_ip: '10.0.0.1'
pxeclient.vm.provider :libvirt do |domain|
domain.memory = 1000
boot_network = {'network' => 'foreman_managed'}
domain.storage :file, :size => '100G', :type => 'qcow2'
domain.boot boot_network
domain.boot 'hd'
end
end
```
An example VM that is PXE booted from the `br1` device (which must already be configured in the host machine), and if that fails, is booted from the disk:
```ruby
Vagrant.configure("2") do |config|
config.vm.define :pxeclient do |pxeclient|
pxeclient.vm.network :public_network,
dev: 'br1',
auto_config: false
pxeclient.vm.provider :libvirt do |domain|
boot_network = {'dev' => 'br1'}
domain.storage :file, :size => '100G'
domain.boot boot_network
domain.boot 'hd'
end
end
end
```
## SSH Access To VM
vagrant-libvirt supports vagrant's [standard ssh
settings](https://docs.vagrantup.com/v2/vagrantfile/ssh_settings.html).
## Forwarded Ports
vagrant-libvirt supports Forwarded Ports via ssh port forwarding. Please note
that due to a well known limitation only the TCP protocol is supported. For
each `forwarded_port` directive you specify in your Vagrantfile,
vagrant-libvirt will maintain an active ssh process for the lifetime of the VM.
If your VM should happen to be rebooted, the SSH session will need to be
restablished by halting the VM and bringing it back up.
vagrant-libvirt supports an additional `forwarded_port` option `gateway_ports`
which defaults to `false`, but can be set to `true` if you want the forwarded
port to be accessible from outside the Vagrant host. In this case you should
also set the `host_ip` option to `'*'` since it defaults to `'localhost'`.
You can also provide a custom adapter to forward from by 'adapter' option.
Default is `eth0`.
**Internally Accessible Port Forward**
`config.vm.network :forwarded_port, guest: 80, host: 2000`
**Externally Accessible Port Forward**
`config.vm.network :forwarded_port, guest: 80, host: 2000, host_ip: "0.0.0.0"`
## Forwarding the ssh-port
Vagrant-libvirt now supports forwarding the standard ssh-port on port 2222 from
the localhost to allow for consistent provisioning steps/ports to be used when
defining across multiple providers.
To enable, set the following:
```ruby
Vagrant.configure("2") do |config|
config.vm.provider :libvirt do |libvirt|
# Enable forwarding of forwarded_port with id 'ssh'.
libvirt.forward_ssh_port = true
end
end
```
Previously by default libvirt skipped the forwarding of the ssh-port because
you can access the machine directly. In the future it is expected that this
will be enabled by default once autocorrect support is added to handle port
collisions for multi machine environments gracefully.
## Synced Folders
Vagrant automatically syncs the project folder on the host to `/vagrant` in
the guest. You can also configure additional synced folders.
**SECURITY NOTE:** for remote Libvirt, nfs synced folders requires a bridged
public network interface and you must connect to Libvirt via ssh.
**NFS**
`vagrant-libvirt` supports
[NFS](https://www.vagrantup.com/docs/synced-folders/nfs) as default with
bidirectional synced folders.
Example with NFS:
``` ruby
Vagrant.configure("2") do |config|
config.vm.synced_folder "./", "/vagrant"
end
```
**RSync**
`vagrant-libvirt` supports
[rsync](https://www.vagrantup.com/docs/synced-folders/rsync) with
unidirectional synced folders.
Example with rsync:
``` ruby
Vagrant.configure("2") do |config|
config.vm.synced_folder "./", "/vagrant", type: "rsync"
end
```
**9P**
`vagrant-libvirt` supports [VirtFS](http://www.linux-kvm.org/page/VirtFS) ([9p
or Plan 9](https://en.wikipedia.org/wiki/9P_\(protocol\))) with bidirectional
synced folders.
Difference between NFS and 9p is explained
[here](https://unix.stackexchange.com/questions/240281/virtfs-plan-9-vs-nfs-as-tool-for-share-folder-for-virtual-machine).
For 9p shares, a `mount: false` option allows to define synced folders without
mounting them at boot.
Example for `accessmode: "squash"` with 9p:
``` ruby
Vagrant.configure("2") do |config|
config.vm.synced_folder "./", "/vagrant", type: "9p", disabled: false, accessmode: "squash", owner: "1000"
end
```
Example for `accessmode: "mapped"` with 9p:
``` ruby
Vagrant.configure("2") do |config|
config.vm.synced_folder "./", "/vagrant", type: "9p", disabled: false, accessmode: "mapped", mount: false
end
```
Further documentation on using 9p can be found in [kernel
docs](https://www.kernel.org/doc/Documentation/filesystems/9p.txt) and in
[QEMU
wiki](https://wiki.qemu.org/Documentation/9psetup#Starting_the_Guest_directly).
Please do note that 9p depends on support in the guest and not all distros
come with the 9p module by default.
**Virtio-fs**
`vagrant-libvirt` supports [Virtio-fs](https://virtio-fs.gitlab.io/) with
bidirectional synced folders.
For virtiofs shares, a `mount: false` option allows to define synced folders
without mounting them at boot.
So far, passthrough is the only supported access mode and it requires running
the virtiofsd daemon as root.
QEMU needs to allocate the backing memory for all the guest RAM as shared
memory, e.g. [Use file-backed
memory](https://libvirt.org/kbase/virtiofs.html#host-setup) by enable
`memory_backing_dir` option in `/etc/libvirt/qemu.conf`:
``` shell
memory_backing_dir = "/dev/shm"
```
Example for Libvirt \>= 6.2.0 (e.g. Ubuntu 20.10 with Linux 5.8.0 + QEMU 5.0 +
Libvirt 6.6.0, i.e. NUMA nodes required) with virtiofs:
``` ruby
Vagrant.configure("2") do |config|
config.vm.provider :libvirt do |libvirt|
libvirt.cpus = 2
libvirt.numa_nodes = [{ :cpus => "0-1", :memory => 8192, :memAccess => "shared" }]
libvirt.memorybacking :access, :mode => "shared"
end
config.vm.synced_folder "./", "/vagrant", type: "virtiofs"
end
```
Example for Libvirt \>= 6.9.0 (e.g. Ubuntu 21.04 with Linux 5.11.0 + QEMU 5.2 +
Libvirt 7.0.0, or Ubuntu 20.04 + [PPA
enabled](https://launchpad.net/~savoury1/+archive/ubuntu/virtualisation)) with
virtiofs:
``` ruby
Vagrant.configure("2") do |config|
config.vm.provider :libvirt do |libvirt|
libvirt.cpus = 2
libvirt.memory = 8192
libvirt.memorybacking :access, :mode => "shared"
end
config.vm.synced_folder "./", "/vagrant", type: "virtiofs"
end
```
Further documentation on using virtiofs can be found in [official
HowTo](https://virtio-fs.gitlab.io/index.html#howto) and in [Libvirt
KB](https://libvirt.org/kbase/virtiofs.html).
Please do note that virtiofs depends on:
- Host: Linux \>= 5.4, QEMU \>= 4.2 and Libvirt \>= 6.2 (e.g. Ubuntu 20.10)
- Guest: Linux \>= 5.4 (e.g. Ubuntu 20.04)
## QEMU Session Support
vagrant-libvirt supports using QEMU user sessions to maintain Vagrant VMs. As the session connection does not have root access to the system features which require root will not work. Access to networks created by the system QEMU connection can be granted by using the [QEMU bridge helper](https://wiki.qemu.org/Features/HelperNetworking). The bridge helper is enabled by default on some distros but may need to be enabled/installed on others.
There must be a virbr network defined in the QEMU system session. The libvirt `default` network which comes by default, the vagrant `vagrant-libvirt` network which is generated if you run a Vagrantfile using the System session, or a manually defined network can be used. These networks can be set to autostart with `sudo virsh net-autostart <net-name>`, which'll mean no further root access is required even after reboots.
The QEMU bridge helper is configured via `/etc/qemu/bridge.conf`. This file must include the virbr you wish to use (e.g. virbr0, virbr1, etc). You can find this out via `sudo virsh net-dumpxml <net-name>`.
```
allow virbr0
```
An example configuration of a machine using the QEMU session connection:
```ruby
Vagrant.configure("2") do |config|
config.vm.provider :libvirt do |libvirt|
# Use QEMU session instead of system connection
libvirt.qemu_use_session = true
# URI of QEMU session connection, default is as below
libvirt.uri = 'qemu:///session'
# URI of QEMU system connection, use to obtain IP address for management, default is below
libvirt.system_uri = 'qemu:///system'
# Path to store Libvirt images for the virtual machine, default is as ~/.local/share/libvirt/images
libvirt.storage_pool_path = '/home/user/.local/share/libvirt/images'
# Management network device, default is below
libvirt.management_network_device = 'virbr0'
end
# Public network configuration using existing network device
# Note: Private networks do not work with QEMU session enabled as root access is required to create new network devices
config.vm.network :public_network, :dev => "virbr1",
:mode => "bridge",
:type => "bridge"
end
```
## Customized Graphics
vagrant-libvirt supports customizing the display and video settings of the
managed guest. This is probably most useful for VNC-type displays with
multiple guests. It lets you specify the exact port for each guest to use
deterministically.
Here is an example of using custom display options:
```ruby
Vagrant.configure("2") do |config|
config.vm.provider :libvirt do |libvirt|
libvirt.graphics_port = 5901
libvirt.graphics_ip = '0.0.0.0'
libvirt.video_type = 'qxl'
end
end
```
## TPM Devices
Modern versions of Libvirt support connecting to TPM devices on the host
system. This allows you to enable Trusted Boot Extensions, among other
features, on your guest VMs.
To passthrough a hardware TPM, you will generally only need to modify the
`tpm_path` variable in your guest configuration. However, advanced usage,
such as the application of a Software TPM, may require modifying the
`tpm_model`, `tpm_type` and `tpm_version` variables.
The TPM options will only be used if you specify a TPM path or version.
Declarations of any TPM options without specifying a path or version will
result in those options being ignored.
Here is an example of using the TPM options:
```ruby
Vagrant.configure("2") do |config|
config.vm.provider :libvirt do |libvirt|
libvirt.tpm_model = 'tpm-tis'
libvirt.tpm_type = 'passthrough'
libvirt.tpm_path = '/dev/tpm0'
end
end
```
It's also possible for Libvirt to start an emulated TPM device on the host.
Requires `swtpm` and `swtpm-tools`
```ruby
Vagrant.configure("2") do |config|
config.vm.provider :libvirt do |libvirt|
libvirt.tpm_model = "tpm-crb"
libvirt.tpm_type = "emulator"
libvirt.tpm_version = "2.0"
end
end
```
## Memory balloon
The configuration of the memory balloon device can be overridden. By default,
libvirt will automatically attach a memory balloon; this behavior is preserved
by not configuring any memballoon-related options. The memory balloon can be
explicitly disabled by setting `memballoon_enabled` to `false`. Setting
`memballoon_enabled` to `true` will allow additional configuration of
memballoon-related options.
Here is an example of using the memballoon options:
```ruby
Vagrant.configure("2") do |config|
config.vm.provider :libvirt do |libvirt|
libvirt.memballoon_enabled = true
libvirt.memballoon_model = 'virtio'
libvirt.memballoon_pci_bus = '0x00'
libvirt.memballoon_pci_slot = '0x0f'
end
end
```
## Libvirt communication channels
For certain functionality to be available within a guest, a private
communication channel must be established with the host. Two notable examples
of this are the QEMU guest agent, and the Spice/QXL graphics type.
Below is a simple example which exposes a virtio serial channel to the guest.
Note: in a multi-VM environment, the channel would be created for all VMs.
```ruby
vagrant.configure(2) do |config|
config.vm.provider :libvirt do |libvirt|
libvirt.channel :type => 'unix', :target_name => 'org.qemu.guest_agent.0', :target_type => 'virtio'
end
end
```
Below is the syntax for creating a spicevmc channel for use by a qxl graphics
card.
```ruby
vagrant.configure(2) do |config|
config.vm.provider :libvirt do |libvirt|
libvirt.channel :type => 'spicevmc', :target_name => 'com.redhat.spice.0', :target_type => 'virtio'
end
end
```
These settings can be specified on a per-VM basis, however the per-guest
settings will OVERRIDE any global 'config' setting. In the following example,
we create 3 VMs with the following configuration:
* **controller**: No channel settings specified, so we default to the provider
setting of a single virtio guest agent channel.
* **node1**: Override the channel setting, setting both the guest agent
channel, and a spicevmc channel
* **node2**: Override the channel setting, setting both the guest agent
channel, and a 'guestfwd' channel. TCP traffic sent by the guest to the given
IP address and port is forwarded to the host socket `/tmp/foo`. Note: this
device must be unique for each VM.
For example:
```ruby
Vagrant.configure(2) do |config|
config.vm.box = "fedora/32-cloud-base"
config.vm.provider :libvirt do |libvirt|
libvirt.channel :type => 'unix', :target_name => 'org.qemu.guest_agent.0', :target_type => 'virtio'
end
config.vm.define "controller" do |controller|
controller.vm.provider :libvirt do |domain|
domain.memory = 1024
end
end
config.vm.define "node1" do |node1|
node1.vm.provider :libvirt do |domain|
domain.channel :type => 'unix', :target_name => 'org.qemu.guest_agent.0', :target_type => 'virtio'
domain.channel :type => 'spicevmc', :target_name => 'com.redhat.spice.0', :target_type => 'virtio'
end
end
config.vm.define "node2" do |node2|
node2.vm.provider :libvirt do |domain|
domain.channel :type => 'unix', :target_name => 'org.qemu.guest_agent.0', :target_type => 'virtio'
domain.channel :type => 'unix', :target_type => 'guestfwd', :target_address => '192.0.2.42', :target_port => '4242',
:source_path => '/tmp/foo'
end
end
end
```
## Custom QEMU arguments and environment variables
You can also specify multiple qemuargs arguments or qemuenv environment variables for qemu-system
* `value` - Value
```ruby
Vagrant.configure("2") do |config|
config.vm.provider :libvirt do |libvirt|
libvirt.qemuargs :value => "-device"
libvirt.qemuargs :value => "intel-iommu"
libvirt.qemuenv QEMU_AUDIO_DRV: 'pa'
libvirt.qemuenv QEMU_AUDIO_TIMER_PERIOD: '150'
libvirt.qemuenv QEMU_PA_SAMPLES: '1024', QEMU_PA_SERVER: '/run/user/1000/pulse/native'
end
end
```

101
docs/index.markdown Normal file
View File

@ -0,0 +1,101 @@
---
title: Quickstart
redirect_from:
- /home/
- /quickstart/
- /extras/
nav_order: 1
toc: true
---
Vagrant-libvirt is a [Vagrant](http://www.vagrantup.com) plugin that adds a
[Libvirt](http://libvirt.org) provider to Vagrant, allowing Vagrant to
control and provision machines via Libvirt toolkit.
{: .info }
Actual version is still a development one. Feedback is welcome and
can help a lot :-)
## Prerequisites
Vagrant-libvirt requires the following:
* Vagrant
* Libvirt (and QEMU)
* GCC and Make (if not using vagrant from your distribution)
{: .warn }
Before you start using vagrant-libvirt, please make sure your Libvirt
and QEMU installation is working correctly and you are able to create QEMU or
KVM type virtual machines with `virsh` or `virt-manager`.
See [Requirements]({{ '/installation/#requirements' | relative_url }}) for guides and details.
## Installation
1. Install Vagrant, Libvirt and QEMU for your distribution
* Ubuntu
```
sudo apt-get update && \
sudo apt install -y qemu libvirt-daemon-system libvirt-clients \
ebtables dnsmasq-base libguestfs-tools
sudo apt install -y --no-install-recommends vagrant ruby-fog-libvirt
```
* Fedora
```
vagrant_libvirt_deps=($(sudo dnf repoquery --depends vagrant-libvirt 2>/dev/null | cut -d' ' -f1))
dependencies=$(sudo dnf repoquery --qf "%{name}" ${vagrant_libvirt_deps[@]/#/--whatprovides })
sudo dnf install --assumeyes --setopt=install_weak_deps=False @virtualization ${dependencies}
```
2. Install the latest release of vagrant-libvirt
```
vagrant plugin install vagrant-libvirt
```
If you encounter any errors during this process, check that you have installed all the prerequisites in [Requirements]({{ '/installation/#requirements' | relative_url }}).
If you still have issues, see [Troubleshooting]({{ '/troubleshooting/#installation-problems' | relative_url }}).
{: .info }
Installation varies based on your operating system or use of upstream vagrant. See our [guides]({{ '/installation/#guides' | relative_url }}) for OS-specific instructions.
## Initial Project Creation
After installing the plugin (instructions above), the quickest way to get
started is to add Libvirt box and specify all the details manually within a
`config.vm.provider` block. So first, add Libvirt box using any name you want.
You can find more Libvirt-ready boxes at
[Vagrant Cloud](https://app.vagrantup.com/boxes/search?provider=libvirt). For
example:
```shell
vagrant init fedora/36-cloud-base
```
Or make a Vagrantfile that looks like the following, filling in your
information where necessary. For example:
```ruby
Vagrant.configure("2") do |config|
config.vm.define :test_vm do |test_vm|
test_vm.vm.box = "fedora/36-cloud-base"
end
end
```
## Start VM
In prepared project directory, run following command:
```shell
$ vagrant up --provider=libvirt
```
Vagrant needs to know that we want to use Libvirt and not default VirtualBox.
That's why there is `--provider=libvirt` option specified. Other way to tell
Vagrant to use Libvirt provider is to setup environment variable
```shell
export VAGRANT_DEFAULT_PROVIDER=libvirt
```

438
docs/installation.markdown Normal file
View File

@ -0,0 +1,438 @@
---
title: Installation
nav_order: 2
toc: true
---
## Requirements
* [Libvirt](http://libvirt.org) - should work with version 1.5 or newer
* [Vagrant](http://www.vagrantup.com) - plugin attempts to support all since 1.5
* [GCC](https://gcc.gnu.org/install/) and [Make](https://www.gnu.org/software/make/) - used to compile native versions of ruby-libvirt and nokogiri when using upstream Vagrant
While we only test with upstream vagrant installed as a gem, we recommend that you install
vagrant as provided by your distribution as installing vagrant-libvirt involves linking between
libvirt (ruby-libvirt) and the ruby installation used by vagrant. Since upstream vagrant
provides an embedded ruby, this typically causes issues with missing symbols between libraries
included and what is expected by libvirt for the ruby bindings linking to work.
First, you should have both QEMU and Libvirt installed if you plan to run VMs on your
local system. For instructions, refer to your Linux distribution's documentation. Suggested
packages are provided in our guides for as a quick reference
{: .warning }
Before you start using vagrant-libvirt, please make sure your Libvirt
and QEMU installation is working correctly and you are able to create QEMU or
KVM type virtual machines with `virsh` or `virt-manager`.
Next, you must have Vagrant installed from your distribution packages.
Vagrant-libvirt supports Vagrant 2.0, 2.1 & 2.2. It should also work with earlier
releases from 1.5 onwards but they are not actively tested.
{% assign repo = site.github.public_repositories | where: "name", site.github.repository_name %}
Check the [unit tests](https://github.com/vagrant-libvirt/vagrant-libvirt/blob/{{ repo.first.default_branch }}/.github/workflows/unit-tests.yml)
for the current list of tested versions.
If there is no distribution package or you wish to use the upstream vagrant, you may wish to use
the our [QA installation script](https://github.com/vagrant-libvirt/vagrant-libvirt-qa/blob/main/scripts/install.bash)
to install both vagrant and vagrant-libvirt
Alternatively you may follow
[vagrant installation instructions](http://docs.vagrantup.com/v2/installation/index.html) along
with the manual instructions for what packages to install where indicated for upstream vagrant below.
In some cases the vagrant version for the distribution may be running with a sufficiently old ruby
that it is difficult to install the required dependencies and you will need to use the upstream.
## Guides
### Docker / Podman
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 built 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.
{: .info }
The default image contains the full toolchain required to build and install vagrant-libvirt
and it's dependencies. There is also a smaller image published with the `-slim` suffix if you
just need vagrant-libvirt and don't need to install any additional plugins for your environment.
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.
#### Using Docker
To get the image with the most recent release:
```bash
docker pull vagrantlibvirt/vagrant-libvirt:latest
```
<div class="info">If you want the very latest code you can use the <code class="language-plaintext highlighter-rouge">edge</code> tag instead.
<div class="language-bash highlighter-rouge" style="margin-top: 1em; margin-bottom: 0;"><div class="highlight"><pre class="highlight">
<code>docker pull vagrantlibvirt/vagrant-libvirt:edge</code>
</pre></div></div>
</div>
Running the image:
```bash
docker run -i --rm \
-e LIBVIRT_DEFAULT_URI \
-v /var/run/libvirt/:/var/run/libvirt/ \
-v ~/.vagrant.d:/.vagrant.d \
-v $(realpath "${PWD}"):${PWD} \
-w $(realpath "${PWD}") \
--network host \
vagrantlibvirt/vagrant-libvirt:latest \
vagrant status
```
It's possible to define a function in `~/.bashrc`, for example:
```bash
vagrant(){
docker run -i --rm \
-e LIBVIRT_DEFAULT_URI \
-v /var/run/libvirt/:/var/run/libvirt/ \
-v ~/.vagrant.d:/.vagrant.d \
-v $(realpath "${PWD}"):${PWD} \
-w $(realpath "${PWD}") \
--network host \
vagrantlibvirt/vagrant-libvirt:latest \
vagrant $@
}
```
#### Using Podman
Preparing the podman run, only once:
```bash
mkdir -p ~/.vagrant.d/{boxes,data,tmp}
```
_N.B. This is needed until the entrypoint works for podman to only mount the `~/.vagrant.d` directory_
To run with Podman you need to include
```bash
--entrypoint /bin/bash \
--security-opt label=disable \
-v ~/.vagrant.d/boxes:/vagrant/boxes \
-v ~/.vagrant.d/data:/vagrant/data \
-v ~/.vagrant.d/tmp:/vagrant/tmp \
```
for example:
```bash
vagrant(){
podman run -it --rm \
-e LIBVIRT_DEFAULT_URI \
-v /var/run/libvirt/:/var/run/libvirt/ \
-v ~/.vagrant.d/boxes:/vagrant/boxes \
-v ~/.vagrant.d/data:/vagrant/data \
-v ~/.vagrant.d/tmp:/vagrant/tmp \
-v $(realpath "${PWD}"):${PWD} \
-w $(realpath "${PWD}") \
--network host \
--entrypoint /bin/bash \
--security-opt label=disable \
docker.io/vagrantlibvirt/vagrant-libvirt:latest \
vagrant $@
}
```
Running Podman in rootless mode maps the root user inside the container to your host user so we need to bypass [entrypoint.sh](https://github.com/vagrant-libvirt/vagrant-libvirt/blob/main/entrypoint.sh) and mount persistent storage directly to `/vagrant`.
#### Extending the container image with additional vagrant plugins
By default the image published and used contains the entire tool chain required
to reinstall the vagrant-libvirt plugin and it's dependencies, as this is the
default behaviour of vagrant anytime a new plugin is installed. This means it
should be possible to use a simple `FROM` statement and ask vagrant to install
additional plugins.
```
FROM vagrantlibvirt/vagrant-libvirt:latest
RUN vagrant plugin install <plugin>
```
### Ubuntu / Debian
{: .info }
You may need to modify your `sources.list` to uncomment the deb-src entries where using build-dep commands below.
#### Ubuntu 18.10, Debian 9 and up
* Distro Vagrant
```shell
sudo apt-get purge vagrant-libvirt
sudo apt-mark hold vagrant-libvirt
sudo apt-get install -y qemu libvirt-daemon-system ebtables libguestfs-tools
sudo apt-get install -y vagrant ruby-fog-libvirt
vagrant plugin install vagrant-libvirt
```
{% include upstream-vagrant-install.html distro="ubuntu" -%}
And subsequently install remaining dependencies and plugin:
```shell
sudo apt-get build-dep vagrant ruby-libvirt
sudo apt-get install -y qemu libvirt-daemon-system ebtables libguestfs-tools \
libxslt-dev libxml2-dev zlib1g-dev ruby-dev
vagrant plugin install vagrant-libvirt
```
#### Ubuntu 18.04, Debian 8 and older
{: .warn }
This has been kept for historical reasons, however only Ubuntu 18.04 is supported due to LTS, please
consider all other versions unsupported.
{% include upstream-vagrant-install.html distro="debian" content=distro_deps -%}
And subsequently install remaining dependencies and plugin:
```shell
sudo apt-get build-dep vagrant ruby-libvirt
sudo apt-get install -y qemu libvirt-bin ebtables libguestfs-tools \
libxslt-dev libxml2-dev zlib1g-dev ruby-dev
vagrant plugin install vagrant-libvirt
```
* Distro Vagrant
```shell
sudo apt-get purge vagrant-libvirt
sudo apt-mark hold vagrant-libvirt
sudo apt-get install -y qemu libvirt-bin ebtables libguestfs-tools
sudo apt-get install -y vagrant ruby-fog-libvirt
vagrant plugin install vagrant-libvirt
```
{: .warn }
Unless you can can install a newer ruby on Debian 8, it is likely that the distro vagrant approach will not be straight forward as vagrant-libvirt requires a fog-core and fog-libvirt releases that depend on ruby 2.5 or newer.
### Fedora
#### Fedora 32 and newer
{: .info }
Due to the involved nature of getting the linking to work correctly when using the upstream
vagrant, it is strongly recommended to either use the distro packaged vagrant, or the
install script from the vagrant-libvirt-qa approach.
* Distro Vagrant
```shell
sudo dnf remove vagrant-libvirt
sudo sed -i \
'/^\(exclude=.*\)/ {/vagrant-libvirt/! s//\1 vagrant-libvirt/;:a;n;ba;q}; $aexclude=vagrant-libvirt' \
/etc/dnf/dnf.conf
sudo dnf install --assumeyes @virtualization vagrant rubygem-fog-libvirt
```
The above `sed` command will add `vagrant-libvirt` to the list of packages to be excluded from being installed.
This prevents it from being pulled in as a weak dependency when installing `vagrant` along with the
`@virtualization` group. Unfortunately the `dnf versionlock` plugin can only lock to a specific version
rather than exclude all versions.
{% include upstream-vagrant-install.html distro="fedora" -%}
Subsequently install remaining dependencies:
```shell
sudo dnf install --assumeyes libvirt libguestfs-tools \
gcc libvirt-devel libxml2-devel make ruby-devel
```
Before installing the plugin it is necessary to compile some libraries to replace those
shipped with the upstream vagrant to prevent the following errors from appearing when
vagrant attempts to use vagrant-libvirt on recent Fedora releases.
{% include patch-vagrant-install.html distro="fedora" %}
Finally install the plugin:
```
vagrant plugin install vagrant-libvirt
```
#### Fedora 22 to 31
This has been kept for historical reasons given closeness to CentOS 6 & 7, however as Fedora no
longer supports these, they can be considered unsupported as well.
{% include upstream-vagrant-install.html distro="fedora" -%}
And subsequently install remaining dependencies and plugin:
```shell
sudo dnf install --assumeyes libvirt libguestfs-tools \
gcc libvirt-devel libxml2-devel make ruby-devel
vagrant plugin install vagrant-libvirt
```
### CentOS
#### CentOS 8
{% include upstream-vagrant-install.html distro="centos" -%}
Subsequently install remaining dependencies:
```shell
sudo dnf install --assumeyes libvirt libguestfs-tools \
gcc libvirt-devel libxml2-devel make ruby-devel
```
Before installing the plugin it is necessary to compile some libraries to replace those
shipped with the upstream vagrant to prevent the following errors from appearing when
vagrant attempts to use vagrant-libvirt on recent CentOS releases.
{% include patch-vagrant-install.html distro="fedora" %}
Finally install the plugin:
```
vagrant plugin install vagrant-libvirt
```
#### CentOS 6 & 7
{% include upstream-vagrant-install.html distro="centos" -%}
And subsequently install remaining dependencies and plugin:
```shell
sudo yum install --assumeyes qemu qemu-kvm libvirt libguestfs-tools \
gcc libvirt-devel make ruby-devel
vagrant plugin install vagrant-libvirt
```
### OpenSUSE
As there is no official upstream repository for OpenSUSE, it is recommended that you stick with the
distribution installation. OpenSUSE Leap appears to make the most recent vagrant available as an
experimental package based on [https://software.opensuse.org/package/vagrant](https://software.opensuse.org/package/vagrant).
#### Leap 15
* Distro Vagrant
```shell
sudo zypper refresh
sudo zypper addlock vagrant-libvirt
fog_libvirt_pkg="$(
sudo zypper --terse -n --quiet search --provides "rubygem(fog-libvirt)" | \
tail -n1 | cut -d' ' -f4)"
sudo zypper install --no-confirm libvirt qemu-kvm libguestfs vagrant ${fog_libvirt_pkg}
vagrant plugin install vagrant-libvirt
```
### Arch
Please read the related [ArchWiki](https://wiki.archlinux.org/index.php/Vagrant#vagrant-libvirt) page.
As Arch is a rolling release, the version of vagrant available from the distribution should always be the most recent.
Unfortunately it does not appear to be possible to install ruby-libvirt from AUR anymore, which would remove
the need for the additional build tools.
```shell
sudo pacman --sync --sysupgrade --refresh
sudo pacman --query --search 'iptables' | grep "local" | grep "iptables " && \
sudo pacman --remove --nodeps --nodeps --noconfirm iptables
sudo pacman --sync --needed --noprogressbar --noconfirm \
iptables-nft libvirt qemu openbsd-netcat bridge-utils dnsmasq vagrant \
pkg-config gcc make ruby
vagrant plugin install vagrant-libvirt
```
## Issues and Known Solutions
### Failure to find Libvirt for Native Extensions
Ensuring `pkg-config` or `pkgconf` is installed should be sufficient in most cases.
In some cases, you will need to specify `CONFIGURE_ARGS` variable before running running `vagrant plugin install`, e.g.:
```shell
export CONFIGURE_ARGS="with-libvirt-include=/usr/include/libvirt with-libvirt-lib=/usr/lib64"
vagrant plugin install vagrant-libvirt
```
If you have issues building ruby-libvirt, try the following (replace `lib` with `lib64` as needed):
```shell
CONFIGURE_ARGS='with-ldflags=-L/opt/vagrant/embedded/lib with-libvirt-include=/usr/include/libvirt with-libvirt-lib=/usr/lib' \
GEM_HOME=~/.vagrant.d/gems \
GEM_PATH=$GEM_HOME:/opt/vagrant/embedded/gems \
PATH=/opt/vagrant/embedded/bin:$PATH \
vagrant plugin install vagrant-libvirt
```
### Failure to Link
If have problem with installation - check your linker. It should be `ld.gold`:
```shell
sudo alternatives --set ld /usr/bin/ld.gold
# OR
sudo ln -fs /usr/bin/ld.gold /usr/bin/ld
```
### LoadError Exceptions
If you encounter the following load error when using the vagrant-libvirt plugin (note the required by libssh):
```/opt/vagrant/embedded/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require': /opt/vagrant/embedded/lib64/libcrypto.so.1.1: version `OPENSSL_1_1_1b' not found (required by /lib64/libssh.so.4) - /home/xxx/.vagrant.d/gems/2.4.6/gems/ruby-libvirt-0.7.1/lib/_libvirt.so (LoadError)```
then the following steps have been found to resolve the problem. Thanks to James Reynolds (see https://github.com/hashicorp/vagrant/issues/11020#issuecomment-540043472). The specific version of libssh will change over time so references to the rpm in the commands below will need to be adjusted accordingly.
{: .info }
See distro specific instructions for variations on this that contain version independent steps.
```shell
# Fedora
dnf download --source libssh
# centos 8 stream, doesn't provide source RPMs, so you need to download like so
git clone https://git.centos.org/centos-git-common
# centos-git-common needs its tools in PATH
export PATH=$(readlink -f ./centos-git-common):$PATH
git clone https://git.centos.org/rpms/libssh
cd libssh
git checkout imports/c8s/libssh-0.9.4-1.el8
into_srpm.sh -d c8s
cd SRPMS
# common commands (make sure to adjust verison accordingly)
rpm2cpio libssh-0.9.4-1c8s.src.rpm | cpio -imdV
tar xf libssh-0.9.4.tar.xz
mkdir build
cmake ../libssh-0.9.4 -DOPENSSL_ROOT_DIR=/opt/vagrant/embedded/
make
sudo cp lib/libssh* /opt/vagrant/embedded/lib64
```
If you encounter the following load error when using the vagrant-libvirt plugin (note the required by libk5crypto):
```/opt/vagrant/embedded/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require': /usr/lib64/libk5crypto.so.3: undefined symbol: EVP_KDF_ctrl, version OPENSSL_1_1_1b - /home/rbelgrave/.vagrant.d/gems/2.4.9/gems/ruby-libvirt-0.7.1/lib/_libvirt.so (LoadError)```
then the following steps have been found to resolve the problem. After the steps below are complete, then reinstall the vagrant-libvirt plugin without setting the `CONFIGURE_ARGS`. Thanks to Marco Bevc (see https://github.com/hashicorp/vagrant/issues/11020#issuecomment-625801983):
```shell
# Fedora
dnf download --source krb5-libs
# centos 8 stream, doesn't provide source RPMs, so you need to download like so
git clone https://git.centos.org/centos-git-common
# make get_sources.sh executable as it is needed in krb5
chmod +x centos-git-common/get_sources.sh
# centos-git-common needs its tools in PATH
export PATH=$(readlink -f ./centos-git-common):$PATH
git clone https://git.centos.org/rpms/krb5
cd krb5
git checkout imports/c8s/krb5-1.18.2-8.el8
get_sources.sh
into_srpm.sh -d c8s
cd SRPMS
# common commands (make sure to adjust verison accordingly)
rpm2cpio krb5-1.18.2-8c8s.src.rpm | cpio -imdV
tar xf krb5-1.18.2.tar.gz
cd krb5-1.18.2/src
./configure
make
sudo cp -P lib/crypto/libk5crypto.* /opt/vagrant/embedded/lib64/
```

View File

@ -20,10 +20,6 @@ Gem::Specification.new do |s|
s.require_paths = ['lib']
s.version = VagrantPlugins::ProviderLibvirt.get_version
s.add_development_dependency "rspec-core", ">= 3.5"
s.add_development_dependency "rspec-expectations", ">= 3.5"
s.add_development_dependency "rspec-mocks", ">= 3.5"
s.add_runtime_dependency 'fog-libvirt', '>= 0.6.0'
s.add_runtime_dependency 'fog-core', '~> 2'
s.add_runtime_dependency 'rexml'
@ -33,4 +29,7 @@ Gem::Specification.new do |s|
s.add_runtime_dependency 'nokogiri', '~> 1.6'
s.add_development_dependency 'rake'
s.add_development_dependency "rspec-core", ">= 3.5"
s.add_development_dependency "rspec-expectations", ">= 3.5"
s.add_development_dependency "rspec-mocks", ">= 3.5"
end