1 .環(huán)境介紹
虛擬機軟件:Vmware
操作系統(tǒng):Ubuntu16.04
程序語言:Python
2.實現功能介紹
程序實現了虛擬機的所有基本操作。包括虛擬機的啟動、暫停、關閉、重啟、強制關機、強制重啟、保存等功能。
3.步驟
(1)更新軟件

image
(2).進入虛擬機之后需要安裝的一些組件:libvirt-bin,libvirt-dev,qemu,virt-manager,python3-libvirt,如圖:

image

image

image

image

image
(3)創(chuàng)建虛擬機鏡像,鏡像和iso文件位置:

image

image
(4)創(chuàng)建**.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
# 列出所有虛擬機狀態(tài)
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())
# 域狀態(tài)
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
# 保存域狀態(tài)
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')
# 創(chuàng)建域函數
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!')
#帶參創(chuàng)建虛擬機
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.保存虛擬機狀態(tài)")
print("8.銷毀虛擬機")
print("9.創(chuàng)建虛擬機")
print("10.帶參創(chuàng)建虛擬機")
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("請輸入你要保存那個虛擬機的狀態(tài):")
cmd[2]=input("請輸入你要保存到那個文件里:")
except IndexError:
print('Wrong CMD')
continue
lib_save(conn, cmd[1], cmd[2])
elif cmd[0] == 'create':
try:
cmd[1]=input("輸入你要創(chuàng)建的虛擬機域的路徑:")
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("請輸入你要創(chuàng)建的虛擬機系統(tǒng)類型(linux/windows):")
cmd[2]=input("請輸入你要創(chuàng)建的虛擬機名字:")
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)執(zhí)行效果圖:

image

image

image

image

image

image