summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorPeter Krempa <pkrempa@redhat.com>2015-04-17 15:07:15 +0200
committerPeter Krempa <pkrempa@redhat.com>2015-05-11 10:53:06 +0200
commit71c1cdb134201fdfb32d7a7c0fadfe307cb5850f (patch)
tree13c8b503b23f478af559bc90e14399a996fdbcf8 /examples
parent36737505c4adaafb8c98b6baa6bcb94eb20720ea (diff)
downloadlibvirt-python-71c1cdb134201fdfb32d7a7c0fadfe307cb5850f.tar.gz
examples: Add example to make guest agent lifecycle event useful
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. 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 and issues the guest agent command.
Diffstat (limited to 'examples')
-rw-r--r--examples/README2
-rwxr-xr-xexamples/guest-vcpus/guest-vcpu-daemon.py160
-rwxr-xr-xexamples/guest-vcpus/guest-vcpu.py74
3 files changed, 236 insertions, 0 deletions
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..c7c08a8
--- /dev/null
+++ b/examples/guest-vcpus/guest-vcpu-daemon.py
@@ -0,0 +1,160 @@
+#!/usr/bin/env python
+
+import libvirt
+import threading
+from xml.dom import minidom
+import time
+import sys
+import getopt
+import os
+
+uri = "qemu:///system"
+customXMLuri = "guest-cpu.python.libvirt.org"
+connectRetryTimeout = 5
+
+def usage():
+ print("usage: "+os.path.basename(sys.argv[0])+" [-h] [uri]")
+ print(" uri will default to qemu:///system")
+ print(" --help, -h Print(this help message")
+ print("")
+ print("This service waits for the guest agent lifecycle event and reissues " +
+ "guest agent calls to modify the cpu count according to the metadata " +
+ "set by guest-vcpu.py example")
+
+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("set vcpu count for domain " + dom.name() + " to " + str(ncpus))
+ 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'
+ 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__":
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
+ except getopt.GetoptError as err:
+ print(str(err))
+ usage()
+ sys.exit(2)
+ for o, a in opts:
+ if o in ("-h", "--help"):
+ usage()
+ sys.exit()
+
+ if len(args) > 1:
+ usage()
+ sys.exit(1)
+ elif len(args) == 1:
+ uri = args[0]
+
+ main()
diff --git a/examples/guest-vcpus/guest-vcpu.py b/examples/guest-vcpus/guest-vcpu.py
new file mode 100755
index 0000000..8faba87
--- /dev/null
+++ b/examples/guest-vcpus/guest-vcpu.py
@@ -0,0 +1,74 @@
+#!/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
+ 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)
+
+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)