Temporary version hack
[libvirt-python/ericb.git] / examples / guest-vcpus / guest-vcpu-daemon.py
blobc7c08a847ac79cfb9af8cb95816826b03ddec1be
1 #!/usr/bin/env python
3 import libvirt
4 import threading
5 from xml.dom import minidom
6 import time
7 import sys
8 import getopt
9 import os
11 uri = "qemu:///system"
12 customXMLuri = "guest-cpu.python.libvirt.org"
13 connectRetryTimeout = 5
15 def usage():
16 print("usage: "+os.path.basename(sys.argv[0])+" [-h] [uri]")
17 print(" uri will default to qemu:///system")
18 print(" --help, -h Print(this help message")
19 print("")
20 print("This service waits for the guest agent lifecycle event and reissues " +
21 "guest agent calls to modify the cpu count according to the metadata " +
22 "set by guest-vcpu.py example")
24 class workerData:
25 def __init__(self):
26 self.doms = list()
27 self.conn = None
28 self.cond = threading.Condition()
30 def notify(self):
31 self.cond.acquire()
32 self.cond.notify()
33 self.cond.release()
35 def waitNotify(self):
36 self.cond.acquire()
37 self.cond.wait()
38 self.cond.release()
40 def addDomainNotify(self, dom):
41 self.doms.append(dom)
42 self.notify()
44 def closeConnectNotify(self):
45 conn = self.conn
46 self.conn = None
47 conn.close()
48 self.notify()
50 def setConnect(self, conn):
51 self.conn = conn
53 def hasConn(self):
54 return self.conn is not None
56 def hasDom(self):
57 return len(self.doms) > 0
59 def getDom(self):
60 return self.doms.pop()
62 def setDoms(self, doms):
63 self.doms = doms
66 def virEventLoopNativeRun():
67 while True:
68 libvirt.virEventRunDefaultImpl()
70 def handleAgentLifecycleEvent(conn, dom, state, reason, opaque):
71 if state == libvirt.VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_STATE_CONNECTED:
72 opaque.addDomainNotify(dom)
74 def handleConnectClose(conn, reason, opaque):
75 print('Disconnected from ' + uri)
76 opaque.closeConnectNotify()
78 def handleLibvirtLibraryError(opaque, error):
79 pass
81 def processAgentConnect(dom):
82 try:
83 cpus = dom.metadata(libvirt.VIR_DOMAIN_METADATA_ELEMENT, customXMLuri,
84 libvirt.VIR_DOMAIN_AFFECT_LIVE)
85 doc = minidom.parseString(cpus)
86 ncpus = int(doc.getElementsByTagName('ncpus')[0].getAttribute('count'))
87 except:
88 return
90 try:
91 dom.setVcpusFlags(ncpus, libvirt.VIR_DOMAIN_AFFECT_LIVE | libvirt.VIR_DOMAIN_VCPU_GUEST)
92 print("set vcpu count for domain " + dom.name() + " to " + str(ncpus))
93 except:
94 print("failed to set vcpu count for domain " + dom.name())
96 def work():
97 data = workerData()
99 print("Using uri: " + uri)
101 while True:
102 if not data.hasConn():
103 try:
104 conn = libvirt.open(uri)
105 except:
106 print('Failed to connect to ' + uri + ', retry in ' + str(connectRetryTimeout)) + ' seconds'
107 time.sleep(connectRetryTimeout)
108 continue
110 print('Connected to ' + uri)
112 data.setConnect(conn)
113 conn.registerCloseCallback(handleConnectClose, data)
114 conn.setKeepAlive(5, 3)
115 conn.domainEventRegisterAny(None,
116 libvirt.VIR_DOMAIN_EVENT_ID_AGENT_LIFECYCLE,
117 handleAgentLifecycleEvent,
118 data)
120 data.setDoms(conn.listAllDomains(libvirt.VIR_CONNECT_LIST_DOMAINS_ACTIVE))
122 while data.hasConn() and data.hasDom():
123 processAgentConnect(data.getDom())
125 data.waitNotify()
127 def main():
128 libvirt.virEventRegisterDefaultImpl()
129 libvirt.registerErrorHandler(handleLibvirtLibraryError, None)
131 worker = threading.Thread(target=work)
132 worker.setDaemon(True)
133 worker.start()
135 eventLoop = threading.Thread(target=virEventLoopNativeRun)
136 eventLoop.setDaemon(True)
137 eventLoop.start()
139 while True:
140 time.sleep(1)
142 if __name__ == "__main__":
143 try:
144 opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
145 except getopt.GetoptError as err:
146 print(str(err))
147 usage()
148 sys.exit(2)
149 for o, a in opts:
150 if o in ("-h", "--help"):
151 usage()
152 sys.exit()
154 if len(args) > 1:
155 usage()
156 sys.exit(1)
157 elif len(args) == 1:
158 uri = args[0]
160 main()