From 0d09e2b7301defd1f408d17373cbf991a922c693 Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Wed, 26 Apr 2017 14:14:43 +0800 Subject: Implement the deployment script with python 1. deploy.py: control the work flow of the deployment 2. daisy_server.py: maintain the ssh connection with daisy server and execute ssh commands 3. environment.py: create/find/delete the nodes/vms, install operating system and openstack on nodes 4. libvirt_utils.py: deal with the vm templates and call virsh commands 5. utils.py: some common functions such as file/directory/bash operation Change-Id: I1caa4b0b3118665e15410e8f02bcb6473e5a530b Signed-off-by: Alex Yang --- deploy/libvirt_utils.py | 211 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 deploy/libvirt_utils.py (limited to 'deploy/libvirt_utils.py') diff --git a/deploy/libvirt_utils.py b/deploy/libvirt_utils.py new file mode 100644 index 00000000..cd203784 --- /dev/null +++ b/deploy/libvirt_utils.py @@ -0,0 +1,211 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import commands +import libvirt +import os +import xml.etree.ElementTree as ET + +from utils import ( + LI, + LE, + LW, + WORKSPACE, + err_exit, + path_join +) + + +def get_nets_name(root): + nets = [] + for interface in root.findall('./devices/interface'): + if 'type' in interface.attrib and interface.attrib['type'] == 'network': + for source in interface.iterfind('source'): + if 'network' in source.attrib: + nets.append(source.attrib['network']) + return nets + + +def modify_vm_boot_order(root, boot_devs): + os_elem = root.find('os') + for boot_elem in os_elem.findall('boot'): + os_elem.remove(boot_elem) + for boot_dev in boot_devs: + boot_elem = ET.Element('boot', attrib={'dev': boot_dev}) + os_elem.append(boot_elem) + return root + + +def modify_vm_name(root, vm_name): + name_elem = root.find('./name') + name_elem.text = vm_name + + +def modify_vm_disk_file(root, disk_file): + for disk in root.findall('./devices/disk'): + if 'device' in disk.attrib and disk.attrib['device'] == 'disk': + for source in disk.iterfind('source'): + if 'file' in source.attrib: + source.attrib['file'] = disk_file + break + + +def create_virtual_disk(disk_file, size): + LI('Create virtual disk file %s size %d GB' % (disk_file, size)) + cmd = 'qemu-img create -f qcow2 {disk_file} {size}G'.format( + disk_file=disk_file, size=size) + status, output = commands.getstatusoutput(cmd) + if status: + LE(output) + err_exit('Fail to create qemu image !') + + +def create_vm(template, name=None, disk_file=None): + LI('Begin to create VM %s' % template) + + if name or disk_file: + tree = ET.ElementTree(file=template) + root = tree.getroot() + if name: + modify_vm_name(root, name) + if disk_file: + modify_vm_disk_file(root, disk_file) + + temp_file = path_join(WORKSPACE, 'tmp.xml') + tree.write(temp_file) + output = commands.getoutput('cat %s' % temp_file) + os.remove(temp_file) + else: + output = commands.getoutput('cat %s' % template) + + conn = libvirt.open('qemu:///system') + domain = conn.defineXML(output) + if domain is None: + err_exit('Failed to define VM %s' % template) + if domain.create() < 0: + err_exit('Failed to start VM %s' % template) + domain.setAutostart(1) + + LI('VM %s is started' % domain.name()) + return + + +def reboot_vm(vm_name, boot_devs=None): + LI('Begin to reboot VM %s', vm_name) + conn = libvirt.open('qemu:///system') + try: + vm = conn.lookupByName(vm_name) + except libvirt.libvirtError as e: + LE(e) + err_exit('VM %s is not found: ' % vm_name) + + if boot_devs: + if vm.isActive(): + vm.destroy() + LI('Destroy VM %s' % vm_name) + + # root = ET.fromstring(vm.XMLDesc()) + temp_file = path_join(WORKSPACE, 'tmp.xml') + commands.getoutput('virsh dumpxml %s > %s' % (vm_name, temp_file)) + tree = ET.parse(temp_file) + root = tree.getroot() + LI('Modify the boot order %s' % boot_devs) + modify_vm_boot_order(root, boot_devs) + tree.write(temp_file) + + LI('Re-define and start the VM %s' % vm_name) + vm.undefine() + vm = conn.defineXML(commands.getoutput('cat %s' % temp_file)) + vm.create() + vm.setAutostart(1) + else: + vm.reset() + + conn.close() + + +def get_disk_file(root): + disks = [] + for disk in root.findall('./devices/disk'): + if 'device' in disk.attrib and disk.attrib['device'] == 'disk': + for source in disk.iterfind('source'): + if 'file' in source.attrib: + disks.append(source.attrib['file']) + return disks + + +def delete_vm_and_disk(vm_name): + LI('Begin to delete VM %s', vm_name) + conn = libvirt.open('qemu:///system') + vm = None + for item in conn.listAllDomains(): + if vm_name == item.name(): + vm = item + break + if vm is None: + conn.close() + LI('VM %s is not found' % vm_name) + return + + output = vm.XMLDesc() + root = ET.fromstring(output) + + if vm.isActive(): + vm.destroy() + LI('Destroy VM %s' % vm.name()) + vm.undefine() + + for disk_file in get_disk_file(root): + if os.path.isfile(disk_file): + status, output = commands.getstatusoutput('rm -f %s' % disk_file) + if status: + LW('Failed to delete the VM disk file %s' % disk_file) + + conn.close() + LI('VM %s is removed' % vm_name) + + +def create_virtual_network(template): + LI('Begin to create virtual network %s' % template) + output = commands.getoutput('cat %s' % template) + conn = libvirt.open('qemu:///system') + network = conn.networkDefineXML(output) + if network is None: + err_exit('Failed to define a virtual network %s' % template) + + network.create() # set the network active + network.setAutostart(1) + conn.close() + LI('Virtual network %s is created' % network.name()) + return network.name() + + +def delete_virtual_network(network_xml): + LI('Begin to find and delete network %s' % network_xml) + tree = ET.ElementTree(file=network_xml) + root = tree.getroot() + names = root.findall('./name') + assert len(names) == 1 + name = names[0].text + + result = 0 + conn = libvirt.open('qemu:///system') + + for net in conn.listAllNetworks(): + if name == net.name(): + if net.isActive(): + net.destroy() + LI('Network %s is destroyed' % name) + net.undefine() + LI('Network %s is deleted' % name) + result = 1 + break + conn.close() + if not result: + LI('Network %s is not found' % name) -- cgit 1.2.3-korg