Browse Source

style: add editorconfig and run shfmt (#95)

pull/96/head 1.2.12
Giovanni Torres 8 months ago committed by GitHub
parent
commit
87e5d65d67
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 22
      .editorconfig
  2. 2
      README.md
  3. 224
      kvm-install-vm
  4. 6
      tests/check_distributions.bats
  5. 0
      tests/run
  6. 3
      tests/vmdir.bash
  7. 3
      tests/vmname.bash

22
.editorconfig

@ -0,0 +1,22 @@
# EditorConfig is awesome: http://EditorConfig.org
root = true
[*]
charset = utf-8
indent_size = 4
end_of_line = lf
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.{md,rst}]
trim_trailing_whitespace = false
[*.sh,test/run]
shell_variant = bash
space_redirects = true # -sr
switch_case_indent = true # -ci
[*.bats]
shell_variant = bats

2
README.md

@ -213,7 +213,7 @@ Tests are powered by [Bats](https://github.com/bats-core/bats-core).\
Run:
```bash
./test.sh
bash tests/run
```
## 🤝 Contributing

224
kvm-install-vm

@ -4,8 +4,7 @@ set -euo pipefail
# Set program name variable - basename without subshell
prog=${0##*/}
function usage ()
{
function usage() {
cat << EOF
NAME
kvm-install-vm - Install virtual guests using cloud-init on a local KVM
@ -31,8 +30,7 @@ EOF
exit 0
}
function usage_subcommand ()
{
function usage_subcommand() {
case "$1" in
create)
printf "NAME\n"
@ -149,7 +147,10 @@ red() { echo -e "\e[31m$@\e[0m" ; }
green() { echo -e "\e[32m$@\e[0m"; }
yellow() { echo -e "\e[33m$@\e[0m"; }
die() { red "ERR: $@" >&2 ; exit 2 ; }
die() {
red "ERR: $@" >&2
exit 2
}
silent() { "$@" > /dev/null 2>&1; }
output() { echo -e "- $@"; }
outputn() { echo -en "- $@ ... "; }
@ -159,8 +160,7 @@ pushd() { command pushd "$@" >/dev/null ; }
popd() { command popd "$@" > /dev/null; }
# Join zero or more strings into a delimited string.
function join ()
{
function join() {
local sep="$1"
if [ $# -eq 0 ]; then
return
@ -175,8 +175,7 @@ function join ()
# Print an optional name=value[,value,..] parameter.
# Prints nothing if no values are given.
function param ()
{
function param() {
if [ $# -lt 2 ]; then
return # skip empty value
fi
@ -187,8 +186,7 @@ function param ()
}
# Output a command, one argument per line.
function output_command ()
{
function output_command() {
local line_cont=$' \\ \n '
local command_lines=$(join "$line_cont" "$@")
printf " %s\n" "$command_lines"
@ -196,12 +194,10 @@ function output_command ()
# Command wrapper to output the command to be run in verbose
# mode and redirect stdout and stderr to the vm log file.
function run ()
{
function run() {
local msg="$1"
shift
if [ "${VERBOSE}" -eq 1 ]
then
if [ "${VERBOSE}" -eq 1 ]; then
output "$msg with the following command"
output_command "$@"
else
@ -211,23 +207,19 @@ function run ()
}
# Detect OS and set wget parameters
function set_wget ()
{
if [ -f /etc/fedora-release ]
then
function set_wget() {
if [ -f /etc/fedora-release ]; then
WGET="wget --quiet --show-progress"
else
WGET="wget"
fi
}
function check_vmname_set ()
{
function check_vmname_set() {
[ -n "${VMNAME}" ] || die "VMNAME not set."
}
function delete_vm ()
{
function delete_vm() {
# Check if domain exists and set DOMAIN_EXISTS variable.
domain_exists "${VMNAME}"
@ -236,29 +228,27 @@ function delete_vm ()
check_vmname_set
if [ "${DOMAIN_EXISTS}" -eq 1 ]
then
if [ "${DOMAIN_EXISTS}" -eq 1 ]; then
outputn "Destroying ${VMNAME} domain"
virsh destroy --graceful ${VMNAME} > /dev/null 2>&1 \
&& ok \
|| yellow "(Domain is not running.)"
virsh destroy --graceful ${VMNAME} > /dev/null 2>&1 &&
ok ||
yellow "(Domain is not running.)"
outputn "Undefining ${VMNAME} domain"
virsh undefine --managed-save --snapshots-metadata --nvram ${VMNAME} > /dev/null 2>&1 \
&& ok \
|| die "Could not undefine domain."
virsh undefine --managed-save --snapshots-metadata --nvram ${VMNAME} > /dev/null 2>&1 &&
ok ||
die "Could not undefine domain."
else
output "Domain ${VMNAME} does not exist"
fi
[[ -d ${VMDIR}/${VMNAME} ]] && DISKDIR=${VMDIR}/${VMNAME} || DISKDIR=${IMAGEDIR}/${VMNAME}
[ -d $DISKDIR ] \
&& outputn "Deleting ${VMNAME} files" \
&& rm -rf $DISKDIR \
&& ok
[ -d $DISKDIR ] &&
outputn "Deleting ${VMNAME} files" &&
rm -rf $DISKDIR &&
ok
if [ "${STORPOOL_EXISTS}" -eq 1 ]
then
if [ "${STORPOOL_EXISTS}" -eq 1 ]; then
outputn "Destroying ${VMNAME} storage pool"
virsh pool-destroy ${VMNAME} > /dev/null 2>&1 && ok
else
@ -266,8 +256,7 @@ function delete_vm ()
fi
}
function fetch_images ()
{
function fetch_images() {
# Create image directory if it doesn't already exist
mkdir -p ${IMAGEDIR}
@ -293,11 +282,9 @@ function fetch_images ()
IMAGE=${IMAGEDIR}/${QCOW}
if [ ! -f ${IMAGEDIR}/${QCOW} ]
then
if [ ! -f ${IMAGEDIR}/${QCOW} ]; then
set_wget
if [ -f ${IMAGEDIR}/${QCOW}.part ]
then
if [ -f ${IMAGEDIR}/${QCOW}.part ]; then
CONTINUE="--continue"
output "Partial cloud image found. Resuming download"
else
@ -308,7 +295,7 @@ function fetch_images ()
${CONTINUE} \
--directory-prefix ${IMAGEDIR} \
--output-document=${IMAGEDIR}/${QCOW}.part \
${IMAGE_URL}/${QCOW} || \
${IMAGE_URL}/${QCOW} ||
die "Could not download image."
mv ${IMAGEDIR}/${QCOW}.part ${IMAGEDIR}/${QCOW}
@ -316,8 +303,7 @@ function fetch_images ()
}
function check_ssh_key ()
{
function check_ssh_key() {
local key
if [ -z "${PUBKEY}" ]; then
# Try to find a suitable key file.
@ -329,8 +315,7 @@ function check_ssh_key ()
done
fi
if [ ! -f "${PUBKEY}" ]
then
if [ ! -f "${PUBKEY}" ]; then
# Check for existence of a pubkey, or else exit with message
die "Please generate an SSH keypair using 'ssh-keygen -t rsa' or \
specify one with the "-k" flag."
@ -340,31 +325,27 @@ function check_ssh_key ()
fi
}
function check_os_variant ()
{
function check_os_variant() {
if [[ ${OS_INFO} != auto ]]; then
osinfo-query os short-id=${OS_INFO} >/dev/null \
|| die "Unknown OS variant '${OS_INFO}'. Please update your osinfo-db. "\
osinfo-query os short-id=${OS_INFO} > /dev/null ||
die "Unknown OS variant '${OS_INFO}'. Please update your osinfo-db. " \
"See https://libosinfo.org/download for more information."
fi
}
function domain_exists ()
{
virsh dominfo "${1}" > /dev/null 2>&1 \
&& DOMAIN_EXISTS=1 \
|| DOMAIN_EXISTS=0
function domain_exists() {
virsh dominfo "${1}" > /dev/null 2>&1 &&
DOMAIN_EXISTS=1 ||
DOMAIN_EXISTS=0
}
function storpool_exists ()
{
virsh pool-info "${1}" > /dev/null 2>&1 \
&& STORPOOL_EXISTS=1 \
|| STORPOOL_EXISTS=0
function storpool_exists() {
virsh pool-info "${1}" > /dev/null 2>&1 &&
STORPOOL_EXISTS=1 ||
STORPOOL_EXISTS=0
}
function set_sudo_group ()
{
function set_sudo_group() {
case "${DISTRO}" in
almalinux* | centos* | fedora* | rocky* | *-atomic | amazon* | opensuse*)
SUDOGROUP="wheel"
@ -378,13 +359,12 @@ function set_sudo_group ()
esac
}
function check_delete_known_host ()
{
function check_delete_known_host() {
output "Checking for ${IP} in known_hosts file"
grep -q ${IP} ${HOME}/.ssh/known_hosts \
&& outputn "Found entry for ${IP}. Removing" \
&& (sed --in-place "/^${IP}/d" ~/.ssh/known_hosts && ok ) \
|| output "No entries found for ${IP}"
grep -q ${IP} ${HOME}/.ssh/known_hosts &&
outputn "Found entry for ${IP}. Removing" &&
(sed --in-place "/^${IP}/d" ~/.ssh/known_hosts && ok) ||
output "No entries found for ${IP}"
}
function set_boot_flag() {
@ -416,8 +396,7 @@ function set_boot_flag() {
BOOTFLAG="--boot uefi,loader=${code_fd},loader.readonly=yes,loader.type=pflash,nvram_template=$vars_fd,nvram=/var/tmp/$(basename "$vars_fd"),loader.secure=$( ((SECUREBOOT)) && echo yes || echo no) --features smm=on $machine"
}
function create_vm ()
{
function create_vm() {
# Create image directory if it doesn't already exist
mkdir -p ${VMDIR}
@ -468,8 +447,7 @@ ssh_authorized_keys:
timezone: ${TIMEZONE}
_EOF_
if [ ! -z "${SCRIPTNAME+x}" ]
then
if [ ! -z "${SCRIPTNAME+x}" ]; then
SCRIPT=$(< $SCRIPTNAME)
cat >> $USER_DATA << _EOF_
@ -486,29 +464,31 @@ _EOF_
_EOF_
fi
{ echo "instance-id: ${VMNAME}"; echo "local-hostname: ${VMNAME}"; } > $META_DATA
{
echo "instance-id: ${VMNAME}"
echo "local-hostname: ${VMNAME}"
} > $META_DATA
outputn "Copying cloud image ($(basename ${IMAGE}))"
DISK=${VMNAME}.qcow2
qemu-img create -q -f qcow2 -F qcow2 -b $IMAGE $DISK && ok
if $RESIZE_DISK
then
if $RESIZE_DISK; then
outputn "Resizing the disk to $DISK_SIZE"
# Workaround to prevent virt-resize from renumbering partitions and breaking grub
# See https://bugzilla.redhat.com/show_bug.cgi?id=1472039
# Ubuntu will automatically grow the partition to the new size on its first boot
case "$DISTRO" in
ubuntu* | amazon2)
qemu-img resize $DISK $DISK_SIZE &>> ${VMNAME}.log \
&& ok \
|| die "Could not resize disk."
qemu-img resize $DISK $DISK_SIZE &>> ${VMNAME}.log &&
ok ||
die "Could not resize disk."
;;
*)
qemu-img create -f qcow2 \
-o preallocation=metadata $DISK.new $DISK_SIZE &>> ${VMNAME}.log \
&& virt-resize --quiet --expand /dev/sda1 $DISK $DISK.new &>> ${VMNAME}.log \
&& (mv $DISK.new $DISK && ok) \
|| die "Could not resize disk."
-o preallocation=metadata $DISK.new $DISK_SIZE &>> ${VMNAME}.log &&
virt-resize --quiet --expand /dev/sda1 $DISK $DISK.new &>> ${VMNAME}.log &&
(mv $DISK.new $DISK && ok) ||
die "Could not resize disk."
;;
esac
fi
@ -518,8 +498,8 @@ _EOF_
virsh pool-create-as \
--name=${VMNAME} \
--type=dir \
--target=${VMDIR}/${VMNAME} \
|| die "Could not create storage pool. VM may already exist. Try removing first."
--target=${VMDIR}/${VMNAME} ||
die "Could not create storage pool. VM may already exist. Try removing first."
# Add custom MAC Address if specified
NETWORK_PARAMS="$(join ',' \
@ -536,8 +516,7 @@ _EOF_
${DISK_EXTRA})"
# Omit the --graphics option to auto-detect.
if [ "${GRAPHICS}" = 'auto' ]
then
if [ "${GRAPHICS}" = 'auto' ]; then
GRAPHICS_PARAMS=""
else
GRAPHICS_PARAMS="$(join ',' \
@ -568,19 +547,18 @@ _EOF_
--noautoconsole \
${GRAPHICS_OPTION} \
${BOOTFLAG} \
${VIRT_INSTALL_EXTRA} \
|| die "Could not create domain with virt-install."
${VIRT_INSTALL_EXTRA} ||
die "Could not create domain with virt-install."
virsh dominfo ${VMNAME} &>> ${VMNAME}.log
# Enable autostart if true
if $AUTOSTART
then
if $AUTOSTART; then
outputn "Enabling autostart"
virsh autostart \
--domain ${VMNAME} > /dev/null 2>&1 \
&& ok \
|| die "Could not enable autostart."
--domain ${VMNAME} > /dev/null 2>&1 &&
ok ||
die "Could not enable autostart."
fi
# Remove the unnecessary cloud init files
@ -626,8 +604,7 @@ _EOF_
output " ssh ${LOGIN_USER}@${VMNAME}"
CONSOLE=$(virsh domdisplay ${VMNAME})
# Workaround because VNC port number shown by virsh domdisplay is offset from 5900
if [ "${GRAPHICS}" = 'vnc' ]
then
if [ "${GRAPHICS}" = 'vnc' ]; then
CONSOLE_NO_PORT=$(echo $CONSOLE | cut -d ':' -f 1,2 -)
CONSOLE_PORT=$(expr 5900 + $(echo $CONSOLE | cut -d ':' -f 3 -))
output "Console at ${CONSOLE_NO_PORT}:${CONSOLE_PORT}"
@ -640,11 +617,9 @@ _EOF_
}
# Delete VM
function remove ()
{
function remove() {
# Parse command line arguments
while getopts ":l:L:hv" opt
do
while getopts ":l:L:hv" opt; do
case "$opt" in
l) IMAGEDIR="${OPTARG}" ;;
L) VMDIR="${OPTARG}" ;;
@ -656,8 +631,7 @@ function remove ()
shift $((OPTIND - 1))
if [ "$#" != 1 ]
then
if [ "$#" != 1 ]; then
printf "Please specify a single host to remove.\n"
printf "Run 'kvm-install-vm help remove' for usage.\n"
exit 1
@ -668,8 +642,7 @@ function remove ()
delete_vm
}
function set_defaults ()
{
function set_defaults() {
# Defaults are set here. Override using command line arguments.
AUTOSTART=false # Automatically start VM at boot time
ARCH=$(uname -m) # Architecture (autodetected)
@ -726,8 +699,7 @@ function set_defaults ()
BUILTIN_VMS=("${DEFAULT_BUILTIN_VMS[@]}")
}
function set_custom_defaults ()
{
function set_custom_defaults() {
# Source custom defaults: first local .kivrc, then fallback to ~/.kivrc
if [ -f "./.kivrc" ]; then
source "./.kivrc"
@ -750,7 +722,6 @@ function set_custom_defaults ()
done
}
function list_available_vms() {
for key in "${!BUILTIN_VM_DESCRIPTIONS[@]}"; do
local arch="${BUILTIN_VM_ARCHS[$key]}"
@ -775,11 +746,9 @@ function list_available_vms() {
done | sort
}
function create ()
{
function create() {
# Parse command line arguments
while getopts ":b:c:d:D:f:g:i:k:l:L:m:M:p:s:t:T:u:V:ahynSv" opt
do
while getopts ":b:c:d:D:f:g:i:k:l:L:m:M:p:s:t:T:u:V:ahynSv" opt; do
case "$opt" in
a) AUTOSTART="${OPTARG}" ;;
b) BRIDGE="${OPTARG}" ;;
@ -812,22 +781,19 @@ function create ()
shift $((OPTIND - 1))
# Resize disk if you specify a disk size either via cmdline option or .kivrc
if [ -n "${DISK_SIZE}" ]
then
if [ -n "${DISK_SIZE}" ]; then
RESIZE_DISK=true
DISK_SIZE="${DISK_SIZE}G" # Append 'G' for Gigabyte
fi
# Yes (-y) and No (-n) are mutually exclusive.
if [[ "${ASSUME_YES}" -eq 1 ]] && [[ "${ASSUME_NO}" -eq 1 ]]
then
if [[ "${ASSUME_YES}" -eq 1 ]] && [[ "${ASSUME_NO}" -eq 1 ]]; then
printf "Please specify only one of -y or -n flags.\n"
exit 1
fi
# After all options are processed, make sure only one variable is left (vmname)
if [ "$#" != 1 ]
then
if [ "$#" != 1 ]; then
printf "Please specify a single host to create.\n"
printf "Run 'kvm-install-vm create help' for usage.\n"
exit 1
@ -842,8 +808,7 @@ function create ()
# Check for ssh key
check_ssh_key
if [ ! -z "${IMAGE+x}" ]
then
if [ ! -z "${IMAGE+x}" ]; then
output "Using custom QCOW2 image: ${IMAGE}."
OS_INFO="auto"
LOGIN_USER="<use the default account in your custom image>"
@ -886,16 +851,14 @@ function create ()
create_vm
}
function attach-disk ()
{
function attach-disk() {
# Set default variables
local FORMAT=qcow2
local TARGET=""
local DISKSIZE=""
# Parse command line arguments
while getopts ":d:f:t:h" opt
do
while getopts ":d:f:t:h" opt; do
case "$opt" in
d) DISKSIZE="${OPTARG}G" ;;
f) FORMAT="${OPTARG}" ;;
@ -910,8 +873,7 @@ function attach-disk ()
[ ! -z ${TARGET} ] || die "You must specify a target device, for e.g. '-t vdb'"
[ ! -z ${DISKSIZE} ] || die "You must specify a size (in GB) for the new device, for e.g. '-d 5'"
if [ "$#" != 1 ]
then
if [ "$#" != 1 ]; then
printf "Please specify a single host to attach a disk to.\n"
printf "Run 'kvm-install-vm help attach-disk' for usage.\n"
exit 1
@ -922,20 +884,18 @@ function attach-disk ()
[[ -d ${VMDIR}/${VMNAME} ]] && DISKDIR=${VMDIR}/${VMNAME} || DISKDIR=${IMAGEDIR}/${VMNAME}
DISKNAME=${VMNAME}-${TARGET}-${DISKSIZE}.${FORMAT}
if [ ! -f "${DISKDIR}/${DISKNAME}" ]
then
if [ ! -f "${DISKDIR}/${DISKNAME}" ]; then
outputn "Creating new '${TARGET}' disk image for domain ${VMNAME}"
(qemu-img create -f ${FORMAT} -o size=$DISKSIZE,preallocation=metadata \
${DISKDIR}/${DISKNAME} &>> ${DISKDIR}/${VMNAME}.log && ok ) && \
${DISKDIR}/${DISKNAME} &>> ${DISKDIR}/${VMNAME}.log && ok) &&
outputn "Attaching ${DISKNAME} to domain ${VMNAME}"
(virsh attach-disk ${VMNAME} \
--source $DISKDIR/${DISKNAME} \
--target ${TARGET} \
--subdriver ${FORMAT} \
--cache none \
--persistent &>> ${DISKDIR}/${VMNAME}.log && ok ) \
|| die "Could not attach disk."
--persistent &>> ${DISKDIR}/${VMNAME}.log && ok) ||
die "Could not attach disk."
else
die "Target ${TARGET} is already created or in use."
fi

6
tests/check_distributions.bats

@ -2,15 +2,13 @@
VMNAME=batstestvm
function create_test_vm ()
{
function create_test_vm() {
local -r var="$1"
run ./kvm-install-vm create -t ${var} ${VMNAME}-${var}
[ "$status" -eq 0 ]
}
function remove_test_vm ()
{
function remove_test_vm() {
local -r var="$1"
run ./kvm-install-vm remove ${VMNAME}-${var}
[ "$status" -eq 0 ]

0
test.sh → tests/run

3
tests/vmdir.bash

@ -1,6 +1,5 @@
VMDIR=${HOME}/virt/vms
if [[ -f .kivrc ]]
then
if [[ -f .kivrc ]]; then
source .kivrc
fi

3
tests/vmname.bash

@ -1,5 +1,4 @@
if [ -z "${VMNAME}" ]
then
if [ -z "${VMNAME}" ]; then
TIMESTAMP=$(date '+%Y%m%d%H%M%S')
export VMNAME="batstestvm-${TIMESTAMP}"
fi

Loading…
Cancel
Save