KVM虚拟机自动化管理系统脚本
#!/bin/bash
source kvm-func.sh
clear
menu
while true
do
clear && menu
read -p ">>:" keyword
clear && menu
case $keyword in
1|a)
vmall
;;
2|b)
baseos
;;
3|c)
copyvm
;;
4|d)
diskadd
;;
5|e)
memadd
;;
6|f)
clone
;;
7|g)
guazai
;;
8|h)
juan
;;
9|i)
snapshot
;;
10|g)
net_bri
;;
q|Q)
echo -e "\e[1;34m退出=============\e[0m"
exit
;;
*)
echo -e "\e[1;35m输入无效,请重新输入\e[0m"
;;
esac
done
KVM虚拟机自动化管理系统函数库
#!/bin/bash
function menu(){
cat<<!
欢迎使用kvm虚拟机管理系统
===================================================================================
1|a) 查看正在运行的虚拟机和全部虚拟机 2|b) 虚拟机基本管理命令
3|c) 快速创建一个虚拟机(请先确保已 4|d) 给指定的虚拟机添加指定容量的硬盘
经在kvm中安装了一个虚拟机模板)
5|e) 给指定的虚拟机添加制定容量的mem内存 6|f) 虚拟机的快速克隆
7|g) 虚拟机挂载到主机 8|h) 虚拟机创建存储卷
9|i) 创建虚拟机快照i 10|g) 配置桥接网卡
q|Q) 退出kvm虚拟机管理系统
===================================================================================
!
}
function vmall(){
echo -e "\e[32;1m正在运行的虚拟机\e[0m"
echo "$(virsh list)"
echo -e "\e[34;1m全部的虚拟机\e[0m"
echo "$(virsh list --all)"
echo "10s后自动返回到主菜单"
sleep 10
}
function menu2(){
cat<<!
=================================================================
1、启动虚拟机 2、暂停虚拟机 3、恢复虚拟机
4、关闭虚拟机 5、强制断电关机 6、重启虚拟机
7、强制断电重启 8、删除虚拟机 9、设置开机自启
10、关闭开机自启 11、查看运行虚拟机ip 12 、查看域磁盘信息
13、删除域磁盘 Q|q、退出基本命令模块
连续输入两次q,返回主菜单
=================================================================
!
}
function readline(){
while read line
do
echo -e "\e[31;1m${line}\e[0m"
done < a.txt
rm -rf a.txt
}
function baseos(){
while true
do
menu2
echo "您可以进行的操作的虚拟机:"
echo "$(virsh list --all)"
read -p "输入要操作的虚拟机名>>:" vmname
read -p "输入要进行的操作>>:" number
case $number in
1)
virsh start "${vmname}" &> a.txt
readline
;;
2)
virsh suspend "${vmname}" &> a.txt
readline
;;
3)
virsh resume "${vmname}" &>a.txt
readline
;;
4)
virsh shutdown "${vmname}" &>a.txt
readline
sleep 10
;;
5)
virsh destroy "${vmname}" &>a.txt
readline
;;
6)
virsh reboot "${vmname}" &>a.txt
readline
;;
7)
virsh reset "${vmname}" &>a.txt
readline
sleep 10
;;
8)
virsh undefine "${vmname}" &>a.txt
readline
;;
9)
virsh autostart "${vmname}" &>a.txt
readline
;;
10)
virsh autostart --disable "${vmname}" &>a.txt
readline
;;
11)
virsh domifaddr "${vmname}" &>a.txt
readline
;;
12)
virsh domblklist "${vmname}" &>a.txt
readline
;;
13)
virsh domblklist "${vmname}"
while true
do
read -p "输入要删除的磁盘名>>:" diskdel
virsh domblklist sunlizhen |awk '{print $1}' >a.txt
grep -w "${diskdel}" a.txt &>/dev/null
if [ $? -eq 0 ];then
rm -rf a.txt
break
else
echo "磁盘不存在,请重新输入"
fi
done
virsh detach-disk "${vmname}" "${diskdel}" --persistent
virsh domblklist "${vmname}"
echo -e "\e[33;1m磁盘"${diskdel}"已经成功从域"${vmname}"删除\e[0m"
;;
q|Q)
clear && menu
break
;;
*)
echo -e "\e[31;1m输入无效,请重新输入\e[0m"
;;
esac
done
}
function copyvm(){
echo "您现有的虚拟机模板为:"
echo "$(virsh list --all)"
virsh list --all |awk -F'[ ]*' '{print $3}' >b.txt
while true
do
read -p "请输入模板虚拟机名称>>:" old
read -p "请输入要创建的虚拟机名称>>:" new
grep -w "${old}" b.txt &>/dev/null
if [ $? -eq 0 ] && [ "$old" ] && [ "$new" ];then
rm -rf b.txt
break
else
echo "请输入已经存在的虚拟机模板,且输入不能为空,请重新输入"
fi
done
echo "正在进行镜像模板复制"
cp /etc/libvirt/qemu/"${old}".xml /etc/libvirt/qemu/"${new}".xml
cp /var/lib/libvirt/images/"${old}".qcow2 /var/lib/libvirt/images/"${new}".qcow2 && \
echo "镜像模板复制成功,正在修改新虚拟机的配置文件"
sleep 1
cd /etc/libvirt/qemu
sed -ri "s#<name>"$old"</name>#<name>$new</name>#" "${new}".xml
sed -ri "s#<uuid>[[:alnum:]-]*</uuid>#<uuid>$(uuidgen)</uuid>#" "${new}".xml
sed -ri "s#(<source file='/var/lib/libvirt/images/)"${old}"(.qcow2')#\1"${new}"\2#" "${new}".xml
n=$(echo -n 52:54:00; dd bs=1 count=3 if=/dev/random 2>/dev/null | hexdump -v -e '/1 ":%02X"')
sed -ri "s#<mac address='52:54:00:[[:alnum:]:]*'/>#<mac address='"$n"'/>#" "${new}".xml
virsh define "${new}".xml && systemctl restart libvirtd && \
echo "已经成功创建新虚拟机${new}" && virsh list --all
grep "net.ipv4.ip_forward = 1/" /etc/sysctl.conf
if [ $? -eq 0 ];then
pass
else
sed -ri '$ a net.ipv4.ip_forward = 1' /etc/sysctl.conf
fi
}
function diskadd(){
echo "请选择已经存在的虚拟机添加磁盘"
echo "$(virsh list --all)"
read -p "请输入需要添加磁盘的虚拟机名称>>:" vm_name
read -p "请输入需要添加磁盘的容量,例如2G>>:" disk_size
virsh list --all |awk -F'[ ]*' '{print $3}' >b.txt
while true
do
grep -w "${vm_name}" b.txt &>/dev/null
if [ $? -eq 0 ] && [ "${vm_name}" ];then
break
else
echo "输入的虚拟机不存在,请重新输入"
read -p "请输入需要添加磁盘的虚拟机名称>>:" vm_name
fi
done
while true
do
if [[ ! "${disk_size}" =~ G$ ]] || [[ ! "${disk_size::-1}" =~ ^[0-9]+$ ]];then
echo "输入的容量格式不符合要求,请重新输入,例如2G"
read -p "请输入需要添加磁盘的容量,例如2G>>:" disk_size
else
break
fi
done
cd /var/lib/libvirt/images/
mkdir "${vm_name}".disk &>/dev/null
qemu-img create -f qcow2 "${vm_name}".disk/"${vm_name}".qcow2 "${disk_size}" >/dev/null
if [ -e disk_mod.xml ];then
rm -rf disk_mod.xml
fi
cat >>disk_mod.xml<<!
echo "<disk type='file' device='disk'>
<driver name='qemu' type='qcow2' cache='writeback' io='threads'/>
<source file='"\${vdisk_path}"'/>
<target dev='"\${device_name}"' bus='virtio'/>
</disk>"
!
virsh domblklist "${vm_name}" |awk -F "(vd)" '/\// {print $2}'|awk '{print $1}' >read.txt
declare -A disk_arr
while read line
do
disk_arr[$line]=1
done < read.txt
for i in {a..z}
do
w=${disk_arr[$i]}
echo $w
if [ -z "$w" ];then
disk_name=vd$i
echo -e "\e[33;1m添加的磁盘名称是$disk_name\e[0m"
break
fi
done
vdisk_path=/var/lib/libvirt/images/"${vm_name}".disk/"${vm_name}".qcow2
device_name="${disk_name}"
echo "${vdisk_path}"
echo "${device_name}"
source disk_mod.xml > disk.xml
cat disk.xml
virsh attach-device "$vm_name" disk.xml --persistent
virsh domblklist "${vm_name}"
echo -e "\e[32;1m已经成功为虚拟机"${vm_name}"添加大小为"${disk_size}"的磁盘"${device_name}"\e[0m"
echo -e "\e[32;1m"${vm_name}"的所有新添加的磁盘为您存放在"${vdisk_path}"\e[0m"
rm -rf b.txt
rm -rf read.txt
rm -rf disk_mod.xml
rm -rf disk.xml
sleep 8
}
function memadd(){
echo "请选择已经存在的虚拟机添加内存mem"
echo "$(virsh list --all)"
read -p "请输入需要添加内存mem的虚拟机名称>>:" vm_name
virsh list --all |awk -F'[ ]*' '{print $3}' >b.txt
while true
do
grep -w "${vm_name}" b.txt &>/dev/null
if [ $? -eq 0 ] && [ "${vm_name}" ];then
rm -rf b.txt
break
else
echo "您输入的虚拟机不存在,请重新输入"
read -p "请输入需要添加内存mem的虚拟机名称>>:" vm_name
fi
done
read -p " 是否为虚拟机"${vm_name}"重新设定最大内存(Y|N),如果您选择同意Y,将会关闭此虚拟机,设置内存完成后,将会为您重新开启此虚拟机,请慎重修改此虚拟机最大内存,如果分配内存过大,将会导致此虚拟机无法开机,如果您选择N,不同意关闭此虚拟机,会为您在线添加内存mem>>:" chose
while true
do
case $chose in
Y)
read -p "请输入需要添加内存mem的容量,例如2G>>:" disk_size
while true
do
if [[ ! "${disk_size}" =~ G$ ]] || [[ ! "${disk_size::-1}" =~ ^[0-9]+$ ]];then
echo "输入的容量格式不符合要求,请重新输入,例如2G"
read -p "请输入需要添加磁盘的容量,例如2G>>:" disk_size
else
break
fi
done
virsh destroy "${vm_name}" &>/dev/null
virsh setmaxmem "${vm_name}" "${disk_size}" --config
virsh start "${vm_name}" >a.txt
readline
break
;;
N)
read -p "请输入需要添加内存mem的容量,例如2G>>:" disk_size
while true
do
if [[ ! "${disk_size}" =~ G$ ]] || [[ ! "${disk_size::-1}" =~ ^[0-9]+$ ]];then
echo "输入的容量格式不符合要求,请重新输入,例如2G"
read -p "请输入需要添加磁盘的容量,例如2G>>:" disk_size
else
break
fi
done
virsh setmem sunlizhen "$disk_size"
break
;;
*)
echo "输入无效,请重新输入"
read -p "是否为"${vm_name}"重新设定最大内存(Y|N),如果您选择同意Y,将会关闭虚拟机"${vm_name}">>:" chose
esac
done
echo -e "\e[32;1m域"${vm_name}"的当前信息\e[0m"
virsh dominfo "${vm_name}"
}
function clone(){
cat<<!
请选择克隆模式
1、快速克隆
2、自定义克隆
q、退出
!
while true
do
read -p ">>:" modd
case $modd in
1)
intname
startlist
virsh destroy "${vm_name}" &>/dev/null
virt-clone -o "${vm_name}" --auto-clone
if [ "$a" == 1 ];then
virsh start "${vm_name}" &>/dev/null
fi
break
;;
2)
intname
read -p "请输入新的虚拟机名称>>:" newname
while true
do
if [ "$newname" ];then
read -p "请输入要用的磁盘镜像绝对路径,输入为空则用模板机的镜像卷,输入错误的路径会创建失败>>:" newfile
if [ "$newfile" ];then
startlist
virsh destroy "${vm_name}" &>/dev/null
virt-clone -o "${vm_name}" -n "${newname}" -f "${newfile}"
if [ "$a" == 1 ];then
virsh start "${vm_name}" &>/dev/null
fi
break
else
startlist
virsh destroy "${vm_name}" &>/dev/null
virt-clone -o "${vm_name}" -n "${newname}" --auto-clone
if [ "$a" == 1 ];then
virsh start "${vm_name}" &>/dev/null
fi
break
fi
fi
done
break
;;
q)
exit
;;
*)
echo "输入无效,请重新输入"
;;
esac
done
virsh list --all >a.txt
readline
}
function intname(){
echo "您可以选择的虚拟机模板有,正在运行的域不能进行克隆,如果您选择了正在运行的域,那么将会为您执行关机命令,克隆结束后会恢复其运行状态:"
virsh list --all
read -p "请输入需要进行克隆的模板机的虚拟机名称>>:" vm_name
virsh list --all |awk -F'[ ]*' '{print $3}' >b.txt
while true
do
grep -w "${vm_name}" b.txt &>/dev/null
if [ $? -eq 0 ] && [ "${vm_name}" ];then
rm -rf b.txt
break
else
echo "您输入的虚拟机不存在,请重新输入"
read -p "请输入需要进行克隆的模板机的虚拟机名称>>:" vm_name
fi
done
}
function startlist(){
virsh list |awk '{print $2}' >a.txt
grep -w "${vm_name}" a.txt &>/dev/null
if [ $? -eq 0 ];then
a=1
fi
}
function guazai(){
virsh list --all
read -p "请输入需要进行挂载的虚拟机名称,输入需要进行克隆的模板机的虚拟机名称,如果模板机处于运行状态会为您进行关机,挂载成功后会为您开启模板虚拟
机>>:" vm_name
virsh list --all |awk -F'[ ]*' '{print $3}' >b.txt
while true
do
grep -w "${vm_name}" b.txt &>/dev/null
if [ $? -eq 0 ] && [ "${vm_name}" ];then
rm -rf b.txt
break
else
echo "您输入的虚拟机不存在,请重新输入"
read -p "请输入需要进行克隆的模板机的虚拟机名称,如果模板机处于运行状态会为您进行关机,挂载成功后会为您开启模板虚拟机>>:" vm_name
fi
done
while true
do
read -p "请输入宿主机被挂载目录绝对路径,保证路径格式正确,建议输入一个未创建的空目录路径(例如:如果您输入错误格式的目录路径/mnt///gua/,系统仍然会为你创建目录/mnt/gua/,但是会造成磁盘挂载失败)>>:" dir
ls "$dir" &>/dev/null
if [ $? -eq 0 ];then
break
else
n=${dir:0:1}
if [[ "$n" =~ "/" ]];then
mkdir -p "$dir"
break
else
echo "您输入的格式不正确,请重新输入"
fi
fi
done
startlist
virsh destroy "${vm_name}" >/dev/null
guestmount -d "${vm_name}" -m /dev/centos/root --rw "${dir}"
if [ "$a" == 1 ];then
virsh start "${vm_name}" >/dev/null
fi
echo -e "\e[34;1m虚拟机挂载成功\e[0m"
ls "${dir}"
sleep 5
}
function juan(){
function poolcreate(){
while true
do
while true
do
read -p "输要构建的存储池的名称>>:" poolname
if [ "$poolname" ];then
break
else
echo "输入不能为空"
continue
fi
done
while true
do
read -p "请输入用于构建存储池的目录路径>>:" dir
ls "$dir" &>/dev/null
if [ $? -eq 0 ];then
break
else
n=${dir:0:1}
if [[ "$n" =~ "/" ]];then
mkdir -p "$dir"
break
else
echo "您输入的格式不正确,请重新输入"
fi
fi
done
echo -e "\e[35;1m正在为您定义和构建存储池\e[0m" &&\
virsh pool-define-as "$poolname" --type dir --target "$dir" &&\
virsh pool-build "$poolname"
if [ $? -eq 0 ];then
virsh pool-list --all
echo -e "\e[35;1m存储池构建成功,您可以接着对存储池进行其他操作\e[0m"
break
else
continue
fi
done
}
poolcreate
function poollist(){
cat<< !
1) 激活已经定义的存储池
2) 为存储池设置开机自启
3) 取消存储池的开机自启
4) 在存储池中创建qcow2格式的虚拟镜像卷
5) 在存储池中删除虚拟镜像卷
6) 取消激活存储池
7) 删除存储池目录
8) 取消定义存储池
9) 返回主菜单
!
}
function dowhat(){
while true
do
echo "请输入您要进行操作的存储池名称"
read -p ">>:" vmname
virsh pool-list --all |awk '{print $1}' >b.txt
grep -w "$vmname" b.txt &>/dev/null
if [ $? -eq 0 ] && [ "$vmname" ];then
rm -rf b.txt
break
else
echo ”输入的存储池不存在,或者不符合要求“
continue
fi
done
}
function juan(){
while true
do
echo "请输入虚拟卷名称,不用写扩展名"
read -p ">>:" juanname
if [ $juanname ];then
break
else
echo "输入错误,请重新输入"
break
fi
done
}
function size(){
while true
do
echo "输入要创建的虚拟卷的大小,比如2G:"
read -p ">>:" disk_size
if [[ ! "${disk_size}" =~ G$ ]] || [[ ! "${disk_size::-1}" =~ ^[0-9]+$ ]];then
echo "输入错误,请重新输入"
continue
else
break
fi
done
}
function diroo(){
while true
do
read -p "请输入要删除的存储池目录路径>>:" dir
ls "$dir" &>/dev/null
if [ $? -eq 0 ];then
break
else
n=${dir:0:1}
if [[ "$n" =~ "/" ]];then
mkdir -p "$dir"
break
else
echo "您输入的格式不正确,请重新输入"
fi
fi
done
}
function koko(){
while true
do
virsh pool-list --all
poollist
dowhat
echo "请输入要进行的操作代号"
read -p ">>:" num
case $num in
1)
virsh pool-start "$vmname"
;;
2)
virsh pool-autostart "$vmname"
;;
3)
virsh pool-autostart --disable "$vmname"
;;
4)
juan
size
virsh vol-create-as "$vmname" "${juanname}".qcow2 "$disk_size" --format qcow2
;;
5)
juan
virsh vol-delete --pool "$vmname" "${juanname}".qcow2
;;
6)
virsh pool-destroy "$vmname"
;;
7)
diroo
virsh pool-delete "$dir"
;;
8)
virsh pool-undefine "$vmname"
;;
9)
break
;;
*)
echo "输入错误,请重新输入"
;;
esac
done
}
function cunchujuan(){
while true
do
cat<<!
y) 继续对存储池进行其他操作
n) 不进行操作,继续进行存储池构建
q) 返回主菜单
!
read -p ">>:" num
case $num in
y)
koko
;;
n)
poolcreate
;;
q)
break
;;
*)
echo "输入无效,请重新输入"
esac
done
}
cunchujuan
}
function snapmenu(){
cat<<!
1)、创建快照
2)、查看快照
3)、恢复快照
4)、删除快照
5)、回主菜单
!
}
function snapshot_create(){
while true
do
virsh list --all
virsh list --all |awk -F'[ ]*' '{print $3}' >b.txt
read -p "输入虚拟机名称>>:" vm_name
grep -w "${vm_name}" b.txt &>/dev/null
if [ $? -eq 0 ] && [ "${vm_name}" ];then
rm -rf b.txt
break
else
echo "您输入的虚拟机不存在,请重新输入"
continue
fi
done
}
function no_name(){
while true
do
virsh snapshot-list "$vm_name"
virsh snapshot-list "$vm_name" >b.txt
read -p "输入快照名称>>:" snapname
grep -w "$snapname" b.txt
if [ $? -ne 0 ] && [ "$snapname" ];then
rm -rf b.txt
break
else
echo "输入错误,请重新输入"
continue
fi
done
}
function yes_name(){
while true
do
virsh snapshot-list "$vm_name"
virsh snapshot-list "$vm_name" >b.txt
read -p "输入快照名称>>:" snapname
grep -w "$snapname" b.txt
if [ $? -eq 0 ] && [ "$snapname" ];then
rm -rf b.txt
break
else
echo "输入错误,请重新输入"
continue
fi
done
}
function snapshot(){
while true
do
snapmenu
read -p ">>:" num
case $num in
1)
snapshot_create
no_name
virsh snapshot-create-as "${vm_name}" "$snapname"
virsh snapshot-list "$vm_name"
;;
2)
snapshot_create
virsh snapshot-list "$vm_name"
;;
3)
snapshot_create
yes_name
virsh shutdown "$vm_name" &>>/dev/null
virsh snapshot-revert "$vm_name" "$snapname"
virsh snapshot-list "$vm_name"
;;
4)
snapshot_create
yes_name
virsh snapshot-delete --snapshotname "$snapname" "$vm_name"
virsh snapshot-list "$vm_name"
;;
5)
break
;;
*)
echo "输入错误,请重新输入"
;;
esac
done
}
function add_bri(){
cd /etc/sysconfig/network-scripts/
cat >>bri_mode<<!
echo "TYPE=Bridge
NAME=br0
DEVICE=br0
ONBOOT="yes"
BOOTPROTO=static
IPADDR="\$ip_addr"
GATEWAY="\$gate_addr"
NETMASK=255.255.255.0
DNS1=114.114.114.114
DNS2=8.8.8.8"
!
ip_addr=$(ip a|grep "scope global"|grep "dynamic"|awk -F'[/ ]+' '{print $3}')
gate=$(echo "$ip_addr"|awk -F'.' 'BEGIN{OFS="."} {print $1,$2,$3}')
gate_addr=${gate}.1
source bri_mode > ifcfg-br0
card=$(ip a|grep ^2|awk -F'[ : ]' '{print $3}')
cp ifcfg-${card}{,.back}
cat >>ifcfg-"$card"<<!
NAME=$card
DEVICE=$card
ONBOOT=yes
BRIDGE=br0
!
systemctl restart network
systemctl restart libvirtd
}
function del_bir(){
cd /etc/sysconfig/network-scripts/
rm -rvf ifcfg-br0
mv ifcfg-enp0s25{,.bak}
mv ifcfg-enp0s25{.back,}
systemctl restart libvirtd
systemctl restart network
}
function net_bri(){
while true
do
cat<<!
1) 配置桥接网卡
2) 删除桥接网卡
q) 回主菜单
!
read -p ">>:" num
case $num in
1)
add_bri
;;
2)
del_bir
;;
q)
break
;;
*)
echo "输入无效,请重新输入"
;;
esac
done
}