debuggers.hg

view tools/python/xen/xend/XendClient.py @ 4647:9c88ba91d330

bitkeeper revision 1.1346.1.1 (42670505dNhgnJm5dQD81pCalXMZgw)

manual merge
author iap10@freefall.cl.cam.ac.uk
date Thu Apr 21 01:42:29 2005 +0000 (2005-04-21)
parents 7fc6eac6da3a 3dc193a9786a
children 86285c9c18c1
line source
1 #!/usr/bin/env python
2 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
3 """Client API for the HTTP interface on xend.
4 Callable as a script - see main().
5 Supports synchronous or asynchronous connection to xend.
7 This API is the 'control-plane' for xend.
8 The 'data-plane' is done separately. For example, consoles
9 are accessed via sockets on xend, but the list of consoles
10 is accessible via this API.
11 """
12 import os
13 import sys
14 import types
16 import sxp
17 import PrettyPrint
18 from XendProtocol import XendClientProtocol, SynchXendClientProtocol, XendError
20 DEBUG = 0
22 def fileof(val):
23 """Converter for passing configs or other 'large' data.
24 Handles lists, files directly.
25 Assumes a string is a file name and passes its contents.
26 """
27 if isinstance(val, types.ListType):
28 return sxp.to_string(val)
29 if isinstance(val, types.StringType):
30 return file(val)
31 if hasattr(val, 'readlines'):
32 return val
33 raise XendError('cannot convert value')
35 # todo: need to sort of what urls/paths are using for objects.
36 # e.g. for domains at the moment return '0'.
37 # should probably return abs path w.r.t. server, e.g. /xend/domain/0.
38 # As an arg, assume abs path is obj uri, otherwise just id.
40 # Function to convert to full url: Xend.uri(path), e.g.
41 # maps /xend/domain/0 to http://wray-m-3.hpl.hp.com:8000/xend/domain/0
42 # And should accept urls for ids?
44 class URL:
45 """A URL.
46 """
48 def __init__(self, proto='http', host='localhost', port=None, path='', query=None, frag=None):
49 self.proto = proto
50 self.host = host
51 if port: port = int(port)
52 self.port = port
53 self.path = path
54 self.query = query
55 self.frag = frag
57 def url(self):
58 """Get the full URL string including protocol, location and the full path.
59 """
60 return self.proto + '://' + self.location() + self.fullpath()
62 def location(self):
63 """Get the location part of the URL, including host and port, if present.
64 """
65 if self.port:
66 return self.host + ':' + str(self.port)
67 else:
68 return self.host
70 def fullpath(self):
71 """Get the full path part of the URL, including query and fragment if present.
72 """
73 u = [ self.path ]
74 if self.query:
75 u.append('?')
76 u.append(self.query)
77 if self.frag:
78 u.append('#')
79 u.append(self.frag)
80 return ''.join(u)
82 def relative(self, path='', query=None, frag=None):
83 """Create a URL relative to this one.
84 """
85 return URL(proto=self.proto,
86 host=self.host,
87 port=self.port,
88 path=self.path + path,
89 query=query,
90 frag=frag)
92 class Xend:
93 """Client interface to Xend.
94 """
96 """Default location of the xend server."""
97 SRV_DEFAULT = "localhost:8000"
99 """Environment variable to set the location of xend."""
100 SRV_VAR = "XEND"
102 """Default path to the xend root on the server."""
103 ROOT_DEFAULT = "/xend/"
105 """Environment variable to set the xend root path."""
106 ROOT_VAR = "XEND_ROOT"
108 def __init__(self, client=None, srv=None, root=None):
109 """Create a xend client interface.
110 If the client protocol is not specified, the default
111 is to use a synchronous protocol.
113 @param client: client protocol to use
114 @param srv: server host, and optional port (format host:port)
115 @param root: xend root path on the server
116 """
117 if client is None:
118 client = SynchXendClientProtocol()
119 self.client = client
120 self.bind(srv, root)
122 def default_server(self):
123 """Get the default location of the xend server.
124 """
125 return os.getenv(self.SRV_VAR, self.SRV_DEFAULT)
127 def default_root(self):
128 """Get the default root path on the xend server.
129 """
130 return os.getenv(self.ROOT_VAR, self.ROOT_DEFAULT)
132 def bind(self, srv=None, root=None):
133 """Bind to a given server.
135 @param srv: server location (host:port)
136 @param root: xend root path on the server
137 """
138 if srv is None: srv = self.default_server()
139 if root is None: root = self.default_root()
140 if not root.endswith('/'): root += '/'
141 (host, port) = srv.split(':', 1)
142 self.url = URL(host=host, port=port, path=root)
144 def xendGet(self, url, args=None):
145 return self.client.xendGet(url, args)
147 def xendPost(self, url, data):
148 return self.client.xendPost(url, data)
150 def nodeurl(self, id=''):
151 return self.url.relative('node/' + str(id))
153 def domainurl(self, id=''):
154 return self.url.relative('domain/' + str(id))
156 def consoleurl(self, id=''):
157 return self.url.relative('console/' + str(id))
159 def deviceurl(self, id=''):
160 return self.url.relative('device/' + str(id))
162 def vneturl(self, id=''):
163 return self.url.relative('vnet/' + str(id))
165 def eventurl(self, id=''):
166 return self.url.relative('event/' + str(id))
168 def xend(self):
169 return self.xendGet(self.url)
171 def xend_node(self):
172 return self.xendGet(self.nodeurl())
174 def xend_node_shutdown(self):
175 return self.xendPost(self.nodeurl(),
176 {'op' : 'shutdown'})
178 def xend_node_restart(self):
179 return self.xendPost(self.nodeurl(),
180 {'op' : 'reboot'})
182 def xend_node_get_dmesg(self):
183 return self.xendGet(self.nodeurl('dmesg'))
185 def xend_node_clear_dmesg(self):
186 return self.xendPost(self.nodeurl('dmesg'),
187 {'op' : 'clear' } )
189 def xend_node_log(self):
190 return self.xendGet(self.nodeurl('log'))
192 def xend_node_cpu_bvt_slice_set(self, ctx_allow):
193 return self.xendPost(self.nodeurl(),
194 {'op' : 'cpu_bvt_slice_set',
195 'ctx_allow' : ctx_allow })
197 def xend_domains(self):
198 return self.xendGet(self.domainurl())
200 def xend_domain_create(self, conf):
201 return self.xendPost(self.domainurl(),
202 {'op' : 'create',
203 'config' : fileof(conf) })
205 def xend_domain_restore(self, filename):
206 return self.xendPost(self.domainurl(),
207 {'op' : 'restore',
208 'file' : filename })
210 def xend_domain_configure(self, id, conf):
211 return self.xendPost(self.domainurl(id),
212 {'op' : 'configure',
213 'config' : fileof(conf) })
215 def xend_domain(self, id):
216 return self.xendGet(self.domainurl(id))
218 def xend_domain_unpause(self, id):
219 return self.xendPost(self.domainurl(id),
220 {'op' : 'unpause' })
222 def xend_domain_pause(self, id):
223 return self.xendPost(self.domainurl(id),
224 {'op' : 'pause' })
226 def xend_domain_shutdown(self, id, reason, key=0):
227 return self.xendPost(self.domainurl(id),
228 {'op' : 'shutdown',
229 'reason' : reason,
230 'key' : key })
232 def xend_domain_destroy(self, id, reason):
233 return self.xendPost(self.domainurl(id),
234 {'op' : 'destroy',
235 'reason' : reason })
237 def xend_domain_save(self, id, filename):
238 return self.xendPost(self.domainurl(id),
239 {'op' : 'save',
240 'file' : filename })
242 def xend_domain_migrate(self, id, dst, live=0, resource=0):
243 return self.xendPost(self.domainurl(id),
244 {'op' : 'migrate',
245 'destination': dst,
246 'live' : live,
247 'resource' : resource })
249 def xend_domain_pincpu(self, id, cpu):
250 return self.xendPost(self.domainurl(id),
251 {'op' : 'pincpu',
252 'cpu' : cpu })
254 def xend_domain_cpu_bvt_set(self, id, mcuadv, warpback, warpvalue, warpl, warpu):
255 return self.xendPost(self.domainurl(id),
256 {'op' : 'cpu_bvt_set',
257 'mcuadv' : mcuadv,
258 'warpback' : warpback,
259 'warpvalue': warpvalue,
260 'warpl' : warpl,
261 'warpu' : warpu })
263 def xend_domain_cpu_sedf_set(self, id, period, slice, latency, extratime, weight):
264 return self.xendPost(self.domainurl(id),
265 {'op' : 'cpu_sedf_set',
266 'period' : period,
267 'slice' : slice,
268 'latency' : latency,
269 'extratime' : extratime,
270 'weight' : weight })
272 def xend_domain_maxmem_set(self, id, memory):
273 return self.xendPost(self.domainurl(id),
274 { 'op' : 'maxmem_set',
275 'memory' : memory })
277 def xend_domain_vif_limit(self, id, vif, credit, period):
278 return self.xendPost(self.domainurl(id),
279 { 'op' : 'vif_credit_limit',
280 'vif' : vif,
281 'credit' : credit,
282 'period' : period })
284 def xend_domain_vifs(self, id):
285 return self.xendGet(self.domainurl(id),
286 { 'op' : 'vifs' })
288 def xend_domain_vif(self, id, vif):
289 return self.xendGet(self.domainurl(id),
290 { 'op' : 'vif',
291 'vif' : vif })
293 def xend_domain_vbds(self, id):
294 return self.xendGet(self.domainurl(id),
295 {'op' : 'vbds'})
297 def xend_domain_vbd(self, id, vbd):
298 return self.xendGet(self.domainurl(id),
299 {'op' : 'vbd',
300 'vbd' : vbd })
302 def xend_domain_device_create(self, id, config):
303 return self.xendPost(self.domainurl(id),
304 {'op' : 'device_create',
305 'config' : fileof(config) })
307 def xend_domain_device_refresh(self, id, type, idx):
308 return self.xendPost(self.domainurl(id),
309 {'op' : 'device_refresh',
310 'type' : type,
311 'idx' : idx })
313 def xend_domain_device_destroy(self, id, type, idx):
314 return self.xendPost(self.domainurl(id),
315 {'op' : 'device_destroy',
316 'type' : type,
317 'idx' : idx })
319 def xend_domain_device_configure(self, id, config, idx):
320 return self.xendPost(self.domainurl(id),
321 {'op' : 'device_configure',
322 'idx' : idx,
323 'config' : fileof(config) })
325 def xend_consoles(self):
326 return self.xendGet(self.consoleurl())
328 def xend_console(self, id):
329 return self.xendGet(self.consoleurl(id))
331 def xend_console_disconnect(self, id):
332 return self.xendPost(self.consoleurl(id),
333 {'op' : 'disconnect'})
335 def xend_vnets(self):
336 return self.xendGet(self.vneturl())
338 def xend_vnet_create(self, conf):
339 return self.xendPost(self.vneturl(),
340 {'op' : 'create',
341 'config' : fileof(conf) })
343 def xend_vnet(self, id):
344 return self.xendGet(self.vneturl(id))
346 def xend_vnet_delete(self, id):
347 return self.xendPost(self.vneturl(id),
348 {'op' : 'delete' })
350 def xend_event_inject(self, sxpr):
351 val = self.xendPost(self.eventurl(),
352 {'op' : 'inject',
353 'event' : fileof(sxpr) })
355 def xend_domain_mem_target_set(self, id, mem_target):
356 val = self.xendPost(self.domainurl(id),
357 {'op' : 'mem_target_set',
358 'target' : mem_target })
359 return val
361 def getAsynchXendClientProtocol():
362 """Load AsynchXendClientProtocol on demand to avoid the cost.
363 """
364 global AsynchXendClientProtocol
365 try:
366 AsynchXendClientProtocol
367 except:
368 from XendAsynchProtocol import AsynchXendClientProtocol
369 return AsynchXendClientProtocol
371 def getAsynchServer():
372 """Load AsynchXendClientProtocol and create an asynch xend client.
374 @return asynch Xend
375 """
376 getAsynchXendClientProtocol()
377 return Xend(AsynchXendClientProtocol())
379 def xendmain(srv, asynch, fn, args):
380 if asynch:
381 getAsynchXendClientProtocol()
382 client = AsynchXendClientProtocol()
383 else:
384 client = None
385 xend = Xend(srv=srv, client=client)
386 xend.rc = 0
387 try:
388 v = getattr(xend, fn)(*args)
389 except XendError, err:
390 print 'ERROR:', err
391 return 1
392 if asynch:
393 def cbok(val):
394 PrettyPrint.prettyprint(val)
395 reactor.stop()
396 def cberr(err):
397 print 'ERROR:', err
398 xend.rc = 1
399 reactor.stop()
400 v.addCallback(cbok)
401 v.addErrback(cberr)
402 reactor.run()
403 return xend.rc
404 else:
405 PrettyPrint.prettyprint(v)
406 return 0
408 def main(argv):
409 """Call an API function:
411 python XendClient.py fn args...
413 The leading 'xend_' on the function can be omitted.
414 Example:
416 python XendClient.py domains
417 (0 8)
418 python XendClient.py domain 0
419 (domain (id 0) (name Domain-0) (memory 128))
420 """
421 global DEBUG
422 from getopt import getopt
423 short_options = 'x:ad'
424 long_options = ['xend=', 'asynch', 'debug']
425 (options, args) = getopt(argv[1:], short_options, long_options)
426 srv = None
427 asynch = 0
428 for k, v in options:
429 if k in ['-x', '--xend']:
430 srv = v
431 elif k in ['-a', '--asynch']:
432 asynch = 1
433 elif k in ['-d', '--debug']:
434 DEBUG = 1
435 if len(args):
436 fn = args[0]
437 args = args[1:]
438 else:
439 fn = 'xend'
440 args = []
441 if not fn.startswith('xend'):
442 fn = 'xend_' + fn
443 sys.exit(xendmain(srv, asynch, fn, args))
445 if __name__ == "__main__":
446 main(sys.argv)
447 else:
448 server = Xend()