1 .环境介绍
虚拟机软件:Vmware
操作系统:Ubuntu16.04
程序语言:Python
2.实现功能介绍
程序实现了虚拟机的所有基本操作。包括虚拟机的启动、暂停、关闭、重启、强制关机、强制重启、保存等功能。
3.步骤
(1)更新软件
(2).进入虚拟机之后需要安装的一些组件:libvirt-bin,libvirt-dev,qemu,virt-manager,python3-libvirt,如图:
(3)创建虚拟机镜像,镜像和iso文件位置:
(4)创建**.xml文件,且文件内容如下:
-----------------------------------------------------------------------------------------------------------------------------------
<domain type='kvm'>
<name>ubuntu14</name> //虚拟机名称
<memory>1048576</memory> //最大内存
<currentMemory>1048576</currentMemory> //可用内存
<vcpu>1</vcpu> //虚拟cpu个数
<os>
<type arch='x86_64' machine='pc'>hvm</type>
<boot dev='cdrom'/> //光盘启动
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset='localtime'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> //此处关键,要求libvirt版本至少应该在0.9以上才能
支持,libvirt版本升级http://blog.csdn.net/gg296231363/article/details/6891460
<source file='/var/lib/libvirt/images/ubuntu14.qcow2'/> //目的镜像路径
<target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<source file='/var/lib/libvirt/images/ubuntu-14.04.5-server-amd64.iso'/> //光盘镜像路径
<target dev='hdb' bus='ide'/>
</disk>
<interface type='network'> //虚拟机网络连接方式
<source network='default'/>
<mac address="00:16:3e:5d:aa:a8"/> //为虚拟机分配mac地址,务必唯一,否则dhcp获得同样ip,引起冲突
</interface>
<input type='mouse' bus='ps2'/>
<graphics type='vnc' port='-1' autoport='yes' listen = '0.0.0.0' keymap='en-us'/>//vnc方式登录,端口号自动分配,自动加1
</devices>
</domain>
(5)程序代码:
import libvirt
import sys, os
from xml.dom import minidom
from datetime import datetime
import readline
# 连接函数
def lib_connect():
try:
conn = libvirt.open('qemu:///system')
except libvirt.libvirtError:
print("connect error")
return 'None'
return conn
# 列出所有虚拟机状态
def lib_listall(conn):
domains = conn.listAllDomains()
print("Id\tName\t\t\t\tState")
print('-' * 52)
for domain in domains:
if domain.ID() == -1:
Id = '--'
else:
Id = str(domain.ID())
print('%-8s%-32s%s' % (Id, domain.name(), State(domain)))
print("")
# 列出正在运行的虚拟机
def lib_listisactive(conn):
domainIDs = conn.listDomainsID()
print('Id\tName\t\t\t\tState')
print('-' * 52)
for domainID in domainIDs:
dom = conn.lookupByID(domainID)
print('%-8s%-32s%s' % (dom.ID(), dom.name(), State(dom)))
print("")
# 定义域函数
def def_Xml(conn, cmd):
f = open(cmd)
xmlconfig = f.read()
f.close()
if conn == None:
print('Failed to open connection to qemu:///system', file=sys.stderr)
return 'Error'
try:
dom = conn.defineXML(xmlconfig)
except libvirt.libvirtError:
return 'Error'
if dom == None:
print('Failed to define a domain from an XML definition.', file=sys.stderr)
return 'Error'
print('Guest ' + dom.name() + ' has booted', file=sys.stderr)
return 'Error'
# 取消定义域
def undef_xml(conn, cmd):
dom = sel_cmd(conn, cmd)
if dom == 'None':
return
name = dom.name()
flag = dom.undefine()
if flag >= 0:
print(cmd, ' undefined')
return name
# 查找域
def sel_cmd(conn, cmd):
CMD = cmd
try:
CMD = int(CMD)
except ValueError:
CMD = cmd
try:
dom = conn.lookupByName(CMD)
except libvirt.libvirtError:
return 'None'
try:
if type(CMD) == int:
dom = conn.lookupByID(CMD)
else:
pass
except libvirt.libvirtError:
return 'Error'
return dom
# 启动域
def lib_start(conn, cmd):
dom = sel_cmd(conn, cmd)
if dom == 'None':
return
try:
flag = dom.create()
except libvirt.libvirtError:
return 'Error'
if flag >= 0:
print('Domain %s started' % dom.name())
# 关闭域
def lib_shutdown(conn, cmd):
dom = sel_cmd(conn, cmd)
if dom == 'None':
return
dom.shutdown()
print('Domain %s is shutting down' % dom.name())
# 销毁域
def lib_destroy(conn, cmd):
dom = sel_cmd(conn, cmd)
if dom == 'None':
return
dom.destroy()
print('Domain %s destroyed' % dom.name())
# 暂停域
def lib_pause(conn, cmd):
dom = sel_cmd(conn, cmd)
if dom == 'None':
return
flag = dom.suspend()
if flag >= 0:
print('Domain %s is paused' % dom.name())
#恢复域
def lib_continue(conn, cmd):
dom = sel_cmd(conn, cmd)
if dom == 'None':
return
flag = dom.resume()
if flag >= 0:
print('Domain %s continue' % dom.name())
# 域状态
def State(dom):
state, reason = dom.state()
if state == libvirt.VIR_DOMAIN_NOSTATE:
sta = 'nostate'
elif state == libvirt.VIR_DOMAIN_RUNNING:
sta = 'running'
elif state == libvirt.VIR_DOMAIN_BLOCKED:
sta = 'blocked'
elif state == libvirt.VIR_DOMAIN_PAUSED:
sta = 'paused'
elif state == libvirt.VIR_DOMAIN_SHUTDOWN:
sta = 'shutdown'
elif state == libvirt.VIR_DOMAIN_SHUTOFF:
sta = 'shut off'
elif state == libvirt.VIR_DOMAIN_CRASHED:
sta = 'crashed'
elif state == libvirt.VIR_DOMAIN_PMSUSPENDED:
sta = 'pmsuspened'
else:
sta = 'unknown'
return sta
# 保存域状态
def lib_save(conn, cmd, path):
dom = sel_cmd(conn, cmd)
if dom == 'None':
return
if State(dom) == 'shut off':
print('guest is not running')
return
try:
path = 'save/' + path
print(path)
dom.save(path)
except libvirt.libvirtError:
print('Save Error')
return
print('save over')
# 创建域函数
def lib_create(conn, cmd):
# cmd=sel_cmd(conn,cmd)
f = open(cmd)
xmlConfig = f.read()
f.close()
try:
dom = conn.createXML(xmlConfig)
except libvirt.libvirtError:
return 'Error'
if dom == None:
print("Failed to create a domain from an XMLdefinition")
return 'Error'
print('Guest' + dom.name() + 'has booted')
return 'Error'
# 上传镜像
def lib_uploadimg(img, Type):
if Type == 'linux':
path = 'img/linux/'
os.system('cp ' + img + ' ' + path)
print("上传成功!")
elif Type == 'windows':
path = 'img/windows/'
os.system('cp ' + img + ' ' + path)
print("上传成功!")
else:
print("no such os,please check")
# 删除镜像
def lib_deleteimg(img, Type):
if Type == 'linux':
path = 'img/linux/' + img
os.system('rm ' + path)
elif Type == 'windows':
path = 'img/windows/' + img
os.system('rm ' + path)
else:
print('No such img,please check!')
#带参创建虚拟机
def lib_createA(cmd1, cmd2, conn, func):
f_localpath = os.popen('pwd')
localpath = f_localpath.read()
localpath = localpath.strip()
orign_file = localpath + '/img/' + cmd1 + '/' +cmd2+'.img'
if cmd2 == 'None':
bkfile_name = datetime.now().strftime('%Y%m%d_%H%m%S_') + Type[-1] + '.img'
bkfile_path = localpath + '/guest/'
bkfile_cmd = 'qemu-img create -f qcow2 ' + bkfile_path + bkfile_name + '10G'
path_guest = bkfile_path + bkfile_name
os.system(bkfile_cmd)
else:
bkfile_path = localpath + '/img/windows/'
path_guest = bkfile_path + cmd2+'.img'
cpuactive = conn.getInfo()[2]
memactive = int(conn.getInfo()[1])
while True:
name = input('Name:')
cpus = input('CPU(s):')
mem = input('Memory(MAX)(M):')
cmem = input('currentMemory(M):')
if name == '':
if cmd2 == 'None':
name = bkfile_name.split('.')[0]
else:
name = cmd2.split('.')[0]
if cpus == '':
cpus = '1'
if mem == '':
mem = '1024'
if cmem == '':
cmem = '1024'
try:
int(mem);
int(cmem);
int(cpus)
except ValueError:
print(' Input Wrong')
continue
if int(mem) > memactive:
print('Sorry No Enough Memory!')
continue
if int(cpus) > cpuactive:
print('Sorry No Enough CPUs')
continue
print('''
Name:%s
CPU(s):%s
Memory(MAX):%s
currentMemory:%s
''' % (name, cpus, mem, cmem))
cmd = input('That is OK(Y)?')
if cmd == 'Y' or cmd == 'y':
break
mem = str(int(mem) * 1024)
cmem = str(int(cmem) * 1024)
orig_domainfile = 'domainfile/img/demo.xml'
dom = minidom.parse(orig_domainfile)
dom_name = dom.getElementsByTagName('name')
dom_mem = dom.getElementsByTagName('memory')
dom_curmem = dom.getElementsByTagName('currentMemory')
dom_vcpu = dom.getElementsByTagName('vcpu')
dom_name[0].childNodes[0].nodeValue = name
dom_mem[0].childNodes[0].nodeValue = mem
dom_curmem[0].childNodes[0].nodeValue = cmem
dom_vcpu[0].childNodes[0].nodeValue = cpus
dom_devices = dom.getElementsByTagName('devices')
dom_disk = dom_devices[0].getElementsByTagName('disk')
dom_source = dom_disk[0].getElementsByTagName('source')
dom_source[0].setAttribute('file', path_guest)
save_domainfile = 'domainfile/img/' + 'demo.xml'
print(save_domainfile)
fp = open(save_domainfile, 'w')
dom.writexml(fp)
fp.close()
recv = func['define'](conn, save_domainfile)
print('Create Over')
#列出镜像
def Imglist():
F_Buffer = os.popen('ls -l img')
# print(F_Buffer)
Floders = F_Buffer.readlines()
# print(Floders)
for Floder in Floders:
if len(Floder.split())>3:
print ('')
F_name=Floder.split()[-1]
print ('%-24s%s'%(F_name,'Size'))
print ('-'*52)
f_Buffer = os.popen('ls -l img/'+F_name)
files = f_Buffer.readlines()
print(files)
for f in files:
if len(f.split())>3:
f_name=f.split()[-1]
f_size=f.split()[4]
f_size=str(int(f_size)/(1024**2))
print ('%-24s%sMB'%(f_name,f_size))
#网络
def net(conn,cmd):
domName=sel_cmd(conn,cmd)
if domName == None:
print('Failed to find the domain ')
exit(1)
raw_xml = domName.XMLDesc(0)
xml = minidom.parseString(raw_xml)
interfaceTypes = xml.getElementsByTagName('interface')
for interfaceType in interfaceTypes:
print('interface: type='+interfaceType.getAttribute('type'))
interfaceNodes = interfaceType.childNodes
for interfaceNode in interfaceNodes:
if interfaceNode.nodeName[0:1] != '#':
if interfaceNode.nodeName=='source':
print(' '+interfaceNode.nodeName)
for attr in interfaceNode.attributes.keys():
if interfaceNode.attributes[attr].name=='network':
netwo=input("请输入网络类型:")
interfaceNode.attributes[attr].value=netwo
print(' '+interfaceNode.attributes[attr].name+' = '+interfaceNode.attributes[attr].value)
save_domainfile = '/etc/libvirt/qemu/' + cmd+'.xml'
fp = open(save_domainfile, 'w')
xml.writexml(fp)
fp.close()
return 'Error'
# 主函数
if __name__ == '__main__':
conn = lib_connect()
if conn == 'None':
sys.exit()
while True:
print("****************-虚拟机生命周期管理-*************")
print("1.定义")
print("2.取消定义")
print("3.开始虚拟机")
print("4关闭虚拟机")
print("5.暂停虚拟机")
print("6.恢复虚拟机")
print("7.保存虚拟机状态")
print("8.销毁虚拟机")
print("9.创建虚拟机")
print("10.带参创建虚拟机")
print("11.列出活动域")
print("12.列出全部域")
print("****************-镜像管理-*************")
print("13.上传镜像")
print("14.删除镜像")
print("15.列出镜像")
print("****************-网络管理-*************")
print("16.网络")
print("quit.退出")
print("*****************************")
cmd1 = input("Virsh(控制窗口)").strip()
cmd = {}
if cmd1 == '1':
cmd[0] = 'define'
if cmd1 == '2':
cmd[0] = 'undefine'
if cmd1 == '3':
cmd[0] = 'start'
if cmd1 == '4':
cmd[0] = 'shutdown'
if cmd1 == '5':
cmd[0] = 'suspend'
if cmd1 == '6':
cmd[0] = 'continue'
if cmd1 == '7':
cmd[0] = 'save'
if cmd1 == '8':
cmd[0] = 'destroy'
if cmd1 == '9':
cmd[0] = 'create'
if cmd1 == '10':
cmd[0] = 'createA'
if cmd1 == '11':
cmd[0] = 'list'
if cmd1 == '12':
cmd[0] = 'list --all'
if cmd1 == '13':
cmd[0] = 'uploadimg'
if cmd1 == '14':
cmd[0] = 'deleteimg'
if cmd1 == '15':
cmd[0] = 'imglist'
if cmd1 == '16':
cmd[0] = 'net'
if cmd1=='quit':
cmd[0]='quit'
if cmd[0] == 'define':
try:
cmd[1] = input("请输入你要定义的域的名字:")
except IndexError:
print("Wrong,please check")
continue
def_Xml(conn, cmd[1])
elif cmd[0] == 'undefine':
try:
cmd[1] = input("请输入你要取消哪个域:")
except IndexError:
print("Wrong cmd")
continue
undef_xml(conn, cmd[1])
elif cmd[0]=='list --all':
lib_listall(conn)
elif cmd[0] == 'list':
lib_listisactive(conn)
elif cmd[0] == 'start':
try:
cmd[1] = input("请输入开启哪个虚拟机:")
except IndexError:
print('Wrong CMD')
continue
lib_start(conn, cmd[1])
elif cmd[0] == 'shutdown':
try:
cmd[1] = input("请输入你要关闭的虚拟机:")
except IndexError:
print('Wrong CMD')
continue
lib_shutdown(conn, cmd[1])
elif cmd[0] == 'destroy':
try:
cmd[1] = input("请输入你要销毁的虚拟机:")
except IndexError:
print('Wrong CMD')
continue
lib_destroy(conn, cmd[1])
elif cmd[0] == 'suspend':
try:
cmd[1] = input("请输入你要暂停的虚拟机:")
except IndexError:
print('Wrong CMD')
continue
lib_pause(conn, cmd[1])
elif cmd[0] == 'quit':
break
elif cmd[0] == 'save':
try:
cmd[1]=input("请输入你要保存那个虚拟机的状态:")
cmd[2]=input("请输入你要保存到那个文件里:")
except IndexError:
print('Wrong CMD')
continue
lib_save(conn, cmd[1], cmd[2])
elif cmd[0] == 'create':
try:
cmd[1]=input("输入你要创建的虚拟机域的路径:")
except IndexError:
print('Wrong CMD')
continue
lib_create(conn, cmd[1])
elif cmd[0]=='createA':
func = {'define': def_Xml, 'start': lib_start}
cmd[1]=input("请输入你要创建的虚拟机系统类型(linux/windows):")
cmd[2]=input("请输入你要创建的虚拟机名字:")
if cmd[2]=='None':
lib_createA(cmd[1], 'None', conn, func)
else:
lib_createA(cmd[1], cmd[2], conn, func)
elif cmd[0] == 'uploadimg':
try:
cmd[2]=input("请输入你要上传的镜像类型:")
cmd[1]=input("请输入你要上传的虚拟机名字:")
except IndexError:
print("Wrong command")
continue
lib_uploadimg(cmd[1], cmd[2])
elif cmd[0] == 'deleteimg':
try:
cmd[2] = input("请输入你要删除的镜像类型:")
cmd[1] = input("请输入你要删除的虚拟机名字:")
except IndexError:
print("Wrong command")
continue
lib_deleteimg(cmd[1], cmd[2])
elif cmd[0]=='imglist':
Imglist()
elif cmd[0]=='net':
try:
cmd[1]=input("输入你要修改那个虚拟机的网络类型:")
except IndexError:
print("Wrong cmd")
continue
net(conn,cmd[1])
elif cmd[0] == 'continue':
try:
cmd[1] = input("请输入你要恢复的虚拟机:")
except IndexError:
print('Wrong CMD')
continue
lib_continue(conn, cmd[1])
(6)执行效果图: