310 lines
6.6 KiB
Bash
Executable File

#!/bin/bash
# This function help to convert measures Bytes to/from Bits
# Usage: <number>[K|M|G|T]Byte|bit [K|M|G|T]Byte|bit
function _convert_bit {
echo $1 $2 | awk -F ' ' ' {
# Manage arguments: in
###################
i_number=gensub(/^([0-9]+(.[0-9]+)?)([kgmtKMGT]?)(.*)$/, "\\1", "g", $1);
i_factor=gensub(/^([0-9]+(.[0-9]+)?)([kgmtKMGT]?)(.*)$/, "\\3", "g", $1);
i_unit=gensub(/^([0-9]+(.[0-9]+)?)([kgmtKMGT]?)(.*)$/, "\\4", "g", $1);
# Manage arguments: out
###################
o_factor=gensub(/^([kgmtKMGT]?)(.*)$/, "\\1", "g", $2);
o_unit=gensub(/^([kgmtKMGT]?)(.*)$/, "\\2", "g", $2);
# Replace factor: in
###################
switch (toupper(i_factor)) {
case "K": i_number=i_number * 1024 ; break
case "M": i_number=i_number * (1024 ^ 2 ) ; break
case "G": i_number=i_number * (1024 ^ 3 ) ; break
case "T": i_number=i_number * (1024 ^ 4 ) ; break
}
# Convert Bytes to Bits if necessary: in
###################
if ( i_unit ~ /^B$|^[Bb]ytes?$/ || i_unit ~ /^[Oo](ctets?)?$/ )
i_number = i_number * 8;
else if ( i_unit ~ /^$/ || i_unit ~ /^(b|[b|B]its?)$/ ) {}
else {
print "Error: " $1 " is not a valid argument.";
exit 1
}
# Remove factor: out
###################
switch (toupper(o_factor)) {
case "K": i_number=i_number / 1024 ; break
case "M": i_number=i_number / (1024 ^ 2 ) ; break
case "G": i_number=i_number / (1024 ^ 3 ) ; break
case "T": i_number=i_number / (1024 ^ 4 ) ; break
}
# Convert Bits to Bytes if necessary: out
###################
if ( o_unit ~ /^B$|^[Bb]ytes?$/ || o_unit ~ /^[Oo](ctets?)?$/ ) {
print i_number / 8
}
else if ( o_unit ~ /^$/ || o_unit ~ /^(b|[b|B]its?)$/ ) {
print i_number
}
else {
print "Error: " o_unit " is not a valid argument.";
exit 1
}
}'
}
# This function helps to colorize console output
_shell_color () {
# Easy
RED='\033[31m'
GREEN='\033[32m'
YELLOW='\033[33m'
BLUE='\033[34m'
PURPLE='\033[35m'
CYAN='\033[36m'
WHITE='\033[37m'
NIL='\033[00m'
}
# This function display an error and quit
function _crit {
local RC=$1
shift 1
local MSG=$@
_log crit "$MSG"
exit $RC
}
# This function display log messages
function _log {
# Init
local CODE=${1,,}
shift 1
local MSG=$@
local COLOR=""
# Detect level
case $CODE in
0|emerg)
CODE="emerg"
COLOR=${RED}
;;
1|alert)
CODE="alert"
COLOR=${RED}
;;
2|crit)
CODE="crit"
COLOR=${RED}
;;
3|error|err)
CODE="error"
COLOR=${RED}
;;
4|warning|warn)
CODE="warn"
COLOR=${YELLOW}
;;
5|notice)
CODE="notice"
COLOR=${GREEN}
;;
6|info)
CODE="info"
COLOR=${CYAN}
;;
7|debug|*)
CODE="debug"
COLOR=${BLUE}
;;
esac
# Display message
echo $CODE | grep -E "$LOG_LEVEL" >/dev/null ; local RC=$?
if [ $RC -eq 0 ]; then
printf "${COLOR}%-6s: %s${NIL}\n" "${CODE^^}" "$MSG"
fi
}
function _help {
echo "Aide: "
}
# Usage:
# bin [-f] [-s <size>] [-t <type>] src_template dst_disk
# -f : force
# -s 15G : size
# -t qcow|qcow2|raw : type of image
# -c (compress)
# -p (show progress)
# -i/-o
#
#convert [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] filename [filename2 [...]] output_filename
# This function will create the volume instances
function virt_disk_template {
# Define default variables
################
local DISK_SRC=
local DISK_DEST=
local DISK_DEST_SIZE=0
local DISK_TYPE=qcow2
local DISK_COMPRESS=0
local DISK_PROGRESS=0
local DISK_FORCE=0
local DISK_HELP=0
local QEMU_IMG_BIN="$(whereis -b qemu-img | cut -d ' ' -f 2)"
local QEMU_IMG_OPT=""
# Get options
################
unset OPTIND
while getopts o:i:t:s:fcp flag; do
case $flag in
# Required variables
o)
DISK_DEST=${OPTARG}
;;
i)
DISK_SRC=${OPTARG}
;;
t)
DISK_TYPE=${OPTARG}
;;
s)
DISK_DEST_SIZE="${OPTARG}"
;;
f)
DISK_FORCE=1
;;
c)
DISK_COMPRESS=1
;;
p)
DISK_PROGRESS=1
;;
*)
_crit 1 "Argument $flag is not valid"
esac
done
shift $(( OPTIND - 1 ));
# Check the file i/o
################
if [[ -z "${DISK_SRC}" || ! -f "${DISK_SRC}" ]]; then
_crit 1 "Source image $DISK_SRC is not valid"
fi
if [[ -z "${DISK_DEST}" ]]; then
_crit 1 "Destination image is empty"
fi
# Get the template size (in G)
################
# get the size in BYTES !
local DISK_SRC_SIZE=$( qemu-img info ${DISK_SRC} \
| grep "virtual size" \
| awk '{ print gensub( /.*\((.*)bytes\)$/ , "\\1", "g" ) }' )
if [ -z "$DISK_SRC_SIZE" ]; then
_log error "The output of qemu-img info ${DISK_SRC} may not return size in Gb?"
_crit 1 "Impossible to get the disk template size"
fi
# Define options
################
if [ ${DISK_COMPRESS} -eq 1 ]; then
QEMU_IMG_OPT="${QEMU_IMG_OPT} -c"
fi
if [ ${DISK_PROGRESS} -eq 1 ]; then
QEMU_IMG_OPT="${QEMU_IMG_OPT} -p"
fi
# Set the final disk size
################
DISK_DEST_SIZE=$(_convert_bit ${DISK_DEST_SIZE} bit); RC=$?
if [ $RC -ne 0 ]; then
_crit 1 "Requested size for disk ${DISK_DEST} is not valid: ${DISK_DEST_SIZE}"
else
if [[ "${DISK_DEST_SIZE}" -ne 0 && "${DISK_DEST_SIZE}" -lt "${DISK_SRC_SIZE}" ]]; then
_log warn "Requested disk size for ${DISK_DEST} is lesser than template. Disk size set to $( _convert_bit ${DISK_SRC_SIZE} Gb)Gb"
else
QEMU_IMG_OPT="${QEMU_IMG_OPT} -S ${DISK_DEST_SIZE}"
fi
fi
# Create the disk
################
if [ "$DISK_TYPE" == "qcow2" ]; then
# Check if the destination exists and is writable
if [[ $DISK_FORCE -ne 1 && -f "$DISK_DEST" ]]; then
_crit 1 "The destination file already exists: $DISK_DEST"
else
_log info "The VM disk will be created in $DISK_DEST"
fi
# Create disk
local CMD="qemu-img convert \
${QEMU_IMG_OPT} \
-O qcow2 \
${DISK_SRC} ${DISK_DEST}"
_log DEBUG "$CMD"
$CMD
fi
}
if [[ -z "${@}" || "${1}" =~ ^--?h(elp)?$ ]]; then
_help
else
virt_disk_template $@
fi