Skip to content

Commit

Permalink
chore: Add initial VM configuration and cloud-init setup scripts
Browse files Browse the repository at this point in the history
Signed-off-by: Schubert Anselme <[email protected]>
  • Loading branch information
sanselme committed Nov 5, 2024
1 parent 4293055 commit 3719751
Show file tree
Hide file tree
Showing 5 changed files with 283 additions and 17 deletions.
46 changes: 41 additions & 5 deletions config/site.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,50 @@
---
spec:
domain: local
dir: /tmp
config:
ssh:
key:
file: ${site_dir}/id_ed25519
gpg:
dir: ${site_dir}/.gnupg
pki:
dir: /tmp/pki
dir: ${site_dir}/pki
ca:
bundle: /tmp/ca.pfx
days: 3065
bundle: ${site_dir}/ca.pfx
days: "3065"
subj: /CN=root-ca
key:
file: /tmp/pki/ca.key
file: ${site_dir}/pki/ca.key
cert:
file: /tmp/pki/ca.crt
file: ${site_dir}/pki/ca.crt
service:
libvirt:
enabled: true
cloudinit: ${libvirt_dir}/boot
emulator: $(command -v ${qemu-system-${arch})
firmware: ${firmware_dir}/edk2-${arch}-code.fd
images: ${libvirt_dir}/images
vm:
- name: skiff
arch: null
cpu: null
image: null
memory: null
os:
name: ubuntu
version: 24.04
url: http://ubuntu.com
cloudinit:
enabled: true
file: ${site_dir}/user-data
networks:
interfaces:
oam:
address:
mac: ba:be:fa:ce:00:00
ipv4:
dhcp: true
ipv6:
dhcpv6: true
status: {}
52 changes: 52 additions & 0 deletions config/vm.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<domain type="${vm_type}">
<vcpu placement="static">2</vcpu>
<metadata>
<libosinfo xmlns="http://libosinfo.org/xmlns/libvirt/domain/1.0">
<os id="${os_url}/${os_name}/${os_version}"/>
</libosinfo>
</metadata>
<os>
<type arch="${arch}" machine="virt-9.1">hvm</type>
<boot dev="hd"/>
<bootmenu enable="yes"/>
</os>
<features>
<gic version="3"/>
</features>
<devices>
<emulator>${libvirt_emulator}</emulator>
<console type="pty"/>
<serial type="pty"/>
<disk device="cdrom">
<driver name="qemu" type="raw"/>
<target dev="sda" bus="sata"/>
<readonly/>
</disk>
<channel type="unix">
<target type="virtio" name="org.qemu.guest_agent.0"/>
</channel>
<channel type="unix">
<target type="virtio" name="org.libguestfs.channel.0"/>
</channel>
<tpm model="tpm-tis">
<backend type="emulator" version="2.0"/>
</tpm>
<rng model="virtio">
<backend model="random">/dev/urandom</backend>
</rng>
</devices>
<commandline xmlns="http://libvirt.org/schemas/domain/qemu/1.0">
<arg value="-drive"/>
<arg value="id=hd0,if=pflash,readonly=on,format=raw,file=${libvirt_firmware}"/>
<arg value="-drive"/>
<arg value="file=${vol},id=hd1,if=none,discard=unmap,format=qcow2"/>
<arg value="-device"/>
<arg value="virtio-scsi-pci,id=scsi1,addr=0x3"/>
<arg value="-device"/>
<arg value="scsi-hd,bus=scsi1.0,drive=hd1"/>
<arg value="-netdev"/>
<arg value="vmnet-shared,id=oam"/>
<arg value="-device"/>
<arg value="virtio-net-pci,id=net1,netdev=oam,addr=0x4,mac=${networks_interfaces_oam_address_mac}"/>
</commandline>
</domain>
145 changes: 145 additions & 0 deletions scripts/createvm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-3.0
# source scripts/aliases.sh
source scripts/environment.sh

create_vm() {
export name="${1}"
config="${2}"

[[ -z "${name}" ]] && echo "name is required" && exit 1
[[ -z "${config}" ]] && echo "config is required" && exit 1
export site_dir="$(yq '.site.dir' "${config}")"

[[ -z "${arch}" ]] && export arch="$(uname -m)"
case "${arch}" in
arm64)
export arch="aarch64"
;;
*) ;;
esac

export $(getenv <(yq '.site.service | select(.libvirt)' "${config}") | envsubst)
export $(getenv <(yq '.site.vm[] | select(.name == env(name))' "${config}") | envsubst)
export vm_id="$(uuidgen)"

if [[ -z "${vm_type}" ]]; then
case "$(uname -s)" in
Linux)
export vm_type="kvm"
[[ -z "${cpu}" ]] && export cpu="host-passthrough"
;;
Darwin)
export vm_type="hvf"
[[ -z "${cpu}" ]] && export cpu="host-passthrough"
;;
*)
export vm_type="qemu"
;;
esac
fi

user_data="${cloudinit_file}"
network_config="${site_dir}/network-config"
vm_file="${site_dir}/vm-${name}.xml"

stat "${vm_file}" >/dev/null 2>&1 ||
cp -f config/vm.xml "${vm_file}"

# create cloudinit iso
if [[ "${cloudinit_enabled}" ]]; then
# meta-data
printf "instance-id: ${vm_id}\nlocal-hostname: ${vm_id}\ncloud-name: nocloud\n" >/tmp/meta-data

# network-config
yq '.network.ethernets.oam.match.macaddress = env(networks_interfaces_oam_address_mac) |
(.. | select(tag == "!!str")) |= envsubst
' config/netplan/default.yaml | tr -d '"' >"${network_config}"

# user-data
stat "${cloudinit_file}" >/dev/null 2>&1 ||
printf "#cloud-config" >"${cloudinit_file}"

if [[ -n "${libvirt_cloudinit}" ]]; then
export vm_cloudinit="${libvirt_cloudinit}"
else
export vm_cloudinit="${site_dir}/cloudinit.iso"
fi

stat "${vm_cloudinit}" >/dev/null 2>&1 ||
createiso "${vm_cloudinit}" /tmp/meta-data "${cloudinit_file}" "${network_config}"

# update vm config
yq --inplace '. |
select(.domain.devices.disk.+@device == "cdrom").domain.devices.disk.source.+@file = env(vm_cloudinit)
' "${vm_file}"
fi

# create volume
if [[ -n "${libvirt_images}" ]]; then
export vol="${libvirt_images}/${name}.qcow2"
else
export vol="/tmp/${name}.qcow2"
fi
if [[ -n "${image}" ]]; then
stat "${vol}" >/dev/null 2>&1 ||
createvol "${vol}" "${image}"
else
stat "${vol}" >/dev/null 2>&1 ||
createvol "${vol}"
fi

# fixme: add vcpu count
[[ -n "${cpu}" ]] && yq --inplace '.domain.cpu.+@mode = env(cpu)' "${vm_file}" # cpu
[[ -z "${memory}" ]] && export memory=4194304 # memory in kib
if [[ "${arch}" != "x86_64" ]]; then
# watchdog
export vm_watchdog_model="i6300esb"
export vm_watchdog_action="reset"
fi

# create vm config
yq --inplace '
.domain.name = env(name) |
.domain.uuid = env(vm_id) |
.domain.memory = env(memory) |
.domain.devices.watchdog.+@model=env(vm_watchdog_model) |
.domain.devices.watchdog.+@action=env(vm_watchdog_action) |
(.. | select(tag == "!!str")) |= envsubst
' "${vm_file}"

grep -q "${name}" <(virsh list --all) ||
virsh define "${vm_file}"
}

delete_vm() {
name="${1}"
[[ -z "${name}" ]] && echo "name is required" && exit 1
if grep -q "${name}" <(sudo virsh list --all); then
sudo virsh destroy "${name}"
sudo virsh dumpxml "${name}" | yq -p xml '.domain.os.nvram.+content' | xargs sudo rm -f -
sudo virsh undefine --remove-all-storage "${name}"
fi
}

case "${1}" in
--create)
create_vm "${@:2}"
;;
--delete)
delete_vm "${2}"
;;
*)
echo """
Usage: ${0} [OPTIONS]
OPTIONS:
--create <name> <config>
--delete <name>
EXAMPLES:
${0} --create myvm /path/to/config.yaml
"""
exit 1
;;
esac
55 changes: 44 additions & 11 deletions scripts/environment.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,23 +49,56 @@ getenvarval() {
# env | awk -F "=" "/${key}/ { print \$2 }"
}

createiso() {
isocmd="genisoimage"
if [[ -z $(command -v "${isocmd}") ]]; then
isocmd="mkisofs"
if [[ -z $(command -v "${isocmd}") ]]; then
echo "genisoimage nor mkisofs found"
exit 1
fi
fi

"${isocmd}" -joliet -rock -output "${1}" -volid cidata "${@:2}"
}

createvol() {
local vol_file="${1}"
local img_file="${2}"

[[ -z "${vol_file}" ]] && echo "name is required" && exit 1
[[ -z "${img_file}" ]] && echo "image file not provided"

if [[ -n "${img_file}" ]]; then
img_dir="$(dirname "${img_file}")"
stat -d "${img_dir}" >/dev/null 2>&1 ||
mkdir -p "${img_dir}"

grep -qa "${vol_file}" <(sudo ls "${vol_file}") ||
qemu-img create -b "${img_file}" -f qcow2 -F qcow2 "${vol_file}" "${3:-16G}"
else
grep -qa "${vol_file}" <(sudo ls "${vol_file}") ||
qemu-img create -f qcow2 "${vol_file}" "${3:-16G}"
fi
}

cache() {
CACHE_DIR=".cache"
local cache_dir=".cache"

REPO="${1}"
ITEMS="${2}"
VERSION="${3:-main}"
local repo="${1}"
local items="${2}"
local version="${3:-main}"

[[ -z "${REPO}" ]] && echo "ERROR: repository is required" && return 1
[[ -z "${ITEMS}" ]] && echo "ERROR: item list is required" && return 1
[[ -z "${repo}" ]] && echo "ERROR: repository is required" && return 1
[[ -z "${items}" ]] && echo "ERROR: item list is required" && return 1

if [[ ! -d "${CACHE_DIR}" ]]; then
mkdir -p "${CACHE_DIR}"
if [[ ! -d "${cache_dir}" ]]; then
mkdir -p "${cache_dir}"
tmp="$(mktemp -d)"
gh repo clone "${REPO}" "${tmp}" -- --depth 1 --branch "${VERSION}"
gh repo clone "${repo}" "${tmp}" -- --depth 1 --branch "${version}"

for ITEM in ${ITEMS[@]}; do
cp -r "${tmp}/${ITEM}" "${CACHE_DIR}/"
for item in ${items[@]}; do
cp -r "${tmp}/${item}" "${cache_dir}/"
done

rm -rf "${tmp}"
Expand Down
2 changes: 1 addition & 1 deletion scripts/gencert.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-3.0
source scripts/aliases.sh
# source scripts/aliases.sh
source scripts/environment.sh

generate_root_ca() {
Expand Down

0 comments on commit 3719751

Please sign in to comment.