python libvirt虚拟机监控

根据python-libvirt写的一个脚本,算比较全,包括虚拟机的开启,关闭,快照,克隆,以及虚拟机的系统参数(设备信息,镜像,CPU,磁盘,内存、网络等)

import libvirt
import os
from datetime import datetime
try:
    from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE, VIR_MIGRATE_LIVE, \
        VIR_MIGRATE_UNSAFE, VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA
except:
    from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE, VIR_MIGRATE_LIVE
from lxml import etree
from xml.etree import ElementTree
import time
class Libvirt():
    def __init__(self, authurl, domainname):
        self.conn = libvirt.open(authurl)
        self.dom = self.conn.lookupByName(domainname)

    def get_xml_path(self, text, path = None, func = None):
        """
        Return the content from the passed xml xpath, or return the result
        of a passed function (receives xpathContext as its only arg)
        """
        doc = None
        ctx = None
        result = None
        html = etree.HTML(str(text), etree.HTMLParser())
        if path and 'domain' in path:
            path = './' + path
        if path:
            if '@' in path:
                pass
            else:
                path = path + '/text()'

        try:
            result = html.xpath(path)
            if len(result) > 0:
                result = int(result[0])
        except:
            pass

        if func:
            result = func(html)
        return result

    def start(self):
        self.dom.create()

    def is_active(self):
        r = self.dom.isActive()
        return r

    def status(self):
        r = self.dom.state()[0]
        return r

    def shutdown(self):
        self.dom.destroy()

    def resume(self):
        self.dom.resume()
   
   def get_network(self,net):
       netw = self.conn.networkLookupByName(net)
       return netw
    def get_net_device(self):
        def get_mac_ipaddr(net, mac_host):
            def fixed(ctx):
                for net in ctx.xpath('/network/ip/dhcp/host'):
                    mac = net.xpath('@mac')[0]
                    host = net.xpath('@ip')[0]
                    if mac == mac_host:
                        return host
                return None

            return self.get_xml_path(net.XMLDesc(0), func=fixed)

        def networks(ctx):
            result = []
            for net in ctx.xpath('.//domain/devices/interface'):
                mac_host = net.xpath('mac/@address')[0]
                nic_host = net.xpath('source/@network|source/@bridge|source/@dev')[0]
                try:
                    net = self.get_network(nic_host)
                    ip = get_mac_ipaddr(net, mac_host)
                except:
                    ip = None
                result.append({'mac': mac_host, 'nic': nic_host, 'ip': ip})
            return result

        return self.get_xml_path(self.dom.XMLDesc(0), func=networks)

    def get_disk_device(self):
        def disks(ctx):
            result = []
            dev = None
            volume = None
            storage = None
            src_fl = None
            disk_format = None
            for disk in ctx.xpath('.//domain/devices/disk'):
                device = disk.xpath('@device')[0]
                if device == 'disk':
                    try:
                        dev = disk.xpath('target/@dev')[0]
                        src_fl = disk.xpath('source/@file|source/@dev|source/@name|source/@volume')[0]
                        disk_format = disk.xpath('driver/@type')[0]
                        try:
                            vol = self.conn.storageVolLookupByPath(src_fl)
                            volume = vol.name()
                            stg = vol.storagePoolLookupByVolume()
                            storage = stg.name()
                        except:
                            volume = src_fl
                    except:
                        pass
                    finally:
                        result.append(
                            {'dev': dev, 'image': volume, 'storage': storage, 'path': src_fl, 'format': disk_format})
            return result

        return self.get_xml_path(self.dom.XMLDesc(0), func = disks)

    def get_memory(self):
        mem = self.get_xml_path(self.dom.XMLDesc(0), "/domain/currentmemory")
        return int(mem) / 1024

    def memory_usage(self):
        self.dom.setMemoryStatsPeriod(10)
        meminfo = self.dom.memoryStats()
        print(meminfo)
        free_mem = float(meminfo['unused'])
        total_mem = float(meminfo['available'])
        mem_usage = ((total_mem - free_mem) / total_mem) * 100
        return mem_usage

    def get_vcpu(self):
        cur_vcpu = self.get_xml_path(self.dom.XMLDesc(0), "/domain/vcpu/@current")
        if cur_vcpu:
            vcpu = cur_vcpu
        else:
            vcpu = self.get_xml_path(self.dom.XMLDesc(0), "/domain/vcpu")
        return vcpu

    def cpu_usage(self):
        cpu_usage = {}
        if self.status() == 1:
            nbcore = self.conn.getInfo()[2]
            cpu_use_ago = self.dom.info()[4]
            time.sleep(1)
            cpu_use_now = self.dom.info()[4]
            diff_usage = cpu_use_now - cpu_use_ago
            cpu_usage['cpuuage'] = 100 * diff_usage / (1 * nbcore * 10 ** 9)
        else:
            cpu_usage['cpuusage'] = 0
        return cpu_usage

    def disk_use(self):
        devices = []
        dev_usrate = []
        dev_usage = []
        tree = ElementTree.fromstring(self.dom.XMLDesc(0))
        for disk in tree.findall('devices/disk'):
            if disk.get('device') == 'disk':
                dev_file = None
                dev_bus = None
                network_disk = True
                for elm in disk:
                    if elm.tag == 'source':
                        if elm.get('protocol'):
                            dev_file = elm.get('protocol')
                            network_disk = True
                        if elm.get('file'):
                            dev_file = elm.get('file')
                        if elm.get('dev'):
                            dev_file = elm.get('dev')
                    if elm.tag == 'target':
                        dev_bus = elm.get('dev')
                if (dev_file and dev_bus) is not None:
                    if network_disk:
                        dev_file = dev_bus
                    devices.append([dev_file, dev_bus])
        for dev in devices:
            if self.status() == 1:
                rd_use_ago = self.dom.blockStats(dev[0])[1]
                wr_use_ago = self.dom.blockStats(dev[0])[3]
                time.sleep(1)
                rd_use_now = self.dom.blockStats(dev[0])[1]
                wr_use_now = self.dom.blockStats(dev[0])[3]
                rd_diff_usage = rd_use_now - rd_use_ago
                wr_diff_usage = wr_use_now - wr_use_ago
            else:
                rd_diff_usage = 0
                wr_diff_usage = 0
            dev_usage.append(({'dev': dev[1], 'usage': round(self.dom.blockInfo(dev[0])[2]*100/self.dom.blockInfo(dev[0])[0], 2)}))
            dev_usrate.append({'dev': dev[1], 'rd': rd_diff_usage, 'wr': wr_diff_usage})
        return dev_usage, dev_usrate

    def net_usrate(self):
        devices = []
        dev_usage = []
        tree = ElementTree.fromstring(self.dom.XMLDesc(0))
        if self.status() == 1:
            tree = ElementTree.fromstring(self.dom.XMLDesc(0))
            for target in tree.findall("devices/interface/target"):
                devices.append(target.get("dev"))
            for i, dev in enumerate(devices):
                rx_use_ago = self.dom.interfaceStats(dev)[0]
                tx_use_ago = self.dom.interfaceStats(dev)[4]
                time.sleep(1)
                rx_use_now = self.dom.interfaceStats(dev)[0]
                tx_use_now = self.dom.interfaceStats(dev)[4]
                rx_diff_usage = (rx_use_now - rx_use_ago) * 8
                tx_diff_usage = (tx_use_now - tx_use_ago) * 8
                dev_usage.append({'dev': i, 'rx': rx_diff_usage, 'tx': tx_diff_usage})
        else:
            for i, dev in enumerate(self.get_net_device()):
                dev_usage.append({'dev': i, 'rx': 0, 'tx': 0})
        return dev_usage

    def create_snapshot(self, name):
        xml = """<domainsnapshot>
                     <name>%s</name>
                     <state>shutoff</state>
                     <creationtime>%d</creationtime>""" % (name, time.time())
        xml += self.dom.XMLDesc(VIR_DOMAIN_XML_SECURE)
        xml += """<active>0</active>
                  </domainsnapshot>"""
        self.dom.snapshotCreateXML(xml, 0)

    def get_snapshot(self):
        snapshots = []
        snapshot_list = self.dom.snapshotListNames(0)
        print(snapshot_list)
        for snapshot in snapshot_list:
            snap = self.dom.snapshotLookupByName(snapshot, 0)
            snap_time_create = self.get_xml_path(snap.getXMLDesc(0), "/domainsnapshot/creationtime")
            print(snap.getXMLDesc(0))
            print(snap_time_create)
            snapshots.append({'date': datetime.fromtimestamp(int(snap_time_create)), 'name': snapshot})
        return snapshots

    def snapshot_delete(self, snapshotname):
        snap = self.dom.snapshotLookupByName(snapshotname, 0)
        snap.delete(0)

    def snapshot_revert(self, snapshotname):
        snap = self.dom.snapshotLookupByName(snapshotname, 0)
        self.dom.revertToSnapshot(snap, 0)

    def clone_instance(self, clone_data):
        #clone_data include name\disk\address\
        clone_dev_path = []

        xml = self.dom.XMLDesc(VIR_DOMAIN_XML_SECURE)
        tree = ElementTree.fromstring(xml)
        name = tree.find('name')
        name.text = clone_data['name']
        uuid = tree.find('uuid')
        tree.remove(uuid)

        for num, net in enumerate(tree.findall('devices/interface')):
            elm = net.find('mac')
            elm.set('address', clone_data['net-' + str(num)])

        for disk in tree.findall('devices/disk'):
            if disk.get('device') == 'disk':
                elm = disk.find('target')
                device_name = elm.get('dev')
                if device_name:
                    target_file = clone_data['disk-' + device_name]
                    try:
                        meta_prealloc = clone_data['meta-' + device_name]
                    except:
                        meta_prealloc = False
                    elm.set('dev', device_name)

                elm = disk.find('source')
                source_file = elm.get('file')
                if source_file:
                    clone_dev_path.append(source_file)
                    clone_path = os.path.join(os.path.dirname(source_file),
                                              target_file)
                    elm.set('file', clone_path)

                    vol = self.get_volume_by_path(source_file)
                    vol_format = self.get_xml_path(vol.XMLDesc(0),
                                                   "/volume/target/format/@type")

                    if vol_format == 'qcow2' and meta_prealloc:
                        meta_prealloc = True
                    vol_clone_xml = """
                                    <volume>
                                        <name>%s</name>
                                        <capacity>0</capacity>
                                        <allocation>0</allocation>
                                        <target>
                                            <format type='%s'/>
                                        </target>
                                    </volume>""" % (target_file, vol_format)
                    stg = vol.storagePoolLookupByVolume()
                    stg.createXMLFrom(vol_clone_xml, vol, meta_prealloc)

        self.dom.defineXML(ElementTree.tostring(tree))
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值