Здесь размещено описание одного из функциональных блоков инструкции с примером управления виртуальными машинами "Qemu-KVM" через простейшие BASH-скрипты. Отдельно неприменимо.
Пример опций конфигурационного файла виртуальной машины:
# vi /usr/local/etc/kvm/cnf.d/mashine0.cnf
....
# Лимит времени (в секундах) выделенный виртуальной машине на завершение работы
shutdown.timeout=300
....
# Лимит времени (в секундах) выделенный виртуальной машине на завершение работы
shutdown.timeout=300
....
Фрагмент кода с функциями формирования строки инициализации остановки виртуальной машины:
# vi /etc/kvm/fnc.d/8.stop.fnc
#!/bin/bash
# This file contains the code snippet for the shell Bash v.4 (Bourne again shell)
# Файл содержит фрагмент кода для командного интерпретатора Bash v.4 (Bourne again shell)
function stop-precheck() {
# Проверяем, запущена ли целевая виртуальная машина
STATE=`ps wax | grep --invert-match grep | grep --ignore-case --count --extended-regexp "kvm[ ]+\-name[ ]+${NAME}[ ]+"`
if [ ${STATE} -eq 0 ]; then
# Виртуальная машина не запущена и дальнейшие процедуры не имеют смысла
return 1
fi
# Узнаём лимит времени (в секундах) выделенный виртуальной машине на прохождение заврешение работы
SHTIMEOUT=`grep --ignore-case "^shutdown.timeout=" "${CNF}" | awk -F = '{print $2}'`
return 0
}
# Определяем функцию остановки виртуальной машины, по возможности со стороны клиента, пытаясь остановить машину с помощью сигнала ACPI (сработает только если гостевая система поддерживает завершение работы по нажатию кнопки)
function stop-acpi() {
# Узнаём месторасположение "локального сокета" для управления виртуальной машиной локальным скриптом
MSOCKETL="/tmp/kvm/monitor/${NAME}.local.socket"
# Посылаем через "сокет" сигнал завершения работы гостевой ОС
echo "system_powerdown" | socat - UNIX-CONNECT:${MSOCKETL} > /dev/null
# Проверяем успешность отрабатывания сеанса связи с "локальным сокетом"
if [ "${?}" = "0" ]; then
echo "${DATE}: Shutdown signal send succeeded." | tee -a "${LOGT}"
# Ожидаем завершения работы виртуальной машины
# В цикле используется C-подобный синтаксис (двойные обрамляющие скобки и переменные в операндах без знака "$")
for ((COUNT=1 ; COUNT <= SHTIMEOUT ; COUNT++))
do
echo " Wait for shutdown VM: ${NAME}... ${COUNT} sec."
sleep 1
# Проверяем, работает ли ещё целевая виртуальная машина
STATE=`ps wax | grep --invert-match grep | grep --ignore-case --count --extended-regexp "kvm[ ]+\-name[ ]+${NAME}[ ]+"`
if [ ${STATE} -eq 0 ]; then
echo "${DATE}: Виртуальная машина ${NAME} успешно остановлена." | tee -a "${LOGT}"
return 0
fi
done
# Учитывая то, что за установленное время виртуальная машина не завершила свою работу, считаем операцию не выполненной
echo "${DATE}: Виртуальная машина ${NAME} за установленное время не завершила свою работу. Операция не выполнена." | tee -a "${LOGT}"
return 1
else
echo "${DATE}: Shutdown ACPI signal send error." | tee -a "${LOGT}"
return 1
fi
return 0
}
# Определяем функцию остановки машины с помощью подсистемы SMB
function stop-smb() {
echo "${DATE}: SMB" | tee -a "${LOGT}"
return 1
return 0
}
# Определяем функцию остановки машины уничтожением процесса (последний аргумент)
function stop-kill() {
# Узнаём месторасположения PID-файла виртуальной машины
MPID="/tmp/kvm/run/${NAME}.pid"
# Запускаем процедуру остановки процесса виртуальной машины путём перебора вариантов сигнала разной степени жёсткости, по нарастанию действующей силы
for SIGNAL in TERM INT HUP KILL
do
# Посылаем сигнал процессу
/bin/kill -s ${SIGNAL} `head -1 ${MPID}`
echo "${DATE}: Shutdown SIGKILL ${SIGNAL} signal send succeeded." | tee -a "${LOGT}"
# Ожидаем завершения процесса в течении десяти секунд
for COUNT in {1..10}
do
echo " Wait for shutdown VM with SIGKILL ${SIGNAL} signal: ${NAME}... ${COUNT} sec."
sleep 1
# Проверяем, работает ли ещё целевая виртуальная машина
STATE=`ps wax | grep --invert-match grep | grep --ignore-case --count --extended-regexp "kvm[ ]+\-name[ ]+${NAME}[ ]+"`
if [ ${STATE} -eq 0 ]; then
echo "${DATE}: Процесс виртуальной машины ${NAME} успешно завершён сигналом SIGKILL ${SIGNAL}." | tee -a "${LOGT}"
return 0
fi
done
done
# Уведомляем о неудачном результате попыток завершения работы виртуальной машины
echo "${DATE}: Не удалось завершить работу виртуальной машины ${NAME}." | tee -a "${LOGT}"
return 1
return 0
}
# This file contains the code snippet for the shell Bash v.4 (Bourne again shell)
# Файл содержит фрагмент кода для командного интерпретатора Bash v.4 (Bourne again shell)
function stop-precheck() {
# Проверяем, запущена ли целевая виртуальная машина
STATE=`ps wax | grep --invert-match grep | grep --ignore-case --count --extended-regexp "kvm[ ]+\-name[ ]+${NAME}[ ]+"`
if [ ${STATE} -eq 0 ]; then
# Виртуальная машина не запущена и дальнейшие процедуры не имеют смысла
return 1
fi
# Узнаём лимит времени (в секундах) выделенный виртуальной машине на прохождение заврешение работы
SHTIMEOUT=`grep --ignore-case "^shutdown.timeout=" "${CNF}" | awk -F = '{print $2}'`
return 0
}
# Определяем функцию остановки виртуальной машины, по возможности со стороны клиента, пытаясь остановить машину с помощью сигнала ACPI (сработает только если гостевая система поддерживает завершение работы по нажатию кнопки)
function stop-acpi() {
# Узнаём месторасположение "локального сокета" для управления виртуальной машиной локальным скриптом
MSOCKETL="/tmp/kvm/monitor/${NAME}.local.socket"
# Посылаем через "сокет" сигнал завершения работы гостевой ОС
echo "system_powerdown" | socat - UNIX-CONNECT:${MSOCKETL} > /dev/null
# Проверяем успешность отрабатывания сеанса связи с "локальным сокетом"
if [ "${?}" = "0" ]; then
echo "${DATE}: Shutdown signal send succeeded." | tee -a "${LOGT}"
# Ожидаем завершения работы виртуальной машины
# В цикле используется C-подобный синтаксис (двойные обрамляющие скобки и переменные в операндах без знака "$")
for ((COUNT=1 ; COUNT <= SHTIMEOUT ; COUNT++))
do
echo " Wait for shutdown VM: ${NAME}... ${COUNT} sec."
sleep 1
# Проверяем, работает ли ещё целевая виртуальная машина
STATE=`ps wax | grep --invert-match grep | grep --ignore-case --count --extended-regexp "kvm[ ]+\-name[ ]+${NAME}[ ]+"`
if [ ${STATE} -eq 0 ]; then
echo "${DATE}: Виртуальная машина ${NAME} успешно остановлена." | tee -a "${LOGT}"
return 0
fi
done
# Учитывая то, что за установленное время виртуальная машина не завершила свою работу, считаем операцию не выполненной
echo "${DATE}: Виртуальная машина ${NAME} за установленное время не завершила свою работу. Операция не выполнена." | tee -a "${LOGT}"
return 1
else
echo "${DATE}: Shutdown ACPI signal send error." | tee -a "${LOGT}"
return 1
fi
return 0
}
# Определяем функцию остановки машины с помощью подсистемы SMB
function stop-smb() {
echo "${DATE}: SMB" | tee -a "${LOGT}"
return 1
return 0
}
# Определяем функцию остановки машины уничтожением процесса (последний аргумент)
function stop-kill() {
# Узнаём месторасположения PID-файла виртуальной машины
MPID="/tmp/kvm/run/${NAME}.pid"
# Запускаем процедуру остановки процесса виртуальной машины путём перебора вариантов сигнала разной степени жёсткости, по нарастанию действующей силы
for SIGNAL in TERM INT HUP KILL
do
# Посылаем сигнал процессу
/bin/kill -s ${SIGNAL} `head -1 ${MPID}`
echo "${DATE}: Shutdown SIGKILL ${SIGNAL} signal send succeeded." | tee -a "${LOGT}"
# Ожидаем завершения процесса в течении десяти секунд
for COUNT in {1..10}
do
echo " Wait for shutdown VM with SIGKILL ${SIGNAL} signal: ${NAME}... ${COUNT} sec."
sleep 1
# Проверяем, работает ли ещё целевая виртуальная машина
STATE=`ps wax | grep --invert-match grep | grep --ignore-case --count --extended-regexp "kvm[ ]+\-name[ ]+${NAME}[ ]+"`
if [ ${STATE} -eq 0 ]; then
echo "${DATE}: Процесс виртуальной машины ${NAME} успешно завершён сигналом SIGKILL ${SIGNAL}." | tee -a "${LOGT}"
return 0
fi
done
done
# Уведомляем о неудачном результате попыток завершения работы виртуальной машины
echo "${DATE}: Не удалось завершить работу виртуальной машины ${NAME}." | tee -a "${LOGT}"
return 1
return 0
}