ia64/xen-unstable

view tools/python/xen/xend/XendClient.py @ 8346:7256d2425fa7

Fix reference to HttpXendClientProtocol. This was previously referring to the
abstract base class, which was never going to work. (This is debugging code
only, so I presume that no-one has used it for a long time, but it's doing no
harm hanging around.)

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@leeni.uk.xensource.com
date Tue Dec 13 17:31:35 2005 +0000 (2005-12-13)
parents 7d7973a21a3d
children f43f094467f6
line source
1 #!/usr/bin/env python
2 #============================================================================
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of version 2.1 of the GNU Lesser General Public
5 # License as published by the Free Software Foundation.
6 #
7 # This library is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 # Lesser General Public License for more details.
11 #
12 # You should have received a copy of the GNU Lesser General Public
13 # License along with this library; if not, write to the Free Software
14 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 #============================================================================
16 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
17 #============================================================================
19 """Client API for the HTTP interface on xend.
20 Callable as a script - see main().
21 Supports inet or unix connection to xend.
23 This API is the 'control-plane' for xend.
24 The 'data-plane' is done separately.
25 """
26 import os
27 import sys
28 import types
30 import sxp
31 import PrettyPrint
32 from XendProtocol import HttpXendClientProtocol, \
33 UnixXendClientProtocol, \
34 XendError
36 def fileof(val):
37 """Converter for passing configs or other 'large' data.
38 Handles lists, files directly.
39 Assumes a string is a file name and passes its contents.
40 """
41 if isinstance(val, types.ListType):
42 return sxp.to_string(val)
43 if isinstance(val, types.StringType):
44 return file(val)
45 if hasattr(val, 'readlines'):
46 return val
47 raise XendError('cannot convert value')
49 class URL:
50 """A URL.
51 """
53 def __init__(self, proto='http', host='localhost', port=None, path='', query=None, frag=None):
54 self.proto = proto
55 self.host = host
56 if port: port = int(port)
57 self.port = port
58 self.path = path
59 self.query = query
60 self.frag = frag
62 def url(self):
63 """Get the full URL string including protocol, location and the full path.
64 """
65 return self.proto + '://' + self.location() + self.fullpath()
67 def location(self):
68 """Get the location part of the URL, including host and port, if present.
69 """
70 if self.port:
71 return self.host + ':' + str(self.port)
72 else:
73 return self.host
75 def fullpath(self):
76 """Get the full path part of the URL, including query and fragment if present.
77 """
78 u = [ self.path ]
79 if self.query:
80 u.append('?')
81 u.append(self.query)
82 if self.frag:
83 u.append('#')
84 u.append(self.frag)
85 return ''.join(u)
87 def relative(self, path='', query=None, frag=None):
88 """Create a URL relative to this one.
89 """
90 return URL(proto=self.proto,
91 host=self.host,
92 port=self.port,
93 path=self.path + path,
94 query=query,
95 frag=frag)
97 class Xend:
98 """Client interface to Xend.
99 """
101 """Default location of the xend server."""
102 SRV_DEFAULT = "localhost:8000"
104 """Environment variable to set the location of xend."""
105 SRV_VAR = "XEND"
107 """Default path to the xend root on the server."""
108 ROOT_DEFAULT = "/xend/"
110 """Environment variable to set the xend root path."""
111 ROOT_VAR = "XEND_ROOT"
113 def __init__(self, client=None, srv=None, root=None):
114 """Create a xend client interface.
115 If the client protocol is not specified, the default
116 is to use a synchronous protocol.
118 @param client: client protocol to use
119 @param srv: server host, and optional port (format host:port)
120 @param root: xend root path on the server
121 """
122 if client is None:
123 client = HttpXendClientProtocol()
124 self.client = client
125 self.bind(srv, root)
127 def default_server(self):
128 """Get the default location of the xend server.
129 """
130 return os.getenv(self.SRV_VAR, self.SRV_DEFAULT)
132 def default_root(self):
133 """Get the default root path on the xend server.
134 """
135 return os.getenv(self.ROOT_VAR, self.ROOT_DEFAULT)
137 def bind(self, srv=None, root=None):
138 """Bind to a given server.
140 @param srv: server location (host:port)
141 @param root: xend root path on the server
142 """
143 if srv is None: srv = self.default_server()
144 if root is None: root = self.default_root()
145 if not root.endswith('/'): root += '/'
146 (host, port) = srv.split(':', 1)
147 self.url = URL(host=host, port=port, path=root)
149 def xendGet(self, url, args=None):
150 return self.client.xendGet(url, args)
152 def xendPost(self, url, data):
153 return self.client.xendPost(url, data)
155 def nodeurl(self, id=''):
156 return self.url.relative('node/' + str(id))
158 def domainurl(self, id=''):
159 return self.url.relative('domain/' + str(id))
161 def deviceurl(self, id=''):
162 return self.url.relative('device/' + str(id))
164 def vneturl(self, id=''):
165 return self.url.relative('vnet/' + str(id))
167 def xend(self):
168 return self.xendGet(self.url)
170 def xend_node(self):
171 return self.xendGet(self.nodeurl())
173 def xend_node_shutdown(self):
174 return self.xendPost(self.nodeurl(),
175 {'op' : 'shutdown'})
177 def xend_node_restart(self):
178 return self.xendPost(self.nodeurl(),
179 {'op' : 'reboot'})
181 def xend_node_get_dmesg(self):
182 return self.xendGet(self.nodeurl('dmesg'))
184 def xend_node_clear_dmesg(self):
185 return self.xendPost(self.nodeurl('dmesg'),
186 {'op' : 'clear' } )
188 def xend_node_log(self):
189 return self.xendGet(self.nodeurl('log'))
191 def xend_node_cpu_bvt_slice_set(self, ctx_allow):
192 return self.xendPost(self.nodeurl(),
193 {'op' : 'cpu_bvt_slice_set',
194 'ctx_allow' : ctx_allow })
196 def xend_domains(self):
197 return self.xendGet(self.domainurl())
199 def xend_list_domains(self):
200 return self.xendGet(self.domainurl(), {'detail': '1'})
202 def xend_domain_vcpuinfo(self, dom):
203 return self.xendGet(self.domainurl(dom), {'op': 'vcpuinfo'})
205 def xend_domain_create(self, conf):
206 return self.xendPost(self.domainurl(),
207 {'op' : 'create',
208 'config' : fileof(conf) })
210 def xend_domain_restore(self, filename):
211 return self.xendPost(self.domainurl(),
212 {'op' : 'restore',
213 'file' : filename })
215 def xend_domain_configure(self, id, conf):
216 return self.xendPost(self.domainurl(id),
217 {'op' : 'configure',
218 'config' : fileof(conf) })
220 def xend_domain(self, id):
221 return self.xendGet(self.domainurl(id))
223 def xend_domain_wait_for_devices(self, id):
224 return self.xendPost(self.domainurl(id),
225 {'op' : 'wait_for_devices' })
227 def xend_domain_unpause(self, id):
228 return self.xendPost(self.domainurl(id),
229 {'op' : 'unpause' })
231 def xend_domain_pause(self, id):
232 return self.xendPost(self.domainurl(id),
233 {'op' : 'pause' })
235 def xend_domain_rename(self, id, name):
236 return self.xendPost(self.domainurl(id),
237 {'op' : 'rename',
238 'name' : name})
240 def xend_domain_shutdown(self, id, reason):
241 return self.xendPost(self.domainurl(id),
242 {'op' : 'shutdown',
243 'reason' : reason})
245 def xend_domain_sysrq(self, id, key):
246 return self.xendPost(self.domainurl(id),
247 {'op' : 'sysrq',
248 'key' : key})
250 def xend_domain_destroy(self, id):
251 return self.xendPost(self.domainurl(id),
252 {'op' : 'destroy' })
254 def xend_domain_save(self, id, filename):
255 return self.xendPost(self.domainurl(id),
256 {'op' : 'save',
257 'file' : filename })
259 def xend_domain_migrate(self, id, dst, live=0, resource=0, port=0):
260 return self.xendPost(self.domainurl(id),
261 {'op' : 'migrate',
262 'destination': dst,
263 'live' : live,
264 'resource' : resource,
265 'port' : port })
267 def xend_domain_pincpu(self, id, vcpu, cpumap):
268 return self.xendPost(self.domainurl(id),
269 {'op' : 'pincpu',
270 'vcpu' : vcpu,
271 'cpumap' : str(cpumap) })
273 def xend_domain_cpu_bvt_set(self, id, mcuadv, warpback, warpvalue, warpl, warpu):
274 return self.xendPost(self.domainurl(id),
275 {'op' : 'cpu_bvt_set',
276 'mcuadv' : mcuadv,
277 'warpback' : warpback,
278 'warpvalue': warpvalue,
279 'warpl' : warpl,
280 'warpu' : warpu })
282 def xend_domain_cpu_sedf_get(self, id):
283 return self.xendPost(self.domainurl(id),
284 {'op' : 'cpu_sedf_get'})
286 def xend_domain_cpu_sedf_set(self, id, period, slice, latency, extratime, weight):
287 return self.xendPost(self.domainurl(id),
288 {'op' : 'cpu_sedf_set',
289 'period' : period,
290 'slice' : slice,
291 'latency' : latency,
292 'extratime' : extratime,
293 'weight' : weight })
295 def xend_domain_maxmem_set(self, id, memory):
296 return self.xendPost(self.domainurl(id),
297 { 'op' : 'maxmem_set',
298 'memory' : memory })
300 def xend_domain_mem_target_set(self, id, mem_target):
301 val = self.xendPost(self.domainurl(id),
302 {'op' : 'mem_target_set',
303 'target' : mem_target })
304 return val
306 def xend_domain_set_vcpus(self, dom, vcpus):
307 return self.xendPost(self.domainurl(dom),
308 {'op' : 'set_vcpus',
309 'vcpus' : vcpus })
311 def xend_domain_devices(self, id, type):
312 return self.xendPost(self.domainurl(id),
313 {'op' : 'devices',
314 'type' : type })
316 def xend_domain_device_create(self, id, config):
317 return self.xendPost(self.domainurl(id),
318 {'op' : 'device_create',
319 'config' : fileof(config) })
321 def xend_domain_device_refresh(self, id, type, dev):
322 return self.xendPost(self.domainurl(id),
323 {'op' : 'device_refresh',
324 'type' : type,
325 'dev' : dev })
327 def xend_domain_device_destroy(self, id, type, dev):
328 return self.xendPost(self.domainurl(id),
329 {'op' : 'device_destroy',
330 'type' : type,
331 'dev' : dev })
333 def xend_domain_device_configure(self, id, config, dev):
334 return self.xendPost(self.domainurl(id),
335 {'op' : 'device_configure',
336 'dev' : dev,
337 'config' : fileof(config) })
339 def xend_vnets(self):
340 return self.xendGet(self.vneturl())
342 def xend_vnet_create(self, conf):
343 return self.xendPost(self.vneturl(),
344 {'op' : 'create',
345 'config' : fileof(conf) })
347 def xend_vnet(self, id):
348 return self.xendGet(self.vneturl(id))
350 def xend_vnet_delete(self, id):
351 return self.xendPost(self.vneturl(id),
352 {'op' : 'delete' })
354 def getHttpServer(srv=None):
355 """Create and return a xend client.
356 """
357 return Xend(srv=srv, client=HttpXendClientProtocol())
359 def getUnixServer(srv=None):
360 """Create and return a unix-domain xend client.
361 """
362 return Xend(client=UnixXendClientProtocol(srv))
364 def xendmain(srv, fn, args, unix=False):
365 if unix:
366 xend = getUnixServer(srv)
367 else:
368 xend = getHttpServer(srv)
369 xend.rc = 0
370 try:
371 v = getattr(xend, fn)(*args)
372 PrettyPrint.prettyprint(v)
373 return 0
374 except XendError, err:
375 print 'ERROR:', err
376 return 1
378 def main(argv):
379 """Call an API function:
381 python XendClient.py fn args...
383 The leading 'xend_' on the function can be omitted.
384 Example:
386 python XendClient.py domains
387 (0 8)
388 python XendClient.py domain 0
389 (domain (id 0) (name Domain-0) (memory 128))
390 """
391 from getopt import getopt
392 short_options = 'x:au:d'
393 long_options = ['xend=', 'unix=', 'debug']
394 (options, args) = getopt(argv[1:], short_options, long_options)
395 srv = None
396 unix = 1
397 for k, v in options:
398 if k in ['-x', '--xend']:
399 srv = v
400 elif k in ['-u', '--unix']:
401 unix = int(v)
402 if len(args):
403 fn = args[0]
404 args = args[1:]
405 else:
406 fn = 'xend'
407 args = []
408 if not fn.startswith('xend'):
409 fn = 'xend_' + fn
410 sys.exit(xendmain(srv, fn, args, unix=unix))
412 if __name__ == "__main__":
413 main(sys.argv)
414 else:
415 server = getUnixServer()