#!/bin/bash
# qcow2 模板文件路径和md5
#qcow2TemplatePath=/var/lib/libvirt/images/wangrui/CentOS-7.0.2009-template-none-50G.qcow2
#qcow2TemplateMD5=4941c69a7e0c3b09ec6768a9cd408af7
qcow2TemplatePath=/var/lib/libvirt/images/jiahong/kylin_server_10.2-esxi-100g.qcow2
qcow2TemplateMD5=247606d55a7804fffb90faa9cc2f29fa
# qcow2 模板密码
password=123@abc.com
# qcow2 模板磁盘大小,单位GB
diskSize=100
# qcow2 模板网卡文件名
ETH_FILE_NAME=ifcfg-eth0
# kvm虚拟机存放路径
BASE_PATH=/var/lib/libvirt/images/wangrui
# kvm虚拟机名称前缀
VIRSH_HOSTNAME_PREFIX=wangrui
# IP 前缀,如:172.16.20,只要两个点
IP_PREFIX=172.16.20
# 网关
GATEWAY=172.16.20.254
# 子网掩码
NETMASK=255.255.255.0
# DNS
DNS=172.16.20.150
# CPU 核数
cpuNumber=2
# 内存大小,单位GB
memorySize=4
# kvm虚拟机创建完后ping的次数
PING_COUNT=20
# 打印正常日志
printInfo() {
echo "INFO: $1"
}
# 打印错误日志
printError() {
echo "ERROR: $1"
echo
exit 1
}
printWelcome() {
echo -e "\n-------------------- kvm 虚拟机创建程序 (by 王睿) start --------------------\n"
}
# 检测文件MD5
checkMD5sum() {
echo -e "虚拟机模板文件: ${qcow2TemplatePath}\n"
if [ -a $2 ]; then
echo -e "qcow2文件md5检测\n"
if [ "$1" != "$(md5sum $2|cut -d ' ' -f1)" ]; then
printError "md5不一致,程序退出"
fi
else
printError "文件: $2 不存在"
fi
}
# 输入机器配置
inputHostConfig() {
echo
echo -n "请输入CPU核数(默认值 $cpuNumber): "
read _cpuNumber
echo
echo -n "请输入内存大小(单位GB, 默认值 $memorySize): "
read _memorySize
if [ "" != "$_cpuNumber" ]; then cpuNumber="$_cpuNumber"; fi
if [ "" != "$_memorySize" ]; then memorySize="$_memorySize"; fi
}
# 主机检测
hostCheck() {
echo -e "\n主机IP可用性检测"
for I in $(seq 120 253)
do
IP="${IP_PREFIX}.$I"
HOSTNAME="host-${IP//./-}"
result=$(echo $(virsh list --all) | grep "${VIRSH_HOSTNAME_PREFIX}-${HOSTNAME}")
if [ "$result" != "" ]; then continue; fi
if [ -d "${BASE_PATH}/${HOSTNAME}" ]; then continue; fi
if [ -f "${BASE_PATH}/${HOSTNAME}" ]; then continue; fi
ping -c 1 $IP &> /dev/null
if [ $? -ne 0 ]; then break; fi
done
echo -e "\n分配IP为: ${IP}"
}
# 创建主机
createHost() {
hostQcow2File=${BASE_PATH}/${HOSTNAME}/${VIRSH_HOSTNAME_PREFIX}-${HOSTNAME}.qcow2
mkdir -p ${BASE_PATH}/${HOSTNAME}
cp ${qcow2TemplatePath} $hostQcow2File
chmod 644 ${BASE_PATH}/${HOSTNAME}/${VIRSH_HOSTNAME_PREFIX}-${HOSTNAME}.qcow2
echo -e "\n当前主机使用qcow2: ${hostQcow2File}"
virt-install \
--virt-type kvm \
--name ${VIRSH_HOSTNAME_PREFIX}-${HOSTNAME} \
--memory $((memorySize * 1024)) \
--vcpus ${cpuNumber} \
--import \
--hvm \
--disk ${BASE_PATH}/${HOSTNAME}/${VIRSH_HOSTNAME_PREFIX}-${HOSTNAME}.qcow2 \
--noreboot \
--bridge=br1 \
--graphics vnc,listen=0.0.0.0 \
--video vga \
--noautoconsole \
--os-type=generic
}
# 修改配置
updateHostConfig() {
mkdir ${BASE_PATH}/${HOSTNAME}/etc
virt-copy-out -d ${VIRSH_HOSTNAME_PREFIX}-${HOSTNAME} /etc/hostname /etc/sysconfig/network-scripts/${ETH_FILE_NAME} ${BASE_PATH}/${HOSTNAME}/etc
echo "${HOSTNAME}" > ${BASE_PATH}/${HOSTNAME}/etc/hostname
echo "TYPE=Ethernet" > ${BASE_PATH}/${HOSTNAME}/etc/${ETH_FILE_NAME}
echo "BOOTPROTO=static" >> ${BASE_PATH}/${HOSTNAME}/etc/${ETH_FILE_NAME}
echo "ONBOOT=yes" >> ${BASE_PATH}/${HOSTNAME}/etc/${ETH_FILE_NAME}
echo "DEVICE=eth0" >> ${BASE_PATH}/${HOSTNAME}/etc/${ETH_FILE_NAME}
echo "PREFIX=24" >> ${BASE_PATH}/${HOSTNAME}/etc/${ETH_FILE_NAME}
echo "IPADDR=${IP}" >> ${BASE_PATH}/${HOSTNAME}/etc/${ETH_FILE_NAME}
echo "GATEWAY=${GATEWAY}" >> ${BASE_PATH}/${HOSTNAME}/etc/${ETH_FILE_NAME}
echo "NETMASK=${NETMASK}" >> ${BASE_PATH}/${HOSTNAME}/etc/${ETH_FILE_NAME}
echo "DNS1=${DNS}" >> ${BASE_PATH}/${HOSTNAME}/etc/${ETH_FILE_NAME}
# sed -i 's/ONBOOT=no/ONBOOT=yes/g' ${BASE_PATH}/${HOSTNAME}/etc/${ETH_FILE_NAME}
# sed -i 's/BOOTPROTO=dhcp/BOOTPROTO=static/g' ${BASE_PATH}/${HOSTNAME}/etc/${ETH_FILE_NAME}
virt-copy-in -d ${VIRSH_HOSTNAME_PREFIX}-${HOSTNAME} ${BASE_PATH}/${HOSTNAME}/etc/hostname /etc
virt-copy-in -d ${VIRSH_HOSTNAME_PREFIX}-${HOSTNAME} ${BASE_PATH}/${HOSTNAME}/etc/${ETH_FILE_NAME} /etc/sysconfig/network-scripts
# updateShadowFile
rm -rf ${BASE_PATH}/${HOSTNAME}/etc
}
# 更新影子文件(TODO 异常,拷贝进去没用)
updateShadowFile() {
shadowTempFile="${BASE_PATH}/${HOSTNAME}/shadow-temp"
> ${shadowTempFile}
cat "${BASE_PATH}/${HOSTNAME}/shadow" | while read line
do
if [[ "${line}" =~ ^'root:'.* ]]; then
suffix=${line#*:}
suffix=${suffix#*:}
line="root:$(openssl ${password} -6 123@abc.com):${suffix}"
fi
echo ${line} >> ${shadowTempFile}
done
rm ${BASE_PATH}/${HOSTNAME}/shadow
mv ${BASE_PATH}/${HOSTNAME}/shadow-temp ${BASE_PATH}/${HOSTNAME}/shadow
virt-copy-in -d ${VIRSH_HOSTNAME_PREFIX}-${HOSTNAME} ${BASE_PATH}/${HOSTNAME}/shadow /etc
}
# 启动虚拟机
startupHost() {
virsh start ${VIRSH_HOSTNAME_PREFIX}-${HOSTNAME}
}
# 打印成功信息
printSuccessInfo() {
echo -e "虚拟机 ${VIRSH_HOSTNAME_PREFIX}-${HOSTNAME} 创建并启动成功, 详细配置如下:\n"
echo -e "主机名: \t${HOSTNAME}"
echo -e "IP: \t\t${IP}"
echo -e "root密码: \t${password}"
echo -e "CPU: \t\t${cpuNumber}核"
echo -e "内存: \t\t${memorySize}GB"
echo -e "磁盘: \t\t${diskSize}GB"
echo
echo -e "重命名域请执行如下命令(重命名后记得 virsh start 启动域):"
echo -e " virsh destroy ${VIRSH_HOSTNAME_PREFIX}-${HOSTNAME}"
echo -e " virsh domrename ${VIRSH_HOSTNAME_PREFIX}-${HOSTNAME} <new-name>"
echo -e "\nTODO: 磁盘扩容待完善"
echo -e "\n-------------------- kvm 虚拟机创建程序 (by 王睿) end --------------------\n"
}
# 主机ping检测
hostPingCheck() {
i=0
while true
do
((i++))
ping -c 1 $IP &> /dev/null
if [ $? -eq 0 ]
then break
else
echo "第$i次 ping $IP 失败"
if [ $i -eq "${PING_COUNT}" ]; then echo; printError "ping ${PING_COUNT}次 均失败, 不再尝试"; break; fi
fi
done
echo -e "\n主机已ping通,请使用ssh终端连接: $IP\n"
}
printWelcome
checkMD5sum $qcow2TemplateMD5 $qcow2TemplatePath
echo -e "qcow2文件md5符合预期, 开始kvm虚拟机创建流程"
inputHostConfig
hostCheck
if [ $? -ne 0 ]; then printError "hostCheck 函数异常退出,程序中止"; fi
createHost
if [ $? -ne 0 ]; then printError "createHost 函数异常退出,程序中止"; fi
updateHostConfig
if [ $? -ne 0 ]; then printError "updateHostConfig 函数异常退出,程序中止"; fi
startupHost
if [ $? -ne 0 ]; then printError "startupHost 函数异常退出,程序中止"; fi
printSuccessInfo
if [ $? -ne 0 ]; then printError "printSuccessInfo 函数异常退出,程序中止"; fi
hostPingCheck