ia64/xen-unstable

view tools/python/xen/xm/main.py @ 5691:88c2d410979f

I updated the vcpu_to_cpu string creation to include a field separator,
which gets rid of the -1 -> # hack and works for cpus > 9.

I ran into some issues with stale vcpu_to_cpu lists when running the
hotplug subprogram. I would take a vcpu offline, and then issue the
command to bring it back and the vcpu_to_cpu list would not have changed
to indicate the the vcpu actually went down. If I injected a xm list -v
(which always showed the correct mapping) then subsequent hotplug
commands would see the state change and fire off the hotplug request. I
don't know that not sending the event when not changing state saves that
much work so I took the state check out and now just send the hotplug
event directly.

> Also the whole hotplug stuff is still missing interrupt re-routing
> when a vcpu is taken down. To do this, we need an evtchn operation to
> change the vcpu affinity of a port by changing notify_vcpu_id.

I don't fully understand all of the mappings that are happening, so this
part of the patch might be way off. In any case, I've added a new
evtchn op to set the notify_vcpu_id field of a channel. I updated the
HOTPLUG_CPU code to use the new routines when bringing cpus up and down.
When taking down a cpu, I route the IPI irq channels to CPU 0, and when
the cpu comes up, it re-routes the channels back to the awakened CPU.

From: Ryan Harper <ryanh@us.ibm.com>
Signed-off-by: ian@xensource.com
author iap10@freefall.cl.cam.ac.uk
date Wed Jul 06 22:23:18 2005 +0000 (2005-07-06)
parents 8ad10be47849
children 707fcf42a5ae 579d1e771025 c1a7ed266c7e
line source
1 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
2 """Grand unified management application for Xen.
3 """
4 import os
5 import os.path
6 import sys
7 from getopt import getopt
8 import socket
9 import warnings
10 warnings.filterwarnings('ignore', category=FutureWarning)
12 from xen.xend import PrettyPrint
13 from xen.xend import sxp
14 from xen.xend.XendClient import XendError, server
15 from xen.xend.XendClient import main as xend_client_main
16 from xen.xm import create, destroy, migrate, shutdown, sysrq
17 from xen.xm.opts import *
19 def unit(c):
20 if not c.isalpha():
21 return 0
22 base = 1
23 if c == 'G' or c == 'g': base = 1024 * 1024 * 1024
24 elif c == 'M' or c == 'm': base = 1024 * 1024
25 elif c == 'K' or c == 'k': base = 1024
26 else:
27 print 'ignoring unknown unit'
28 return base
30 def int_unit(str, dest):
31 base = unit(str[-1])
32 if not base:
33 return int(str)
35 value = int(str[:-1])
36 dst_base = unit(dest)
37 if dst_base == 0:
38 dst_base = 1
39 if dst_base > base:
40 return value / (dst_base / base)
41 else:
42 return value * (base / dst_base)
44 class Group:
46 name = ""
47 info = ""
49 def __init__(self, xm):
50 self.xm = xm
51 self.progs = {}
53 def addprog(self, prog):
54 self.progs[prog.name] = prog
56 def getprog(self, name):
57 return self.progs.get(name)
59 def proglist(self):
60 kl = self.progs.keys()
61 kl.sort()
62 return [ self.getprog(k) for k in kl ]
64 def help(self, args):
65 if self.info:
66 print
67 print self.info
68 print
69 else:
70 print
72 def shortHelp(self, args):
73 self.help(args)
74 for p in self.proglist():
75 p.shortHelp(args)
77 class Prog:
78 """Base class for sub-programs.
79 """
81 """Program group it belongs to"""
82 group = 'all'
83 """Program name."""
84 name = '??'
85 """Short program info."""
86 info = ''
88 def __init__(self, xm):
89 self.xm = xm
91 def err(self, msg):
92 self.xm.err(msg)
94 def help(self, args):
95 self.shortHelp(args)
97 def shortHelp(self, args):
98 print "%-14s %s" % (self.name, self.info)
100 def main(self, args):
101 """Program main entry point.
102 """
103 pass
106 class ProgUnknown(Prog):
108 name = 'unknown'
109 info = ''
111 def help(self, args):
112 self.xm.err("Unknown command: %s\nTry '%s help' for more information."
113 % (args[0], self.xm.name))
115 main = help
117 class Xm:
118 """Main application.
119 """
121 def __init__(self):
122 self.name = 'xm'
123 self.unknown = ProgUnknown(self)
124 self.progs = {}
125 self.groups = {}
127 def err(self, msg):
128 print >>sys.stderr, "Error:", msg
129 sys.exit(1)
131 def main(self, args):
132 try:
133 self.main_call(args)
134 except socket.error, ex:
135 print >>sys.stderr, ex
136 self.err("Error connecting to xend, is xend running?")
137 except XendError, ex:
138 self.err(str(ex))
140 def main_call(self, args):
141 """Main entry point. Dispatches to the progs.
142 """
143 self.name = args[0]
144 if len(args) < 2:
145 args.append('help')
146 help = self.helparg(args)
147 p = self.getprog(args[1], self.unknown)
148 if help or len(args) < 2:
149 p.help(args[1:])
150 else:
151 p.main(args[1:])
153 def helparg(self, args):
154 for a in args:
155 if a in ['-h', '--help']:
156 return 1
157 return 0
159 def prog(self, pklass):
160 """Add a sub-program.
162 pklass program class (Prog subclass)
163 """
164 p = pklass(self)
165 self.progs[p.name] = p
166 self.getgroup(p.group).addprog(p)
167 return p
169 def getprog(self, name, val=None):
170 """Get a sub-program.
171 name Name of the sub-program (or optionally, an unambiguous
172 prefix of its name)
173 val Default return value if no (unique) match is found
174 """
176 match = None
177 for progname in self.progs.keys():
178 if progname == name:
179 match = progname
180 break
181 if progname.startswith(name):
182 if not match:
183 match = progname
184 else:
185 return val # name is ambiguous - bail out
187 return self.progs.get(match, val)
189 def group(self, klass):
190 g = klass(self)
191 self.groups[g.name] = g
192 return g
194 def getgroup(self, name):
195 return self.groups[name]
197 def grouplist(self):
198 kl = self.groups.keys()
199 kl.sort()
200 return [ self.getgroup(k) for k in kl ]
202 # Create the application object, then add the sub-program classes.
203 xm = Xm()
205 class GroupAll(Group):
207 name = "all"
208 info = ""
210 xm.group(GroupAll)
212 class GroupDomain(Group):
214 name = "domain"
215 info = "Commands on domains:"
217 xm.group(GroupDomain)
219 class GroupScheduler(Group):
221 name = "scheduler"
222 info = "Comands controlling scheduling:"
224 xm.group(GroupScheduler)
226 class GroupHost(Group):
228 name = "host"
229 info = "Commands related to the xen host (node):"
231 xm.group(GroupHost)
233 class GroupConsole(Group):
235 name = "console"
236 info = "Commands related to consoles:"
238 xm.group(GroupConsole)
240 class GroupVbd(Group):
242 name = "vbd"
243 info = "Commands related to virtual block devices:"
245 xm.group(GroupVbd)
247 class GroupVif(Group):
249 name = "vif"
250 info = "Commands related to virtual network interfaces:"
252 xm.group(GroupVif)
254 class ProgHelp(Prog):
256 name = "help"
257 info = "Print help."
259 def help(self, args):
260 if len(args) == 2:
261 name = args[1]
262 p = self.xm.getprog(name)
263 if p:
264 p.help(args[1:])
265 else:
266 print '%s: Unknown command: %s' % (self.name, name)
267 else:
268 for g in self.xm.grouplist():
269 g.shortHelp(args)
270 print "\nTry '%s help CMD' for help on CMD" % self.xm.name
272 main = help
274 xm.prog(ProgHelp)
276 class ProgCreate(Prog):
278 group = 'domain'
279 name = "create"
280 info = """Create a domain."""
282 def help(self, args):
283 create.main([args[0], '-h'])
285 def main(self, args):
286 create.main(args)
288 xm.prog(ProgCreate)
290 class ProgSave(Prog):
291 group = 'domain'
292 name = "save"
293 info = """Save domain state (and config) to file."""
295 def help(self, args):
296 print args[0], "DOM FILE"
297 print """\nSave domain with id DOM to FILE."""
299 def main(self, args):
300 if len(args) < 3: self.err("%s: Missing arguments" % args[0])
301 dom = args[1]
302 savefile = os.path.abspath(args[2])
303 server.xend_domain_save(dom, savefile)
305 xm.prog(ProgSave)
307 class ProgRestore(Prog):
308 group = 'domain'
309 name = "restore"
310 info = """Create a domain from a saved state."""
312 def help(self, args):
313 print args[0], "FILE"
314 print "\nRestore a domain from FILE."
316 def main(self, args):
317 if len(args) < 2: self.err("%s: Missing arguments" % args[0])
318 savefile = os.path.abspath(args[1])
319 info = server.xend_domain_restore(savefile)
320 PrettyPrint.prettyprint(info)
321 id = sxp.child_value(info, 'id')
322 if id is not None:
323 server.xend_domain_unpause(id)
325 xm.prog(ProgRestore)
327 class ProgMigrate(Prog):
328 group = 'domain'
329 name = "migrate"
330 info = """Migrate a domain to another machine."""
332 def help(self, args):
333 migrate.help([self.name] + args)
335 def main(self, args):
336 migrate.main(args)
338 xm.prog(ProgMigrate)
340 class ProgList(Prog):
341 group = 'domain'
342 name = "list"
343 info = """List information about domains."""
345 short_options = 'lv'
346 long_options = ['long','vcpus']
348 def help(self, args):
349 if help:
350 print args[0], '[options] [DOM...]'
351 print """\nGet information about domains.
352 Either all domains or the domains given.
354 -l, --long Get more detailed information.
355 -v, --vcpus Show VCPU to CPU mapping.
356 """
357 return
359 def main(self, args):
360 use_long = 0
361 show_vcpus = 0
362 (options, params) = getopt(args[1:],
363 self.short_options,
364 self.long_options)
365 n = len(params)
366 for (k, v) in options:
367 if k in ['-l', '--long']:
368 use_long = 1
369 if k in ['-v', '--vcpus']:
370 show_vcpus = 1
372 if n == 0:
373 doms = server.xend_domains()
374 doms.sort()
375 else:
376 doms = params
378 if use_long:
379 self.long_list(doms)
380 elif show_vcpus:
381 self.show_vcpus(doms)
382 else:
383 self.brief_list(doms)
385 def brief_list(self, doms):
386 print 'Name Id Mem(MB) CPU VCPU(s) State Time(s) Console'
387 for dom in doms:
388 info = server.xend_domain(dom)
389 d = {}
390 d['dom'] = int(sxp.child_value(info, 'id', '-1'))
391 d['name'] = sxp.child_value(info, 'name', '??')
392 d['mem'] = int(sxp.child_value(info, 'memory', '0'))
393 d['cpu'] = int(sxp.child_value(info, 'cpu', '0'))
394 d['vcpus'] = int(sxp.child_value(info, 'vcpus', '0'))
395 d['state'] = sxp.child_value(info, 'state', '??')
396 d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
397 console = sxp.child(info, 'console')
398 if console:
399 d['port'] = sxp.child_value(console, 'console_port')
400 else:
401 d['port'] = ''
402 if ((int(sxp.child_value(info, 'ssidref', '0'))) != 0):
403 d['ssidref1'] = int(sxp.child_value(info, 'ssidref', '0')) & 0xffff
404 d['ssidref2'] = (int(sxp.child_value(info, 'ssidref', '0')) >> 16) & 0xffff
405 print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3d %(vcpus)5d %(state)5s %(cpu_time)7.1f %(port)4s s:%(ssidref2)02x/p:%(ssidref1)02x" % d)
406 else:
407 print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3d %(vcpus)5d %(state)5s %(cpu_time)7.1f %(port)4s" % d)
409 def show_vcpus(self, doms):
410 print 'Name Id VCPU CPU CPUMAP'
411 for dom in doms:
412 info = server.xend_domain(dom)
413 vcpu_to_cpu = sxp.child_value(info, 'vcpu_to_cpu', '-1').split('|')
414 cpumap = sxp.child_value(info, 'cpumap', [])
415 mask = ((int(sxp.child_value(info, 'vcpus', '0')))**2) - 1
416 count = 0
417 for cpu in vcpu_to_cpu:
418 d = {}
419 d['name'] = sxp.child_value(info, 'name', '??')
420 d['dom'] = int(sxp.child_value(info, 'id', '-1'))
421 d['vcpu'] = int(count)
422 d['cpu'] = int(cpu)
423 d['cpumap'] = int(cpumap[count])&mask
424 count = count + 1
425 print ("%(name)-16s %(dom)3d %(vcpu)4d %(cpu)3d 0x%(cpumap)x" % d)
427 def long_list(self, doms):
428 for dom in doms:
429 info = server.xend_domain(dom)
430 PrettyPrint.prettyprint(info)
432 xm.prog(ProgList)
434 class ProgDestroy(Prog):
435 group = 'domain'
436 name = "destroy"
437 info = """Terminate a domain immediately."""
439 def help(self, args):
440 destroy.main([args[0], '-h'])
442 def main(self, args):
443 destroy.main(args)
445 xm.prog(ProgDestroy)
447 class ProgShutdown(Prog):
448 group = 'domain'
449 name = "shutdown"
450 info = """Shutdown a domain."""
452 def help(self, args):
453 shutdown.main([args[0], '-h'])
455 def main(self, args):
456 shutdown.main(args)
458 xm.prog(ProgShutdown)
460 class ProgSysrq(Prog):
461 group = 'domain'
462 name = "sysrq"
463 info = """Send a sysrq to a domain."""
465 def help(self, args):
466 sysrq.main([args[0], '-h'])
468 def main(self, args):
469 sysrq.main(args)
471 xm.prog(ProgSysrq)
473 class ProgPause(Prog):
474 group = 'domain'
475 name = "pause"
476 info = """Pause execution of a domain."""
478 def help(self, args):
479 print args[0], 'DOM'
480 print '\nPause execution of domain DOM.'
482 def main(self, args):
483 if len(args) < 2: self.err("%s: Missing domain" % args[0])
484 dom = args[1]
485 server.xend_domain_pause(dom)
487 xm.prog(ProgPause)
489 class ProgUnpause(Prog):
490 group = 'domain'
491 name = "unpause"
492 info = """Unpause a paused domain."""
494 def help(self, args):
495 print args[0], 'DOM'
496 print '\nUnpause execution of domain DOM.'
498 def main(self, args):
499 if len(args) < 2: self.err("%s: Missing domain" % args[0])
500 dom = args[1]
501 server.xend_domain_unpause(dom)
503 xm.prog(ProgUnpause)
505 class ProgPincpu(Prog):
506 group = 'domain'
507 name = "pincpu"
508 info = """Set which cpus a VCPU can use. """
510 def help(self, args):
511 print args[0],'DOM VCPU CPUS'
512 print '\nSet which cpus VCPU in domain DOM can use.'
514 # convert list of cpus to bitmap integer value
515 def make_map(self, cpulist):
516 cpus = []
517 cpumap = 0
518 for c in cpulist.split(','):
519 if c.find('-') != -1:
520 (x,y) = c.split('-')
521 for i in range(int(x),int(y)+1):
522 cpus.append(int(i))
523 else:
524 cpus.append(int(c))
525 cpus.sort()
526 for c in cpus:
527 cpumap = cpumap | 1<<c
529 return cpumap
531 def main(self, args):
532 if len(args) != 4: self.err("%s: Invalid argument(s)" % args[0])
533 dom = args[1]
534 vcpu = int(args[2])
535 cpumap = self.make_map(args[3]);
536 server.xend_domain_pincpu(dom, vcpu, cpumap)
538 xm.prog(ProgPincpu)
540 class ProgMaxmem(Prog):
541 group = 'domain'
542 name = 'maxmem'
543 info = """Set domain memory limit."""
545 def help(self, args):
546 print args[0], "DOM MEMORY"
547 print "\nSet the memory limit for domain DOM to MEMORY megabytes."
549 def main(self, args):
550 if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
551 dom = args[1]
552 mem = int_unit(args[2], 'm')
553 server.xend_domain_maxmem_set(dom, mem)
555 xm.prog(ProgMaxmem)
557 class ProgBalloon(Prog):
558 group = 'domain'
559 name = 'balloon'
560 info = """Set the domain's memory footprint using the balloon driver."""
562 def help(self, args):
563 print args[0], "DOM MEMORY_TARGET"
564 print """\nRequest domain DOM to adjust its memory footprint to
565 MEMORY_TARGET megabytes"""
567 def main(self, args):
568 if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
569 dom = args[1]
570 mem_target = int_unit(args[2], 'm')
571 server.xend_domain_mem_target_set(dom, mem_target)
573 xm.prog(ProgBalloon)
575 class ProgVcpuhotplug(Prog):
576 group = 'domain'
577 name = 'vcpu-hotplug'
578 info = """Enable or disable a VCPU in a domain."""
580 def help(self, args):
581 print args[0], "DOM VCPU [0|1]"
582 print """\nRequest virtual processor VCPU to be disabled or enabled in
583 domain DOM"""
585 def main(self, args):
586 if len(args) != 4: self.err("%s: Invalid arguments(s)" % args[0])
587 name = args[1]
588 vcpu = int(args[2])
589 state = int(args[3])
590 dom = server.xend_domain(name)
591 id = sxp.child_value(dom, 'id')
592 server.xend_domain_vcpu_hotplug(id, vcpu, state)
594 xm.prog(ProgVcpuhotplug)
596 class ProgDomid(Prog):
597 group = 'domain'
598 name = 'domid'
599 info = 'Convert a domain name to a domain id.'
601 def help(self, args):
602 print args[0], "DOM"
603 print '\nGet the domain id for the domain with name DOM.'
605 def main (self, args):
606 if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
607 name = args[1]
608 dom = server.xend_domain(name)
609 print sxp.child_value(dom, 'id')
611 xm.prog(ProgDomid)
613 class ProgDomname(Prog):
614 group = 'domain'
615 name = 'domname'
616 info = 'Convert a domain id to a domain name.'
618 def help(self, args):
619 print args[0], "DOM"
620 print '\nGet the name for the domain with id DOM.'
622 def main (self, args):
623 if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
624 name = args[1]
625 dom = server.xend_domain(name)
626 print sxp.child_value(dom, 'name')
628 xm.prog(ProgDomname)
630 class ProgBvt(Prog):
631 group = 'scheduler'
632 name = "bvt"
633 info = """Set BVT scheduler parameters."""
635 def help(self, args):
636 print args[0], "DOM MCUADV WARPBACK WARPVALUE WARPL WARPU"
637 print '\nSet Borrowed Virtual Time scheduler parameters.'
639 def main(self, args):
640 if len(args) != 7: self.err("%s: Invalid argument(s)" % args[0])
641 dom = args[1]
642 v = map(long, args[2:7])
643 server.xend_domain_cpu_bvt_set(dom, *v)
645 xm.prog(ProgBvt)
647 class ProgBvtslice(Prog):
648 group = 'scheduler'
649 name = "bvt_ctxallow"
650 info = """Set the BVT scheduler context switch allowance."""
652 def help(self, args):
653 print args[0], 'CTX_ALLOW'
654 print '\nSet Borrowed Virtual Time scheduler context switch allowance.'
656 def main(self, args):
657 if len(args) < 2: self.err('%s: Missing context switch allowance'
658 % args[0])
659 slice = int(args[1])
660 server.xend_node_cpu_bvt_slice_set(slice)
662 xm.prog(ProgBvtslice)
664 class ProgSedf(Prog):
665 group = 'scheduler'
666 name= "sedf"
667 info = """Set simple EDF parameters."""
669 def help(self, args):
670 print args[0], "DOM PERIOD SLICE LATENCY EXTRATIME WEIGHT"
671 print "\nSet simple EDF parameters."
673 def main(self, args):
674 if len(args) != 7: self.err("%s: Invalid argument(s)" % args[0])
675 dom = args[1]
676 v = map(int, args[2:7])
677 server.xend_domain_cpu_sedf_set(dom, *v)
679 xm.prog(ProgSedf)
681 class ProgInfo(Prog):
682 group = 'host'
683 name = "info"
684 info = """Get information about the xen host."""
686 def main(self, args):
687 info = server.xend_node()
688 for x in info[1:]:
689 print "%-23s:" % x[0], x[1]
691 xm.prog(ProgInfo)
693 class ProgConsoles(Prog):
694 group = 'console'
695 name = "consoles"
696 info = """Get information about domain consoles."""
698 def main(self, args):
699 l = server.xend_consoles()
700 print "Dom Port Id Connection"
701 for x in l:
702 info = server.xend_console(x)
703 d = {}
704 d['dom'] = sxp.child(info, 'domain', '?')[1]
705 d['port'] = sxp.child_value(info, 'console_port', '?')
706 d['id'] = sxp.child_value(info, 'id', '?')
707 connected = sxp.child(info, 'connected')
708 if connected:
709 d['conn'] = '%s:%s' % (connected[1], connected[2])
710 else:
711 d['conn'] = ''
712 print "%(dom)3s %(port)4s %(id)3s %(conn)s" % d
714 xm.prog(ProgConsoles)
716 class ProgConsole(Prog):
717 group = 'console'
718 name = "console"
719 info = """Open a console to a domain."""
721 def help(self, args):
722 print args[0], "DOM"
723 print "\nOpen a console to domain DOM."
725 def main(self, args):
726 if len(args) < 2: self.err("%s: Missing domain" % args[0])
727 dom = args[1]
728 info = server.xend_domain(dom)
729 console = sxp.child(info, "console")
730 if not console:
731 self.err("No console information")
732 port = sxp.child_value(console, "console_port")
733 from xen.util import console_client
734 path = "/var/lib/xend/console-%s" % port
735 console_client.connect("localhost", int(port), path=path)
737 xm.prog(ProgConsole)
739 class ProgCall(Prog):
740 name = "call"
741 info = "Call xend api functions."
743 def help (self, args):
744 print args[0], "function args..."
745 print """
746 Call a xend HTTP API function. The leading 'xend_' on the function
747 can be omitted. See xen.xend.XendClient for the API functions.
748 """
750 def main(self, args):
751 xend_client_main(args)
753 xm.prog(ProgCall)
755 class ProgDmesg(Prog):
756 group = 'host'
757 name = "dmesg"
758 info = """Read or clear Xen's message buffer."""
760 gopts = Opts(use="""[-c|--clear]
762 Read Xen's message buffer (boot output, warning and error messages) or clear
763 its contents if the [-c|--clear] flag is specified.
764 """)
766 gopts.opt('clear', short='c',
767 fn=set_true, default=0,
768 use="Clear the contents of the Xen message buffer.")
770 short_options = ['-c']
771 long_options = ['--clear']
773 def help(self, args):
774 self.gopts.argv = args
775 self.gopts.usage()
777 def main(self, args):
778 self.gopts.parse(args)
779 if not (1 <= len(args) <=2):
780 self.gopts.err('Invalid arguments: ' + str(args))
782 if not self.gopts.vals.clear:
783 print server.xend_node_get_dmesg()
784 else:
785 server.xend_node_clear_dmesg()
787 xm.prog(ProgDmesg)
789 class ProgLog(Prog):
790 group = 'host'
791 name = "log"
792 info = """Print the xend log."""
794 def main(self, args):
795 print server.xend_node_log()
797 xm.prog(ProgLog)
799 class ProgVifCreditLimit(Prog):
800 group = 'vif'
801 name= "vif-limit"
802 info = """Limit the transmission rate of a virtual network interface."""
804 def help(self, args):
805 print args[0], "DOMAIN VIF CREDIT_IN_BYTES PERIOD_IN_USECS"
806 print "\nSet the credit limit of a virtual network interface."
808 def main(self, args):
809 if len(args) != 5: self.err("%s: Invalid argument(s)" % args[0])
810 dom = args[1]
811 v = map(int, args[2:5])
812 server.xend_domain_vif_limit(dom, *v)
814 xm.prog(ProgVifCreditLimit)
816 class ProgVifList(Prog):
817 group = 'vif'
818 name = 'vif-list'
819 info = """List virtual network interfaces for a domain."""
821 def help(self, args):
822 print args[0], "DOM"
823 print "\nList virtual network interfaces for domain DOM"
825 def main(self, args):
826 if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
827 dom = args[1]
828 for x in server.xend_domain_devices(dom, 'vif'):
829 sxp.show(x)
830 print
832 xm.prog(ProgVifList)
834 class ProgVbdList(Prog):
835 group = 'vbd'
836 name = 'vbd-list'
837 info = """List virtual block devices for a domain."""
839 def help(self, args):
840 print args[0], "DOM"
841 print "\nList virtual block devices for domain DOM"
843 def main(self, args):
844 if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
845 dom = args[1]
846 for x in server.xend_domain_devices(dom, 'vbd'):
847 sxp.show(x)
848 print
850 xm.prog(ProgVbdList)
852 class ProgVbdCreate(Prog):
853 group = 'vbd'
854 name = 'vbd-create'
855 info = """Create a new virtual block device for a domain"""
857 def help(self, args):
858 print args[0], "DOM UNAME DEV MODE [BACKEND]"
859 print """
860 Create a virtual block device for a domain.
862 UNAME - device to export, e.g. phy:hda2
863 DEV - device name in the domain, e.g. sda1
864 MODE - access mode: r for read, w for read-write
865 BACKEND - backend driver domain
866 """
868 def main(self, args):
869 n = len(args)
870 if n < 5 or n > 6: self.err("%s: Invalid argument(s)" % args[0])
871 dom = args[1]
872 vbd = ['vbd',
873 ['uname', args[2]],
874 ['dev', args[3]],
875 ['mode', args[4]]]
876 if n == 6:
877 vbd.append(['backend', args[5]])
878 server.xend_domain_device_create(dom, vbd)
880 xm.prog(ProgVbdCreate)
882 class ProgVbdRefresh(Prog):
883 group = 'vbd'
884 name = 'vbd-refresh'
885 info = """Refresh a virtual block device for a domain"""
887 def help(self, args):
888 print args[0], "DOM DEV"
889 print """
890 Refresh a virtual block device for a domain.
892 DEV - idx field in the device information
893 """
895 def main(self, args):
896 if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
897 dom = args[1]
898 dev = args[2]
899 server.xend_domain_device_refresh(dom, 'vbd', dev)
901 xm.prog(ProgVbdRefresh)
904 class ProgVbdDestroy(Prog):
905 group = 'vbd'
906 name = 'vbd-destroy'
907 info = """Destroy a domain's virtual block device"""
909 def help(self, args):
910 print args[0], "DOM DEV"
911 print """
912 Destroy vbd DEV attached to domain DOM. Detaches the device
913 from the domain, but does not destroy the device contents.
914 The device indentifier DEV is the idx field in the device
915 information. This is visible in 'xm vbd-list'."""
917 def main(self, args):
918 if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
919 dom = args[1]
920 dev = args[2]
921 server.xend_domain_device_destroy(dom, 'vbd', dev)
923 xm.prog(ProgVbdDestroy)
925 def main(args):
926 xm.main(args)