[libvirt] [python PATCH] examples: Add example to make guest agent lifecycle event useful
John Ferlan
jferlan at redhat.com
Wed Apr 29 15:32:09 UTC 2015
On 04/17/2015 09:09 AM, Peter Krempa wrote:
> This example allows to use the guest agent event and metadata to track
> vCPU count set via the guest agent (agent-based onlining/offlining) and
> keep it persistent accross domain restarts.
>
s/accross/across (or between)
> The daemon listens for the agent lifecycle event, and if it's received
> it looks into doman's metadata to see whether a desired count was set
s/into doman's/into the domain's/
> and issues the guest agent command.
> ---
> MANIFEST.in | 2 +
> examples/README | 2 +
> examples/guest-vcpus/guest-vcpu-daemon.py | 131 ++++++++++++++++++++++++++++++
> examples/guest-vcpus/guest-vcpu.py | 76 +++++++++++++++++
> 4 files changed, 211 insertions(+)
> create mode 100755 examples/guest-vcpus/guest-vcpu-daemon.py
> create mode 100755 examples/guest-vcpus/guest-vcpu.py
>
Couple of more nits listed below - some are just typo's others are
observations while reviewing.
I don't have python3 installed in order to try this, but at least the
print and except clauses which caused previous issues appear to follow
the python3 rules.
ACK in general - I'm sure it'll be obvious which nits are relevant.
John
> diff --git a/MANIFEST.in b/MANIFEST.in
> index dd05221..2cd1b46 100644
> --- a/MANIFEST.in
> +++ b/MANIFEST.in
> @@ -11,6 +11,8 @@ include examples/domsave.py
> include examples/domstart.py
> include examples/esxlist.py
> include examples/event-test.py
> +include examples/guest-vcpus/guest-vcpu-daemon.py
> +include examples/guest-vcpus/guest-vcpu.py
> include examples/topology.py
> include generator.py
> include libvirt-lxc-override-api.xml
> diff --git a/examples/README b/examples/README
> index 1d4b425..0cb4513 100644
> --- a/examples/README
> +++ b/examples/README
> @@ -12,6 +12,8 @@ esxlist.py - list active domains of an VMware ESX host and print some info.
> also demonstrates how to use the libvirt.openAuth() method
> dhcpleases.py - list dhcp leases for a given virtual network
> domipaddrs.py - list IP addresses for guest domains
> +guest-vcpus - two helpers to make the guest agent event useful with agent based
> + vCPU state modification
>
> The XML files in this directory are examples of the XML format that libvirt
> expects, and will have to be adapted for your setup. They are only needed
> diff --git a/examples/guest-vcpus/guest-vcpu-daemon.py b/examples/guest-vcpus/guest-vcpu-daemon.py
> new file mode 100755
> index 0000000..e5a389e
> --- /dev/null
> +++ b/examples/guest-vcpus/guest-vcpu-daemon.py
> @@ -0,0 +1,131 @@
> +#!/usr/bin/env python
> +
> +import libvirt
> +import threading
> +from xml.dom import minidom
> +import time
> +
> +uri = "qemu:///system"
Although just an example, this one doesn't allow setting of the uri;
however, the guest-vcpu.py does.
> +customXMLuri = "guest-cpu.python.libvirt.org"
> +connectRetryTimeout = 5
> +
> +class workerData:
> + def __init__(self):
> + self.doms = list()
> + self.conn = None
> + self.cond = threading.Condition()
> +
> + def notify(self):
> + self.cond.acquire()
> + self.cond.notify()
> + self.cond.release()
> +
> + def waitNotify(self):
> + self.cond.acquire()
> + self.cond.wait()
> + self.cond.release()
> +
> + def addDomainNotify(self, dom):
> + self.doms.append(dom)
> + self.notify()
> +
> + def closeConnectNotify(self):
> + conn = self.conn
> + self.conn = None
> + conn.close()
> + self.notify()
> +
> + def setConnect(self, conn):
> + self.conn = conn
> +
> + def hasConn(self):
> + return self.conn is not None
> +
> + def hasDom(self):
> + return len(self.doms) > 0
> +
> + def getDom(self):
> + return self.doms.pop()
> +
> + def setDoms(self, doms):
> + self.doms = doms
> +
> +
> +def virEventLoopNativeRun():
> + while True:
> + libvirt.virEventRunDefaultImpl()
> +
> +def handleAgentLifecycleEvent(conn, dom, state, reason, opaque):
> + if state == libvirt.VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_STATE_CONNECTED:
> + opaque.addDomainNotify(dom)
> +
> +def handleConnectClose(conn, reason, opaque):
> + print('Disconnected from ' + uri)
> + opaque.closeConnectNotify()
> +
> +def handleLibvirtLibraryError(opaque, error):
> + pass
> +
> +def processAgentConnect(dom):
> + try:
> + cpus = dom.metadata(libvirt.VIR_DOMAIN_METADATA_ELEMENT, customXMLuri,
> + libvirt.VIR_DOMAIN_AFFECT_LIVE)
> + doc = minidom.parseString(cpus)
> + ncpus = int(doc.getElementsByTagName('ncpus')[0].getAttribute('count'))
> + except:
> + return
> +
> + try:
> + dom.setVcpusFlags(ncpus, libvirt.VIR_DOMAIN_AFFECT_LIVE | libvirt.VIR_DOMAIN_VCPU_GUEST)
> + print("seting vcpus for domain " + dom.name() + " count " + str(ncpus))
s/seting vcpus/setting vcpu count/ (or set vcpu count, since setting
implies you're about to do it and set implies you've done it)
> + except:
> + print("failed to set vcpu count for domain " + dom.name())
> +
> +def work():
> + data = workerData()
> +
> + print("Using uri: " + uri)
> +
> + while True:
> + if not data.hasConn():
> + try:
> + conn = libvirt.open(uri)
> + except:
> + print('Failed to connect to ' + uri + ' Retry in ' + str(connectRetryTimeout)) + ' seconds'
s/Retry/, retry/
> + time.sleep(connectRetryTimeout)
> + continue
> +
> + print('Connected to ' + uri)
> +
> + data.setConnect(conn)
> + conn.registerCloseCallback(handleConnectClose, data)
> + conn.setKeepAlive(5, 3)
> + conn.domainEventRegisterAny(None,
> + libvirt.VIR_DOMAIN_EVENT_ID_AGENT_LIFECYCLE,
> + handleAgentLifecycleEvent,
> + data)
> +
> + data.setDoms(conn.listAllDomains(libvirt.VIR_CONNECT_LIST_DOMAINS_ACTIVE))
> +
> + while data.hasConn() and data.hasDom():
> + processAgentConnect(data.getDom())
> +
> + data.waitNotify()
> +
> +def main():
> + libvirt.virEventRegisterDefaultImpl()
> + libvirt.registerErrorHandler(handleLibvirtLibraryError, None)
> +
> + worker = threading.Thread(target=work)
> + worker.setDaemon(True)
> + worker.start()
> +
> + eventLoop = threading.Thread(target=virEventLoopNativeRun)
> + eventLoop.setDaemon(True)
> + eventLoop.start()
> +
> + while True:
> + time.sleep(1)
> +
> +if __name__ == "__main__":
> + main()
If you decide to allow uri setting then you'll need the usage for this
one as well as obviously parsing the args.
> diff --git a/examples/guest-vcpus/guest-vcpu.py b/examples/guest-vcpus/guest-vcpu.py
> new file mode 100755
> index 0000000..965b09c
> --- /dev/null
> +++ b/examples/guest-vcpus/guest-vcpu.py
> @@ -0,0 +1,76 @@
> +#!/usr/bin/env python
> +
> +import libvirt
> +import sys
> +import getopt
> +import os
> +
> +customXMLuri = "guest-cpu.python.libvirt.org"
> +
> +def usage():
> + print("usage: "+os.path.basename(sys.argv[0])+" [-hcl] domain count [uri]")
> + print(" uri will default to qemu:///system")
> + print(" --help, -h Print(this help message")
> + print(" --config, -c Modify persistent domain configuration")
> + print(" --live, -l Modify live domain configuration")
> + print("")
> + print("Sets the vCPU count via the guest agent and sets the metadata element " +
> + "used by guest-vcpu-daemon.py example")
> +
> +uri = "qemu:///system"
> +flags = 0
> +live = False;
> +config = False;
> +
> +try:
> + opts, args = getopt.getopt(sys.argv[1:], "hcl", ["help", "config", "live"])
> +except getopt.GetoptError as err:
> + # print help information and exit:
> + print(str(err)) # will print something like "option -a not recognized"
> + usage()
> + sys.exit(2)
> +for o, a in opts:
> + if o in ("-h", "--help"):
> + usage()
> + sys.exit()
> + if o in ("-c", "--config"):
> + config = True
> + flags |= libvirt.VIR_DOMAIN_AFFECT_CONFIG
> +
extra line
> + if o in ("-l", "--live"):
> + live = True
> + flags |= libvirt.VIR_DOMAIN_AFFECT_LIVE
> +
> +if len(args) < 2:
> + usage()
> + sys.exit(1)
> +elif len(args) >= 3:
> + uri = args[2]
> +
> +domain = args[0]
> +count = int(args[1])
> +
> +conn = libvirt.open(uri)
> +dom = conn.lookupByName(domain)
> +
> +if flags == 0 or config:
> + confvcpus = dom.vcpusFlags(libvirt.VIR_DOMAIN_AFFECT_CONFIG)
> +
> + if confvcpus < count:
> + print("Persistent domain configuration has only " + str(confvcpus) + " vcpus configured")
> + sys.exit(1)
> +
> +if flags == 0 or live:
> + livevcpus = dom.vcpusFlags(libvirt.VIR_DOMAIN_AFFECT_LIVE)
> +
> + if livevcpus < count:
> + print("Live domain configuration has only " + str(livevcpus) + " vcpus configured")
> + sys.exit(1)
> +
another extra line
> +
> +if flags == 0 or live:
> + dom.setVcpusFlags(count, libvirt.VIR_DOMAIN_AFFECT_LIVE | libvirt.VIR_DOMAIN_VCPU_GUEST)
> +
> +meta = "<ncpus count='" + str(count) + "'/>"
> +
> +dom.setMetadata(libvirt.VIR_DOMAIN_METADATA_ELEMENT, meta, "guestvcpudaemon", customXMLuri, flags)
>
More information about the libvir-list
mailing list