#!/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