在原有的基础上,做些功能上的添加.
修改虚拟机的主机名
修改虚拟机的MAC
修改虚拟机的IP
虚拟机采用qcow2格式,使用qemu-img的backing_file技术,快速生成虚拟机
这样,虚拟机创建好后,便可以远程管理了。
第1版,请参考:
http://5ydycm.blog.51cto.com/115934/1211630
第2版,create_delete_vm.py代码:
#!/usr/bin/env python
#coding:utf-8
###################################################################
#Auth:Zhuzhengjun
#LastModified:2015/01/14
#Version 1.0
#Function Description:
#Batch automatically generated/delete VM
#1.Generated VM
##1.1.Create qcow2 vm img file
##1.2.Create VM XML file
###1.2.1.Update UUID
###1.2.2.Update MAC
###1.2.3.Update img path
###1.2.4.Update VM Name
#2.Edit VM
##2.1.Edit HostName
##2.2.Edit Mac
##2.3.Edit IP
#3.Start VM
#4.Delete VM
####################################################################
#import module
import shutil
import os,sys
from virtinst.util import *
import libvirt
import re
import subprocess
import guestfs
import jinja2
if sys.version_info < (2,5):
import lxml.etree as ET
else:
import xml.etree.ElementTree as ET
#Define variables
template_img_path="/template/img"
template_xml_path="/template/xml"
vm_img_path="/var/lib/libvirt/images"
vm_xml_path="/etc/libvirt/qemu"
vm_file="/template/scripts/vm.ini"
uri="qemu:///system"
domain=".tc.com"
JINJA = jinja2.Environment(
loader=jinja2.FileSystemLoader(
'/template/jinja'
)
)
def file_exists(file):
if os.path.exists(file):
return 1
else:
return 0
def create_vm_img_file(src_img_file,dst_img_file):
command="/usr/bin/qemu-img create -f qcow2 -o cluster_size=2M,backing_file="+src_img_file+" "+dst_img_file+" 20G"
try:
subprocess.check_call(command,shell=True)
except subprocess.CalledProcessError as err:
print "Error:",err
sys.exit(1)
print "Done!"
'''
def copy_vm_img_file(src_img_file,dst_img_file):
print "Start Copy",src_img_file,"to",dst_img_file
if file_exists(dst_img_file):
print "File %s exists, abort" % dst_img_file
sys.exit(1)
shutil.copyfile(src_img_file,dst_img_file)
print "Done!"
'''
def start_vm(vm_xml_file,vm_name):
try:
conn = libvirt.open(uri)
except Exception,e:
print 'Faild to open connection to the hypervisor'
sys.exit(1)
create = True
if create:
xmlfile=open(vm_xml_file)
xmldesc=xmlfile.read()
xmlfile.close()
try:
vmname = conn.defineXML(xmldesc)
except Exception,e:
print "Failed to define %s:%s" %(vm_name,e)
sys.exit(1)
if vmname is None:
print 'whoops this shouldnt happen!'
try:
vmname.create()
except Exception,e:
print "Failed to create %s:%s" %(vm_name,e)
sys.exit(1)
try:
print "Domain 0:id %d running %s" %(vmname.ID(),vmname.name())
except Exception,e:
print e
try:
conn.close()
except:
print "Faild to close the connection!"
sys.exit(1)
print "Done!"
print "="*100
def edit_vm(dst_img_file,vm_mac,vm_ip,hostname):
g = guestfs.GuestFS(python_return_dict=True)
g.add_drive_opts(dst_img_file)
g.launch()
partions_root=g.inspect_os()
g.mount(partions_root[0],'/')
#edit hostname
hostname_fn='hostname.jinja'
try:
template_hostname = JINJA.get_template(hostname_fn)
except jinja2.exceptions.TemplateNotFound:
print "error"
sys.exit(1)
hostname_context={'hostname':hostname}
hostname_content=template_hostname.render(**hostname_context)
g.write('/etc/sysconfig/network',hostname_content)
#edit mac
mac_fn='mac.jinja'
try:
template_mac = JINJA.get_template(mac_fn)
except jinja2.exceptions.TemplateNotFound:
print "error"
sys.exit(1)
mac_context={'mac':vm_mac}
mac_content=template_mac.render(**mac_context)
g.write('/etc/udev/rules.d/70-persistent-net.rules',mac_content)
#edit ip
net_fn='net.jinja'
try:
template_net = JINJA.get_template(net_fn)
except jinja2.exceptions.TemplateNotFound:
print "error"
sys.exit(1)
net_context={'mac':vm_mac,'ip':vm_ip}
net_content=template_net.render(**net_context)
g.write('/etc/sysconfig/network-scripts/ifcfg-eth0',net_content)
g.close()
def create_vm_xml_file(src_xml_file,vm_name,dst_img_file,vm_ip,hostname):
config = ET.parse(src_xml_file)
name = config.find('name')
name.text = vm_name.strip()
uuid = config.find('uuid')
uuid.text = uuidToString(randomUUID())
mac = config.find('devices/interface/mac')
vm_mac=randomMAC(type='qemu')
mac.attrib['address'] = vm_mac
disk = config.find('devices/disk/source')
disk.attrib['file']=dst_img_file
vm_xml_name=vm_name.strip() + '.xml'
vm_xml_file=os.path.join(vm_xml_path,vm_xml_name)
if file_exists(vm_xml_file):
print "File %s exists, abort" % vm_xml_file
sys.exit(1)
config.write(vm_xml_file)
print "Created vm config file %s" % vm_xml_file
#print "Use disk image %s, you must create it from the template disk: %s" % (disk_image, disk_old)
print "Done!"
#Function 2 Edit VM
edit_vm(dst_img_file,vm_mac,vm_ip,hostname)
#Function 3 Start VM
print "Start VM "+hostname
start_vm(vm_xml_file,vm_name)
def delete_file(file_name):
if file_exists(file_name):
os.unlink(file_name)
def delete_vm(vm_name):
vmimg=vm_name+".qcow2"
vmxml=vm_name+".xml"
img_file=os.path.join(vm_img_path,vmimg)
xml_file=os.path.join(vm_xml_path,vmxml)
try:
conn = libvirt.open(uri)
except Exception,e:
print 'Faild to open connection to the hypervisor'
sys.exit(1)
try:
server=conn.lookupByName(vm_name)
except Exception,e:
print e
sys.exit(1)
if server.isActive():
print "VM %s will be shutdown!" %vm_name
try:
#server.shutdown()#VM need install acpid
server.destroy()
except Exception,e:
print e
sys.exit(1)
print "VM %s will be delete!" %vm_name
try:
server.undefine()
except Exception,e:
print e
sys.exit(1)
delete_file(img_file)
delete_file(xml_file)
try:
conn.close()
except:
print "Faild to close the connection!"
sys.exit(1)
else:
print "VM %s will be delete!" %vm_name
try:
server.undefine()
except Exception,e:
print e
sys.exit(1)
delete_file(img_file)
delete_file(xml_file)
print "Done"
print "="*100
###############Main############################################
#Open config file
fh=open(vm_file)
vm_config=fh.readlines()
fh.close()
for line in vm_config:
passline=re.compile("#.*")
if re.search(passline,line)!=None:
continue
(action,vm_name,src_file,xml_file,vm_ip)=line.strip().split(",")
hostname=vm_name+domain
if action=='add':
src_img_file=os.path.join(template_img_path,src_file)
dst_img_file=os.path.join(vm_img_path,vm_name.strip()+".qcow2")
src_xml_file=os.path.join(template_xml_path,xml_file)
if not (file_exists(src_img_file) and file_exists(src_xml_file)):
print "File %s or %s not exists,abort!" %(src_img_file,src_xml_file)
sys.exit(1)
#Function1.1 Create qcow2 vm img file
print "Create VM "+hostname+" image file and file type qcow2"
create_vm_img_file(src_img_file,dst_img_file)
#Function1.2 Create VM XML file
print "Create VM "+hostname+" Xml config file"
create_vm_xml_file(src_xml_file,vm_name,dst_img_file,vm_ip,hostname)
elif action=="delete":
#Function4 Delete VM
print "Delete VM"
delete_vm(vm_name)
虚拟机的配置文件:
vm.ini
#Action,Vm_name,Template_img_file,Template_xml_file,vm_ip
add,web20,Template_Centos63x64.img,Template_Centos63x64.xml,192.168.x.26
add,web30,Template_Centos63x64.img,Template_Centos63x64.xml,192.168.x.27
#delete,web20,none,none,none
#delete,web30,none,none,none
jinja相关的配置文件
hostname.jinja
HOSTNAME=`hostname`
NETWORKING=yes
# IPv4
NETWORKING=yes
NOZEROCONF=yes
# IPv6, necessary for bonding
NETWORKING_IPV6=yes
IPV6INIT=yes
mac.jinja
# This file was automatically generated by the /lib/udev/write_net_rules
# program, run by the persistent-net-generator.rules rules file.
#
# You can modify it, as long as you keep each rule on a single
# line, and change only the value of the NAME= key.
# PCI device 0x1af4:0x1000 (virtio-pci)
#context={'macs':{'eth0': {'mac': 'mac0'}, 'eth1': {'mac': 'mac1'}}}
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="`mac`", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
net.jinja
DEVICE="eth0"
BOOTPROTO="static"
HWADDR=`mac`
IPADDR=`ip`
NETMASK=255.255.255.0
GATEWAY=192.168.x.254
NM_CONTROLLED="yes"
ONBOOT="yes"
TYPE="Ethernet"
批量生成如下:
[root@kvm scripts]# python create_delete_vm.py
Create VM web20.tc.com image file and file type qcow2
Formatting '/var/lib/libvirt/images/web20.qcow2', fmt=qcow2 size=21474836480 backing_file='/template/img/Template_Centos63x64.img' encryption=off cluster_size=2097152
Done!
Create VM web20.tc.com Xml config file
Created vm config file /etc/libvirt/qemu/web20.xml
Done!
Start VM web20.tc.com
Domain 0:id 60 running web20
Done!
====================================================================================================
Create VM web30.tc.com image file and file type qcow2
Formatting '/var/lib/libvirt/images/web30.qcow2', fmt=qcow2 size=21474836480 backing_file='/template/img/Template_Centos63x64.img' encryption=off cluster_size=2097152
Done!
Create VM web30.tc.com Xml config file
Created vm config file /etc/libvirt/qemu/web30.xml
Done!
Start VM web30.tc.com
Domain 0:id 61 running web30
Done!
====================================================================================================
供参考!
如果想了解更多,请关注我们的公众号
公众号ID:opdevos
扫码关注