ia64/xen-unstable

view tools/xen/lib/xend/XendDomain.py @ 1617:9ba1d5f8219c

bitkeeper revision 1.1026.2.2 (40e17d5fDAUxwe75FLw7um8OnJVbFQ)

Fixes to the Python scripts importing xenctl.ip. Required to run xend. Any problems -> let me know (gm281)
author gm281@boulderdash.cl.cam.ac.uk
date Tue Jun 29 14:31:59 2004 +0000 (2004-06-29)
parents 3d3f21585b96
children
line source
1 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
3 """Handler for domain operations.
4 Nothing here is persistent (across reboots).
5 Needs to be persistent for one uptime.
6 """
7 import sys
9 from twisted.internet import defer
11 import xen.ext.xc; xc = xen.ext.xc.new()
12 from xen.util import ip
14 import sxp
15 import XendRoot
16 xroot = XendRoot.instance()
17 import XendDB
18 import XendDomainInfo
19 import XendConsole
20 import EventServer
22 from xen.xend.server import SrvDaemon
23 xend = SrvDaemon.instance()
25 eserver = EventServer.instance()
27 __all__ = [ "XendDomain" ]
29 class XendDomain:
30 """Index of all domains. Singleton.
31 """
33 dbpath = "domain"
34 domain = {}
36 def __init__(self):
37 self.xconsole = XendConsole.instance()
38 # Table of domain info indexed by domain id.
39 self.db = XendDB.XendDB(self.dbpath)
40 #self.domain = {}
41 self.domain_db = self.db.fetchall("")
42 if xroot.get_rebooted():
43 print 'XendDomain> rebooted: removing all domain info'
44 self.rm_all()
45 eserver.subscribe('xend.virq', self.onVirq)
46 self.initial_refresh()
48 def onVirq(self, event, val):
49 print 'XendDomain> virq', val
50 self.reap()
52 def rm_all(self):
53 """Remove all domain info. Used after reboot.
54 """
55 for (k, v) in self.domain_db.items():
56 self._delete_domain(k, notify=0)
58 def initial_refresh(self):
59 """Refresh initial domain info from domain_db.
60 """
61 print "initial_refresh>"
62 for d in self.domain_db.values(): print 'db dom=', d
63 domlist = xc.domain_getinfo()
64 for d in domlist: print 'xc dom=', d
65 doms = {}
66 for d in domlist:
67 domid = str(d['dom'])
68 doms[domid] = d
69 dlist = []
70 for config in self.domain_db.values():
71 domid = str(sxp.child_value(config, 'id'))
72 print "dom=", domid, "config=", config
73 if domid in doms:
74 print "dom=", domid, "new"
75 deferred = self._new_domain(config, doms[domid])
76 dlist.append(deferred)
77 else:
78 print "dom=", domid, "del"
79 self._delete_domain(domid)
80 deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
81 def cbok(val):
82 #print "doms:"
83 #for d in self.domain.values(): print 'dom', d
84 self.refresh()
85 print "XendDomain>initial_refresh> doms:"
86 for d in self.domain.values(): print 'dom', d
87 deferred.addCallback(cbok)
89 def sync(self):
90 """Sync domain db to disk.
91 """
92 self.db.saveall("", self.domain_db)
94 def sync_domain(self, dom):
95 """Sync info for a domain to disk.
97 dom domain id (string)
98 """
99 self.db.save(dom, self.domain_db[dom])
101 def close(self):
102 pass
104 def _new_domain(self, savedinfo, info):
105 """Create a domain entry from saved info.
106 """
107 ## console = None
108 ## kernel = None
109 ## id = sxp.child_value(info, 'id')
110 ## dom = int(id)
111 ## name = sxp.child_value(info, 'name')
112 ## memory = int(sxp.child_value(info, 'memory'))
113 ## consoleinfo = sxp.child(info, 'console')
114 ## if consoleinfo:
115 ## consoleid = sxp.child_value(consoleinfo, 'id')
116 ## console = self.xconsole.console_get(consoleid)
117 ## if dom and console is None:
118 ## # Try to connect a console.
119 ## console = self.xconsole.console_create(dom)
120 ## config = sxp.child(info, 'config')
121 ## if config:
122 ## image = sxp.child(info, 'image')
123 ## if image:
124 ## image = sxp.child0(image)
125 ## kernel = sxp.child_value(image, 'kernel')
126 ## dominfo = XendDomainInfo.XendDomainInfo(
127 ## config, dom, name, memory, kernel, console)
128 config = sxp.child_value(savedinfo, 'config')
129 deferred = XendDomainInfo.vm_recreate(config, info)
130 def fn(dominfo):
131 self.domain[dominfo.id] = dominfo
132 deferred.addCallback(fn)
133 return deferred
135 def _add_domain(self, id, info, notify=1):
136 self.domain[id] = info
137 self.domain_db[id] = info.sxpr()
138 self.sync_domain(id)
139 if notify: eserver.inject('xend.domain.created', id)
141 def _delete_domain(self, id, notify=1):
142 if id in self.domain:
143 if notify: eserver.inject('xend.domain.died', id)
144 del self.domain[id]
145 if id in self.domain_db:
146 del self.domain_db[id]
147 self.db.delete(id)
149 def reap(self):
150 """Go through the domains looking for ones that have crashed or stopped.
151 Tidy them up.
152 """
153 print 'XendDomain>reap>'
154 domlist = xc.domain_getinfo()
155 casualties = []
156 for d in domlist:
157 #print 'dom', d
158 dead = 0
159 dead = dead or (d['crashed'] or d['shutdown'])
160 dead = dead or (d['dying'] and
161 not(d['running'] or d['paused'] or d['blocked']))
162 if dead:
163 casualties.append(d)
164 for d in casualties:
165 id = str(d['dom'])
166 print 'XendDomain>reap> died id=', id, d
167 dominfo = self.domain.get(id)
168 if not dominfo: continue
169 dominfo.died()
170 self.domain_destroy(id, refresh=0)
171 print 'XendDomain>reap<'
173 def refresh(self):
174 """Refresh domain list from Xen.
175 """
176 domlist = xc.domain_getinfo()
177 # Index the domlist by id.
178 # Add entries for any domains we don't know about.
179 doms = {}
180 for d in domlist:
181 id = str(d['dom'])
182 doms[id] = d
183 if id not in self.domain:
184 config = None
185 #image = None
186 #newinfo = XendDomainInfo.XendDomainInfo(
187 # config, d['dom'], d['name'], d['mem_kb']/1024, image=image, info=d)
188 deferred = XendDomainInfo.vm_recreate(config, d)
189 def fn(dominfo):
190 self._add_domain(dominfo.id, dominfo)
191 deferred.addCallback(fn)
192 # Remove entries for domains that no longer exist.
193 for d in self.domain.values():
194 dominfo = doms.get(d.id)
195 if dominfo:
196 d.update(dominfo)
197 else:
198 self._delete_domain(d.id)
199 self.reap()
201 def refresh_domain(self, id):
202 dom = int(id)
203 dominfo = xc.domain_getinfo(dom, 1)
204 if dominfo == [] or dominfo[0]['dom'] != dom:
205 try:
206 self._delete_domain(id)
207 except:
208 print 'refresh_domain: error'
209 raise
210 pass
211 else:
212 d = self.domain.get(id)
213 if d:
214 d.update(dominfo[0])
216 def domain_ls(self):
217 # List domains.
218 # Update info from kernel first.
219 self.refresh()
220 return self.domain.keys()
222 def domains(self):
223 self.refresh()
224 return self.domain.values()
226 def domain_create(self, config):
227 # Create domain, log it.
228 deferred = XendDomainInfo.vm_create(config)
229 def fn(dominfo):
230 self._add_domain(dominfo.id, dominfo)
231 return dominfo
232 deferred.addCallback(fn)
233 return deferred
235 def domain_get(self, id):
236 id = str(id)
237 self.refresh_domain(id)
238 return self.domain[id]
240 def domain_unpause(self, id):
241 """(Re)start domain running.
242 """
243 dom = int(id)
244 eserver.inject('xend.domain.unpause', id)
245 return xc.domain_unpause(dom=dom)
247 def domain_pause(self, id):
248 """Pause domain execution.
249 """
250 dom = int(id)
251 eserver.inject('xend.domain.pause', id)
252 return xc.domain_pause(dom=dom)
254 def domain_shutdown(self, id, reason='poweroff'):
255 """Shutdown domain (nicely).
256 """
257 dom = int(id)
258 if dom <= 0:
259 return 0
260 eserver.inject('xend.domain.shutdown', [id, reason])
261 val = xend.domain_shutdown(dom, reason)
262 self.refresh()
263 return val
265 def domain_destroy(self, id, refresh=1):
266 """Terminate domain immediately.
267 """
268 dom = int(id)
269 if dom <= 0:
270 return 0
271 eserver.inject('xend.domain.destroy', id)
272 val = xc.domain_destroy(dom=dom)
273 if refresh: self.refresh()
274 return val
276 def domain_migrate(self, id, dst):
277 """Start domain migration.
278 """
279 # Need a cancel too?
280 pass
282 def domain_save(self, id, dst, progress=0):
283 """Save domain state to file, destroy domain.
284 """
285 dom = int(id)
286 self.domain_pause(id)
287 eserver.inject('xend.domain.save', id)
288 rc = xc.linux_save(dom=dom, state_file=dst, progress=progress)
289 if rc == 0:
290 self.domain_destroy(id)
291 return rc
293 def domain_restore(self, src, config, progress=0):
294 """Restore domain from file.
295 """
296 dominfo = XendDomainInfo.dom_restore(dom, config)
297 self._add_domain(dominfo.id, dominfo)
298 return dominfo
300 #============================================================================
301 # Backward compatibility stuff from here on.
303 def domain_pincpu(self, dom, cpu):
304 dom = int(dom)
305 return xc.domain_pincpu(dom, cpu)
307 def domain_cpu_bvt_set(self, dom, mcuadv, warp, warpl, warpu):
308 dom = int(dom)
309 return xc.bvtsched_domain_set(dom=dom, mcuadv=mcuadv,
310 warp=warp, warpl=warpl, warpu=warpu)
312 def domain_cpu_bvt_get(self, dom):
313 dom = int(dom)
314 return xc.bvtsched_domain_get(dom)
316 def domain_cpu_atropos_set(self, dom, period, slice, latency, xtratime):
317 dom = int(dom)
318 return xc.atropos_domain_set(dom, period, slice, latency, xtratime)
320 def domain_cpu_atropos_get(self, dom):
321 dom = int(dom)
322 return xc.atropos_domain_get(dom)
324 def domain_vif_ls(self, dom):
325 dominfo = self.domain_get(dom)
326 if not dominfo: return None
327 devs = dominfo.get_devices('vif')
328 return range(0, len(devs))
330 def domain_vif_get(self, dom, vif):
331 dominfo = self.domain_get(dom)
332 if not dominfo: return None
333 return dominfo.get_device_by_index(vif)
335 def domain_vif_ip_add(self, dom, vif, ip):
336 dom = int(dom)
337 return xenctl.ip.setup_vfr_rules_for_vif(dom, vif, ip)
339 def domain_vbd_ls(self, dom):
340 dominfo = self.domain_get(dom)
341 if not dominfo: return []
342 devs = dominfo.get_devices('vbd')
343 return [ sxp.child_value(v, 'dev') for v in devs ]
345 def domain_vbd_get(self, dom, vbd):
346 dominfo = self.domain_get(dom)
347 if not dominfo: return None
348 devs = dominfo.get_devices('vbd')
349 for v in devs:
350 if sxp.child_value(v, 'dev') == vbd:
351 return v
352 return None
354 def domain_shadow_control(self, dom, op):
355 dom = int(dom)
356 return xc.shadow_control(dom, op)
358 #============================================================================
360 def instance():
361 global inst
362 try:
363 inst
364 except:
365 inst = XendDomain()
366 return inst