python2.7管理kvm虚拟主机
说明:
- 脚本是基于
python 2.7.5
版本调试- 脚本使用到
libvirt
库,请安装好相应的库- kvm虚拟机需要
qemu-guest-agent sg3_utils sg3_utils-libs
安装包
kvm虚机依赖包
[root@localhost ~]# rpm -qa qemu-guest-agent sg3_utils sg3_utils-libs
qemu-guest-agent-2.12.0-3.el7.x86_64
sg3_utils-1.37-19.el7.x86_64
sg3_utils-libs-1.37-19.el7.x86_64
[root@localhost ~]# systemctl is-active qemu-guest-agent
active
没有安装上述三个包,获取IP地址会报错
Guest agent is not responding: QEMU guest agent is not connected
python依赖库
检查 libvirt
库
[root@localhost ~]# python
Python 2.7.5 (default, Oct 30 2018, 23:45:53)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import libvirt
>>>
由与上述不一样,请安装好libvirt-python包即可
[root@localhost ~]# rpm -qa libvirt-python
libvirt-python-4.5.0-1.el7.x86_64
epel-release
仓库提供libvirt-python
包
python代码
#!/usr/bin/python
# coding=utf-8
import sys
import re
import os
import time
import getopt
import libvirt
# 命令的帮助文档
def scriptHelp():
print('''
Usage:
python test.py [-o operate] [-n vmnames] [-c cloneName] [-l list] [ip]
-o operate: Operation of kvm virtual host, such as start, stop, restart, delete, clone..
-n vmnames: The kvm virtual host being operated, Separate multiple hosts with commas
-c cloneName: The parameters of the clone host must be used with the -o clone option and the -n parameter can only specify one host
-l list: View the running status of all kvm virtual machines on the machine
--ip: View all started kvm virtual host IP addresses
Example:
# Start multiple kvm virtual hosts
kvmmanage -o start -n test01,test02
# Shut down all kvm virtual hosts
kvmmanage -o stop -n all
# Quickly create kvm virtual host
kvmmanage -o clone -n CentOS7 -c test01
# delete kvm virtual host
kvmmanage -o delete -n test01
# View all started kvm virtual host IP addresses
kvmmanage --ip
''')
sys.exit()
# 连接 qemu 装饰器
def conn_qemu(func):
def inner(*args, **kwargs):
global conn
conn = createConnection()
func(*args, **kwargs)
closeConnection(conn)
return inner
# 创建 qemu 连接
def createConnection():
try:
conn = libvirt.open("qemu:///system")
except Exception as e:
print("\033[1;31m[ERROR]\033[0m libvirtd service not running.")
else:
print("---Successfully opened connection to hypervisor---")
return conn
# 关闭 qemu 连接
def closeConnection(conn):
try:
conn.close()
except Exception as e:
print(e)
else:
print("---Successfully closed the hypervisor connection---")
# 启动虚拟机
@conn_qemu
def startDomain(VmNames):
# 处理批量启动所有虚拟机
if len(VmNames) == 1 and VmNames[0] == "all":
# 排除 except_vm_list 列表的虚拟机
for name in except_vm_list:
VmNames = conn.listDefinedDomains()
VmNames.remove(name)
# 如果为空,则说明所有主机处于启动状态
if VmNames == []:
print("\033[1;31m[ERROR]\033[0m All hosts have been started")
return
up_vm_list_name = []
for id in conn.listDomainsID():
up_vm_list_name.append(conn.lookupByID(id).name())
for VmName in VmNames:
if VmName in conn.listDefinedDomains():
dom = conn.lookupByName(VmName)
dom.create()
print("The virtual machine \033[1;36m%s\033[0m has executed the boot instruction"%VmName)
elif VmName in up_vm_list_name:
print("\033[1;31m[ERROR]\033[0m The virtual machine \033[1;36m%s\033[0m is started"%VmName)
continue
else:
print("\033[1;31m[ERROR]\033[0m \033[1;36m%s\033[0m The VM name is incorrect"%VmName)
continue
# 关闭虚拟机
@conn_qemu
def stopDomain(VmNames):
up_vm_list_name = []
for id in conn.listDomainsID():
up_vm_list_name.append(conn.lookupByID(id).name())
if len(VmNames) == 1 and VmNames[0] == "all":
VmNames = up_vm_list_name
if VmNames == []:
print("\033[1;31m[ERROR]\033[0m All hosts have been powered off")
for VmName in VmNames:
if VmName in conn.listDefinedDomains():
print("\033[1;31m[ERROR]\033[0m The virtual machine \033[1;36m%s\033[0m is shut down"%VmName)
continue
elif VmName in up_vm_list_name:
dom = conn.lookupByName(VmName)
dom.destroy()
print("The shutdown command has been executed for the virtual machine \033[1;36m%s\033[0m"%VmName)
else:
print("\033[1;31m[ERROR]\033[0m \033[1;36m%s\033[0m The VM name is incorrect"%VmName)
continue
# 重启虚拟机
@conn_qemu
def restartDomain(VmNames):
up_vm_list_name = []
for id in conn.listDomainsID():
up_vm_list_name.append(conn.lookupByID(id).name())
if len(VmNames) == 1 and VmNames[0] == "all":
VmNames = up_vm_list_name
if VmNames == []:
print("\033[1;31m[ERROR]\033[0m All hosts have been powered off")
for VmName in VmNames:
if VmName in up_vm_list_name:
dom = conn.lookupByName(VmName)
dom.reboot()
print("The virtual machine \033[1;36m%s\033[0m has executed the restart instruction"%VmName)
elif VmName in conn.listDefinedDomains():
print("\033[1;31m[ERROR]\033[0m \033[1;36m%s\033[0m The VM is stopped. Procedure"%VmName)
continue
else:
print("\033[1;31m[ERROR]\033[0m \033[1;36m%s\033[0m The VM name is incorrect"%VmName)
continue
# 删除虚拟机
def deleteDomain(VmNames):
warn = raw_input("[Dangerous operation] Are you sure you want to delete the kvm virtual machine? [y/n]: ").strip()
if warn not in ["y", "Y"]:
print("The input option is not y, and the deletion action is not performed...")
sys.exit()
stopDomain(VmNames)
for VmName in VmNames:
delete_cmd = '''virsh undefine %s && rm -rf /var/lib/libvirt/images/%s.qcow2''' % (VmName, VmName)
print("[CMD] %s" % delete_cmd)
if os.system(delete_cmd) != 0:
print("\033[1;31m[ERROR]\033[0m delete failed...")
# 克隆虚拟机
def cloneDomain(vmNames, cloneNames):
for cloneName in cloneNames:
clone_cmd = "virt-clone -o %s -n %s -f /var/lib/libvirt/images/%s.qcow2" % (vmNames[0], cloneName, cloneName)
print("[CMD] %s" % clone_cmd)
if os.system(clone_cmd) != 0:
print("\033[1;31m[ERROR]\033[0m clone failed...")
# 查看所有虚拟机状态
@conn_qemu
def getVmStatus():
down_vm_list_name = conn.listDefinedDomains()
print("\033[1;32mVirtual host not started [ total of %s ]:\033[0m \n%s\n"%(len(down_vm_list_name), sorted(down_vm_list_name)))
up_vm_list_name = []
for id in conn.listDomainsID():
up_vm_list_name.append(conn.lookupByID(id).name())
print("\033[1;32mStart virtual host [ total of %s ]:\033[0m \n%s" % (len(up_vm_list_name), sorted(up_vm_list_name)))
# 获取已启动虚拟机ip地址
@conn_qemu
def getVmAddress():
# 获取虚机名称
up_vm_list_name = []
for id in conn.listDomainsID():
up_vm_list_name.append(conn.lookupByID(id).name())
up_vm_list_name = sorted(up_vm_list_name)
# 获取虚机ip地址
up_vm_list_ip = []
for name in up_vm_list_name:
IP = []
dom = conn.lookupByName(name)
try:
ifaces = dom.interfaceAddresses(libvirt.VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT, 0)
except Exception as e:
IP.append("Null")
else:
for key, value in ifaces.items():
# print(conn.lookupByID(id).name(), key, value)
if re.search("lo|docker.*|kube-ipvs.*|tunl.*|cali.*", key) != None or value["addrs"] == None:
# print(conn.lookupByID(id).name(), key, value)
continue
else:
for ip in value["addrs"]:
# print(conn.lookupByID(id).name(), key, ip)
if re.search("2[1-8]", str(ip["prefix"])) != None:
IP.append(ip[r'addr'])
elif ip["prefix"] == 64 and ip["addr"] != "::1":
IP.append(ip["addr"])
up_vm_list_ip.append(IP)
# 判断是否有虚机运行中
if up_vm_list_name == []:
print("All the VM hosts are not started")
return
# 统计up_vm_list_name列表元素的字符数
a = [len(nums) for nums in up_vm_list_name]
# 统计up_vm_list_ip列表元素的字符数
b = []
for host_ip in up_vm_list_ip:
c = [len(nums) for nums in host_ip]
b.append(sum(c))
list_ip_num_many = len(up_vm_list_ip[b.index(max(b))])
if max(b) + list_ip_num_many*2 >= 12:
print("{:>3}{}+".format("+", "-"*(max(a) + max(b) + list_ip_num_many*2+3 )))
print("{:>3}{:^{}}|{:^{}}|".format("|", "Hostname", max(a) + 2, "IP Address", max(b) + list_ip_num_many*2 ))
print("{:>3}{}+".format("+", "-"*(max(a) + max(b) + list_ip_num_many*2+3 )))
for i, host_ip in enumerate(up_vm_list_ip):
print("{:>3}{:^{}}|{:^{}}|".format("|", up_vm_list_name[i], max(a) + 2, "__".join(host_ip), max(b) + list_ip_num_many*2))
print("{:>3}{}+".format("+", "-"*(max(a)+max(b) + list_ip_num_many*2+3)))
else:
print("{:>3}{}+".format("+", "-"*(max(a) + 15)))
print("{:>3}{:^{}}| {:^{}} |".format("|", "Hostname", max(a) + 2, "IP Address", max(b) + list_ip_num_many*2 ))
print("{:>3}{}+".format("+", "-"*(max(a) + 15)))
for i, host_ip in enumerate(up_vm_list_ip):
print("{:>3}{:^{}}|{:^{}}|".format("|", up_vm_list_name[i], max(a) + 2, "__".join(host_ip), 12))
print("{:>3}{}+".format("+", "-"*(max(a) + 15)))
# 操作虚机
def operateType(operate, vmNames, cloneNames=''):
if operate == "start":
startDomain(vmNames)
elif operate == "stop":
stopDomain(vmNames)
elif operate == "restart":
restartDomain(vmNames)
elif operate == "delete":
deleteDomain(vmNames)
elif operate == "clone":
cloneDomain(vmNames, cloneNames)
else:
scriptHelp()
# 判断参数及调用函数
def main(operate, vmNames, cloneNames, NoValueParameter):
if len(NoValueParameter) >= 2:
scriptHelp()
elif len(NoValueParameter) == 1 and operate == '' and cloneNames == '':
if NoValueParameter[0] == "help":
scriptHelp()
elif NoValueParameter[0] == "list":
getVmStatus()
elif NoValueParameter[0] == "ip":
getVmAddress()
elif operate == "clone" and vmNames != '':
if len(vmNames) != 1:
print("\033[1;31m[ERROR]\033[0m Only one virtual machine can be specified as the template machine (-n parameter)\n")
elif cloneNames == '':
print("\033[1;31m[ERROR]\033[0m For cloning operations, the -c parameter cannot be null")
else:
operateType(operate, vmNames, cloneNames)
elif operate != '' and vmNames != '':
operateType(operate, vmNames)
else:
scriptHelp()
# 获取命令的传递参数
def getScriptParameter(args):
try:
opts, args = getopt.getopt(args, "hlo:n:c:", ["help", "operate=", "vmnames=", "list", "clonename=", "ip"])
except getopt.GetoptError:
scriptHelp()
operate = vmNames = cloneNames = ""
NoValueParameter = []
for opt, arg in opts:
if opt in ("-o", "--operate"):
operate = arg
elif opt in ("-n", "--vmnames"):
vmNames = arg.split(",")
elif opt in ("-c", "--clonename"):
cloneNames = arg.split(",")
elif opt in ("-l", "--list"):
NoValueParameter.append("list")
elif opt in ("--ip"):
NoValueParameter.append("ip")
elif opt in ("-h", "--help"):
NoValueParameter.append("help")
return operate, vmNames, cloneNames, NoValueParameter
if __name__ == '__main__':
# 操作主机时,使用all表示启动所有主机,但是排除except_vm_list外...
except_vm_list=["CentOS7"]
start_time = time.time()
if len(sys.argv) <= 1:
scriptHelp()
operate, vmNames, cloneNames, NoValueParameter = getScriptParameter(sys.argv[1:])
main(operate, vmNames, cloneNames, NoValueParameter)
print("\nThis operation takes %.3f seconds" % (time.time() - start_time))
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具