194 lines
7.2 KiB
Bash
194 lines
7.2 KiB
Bash
#!/bin/bash
|
||
### МЫСЛИ ПО ФИЧАМ
|
||
# Сделать проверку, какие правила НА существуют, и вывести выбор /etc/pve/ha/rules.cfg
|
||
# Сделать добавление кастомного полльзователя с паролем
|
||
# Сделать замену тега влан
|
||
# Сделать проверку наличия ВМ перед клонированием. Если создать ВМ не удалось, скипаем, а не выходим.
|
||
# Добавить переезд на ноду, выбор ноды
|
||
# ИЗУЧИТЬ!!!! /usr/share/pve-docs/examples/guest-example-hookscript.pl
|
||
|
||
storage="syno-tigra"
|
||
path="/mnt/pve/$storage/snippets"
|
||
|
||
show_help()
|
||
echo 'Usage:'
|
||
echo 'vmcreate [-h][-a rule_name][-k pub_keyfile][-u][-p][-f filename]'
|
||
echo 'Arguments:'
|
||
echo '-h - show this help;'
|
||
echo '-a - add hosts to HA affinity rules;'
|
||
echo "-k - embed custom public key or create new if `pub_keyfile` not specified"
|
||
echo "-u - specify user instead of default `root`"
|
||
echo "-p - UNDER CONSTRUCTION!!!!!! specify password instead of default"
|
||
echo "-f - get IP addresses and Hostnames from `flilename`;"
|
||
echo "\nIf file not specified, script will use arguments as a list of IP addresses."
|
||
echo "In this case Hostname will be inherited from 2 last IP octets. Example for 10.10.35.20: `vm035020`."
|
||
echo "IP address should be 10.10.*.*"
|
||
|
||
|
||
# Обрабатываем опции
|
||
while getopts "a:f:h" opt; do
|
||
case $opt in
|
||
a) harule="$OPTARG";;
|
||
f) file="$OPTARG" ;;
|
||
h) show_help ; exit 0;;
|
||
k) pubkey="$OPTARG";;
|
||
u) username="$OPTARG";;
|
||
p) password="$OPTARG";;
|
||
# *) noopts=true
|
||
esac
|
||
done
|
||
|
||
# Если файл не задан, но флаг есть
|
||
if [[ $# -eq 0 && -v $file && ! -f $file ]]; then
|
||
input=y
|
||
read -p "File `$file` does not exist. Use default `hosts` file? Y/n: " input
|
||
case $input in
|
||
y) file=hosts;;
|
||
Y) file=hosts;;
|
||
n) read -p "Enter file name: " file;;
|
||
N) read -p "Enter file name: " file;;
|
||
*) echo "Use '-f' flag for help"; exit 0;;
|
||
esac
|
||
if [ ! -f hosts ]; then echo "File `hosts` does not exist. Exiting."; exit 0; fi
|
||
fi
|
||
|
||
# Если заданы аргументы И файл
|
||
if [[ $# -ne 0 && -v file ]]; then echo "Please enter file OR arguments. Use '-f' flag for help"; exit 0; fi
|
||
|
||
# Проверка файла на соответствие шаблону IPv4 адреса и hostname, создаём временный файл из валидных строк
|
||
if [ -e $file ]; then
|
||
touch hosts.tmp
|
||
echo -n "" > hosts.tmp
|
||
for line in $(<$file); do
|
||
ip=$(echo $line | cut -d ' ' -f 1)
|
||
hostname=$(echo $line | cut -d ' ' -f 2)
|
||
ipcheck "$ip"
|
||
if [ $? -eq 0 ]; then
|
||
hostcheck "$hostname"
|
||
if [ $? -eq 0 ];
|
||
then
|
||
echo $line >> hosts.tmp
|
||
else
|
||
echo "Hostname `$hostname` is not valid. Should contain only letters, numbers and dash. Skipping this line."
|
||
sleep 2
|
||
fi
|
||
else
|
||
echo "$ip is not a valid IPv4 address (10.10.*.*). Skipping this line."
|
||
sleep 2
|
||
fi
|
||
done
|
||
fi
|
||
|
||
# Если заданы аргументы, то создаем временный файл
|
||
if [ $# -ne 0 ] then
|
||
touch hosts.tmp
|
||
echo -n "" > hosts.tmp
|
||
for arg in "$@"; do
|
||
ipcheck "$arg"
|
||
if [ $? -eq 0 ]
|
||
then
|
||
echo -n "$arg " >> ./hosts.tmp
|
||
echo -n "vm" >> ./hosts.tmp
|
||
printf "%03d\n" "$(echo -n $arg | cut -d '.' -f 3)" >> ./hosts.tmp
|
||
printf "%03d\n" "$(echo -n $arg | cut -d '.' -f 4)" >> ./hosts.tmp
|
||
echo >> ./hosts.tmp
|
||
else
|
||
echo "Argument `$arg` is not a valid IPv4 address (10.10.*.*). Using next argument."
|
||
fi
|
||
done
|
||
fi
|
||
|
||
# Функция для проверки IP адреса по шаблону 10.10.*.*, написана гуглом
|
||
ipcheck() {
|
||
local ip=$1
|
||
local stat=1
|
||
oldIFS=$IFS
|
||
# Check if the IP matches the general IPv4 pattern
|
||
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
||
# Split the IP into octets
|
||
IFS='.' read -r -a octets <<< "$ip"
|
||
# Check if each octet is within the valid range (0-255)
|
||
if [[ ${octets[0]} -eq 10 && ${octets[1]} -eq 10 && ${octets[2]} -le 252 && ${octets[3]} -le 252 && ${octets[3]} -ne 0 ]]; then
|
||
stat=0
|
||
fi
|
||
fi
|
||
return $stat
|
||
IFS=$oldIFS
|
||
}
|
||
|
||
# Функция для проверки hostname на валидные символы (буквы, цифры, дефис)
|
||
hostcheck (){
|
||
local hostname=$1
|
||
local pattern="^[a-zA-Z0-9-]+$"
|
||
if [[ "$hostname" =~ $pattern ]]; then return 0; else return 1; fi
|
||
}
|
||
|
||
# Проверяем ключ
|
||
if [ -v pubkey ]; then
|
||
if [[ ! -f pubkey ]]; then
|
||
input=y
|
||
echo "Private key does not exist. Generate new pair? y/n"
|
||
read input
|
||
case $input in
|
||
y) read -p "Enter name for your private key: " privkey && keypair_generate ("$privkey");;
|
||
Y) read -p "Enter name for your private key: " privkey && keypair_generate ("$privkey");;
|
||
n) echo "Public key is necessary to continue. Please specify or generate new pair.";;
|
||
N) echo "Public key is necessary to continue. Please specify or generate new pair.";;
|
||
*) echo "Use '-h' flag for help"; exit 0;;
|
||
esac
|
||
fi
|
||
else
|
||
pubkey="key.pub"
|
||
if [[ ! -e key.pub ]]; then echo "`key.pub` does not exist. Please use `-k` flag to specify public key."; exit 0; fi
|
||
fi
|
||
|
||
keypair_generate (){
|
||
ssh-keygen -t rsa -N "" -f $privkey
|
||
pubkey="$privkey".pub
|
||
}
|
||
|
||
mksnippet (){
|
||
cp ./user.yaml ${path}${vmnum}_user.yaml
|
||
sed -i "s/HOSTNAME/$hostname/g" ${path}${vmnum}_user.yaml
|
||
if [[ -v $username ]];
|
||
then sed -i "s|user: root|user: ${username}\nsudo: ALL=(ALL) NOPASSWD:ALL|"
|
||
|
||
}
|
||
|
||
for line in $(cat hosts.tmp)
|
||
do
|
||
ip=$(echo $line | cut -d ' ' -f 1)
|
||
vlan=$(echo $ip | cut -d '.' -f 3)
|
||
if [[ vlan -eq 0 ]]; then mask=23; gw="10.10.0.1"; else mask=24; gw="10.10.${vlan}.1"
|
||
hostname=$(echo $line | cut -d ' ' -f 2)
|
||
vmnum=$(echo $ip | cut -d '.' -f 3,4 | sed 's/\.//')
|
||
if [[ $vlan -eq 0 ]]; then $vlan=100
|
||
qm clone 5000 $vmnum --name $hostname --full
|
||
if [ $? -eq 0 ]
|
||
then echo "clone OK"
|
||
else "clone ERROR"; exit 1
|
||
fi
|
||
qm set $vmnum --tags 3,gfx
|
||
## preparing custom CloudInit snippets
|
||
|
||
qm resize $vmnum scsi0 +50G
|
||
qm set $vmnum --cicustom "user=${storage}:snippets/${vmnum}_user.yaml"
|
||
qm set $vmnum --ipconfig0 ip=$ip/24,gw=10.10.35.1
|
||
qm cloudinit update $vmnum
|
||
qm start $vmnum
|
||
if [ -v harule ]
|
||
then
|
||
ha-manager add vm:$vmnum --state started --max_relocate 2
|
||
ha-manager rules add node-affinity $harule --resources vm:$vmnum --nodes pve1,pve2,pve3 --strict 1
|
||
# ОБЯЗАТЕЛЬНО ПРОВЕРИТЬ КОМАНДУ!!!
|
||
fi
|
||
echo "HA rules added"
|
||
done
|
||
|
||
# Финальная часть
|
||
rm hosts.tmp
|
||
if [ -v $privkey ]
|
||
then
|
||
echo "\nGenerated private key `$privkey`"
|
||
echo "SAVE IT IMMEDIATELY!!!"
|
||
fi |