310 lines
6.6 KiB
Bash
Executable File
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
|
|
|