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. 454
      kvm-install-vm
  4. 6
      tests/check_distributions.bats
  5. 4
      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

454
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
@ -28,11 +27,10 @@ COMMANDS
remove - delete a guest domain
EOF
exit 0
exit 0
}
function usage_subcommand ()
{
function usage_subcommand() {
case "$1" in
create)
printf "NAME\n"
@ -72,7 +70,7 @@ function usage_subcommand ()
printf "\n"
printf "DISTRIBUTIONS\n"
list_available_vms
printf "\n"
printf "\n"
printf "EXAMPLES\n"
printf " %s create foo\n" "$prog"
printf " Create VM with the default parameters: CentOS 8, 1 vCPU, 1GB RAM, 10GB\n"
@ -145,22 +143,24 @@ function usage_subcommand ()
}
# Console output colors
red() { echo -e "\e[31m$@\e[0m" ; }
green() { echo -e "\e[32m$@\e[0m" ; }
yellow() { echo -e "\e[33m$@\e[0m" ; }
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 ; }
silent() { "$@" > /dev/null 2>&1 ; }
output() { echo -e "- $@" ; }
outputn() { echo -en "- $@ ... " ; }
ok() { green "${@:-OK}" ; }
die() {
red "ERR: $@" >&2
exit 2
}
silent() { "$@" > /dev/null 2>&1; }
output() { echo -e "- $@"; }
outputn() { echo -en "- $@ ... "; }
ok() { green "${@:-OK}"; }
pushd() { command pushd "$@" >/dev/null ; }
popd() { command popd "$@" >/dev/null ; }
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,38 +194,32 @@ 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
outputn "$msg"
fi
( "$@" &>> ${VMNAME}.log && ok )
("$@" &>> ${VMNAME}.log && ok)
}
# 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}
@ -277,9 +266,9 @@ function fetch_images ()
for vm in "${BUILTIN_VMS[@]}"; do
IFS=\| read -r vm_distro vm_desc vm_arch vm_url vm_login_user <<< "$vm"
if [[ "$vm_distro" == "$DISTRO" && "$vm_arch" == "$ARCH" ]]; then
QCOW="${vm_url##*/}" # Grab just the file from the URL to pass into virt-install
OS_INFO="$vm_distro" # Distro name should come from osinfo
IMAGE_URL="${vm_url%/*}" # Grab everything but the filename and the slash
QCOW="${vm_url##*/}" # Grab just the file from the URL to pass into virt-install
OS_INFO="$vm_distro" # Distro name should come from osinfo
IMAGE_URL="${vm_url%/*}" # Grab everything but the filename and the slash
DISK_FORMAT="qcow2"
LOGIN_USER="$vm_login_user"
found="true"
@ -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,47 +315,42 @@ 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."
else
# Place contents of $PUBKEY into $KEY
KEY=$(<${PUBKEY})
KEY=$(< ${PUBKEY})
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. "\
"See https://libosinfo.org/download for more information."
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* )
almalinux* | centos* | fedora* | rocky* | *-atomic | amazon* | opensuse*)
SUDOGROUP="wheel"
;;
ubuntu*|debian* )
ubuntu* | debian*)
SUDOGROUP="sudo"
;;
*)
@ -378,46 +359,44 @@ 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() {
local share_dir=""
if command -v rpm >/dev/null 2>&1 && rpm -q edk2-ovmf >/dev/null 2>&1; then
share_dir="/usr/share/edk2/ovmf"
elif command -v dpkg >/dev/null 2>&1 && dpkg -s edk2-ovmf >/dev/null 2>&1; then
share_dir="/usr/share/OVMF"
else
BOOTFLAG=""
return
fi
local machine
case "$ARCH" in
x86_64) machine="--machine q35" ;;
aarch64) machine="--machine virt" ;;
*) machine="" ;;
esac
local suffix=""
if (( SECUREBOOT )); then
suffix=".secboot"
fi
local code_fd="${share_dir}/OVMF_CODE${suffix}.fd"
local vars_fd="${share_dir}/OVMF_VARS${suffix}.fd"
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"
local share_dir=""
if command -v rpm > /dev/null 2>&1 && rpm -q edk2-ovmf > /dev/null 2>&1; then
share_dir="/usr/share/edk2/ovmf"
elif command -v dpkg > /dev/null 2>&1 && dpkg -s edk2-ovmf > /dev/null 2>&1; then
share_dir="/usr/share/OVMF"
else
BOOTFLAG=""
return
fi
local machine
case "$ARCH" in
x86_64) machine="--machine q35" ;;
aarch64) machine="--machine virt" ;;
*) machine="" ;;
esac
local suffix=""
if ((SECUREBOOT)); then
suffix=".secboot"
fi
local code_fd="${share_dir}/OVMF_CODE${suffix}.fd"
local vars_fd="${share_dir}/OVMF_VARS${suffix}.fd"
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_
@ -480,36 +458,38 @@ ${SCRIPT}
--==BOUNDARY==--
_EOF_
else
cat >> $USER_DATA << _EOF_
cat >> $USER_DATA << _EOF_
--==BOUNDARY==--
_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 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."
;;
ubuntu* | amazon2)
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."
;;
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
@ -592,15 +570,15 @@ _EOF_
status_file="/var/lib/libvirt/dnsmasq/${BRIDGE}.status"
IP=""
timeout=60 # seconds
timeout=60 # seconds
if [[ -f "$status_file" ]]; then
outputn "Waiting for domain to get an IP address "
for (( i=0; i<timeout; i++ )); do
for ((i = 0; i < timeout; i++)); do
IP=$(
{ grep -B1 -m1 "\"mac-address\": \"$MAC\"" "$status_file" || true; } |
awk -F'"' '/ip-address/ {print $4; exit}'
awk -F'"' '/ip-address/ {print $4; exit}'
)
if [[ -n "$IP" ]]; then
@ -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,24 +617,21 @@ _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}" ;;
v ) VERBOSE=1 ;;
h ) usage ;;
* ) die "Unsupported option. Run 'kvm-install-vm help remove'." ;;
l) IMAGEDIR="${OPTARG}" ;;
L) VMDIR="${OPTARG}" ;;
v) VERBOSE=1 ;;
h) usage ;;
*) die "Unsupported option. Run 'kvm-install-vm help remove'." ;;
esac
done
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,32 +642,31 @@ 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)
CPUS=1 # Number of virtual CPUs
FEATURE=host-model # Use host cpu features to the guest
MEMORY=1536 # Amount of RAM in MB
DISK_SIZE="" # Disk Size in GB
DNSDOMAIN=example.local # DNS domain
GRAPHICS=spice # Graphics type or "auto"
RESIZE_DISK=false # Resize disk (boolean)
IMAGEDIR=${HOME}/virt/images # Directory to store images
VMDIR=${HOME}/virt/vms # Directory to store virtual machines
BRIDGE=virbr0 # Hypervisor bridge
PUBKEY="" # SSH public key
DISTRO=rocky9 # Distribution
MACADDRESS="" # MAC Address
PORT=-1 # Console port
TIMEZONE=US/Eastern # Timezone
ADDITIONAL_USER=${USER} # User
ASSUME_YES=0 # Assume yes to prompts
ASSUME_NO=0 # Assume no to prompts
VERBOSE=0 # Verbosity
VIRTTYPE=kvm # Virt type (kvm, xen, qemu)
SECUREBOOT=0 # Enable UEFI with SecureBoot
AUTOSTART=false # Automatically start VM at boot time
ARCH=$(uname -m) # Architecture (autodetected)
CPUS=1 # Number of virtual CPUs
FEATURE=host-model # Use host cpu features to the guest
MEMORY=1536 # Amount of RAM in MB
DISK_SIZE="" # Disk Size in GB
DNSDOMAIN=example.local # DNS domain
GRAPHICS=spice # Graphics type or "auto"
RESIZE_DISK=false # Resize disk (boolean)
IMAGEDIR=${HOME}/virt/images # Directory to store images
VMDIR=${HOME}/virt/vms # Directory to store virtual machines
BRIDGE=virbr0 # Hypervisor bridge
PUBKEY="" # SSH public key
DISTRO=rocky9 # Distribution
MACADDRESS="" # MAC Address
PORT=-1 # Console port
TIMEZONE=US/Eastern # Timezone
ADDITIONAL_USER=${USER} # User
ASSUME_YES=0 # Assume yes to prompts
ASSUME_NO=0 # Assume no to prompts
VERBOSE=0 # Verbosity
VIRTTYPE=kvm # Virt type (kvm, xen, qemu)
SECUREBOOT=0 # Enable UEFI with SecureBoot
# Reset OPTIND
OPTIND=1
@ -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,59 +746,54 @@ 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}" ;;
c ) CPUS="${OPTARG}" ;;
d ) DISK_SIZE="${OPTARG}" ;;
D ) DNSDOMAIN="${OPTARG}" ;;
f ) FEATURE="${OPTARG}" ;;
g ) GRAPHICS="${OPTARG}" ;;
i ) IMAGE="${OPTARG}" ;;
k ) PUBKEY="${OPTARG}" ;;
l ) IMAGEDIR="${OPTARG}" ;;
L ) VMDIR="${OPTARG}" ;;
m ) MEMORY="${OPTARG}" ;;
M ) MACADDRESS="${OPTARG}" ;;
p ) PORT="${OPTARG}" ;;
s ) SCRIPTNAME="${OPTARG}" ;;
t ) DISTRO="${OPTARG}" ;;
T ) TIMEZONE="${OPTARG}" ;;
u ) ADDITIONAL_USER="${OPTARG}" ;;
V ) VIRTTYPE="${OPTARG}" ;;
y ) ASSUME_YES=1 ;;
n ) ASSUME_NO=1 ;;
S ) SECUREBOOT=1 ;;
v ) VERBOSE=1 ;;
h ) usage ;;
* ) die "Unsupported option. Run 'kvm-install-vm help create'." ;;
a) AUTOSTART="${OPTARG}" ;;
b) BRIDGE="${OPTARG}" ;;
c) CPUS="${OPTARG}" ;;
d) DISK_SIZE="${OPTARG}" ;;
D) DNSDOMAIN="${OPTARG}" ;;
f) FEATURE="${OPTARG}" ;;
g) GRAPHICS="${OPTARG}" ;;
i) IMAGE="${OPTARG}" ;;
k) PUBKEY="${OPTARG}" ;;
l) IMAGEDIR="${OPTARG}" ;;
L) VMDIR="${OPTARG}" ;;
m) MEMORY="${OPTARG}" ;;
M) MACADDRESS="${OPTARG}" ;;
p) PORT="${OPTARG}" ;;
s) SCRIPTNAME="${OPTARG}" ;;
t) DISTRO="${OPTARG}" ;;
T) TIMEZONE="${OPTARG}" ;;
u) ADDITIONAL_USER="${OPTARG}" ;;
V) VIRTTYPE="${OPTARG}" ;;
y) ASSUME_YES=1 ;;
n) ASSUME_NO=1 ;;
S) SECUREBOOT=1 ;;
v) VERBOSE=1 ;;
h) usage ;;
*) die "Unsupported option. Run 'kvm-install-vm help create'." ;;
esac
done
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
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,22 +851,20 @@ 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}" ;;
t ) TARGET="${OPTARG}" ;;
h ) usage ;;
* ) die "Unsupported option. Run 'kvm-install-vm help attach-disk'." ;;
d) DISKSIZE="${OPTARG}G" ;;
f) FORMAT="${OPTARG}" ;;
t) TARGET="${OPTARG}" ;;
h) usage ;;
*) die "Unsupported option. Run 'kvm-install-vm help attach-disk'." ;;
esac
done
@ -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 ) && \
outputn "Attaching ${DISKNAME} to domain ${VMNAME}"
${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
@ -969,7 +929,7 @@ case "${subcommand}" in
virsh list --all
exit 0
;;
create|remove|attach-disk|remove-disk)
create | remove | attach-disk | remove-disk)
set_defaults
set_custom_defaults

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 ]

4
test.sh → tests/run

@ -1,7 +1,7 @@
#!/bin/bash
if ! command -v bats >/dev/null 2>&1; then
cat <<EOF >&2
cat <<EOF >&2
Error: The 'bats' testing framework is required but was not found.
Please install it and try again:
@ -12,7 +12,7 @@ Please install it and try again:
sudo dnf install bats
EOF
exit 1
exit 1
fi
$(which bats) tests/

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