You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
4.3 KiB
111 lines
4.3 KiB
#!/bin/bash
|
|
|
|
set -Eeuo pipefail
|
|
|
|
if [[ $# -ne 1 ]]; then
|
|
echo "Usage: $0 <vm-name>"
|
|
exit 1
|
|
fi
|
|
|
|
VM="${1}"
|
|
if [ -d "/var/lib/libvirt/images/${VM}/" ]; then
|
|
echo "VM ${VM} already exists. Please remove it first."
|
|
exit 1
|
|
fi
|
|
|
|
temp_dir=$(mktemp -d)
|
|
cleanup() {
|
|
local exit_code=$?
|
|
rm -rf "$temp_dir"
|
|
if [ $exit_code -ne 0 ]; then
|
|
echo "An error occurred. Cleaning up..."
|
|
virsh destroy "${VM}" || true
|
|
virsh undefine "${VM}" --nvram || true
|
|
rm -rf "/var/lib/libvirt/images/${VM}/"
|
|
fi
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
# This function extracts the first layer blob from a Podman artifact and saves it to the specified output file.
|
|
# It is used when the "podman artifact extract" command is not available.
|
|
function podman_artifact_extract() {
|
|
local ARTIFACT="$1"
|
|
local OUTPUT_FILE="$2"
|
|
local container_id
|
|
|
|
local DIGEST_WITH_ALGO="$(podman artifact inspect $ARTIFACT | jq -r '.Manifest.layers[0].digest')"
|
|
local FILENAME="$(podman artifact inspect $ARTIFACT | jq -r '.Manifest.layers[0].annotations["org.opencontainers.image.title"]')"
|
|
echo "Extracting blob $DIGEST_WITH_ALGO ($FILENAME) from artifact $ARTIFACT to $OUTPUT_FILE..."
|
|
|
|
local BLOB_HASH="${DIGEST_WITH_ALGO#sha256:}"
|
|
local SOURCE_PATH="$(find /var/lib/containers/storage -type f -name $BLOB_HASH)"
|
|
if [ -z "$SOURCE_PATH" ]; then
|
|
echo "Blob $BLOB_HASH not found in container storage!"
|
|
return 1
|
|
fi
|
|
|
|
cp "$SOURCE_PATH" "$OUTPUT_FILE"
|
|
}
|
|
|
|
# Create a temporary directory to hold the VM image and copy the base image there
|
|
install -m 0710 -o root -g qemu --context=system_u:object_r:virt_image_t:s0 -d "$temp_dir"
|
|
|
|
# Pull the base image defined in the environment file
|
|
podman artifact pull "${DOMAIN_DISK_SOURCE}"
|
|
#podman artifact extract "${DOMAIN_DISK_SOURCE}" "$temp_dir/root.qcow2"
|
|
podman_artifact_extract "${DOMAIN_DISK_SOURCE}" "$temp_dir/root.qcow2"
|
|
chown root:qemu "$temp_dir/root.qcow2"
|
|
chmod 0660 "$temp_dir/root.qcow2"
|
|
chcon system_u:object_r:virt_image_t:s0 "$temp_dir/root.qcow2"
|
|
|
|
# Inject the Flightctl configuration file (w/ enrollment certificates) into the VM image
|
|
# Note: The injected config file will be moved to the right place in the VM by a systemd override in the base image
|
|
if [ -f /etc/flightctl/config.yaml ]; then
|
|
if [ -n "${FLIGHTCTL_LABELS_OVERRIDE:-}" ]; then
|
|
echo "Overriding default labels with: ${FLIGHTCTL_LABELS_OVERRIDE}"
|
|
yq e ". * { \"default-labels\": ${FLIGHTCTL_LABELS_OVERRIDE} } | .default-labels.aap-group = ((.default-labels.site + \"_\" + .default-labels.type) | sub(\"-\", \"_\"))" /etc/flightctl/config.yaml > "$temp_dir/config.yaml"
|
|
else
|
|
cp /etc/flightctl/config.yaml "$temp_dir/config.yaml"
|
|
fi
|
|
echo "Injecting Flightctl configuration into the VM image..."
|
|
guestfish --add "$temp_dir/root.qcow2" -m /dev/sda4 <<EOF
|
|
copy-in $temp_dir/config.yaml /ostree/deploy/default/var/lib/private/flightctl/
|
|
EOF
|
|
fi
|
|
|
|
# Inject the OSTree auth.json file into the VM image if it exists on the host
|
|
# Note: The injected config file will be moved to the right place in the VM by a systemd override in the base image
|
|
if [ -f /etc/ostree/auth.json ]; then
|
|
echo "Injecting OSTree auth.json into the VM image..."
|
|
guestfish --add "$temp_dir/root.qcow2" -m /dev/sda4 <<'EOF'
|
|
copy-in /etc/ostree/auth.json /ostree/deploy/default/var/lib/private/flightctl/
|
|
EOF
|
|
fi
|
|
|
|
# Copy the VM image to the libvirt images directory
|
|
echo "Copying the VM disk to the libvirt images directory..."
|
|
install -m 0710 -o root -g qemu -Z -d "/var/lib/libvirt/images/${VM}"
|
|
install -m 0660 -o root -g qemu -Z "$temp_dir/root.qcow2" "/var/lib/libvirt/images/${VM}/root.qcow2"
|
|
|
|
# Create and start the VM using virt-install
|
|
echo "Creating and starting the VM ${VM}..."
|
|
virt-install --name "${VM}" \
|
|
--autostart \
|
|
--cpu=host-passthrough \
|
|
--vcpus=${DOMAIN_VCPUS} \
|
|
--ram=${DOMAIN_RAM} \
|
|
--os-variant=${DOMAIN_OS_VARIANT} \
|
|
--disk=path=/var/lib/libvirt/images/${VM}/root.qcow2,bus=virtio,format=qcow2,size=${DOMAIN_DISK_SIZE} \
|
|
--console=pty,target_type=virtio \
|
|
--serial=pty \
|
|
--graphics=none \
|
|
--import \
|
|
--network=network=default,mac=${DOMAIN_MAC_ADDRESS} \
|
|
--noautoconsole
|
|
|
|
echo "VM ${VM} has been created and started."
|
|
|
|
# Cleanup the pulled image
|
|
podman artifact rm "${DOMAIN_DISK_SOURCE}" || true
|
|
|
|
exit 0
|
|
|