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) > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list