ia64/xen-unstable

changeset 6072:3cd4f2c38aaf

The following patch is a major restructuring of main.py to be more straight forward, and remove as much code as possible.
It does a number of things:

* It implements the standardized options proposed via my RFC for xm
* It restructures the calling of these functions to be function pointers out
of a dictionary, instead of subclasses found through inspection
* It consolidates all help info, making it easier to see that the help
screen looks consistent across commands. (Per command help isn't yet in
this patch just global help)
* It moves object importing into the functions that require them only,
allowing commands like "xm help" to be runable as non root
* It adds command aliasing to provide backwards compatibility with many
commands (i.e. xm balloon)
* It provides more useful error messages is most fail cases
* It implements a short help by default (which takes < 24 screen lines) as
requested by Mark W at OLS
* It attempts to trap more exceptions than before and provide useful errors
based on them (this requires more testing)

This patch makes no changes to any other elements of xen/xm, and works with
all other objects and libraries as is.

Signed-off-by: Sean Dague <sean@dague.net>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Tue Aug 09 12:50:22 2005 +0000 (2005-08-09)
parents 663f0fb1e444
children 4125b9fea242
files tools/python/xen/xm/main.py
line diff
     1.1 --- a/tools/python/xen/xm/main.py	Tue Aug 09 09:34:06 2005 +0000
     1.2 +++ b/tools/python/xen/xm/main.py	Tue Aug 09 12:50:22 2005 +0000
     1.3 @@ -1,28 +1,113 @@
     1.4 -# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     1.5 +# (C) Copyright IBM Corp. 2005
     1.6 +# Copyright (C) 2004 Mike Wray
     1.7 +#
     1.8 +# Authors:
     1.9 +#     Sean Dague <sean at dague dot net>
    1.10 +#     Mike Wray <mike dot wray at hp dot com>
    1.11 +#
    1.12 +# This software may be used and distributed according to the terms
    1.13 +# of the GNU General Public License v2.  Full details on license
    1.14 +# terms and conditions are included with this distribution
    1.15 +
    1.16  """Grand unified management application for Xen.
    1.17  """
    1.18  import os
    1.19  import os.path
    1.20  import sys
    1.21  import commands
    1.22 +import re
    1.23  from getopt import getopt
    1.24  import socket
    1.25  import warnings
    1.26  warnings.filterwarnings('ignore', category=FutureWarning)
    1.27 -
    1.28  from xen.xend import PrettyPrint
    1.29  from xen.xend import sxp
    1.30 -# this is a nasty place to stick this in, but required because
    1.31 -# log file access is set up via a 5 deep import chain.  This
    1.32 -# ensures the user sees a useful message instead of a stack trace
    1.33 -if os.getuid() != 0:
    1.34 -    print "xm requires root access to execute, please try again as root"
    1.35 -    sys.exit(1)
    1.36 +from xen.xm.opts import *
    1.37 +shorthelp = """Usage: xm <subcommand> [args]
    1.38 +    Control, list, and manipulate Xen guest instances
    1.39 +
    1.40 +xm common subcommands:
    1.41 +    console <DomId>         attach to console of DomId
    1.42 +    create <CfgFile>        create a domain based on Config File
    1.43 +    destroy <DomId>         terminate a domain immediately
    1.44 +    help                    display this message
    1.45 +    list [DomId, ...]       list information about domains
    1.46 +    mem-max <DomId> <Mem>   set the maximum memory reservation for a domain
    1.47 +    mem-set <DomId> <Mem>   adjust the current memory usage for a domain
    1.48 +    migrate <DomId> <Host>  migrate a domain to another machine
    1.49 +    pause <DomId>           pause execution of a domain
    1.50 +    reboot <DomId>          reboot a domain
    1.51 +    restore <File>          create a domain from a saved state file
    1.52 +    save <DomId> <File>     save domain state (and config) to file
    1.53 +    shutdown <DomId>        shutdown a domain
    1.54 +    unpause <DomId>         unpause a paused domain
    1.55 +
    1.56 +For a complete list of subcommands run 'xm help --long'
    1.57 +For more help on xm see the xm(1) man page
    1.58 +For more help on xm create, see the xmdomain.cfg(5) man page"""
    1.59 +
    1.60 +longhelp = """Usage: xm <subcommand> [args]
    1.61 +    Control, list, and manipulate Xen guest instances
    1.62 +
    1.63 +xm full list of subcommands:
    1.64  
    1.65 -from xen.xend.XendClient import XendError, server
    1.66 -from xen.xend.XendClient import main as xend_client_main
    1.67 -from xen.xm import create, destroy, migrate, shutdown, sysrq
    1.68 -from xen.xm.opts import *
    1.69 +  Domain Commands:
    1.70 +    console <DomId>         attach to console of DomId
    1.71 +    cpus-list <DomId> <VCpu>          get the list of cpus for a VCPU
    1.72 +    cpus-set <DomId> <VCpu> <CPUS>    set which cpus a VCPU can use. 
    1.73 +    create  <ConfigFile>      create a domain
    1.74 +    destroy <DomId>           terminate a domain immediately
    1.75 +    domid   <DomName>         convert a domain name to a domain id
    1.76 +    domname <DomId>           convert a domain id to a domain name
    1.77 +    list                      list information about domains
    1.78 +    mem-max <DomId> <Mem>     set domain maximum memory limit
    1.79 +    mem-set <DomId> <Mem>     set the domain's memory dynamically
    1.80 +    migrate <DomId> <Host>    migrate a domain to another machine
    1.81 +    pause   <DomId>           pause execution of a domain
    1.82 +    reboot   [-w|-a] <DomId>  reboot a domain
    1.83 +    restore <File>            create a domain from a saved state file
    1.84 +    save    <DomId> <File>    save domain state (and config) to file
    1.85 +    shutdown [-w|-a] <DomId>  shutdown a domain
    1.86 +    sysrq   <DomId> <letter>  send a sysrq to a domain
    1.87 +    unpause <DomId>           unpause a paused domain
    1.88 +    vcpu-enable <DomId> <VCPU>        disable VCPU in a domain
    1.89 +    vcpu-disable <DomId> <VCPU>       enable VCPU in a domain
    1.90 +    vcpu-list <DomId>                 get the list of VCPUs for a domain
    1.91 +
    1.92 +  Xen Host Commands:
    1.93 +    dmesg   [--clear]         read or clear Xen's message buffer
    1.94 +    info                      get information about the xen host
    1.95 +    log                       print the xend log
    1.96 +
    1.97 +  Scheduler Commands:
    1.98 +    bvt <options>             set BVT scheduler parameters
    1.99 +    bvt_ctxallow <Allow>      set the BVT scheduler context switch allowance
   1.100 +    sedf <options>            set simple EDF parameters
   1.101 +
   1.102 +  Virtual Device Commands:
   1.103 +    block-create <DomId> <BackDev> <FrontDev> <Mode> [BackDomId]
   1.104 +        Create a new virtual block device 
   1.105 +    block-destroy <DomId> <DevId>  Destroy a domain's virtual block device
   1.106 +    block-list    <DomId>          List virtual block devices for a domain
   1.107 +    block-refresh <DomId> <DevId>  Refresh a virtual block device for a domain
   1.108 +    network-limit   <DomId> <Vif> <Credit> <Period>
   1.109 +        Limit the transmission rate of a virtual network interface
   1.110 +    network-list    <DomId>        List virtual network interfaces for a domain
   1.111 +
   1.112 +For a short list of subcommands run 'xm help'
   1.113 +For more help on xm see the xm(1) man page
   1.114 +For more help on xm create, see the xmdomain.cfg(5) man page"""
   1.115 +
   1.116 +####################################################################
   1.117 +#
   1.118 +#  Utility functions
   1.119 +#
   1.120 +####################################################################
   1.121 +
   1.122 +def arg_check(args,num,name):
   1.123 +    if len(args) < num:
   1.124 +        err("'xm %s' requires %s argument(s)!\n" % (name, num))
   1.125 +        usage(name)
   1.126  
   1.127  def unit(c):
   1.128      if not c.isalpha():
   1.129 @@ -49,692 +134,318 @@ def int_unit(str, dest):
   1.130      else:
   1.131          return value * (base / dst_base)
   1.132  
   1.133 -class Group:
   1.134 -
   1.135 -    name = ""
   1.136 -    info = ""
   1.137 -    
   1.138 -    def __init__(self, xm):
   1.139 -        self.xm = xm
   1.140 -        self.progs = {}
   1.141 -
   1.142 -    def addprog(self, prog):
   1.143 -        self.progs[prog.name] = prog
   1.144 -
   1.145 -    def getprog(self, name):
   1.146 -        return self.progs.get(name)
   1.147 +def err(msg):
   1.148 +    print >>sys.stderr, "Error:", msg
   1.149  
   1.150 -    def proglist(self):
   1.151 -        kl = self.progs.keys()
   1.152 -        kl.sort()
   1.153 -        return [ self.getprog(k) for k in kl ]
   1.154 -
   1.155 -    def help(self, args):
   1.156 -        if self.info:
   1.157 -            print 
   1.158 -            print self.info
   1.159 -            print
   1.160 -        else:
   1.161 -            print
   1.162 -        
   1.163 -    def shortHelp(self, args):
   1.164 -        self.help(args)
   1.165 -        for p in self.proglist():
   1.166 -            p.shortHelp(args)
   1.167 -
   1.168 -class Prog:
   1.169 -    """Base class for sub-programs.
   1.170 -    """
   1.171 +def handle_xend_error(cmd, dom, ex):
   1.172 +    error = str(ex)
   1.173 +    if error == "Not found" and dom != None:
   1.174 +        err("Domain '%s' not found when running 'xm %s'" % (dom, cmd))
   1.175 +        sys.exit(1)
   1.176 +    else:
   1.177 +        raise ex
   1.178 +    
   1.179  
   1.180 -    """Program group it belongs to"""
   1.181 -    group = 'all'
   1.182 -    """Program name."""
   1.183 -    name = '??'
   1.184 -    """Short program info."""
   1.185 -    info = ''
   1.186 -
   1.187 -    def __init__(self, xm):
   1.188 -        self.xm = xm
   1.189 -
   1.190 -    def err(self, msg):
   1.191 -        self.xm.err(msg)
   1.192 -
   1.193 -    def help(self, args):
   1.194 -        self.shortHelp(args)
   1.195 -
   1.196 -    def shortHelp(self, args):
   1.197 -        print "%-14s %s" % (self.name, self.info)
   1.198 +#########################################################################
   1.199 +#
   1.200 +#  Main xm functions
   1.201 +#
   1.202 +#########################################################################
   1.203  
   1.204 -    def main(self, args):
   1.205 -        """Program main entry point.
   1.206 -        """
   1.207 -        pass
   1.208 -
   1.209 -
   1.210 -class ProgUnknown(Prog):
   1.211 +def xm_create(args):
   1.212 +    from xen.xm import create
   1.213 +    # ugly hack because the opt parser apparently wants
   1.214 +    # the subcommand name just to throw it away!
   1.215 +    args.insert(0,"bogus")
   1.216 +    create.main(args)
   1.217  
   1.218 -    name = 'unknown'
   1.219 -    info = ''
   1.220 -    
   1.221 -    def help(self, args):
   1.222 -        self.xm.err("Unknown command: %s\nTry '%s help' for more information."
   1.223 -                    % (args[0], self.xm.name))
   1.224 -
   1.225 -    main = help
   1.226 -
   1.227 -class Xm:
   1.228 -    """Main application.
   1.229 -    """
   1.230 -
   1.231 -    def __init__(self):
   1.232 -        self.name = 'xm'
   1.233 -        self.unknown = ProgUnknown(self)
   1.234 -        self.progs = {}
   1.235 -        self.groups = {}
   1.236 +def xm_save(args):
   1.237 +    arg_check(args,2,"save")
   1.238  
   1.239 -    def err(self, msg):
   1.240 -        print >>sys.stderr, "Error:", msg
   1.241 -        sys.exit(1)
   1.242 -
   1.243 -    def main(self, args):
   1.244 -        try:
   1.245 -            self.main_call(args)
   1.246 -        except socket.error, ex:
   1.247 -            print >>sys.stderr, ex
   1.248 -            self.err("Error connecting to xend, is xend running?")
   1.249 -        except XendError, ex:
   1.250 -            self.err(str(ex))
   1.251 +    dom = args[0] # TODO: should check if this exists
   1.252 +    savefile = os.path.abspath(args[1])
   1.253 +    
   1.254 +    from xen.xend.XendClient import server
   1.255 +    server.xend_domain_save(dom, savefile)
   1.256 +    
   1.257 +def xm_restore(args):
   1.258 +    arg_check(args,1,"restore")
   1.259  
   1.260 -    def main_call(self, args):
   1.261 -        """Main entry point. Dispatches to the progs.
   1.262 -        """
   1.263 -        self.name = args[0]
   1.264 -        if len(args) < 2:
   1.265 -        	args.append('help')
   1.266 -	help = self.helparg(args)
   1.267 -        p = self.getprog(args[1], self.unknown)
   1.268 -        if help or len(args) < 2: 
   1.269 -            p.help(args[1:])
   1.270 -        else:
   1.271 -            p.main(args[1:])
   1.272 +    savefile = os.path.abspath(args[0])
   1.273  
   1.274 -    def helparg(self, args):
   1.275 -        for a in args:
   1.276 -            if a in ['-h', '--help']:
   1.277 -                return 1
   1.278 -        return 0
   1.279 -
   1.280 -    def prog(self, pklass):
   1.281 -        """Add a sub-program.
   1.282 -
   1.283 -        pklass  program class (Prog subclass)
   1.284 -        """
   1.285 -        p = pklass(self)
   1.286 -        self.progs[p.name] = p
   1.287 -        self.getgroup(p.group).addprog(p)
   1.288 -        return p
   1.289 +    from xen.xend.XendClient import server
   1.290 +    info = server.xend_domain_restore(savefile)
   1.291 +    PrettyPrint.prettyprint(info)
   1.292 +    id = sxp.child_value(info, 'id')
   1.293 +    if id is not None:
   1.294 +        server.xend_domain_unpause(id)
   1.295  
   1.296 -    def getprog(self, name, val=None):
   1.297 -        """Get a sub-program.
   1.298 -        name  Name of the sub-program (or optionally, an unambiguous
   1.299 -              prefix of its name)
   1.300 -        val   Default return value if no (unique) match is found
   1.301 -        """
   1.302 -
   1.303 -        match = None
   1.304 -        for progname in self.progs.keys():
   1.305 -            if progname == name:
   1.306 -                match = progname
   1.307 -                break
   1.308 -            if progname.startswith(name):
   1.309 -                if not match:
   1.310 -                    match = progname
   1.311 -                else:
   1.312 -                    return val # name is ambiguous - bail out
   1.313 -
   1.314 -        return self.progs.get(match, val)
   1.315 +def xm_migrate(args):
   1.316 +    # TODO: arg_check
   1.317 +    from xen.xm import migrate
   1.318 +    # ugly hack because the opt parser apparently wants
   1.319 +    # the subcommand name just to throw it away!
   1.320 +    args.insert(0,"bogus")
   1.321 +    migrate.main(args)
   1.322  
   1.323 -    def group(self, klass):
   1.324 -        g = klass(self)
   1.325 -        self.groups[g.name] = g
   1.326 -        return g
   1.327 -
   1.328 -    def getgroup(self, name):
   1.329 -        return self.groups[name]
   1.330 -
   1.331 -    def grouplist(self):
   1.332 -        kl = self.groups.keys()
   1.333 -        kl.sort()
   1.334 -        return [ self.getgroup(k) for k in kl ]
   1.335 -        
   1.336 -# Create the application object, then add the sub-program classes.
   1.337 -xm = Xm()
   1.338 -
   1.339 -class GroupAll(Group):
   1.340 -
   1.341 -    name = "all"
   1.342 -    info = ""
   1.343 -
   1.344 -xm.group(GroupAll)
   1.345 -
   1.346 -class GroupDomain(Group):
   1.347 +def xm_list(args):
   1.348 +    use_long = 0
   1.349 +    show_vcpus = 0
   1.350 +    (options, params) = getopt(args, 'lv', ['long','vcpus'])
   1.351 +    
   1.352 +    n = len(params)
   1.353 +    for (k, v) in options:
   1.354 +        if k in ['-l', '--long']:
   1.355 +            use_long = 1
   1.356 +        if k in ['-v', '--vcpus']:
   1.357 +            show_vcpus = 1
   1.358  
   1.359 -    name = "domain"
   1.360 -    info = "Commands on domains:"
   1.361 -    
   1.362 -xm.group(GroupDomain)
   1.363 -
   1.364 -class GroupScheduler(Group):
   1.365 -
   1.366 -    name = "scheduler"
   1.367 -    info = "Comands controlling scheduling:"
   1.368 -
   1.369 -xm.group(GroupScheduler)
   1.370 -
   1.371 -class GroupHost(Group):
   1.372 -
   1.373 -    name = "host"
   1.374 -    info = "Commands related to the xen host (node):"
   1.375 -
   1.376 -xm.group(GroupHost)
   1.377 -
   1.378 -class GroupConsole(Group):
   1.379 -
   1.380 -    name = "console"
   1.381 -    info = "Commands related to consoles:"
   1.382 -
   1.383 -xm.group(GroupConsole)
   1.384 -
   1.385 -class GroupVbd(Group):
   1.386 -
   1.387 -    name = "vbd"
   1.388 -    info = "Commands related to virtual block devices:"
   1.389 -
   1.390 -xm.group(GroupVbd)
   1.391 -
   1.392 -class GroupVif(Group):
   1.393 -
   1.394 -    name = "vif"
   1.395 -    info = "Commands related to virtual network interfaces:"
   1.396 -
   1.397 -xm.group(GroupVif)
   1.398 -
   1.399 -class ProgHelp(Prog):
   1.400 +    domsinfo = []
   1.401 +    from xen.xend.XendClient import server
   1.402 +    if n == 0:
   1.403 +        doms = server.xend_domains()
   1.404 +        doms.sort()
   1.405 +    else:
   1.406 +        doms = params
   1.407 +    for dom in doms:
   1.408 +        info = server.xend_domain(dom)
   1.409 +        domsinfo.append(parse_doms_info(info))
   1.410 +               
   1.411 +    if use_long:
   1.412 +        # this actually seems like a bad idea, as it just dumps sexp out
   1.413 +        PrettyPrint.prettyprint(info)
   1.414 +    elif show_vcpus:
   1.415 +        xm_show_vcpus(domsinfo)
   1.416 +    else:
   1.417 +        xm_brief_list(domsinfo)
   1.418  
   1.419 -    name = "help"
   1.420 -    info = "Print help."
   1.421 -    
   1.422 -    def help(self, args):
   1.423 -        if len(args) == 2:
   1.424 -            name = args[1]
   1.425 -            p = self.xm.getprog(name)
   1.426 -            if p:
   1.427 -                p.help(args[1:])
   1.428 -            else:
   1.429 -                print '%s: Unknown command: %s' % (self.name, name)
   1.430 -        else:
   1.431 -            for g in self.xm.grouplist():
   1.432 -                g.shortHelp(args)
   1.433 -            print "\nTry '%s help CMD' for help on CMD" % self.xm.name
   1.434 -
   1.435 -    main = help
   1.436 -
   1.437 -xm.prog(ProgHelp)
   1.438 -
   1.439 -class ProgCreate(Prog):
   1.440 -
   1.441 -    group = 'domain'
   1.442 -    name = "create"
   1.443 -    info = """Create a domain."""
   1.444 -
   1.445 -    def help(self, args):
   1.446 -        create.main([args[0], '-h'])
   1.447 -
   1.448 -    def main(self, args):
   1.449 -        create.main(args)
   1.450 -
   1.451 -xm.prog(ProgCreate)
   1.452 -
   1.453 -class ProgSave(Prog):
   1.454 -    group = 'domain'
   1.455 -    name = "save"
   1.456 -    info = """Save domain state (and config) to file."""
   1.457 -
   1.458 -    def help(self, args):
   1.459 -        print args[0], "DOM FILE"
   1.460 -        print """\nSave domain with id DOM to FILE."""
   1.461 +def parse_doms_info(info):
   1.462 +    dominfo = {}
   1.463 +    dominfo['dom'] = int(sxp.child_value(info, 'id', '-1'))
   1.464 +    dominfo['name'] = sxp.child_value(info, 'name', '??')
   1.465 +    dominfo['mem'] = int(sxp.child_value(info, 'memory', '0'))
   1.466 +    dominfo['cpu'] = str(sxp.child_value(info, 'cpu', '0'))
   1.467 +    dominfo['vcpus'] = int(sxp.child_value(info, 'vcpus', '0'))
   1.468 +    # if there is more than 1 cpu, the value doesn't mean much
   1.469 +    if dominfo['vcpus'] > 1:
   1.470 +        dominfo['cpu'] = '-'
   1.471 +    dominfo['state'] = sxp.child_value(info, 'state', '??')
   1.472 +    dominfo['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
   1.473 +    # security identifiers
   1.474 +    if ((int(sxp.child_value(info, 'ssidref', '0'))) != 0):
   1.475 +        dominfo['ssidref1'] =  int(sxp.child_value(info, 'ssidref', '0')) & 0xffff
   1.476 +        dominfo['ssidref2'] = (int(sxp.child_value(info, 'ssidref', '0')) >> 16) & 0xffff
   1.477 +    # get out the vcpu information
   1.478 +    dominfo['vcpulist'] = []
   1.479 +    vcpu_to_cpu = sxp.child_value(info, 'vcpu_to_cpu', '-1').split('|')
   1.480 +    cpumap = sxp.child_value(info, 'cpumap', [])
   1.481 +    mask = ((int(sxp.child_value(info, 'vcpus', '0')))**2) - 1
   1.482 +    count = 0
   1.483 +    for cpu in vcpu_to_cpu:
   1.484 +        vcpuinfo = {}
   1.485 +        vcpuinfo['name']   = sxp.child_value(info, 'name', '??')
   1.486 +        vcpuinfo['dom']    = int(sxp.child_value(info, 'id', '-1'))
   1.487 +        vcpuinfo['vcpu']   = int(count)
   1.488 +        vcpuinfo['cpu']    = int(cpu)
   1.489 +        vcpuinfo['cpumap'] = int(cpumap[count])&mask
   1.490 +        count = count + 1
   1.491 +        dominfo['vcpulist'].append(vcpuinfo)
   1.492 +    return dominfo
   1.493          
   1.494 -    def main(self, args):
   1.495 -        if len(args) < 3: self.err("%s: Missing arguments" % args[0])
   1.496 -        dom = args[1]
   1.497 -        savefile = os.path.abspath(args[2])
   1.498 -        server.xend_domain_save(dom, savefile)
   1.499 -
   1.500 -xm.prog(ProgSave)
   1.501 -
   1.502 -class ProgRestore(Prog):
   1.503 -    group = 'domain'
   1.504 -    name = "restore"
   1.505 -    info = """Create a domain from a saved state."""
   1.506 +def xm_brief_list(domsinfo):
   1.507 +    print 'Name              Id  Mem(MB)  CPU VCPU(s)  State  Time(s)'
   1.508 +    for dominfo in domsinfo:
   1.509 +        if dominfo.has_key("ssidref1"):
   1.510 +            print ("%(name)-16s %(dom)3d  %(mem)7d  %(cpu)3s  %(vcpus)5d   %(state)5s  %(cpu_time)7.1f     %s:%(ssidref2)02x/p:%(ssidref1)02x" % dominfo)
   1.511 +        else:
   1.512 +            print ("%(name)-16s %(dom)3d  %(mem)7d  %(cpu)3s  %(vcpus)5d   %(state)5s  %(cpu_time)7.1f" % dominfo)
   1.513  
   1.514 -    def help(self, args):
   1.515 -        print args[0], "FILE"
   1.516 -        print "\nRestore a domain from FILE."
   1.517 -    
   1.518 -    def main(self, args):
   1.519 -        if len(args) < 2: self.err("%s: Missing arguments" % args[0])
   1.520 -        savefile = os.path.abspath(args[1])
   1.521 -        info = server.xend_domain_restore(savefile)
   1.522 -        PrettyPrint.prettyprint(info)
   1.523 -        id = sxp.child_value(info, 'id')
   1.524 -        if id is not None:
   1.525 -            server.xend_domain_unpause(id)
   1.526 +def xm_show_vcpus(domsinfo):
   1.527 +    print 'Name              Id  VCPU  CPU  CPUMAP'
   1.528 +    for dominfo in domsinfo:
   1.529 +        for vcpuinfo in dominfo['vcpulist']:
   1.530 +            print ("%(name)-16s %(dom)3d  %(vcpu)4d  %(cpu)3d  0x%(cpumap)x" %
   1.531 +                   vcpuinfo)
   1.532  
   1.533 -xm.prog(ProgRestore)
   1.534 -
   1.535 -class ProgMigrate(Prog):
   1.536 -    group = 'domain'
   1.537 -    name = "migrate"
   1.538 -    info = """Migrate a domain to another machine."""
   1.539 -
   1.540 -    def help(self, args):
   1.541 -        migrate.help([self.name] + args)
   1.542 -    
   1.543 -    def main(self, args):
   1.544 -        migrate.main(args)
   1.545 -
   1.546 -xm.prog(ProgMigrate)
   1.547 +def xm_vcpu_list(args):
   1.548 +    args.insert(0,"-v")
   1.549 +    xm_list(args)
   1.550  
   1.551 -class ProgList(Prog):
   1.552 -    group = 'domain'
   1.553 -    name = "list"
   1.554 -    info = """List information about domains."""
   1.555 -
   1.556 -    short_options = 'lv'
   1.557 -    long_options = ['long','vcpus']
   1.558 -
   1.559 -    def help(self, args):
   1.560 -        if help:
   1.561 -            print args[0], '[options] [DOM...]'
   1.562 -            print """\nGet information about domains.
   1.563 -            Either all domains or the domains given.
   1.564 +def xm_destroy(args):
   1.565 +    arg_check(args,1,"destroy")
   1.566  
   1.567 -            -l, --long   Get more detailed information.
   1.568 -            -v, --vcpus  Show VCPU to CPU mapping.
   1.569 -            """
   1.570 -            return
   1.571 -        
   1.572 -    def main(self, args):
   1.573 -        use_long = 0
   1.574 -        show_vcpus = 0
   1.575 -        (options, params) = getopt(args[1:],
   1.576 -                                   self.short_options,
   1.577 -                                   self.long_options)
   1.578 -        n = len(params)
   1.579 -        for (k, v) in options:
   1.580 -            if k in ['-l', '--long']:
   1.581 -                use_long = 1
   1.582 -            if k in ['-v', '--vcpus']:
   1.583 -                show_vcpus = 1
   1.584 -                
   1.585 -        if n == 0:
   1.586 -            doms = server.xend_domains()
   1.587 -            doms.sort()
   1.588 -        else:
   1.589 -            doms = params
   1.590 +    from xen.xm import destroy
   1.591 +    # ugly hack because the opt parser apparently wants
   1.592 +    # the subcommand name just to throw it away!
   1.593 +    args.insert(0,"bogus")
   1.594 +    destroy.main(args)
   1.595              
   1.596 -        if use_long:
   1.597 -            self.long_list(doms)
   1.598 -        elif show_vcpus:
   1.599 -            self.show_vcpus(doms)
   1.600 -        else:
   1.601 -            self.brief_list(doms)
   1.602 +# TODO: make reboot do the right thing, right now
   1.603 +# reboot and shutdown are exactly the same
   1.604 +def xm_reboot(args):
   1.605 +    arg_check(args,1,"reboot")
   1.606 +    # ugly hack because the opt parser apparently wants
   1.607 +    # the subcommand name just to throw it away!
   1.608 +    args.insert(0,"bogus")
   1.609 +    from xen.xm import shutdown
   1.610 +    shutdown.main(args)
   1.611  
   1.612 -    def brief_list(self, doms):
   1.613 -        print 'Name              Id  Mem(MB)  CPU VCPU(s)  State  Time(s)'
   1.614 -        for dom in doms:
   1.615 -            info = server.xend_domain(dom)
   1.616 -            d = {}
   1.617 -            d['dom'] = int(sxp.child_value(info, 'id', '-1'))
   1.618 -            d['name'] = sxp.child_value(info, 'name', '??')
   1.619 -            d['mem'] = int(sxp.child_value(info, 'memory', '0'))
   1.620 -            d['cpu'] = str(sxp.child_value(info, 'cpu', '0'))
   1.621 -            d['vcpus'] = int(sxp.child_value(info, 'vcpus', '0'))
   1.622 -            d['state'] = sxp.child_value(info, 'state', '??')
   1.623 -            d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
   1.624 -            if d['vcpus'] > 1:
   1.625 -                d['cpu'] = '-'
   1.626 -            if ((int(sxp.child_value(info, 'ssidref', '0'))) != 0):
   1.627 -                d['ssidref1'] =  int(sxp.child_value(info, 'ssidref', '0')) & 0xffff
   1.628 -                d['ssidref2'] = (int(sxp.child_value(info, 'ssidref', '0')) >> 16) & 0xffff
   1.629 -                print ("%(name)-16s %(dom)3d  %(mem)7d  %(cpu)3s  %(vcpus)5d   %(state)5s  %(cpu_time)7.1f     %s:%(ssidref2)02x/p:%(ssidref1)02x" % d)
   1.630 -            else:
   1.631 -                print ("%(name)-16s %(dom)3d  %(mem)7d  %(cpu)3s  %(vcpus)5d   %(state)5s  %(cpu_time)7.1f" % d)
   1.632 +def xm_shutdown(args):
   1.633 +    arg_check(args,1,"shutdown")
   1.634  
   1.635 -    def show_vcpus(self, doms):
   1.636 -        print 'Name              Id  VCPU  CPU  CPUMAP'
   1.637 -        for dom in doms:
   1.638 -            info = server.xend_domain(dom)
   1.639 -            vcpu_to_cpu = sxp.child_value(info, 'vcpu_to_cpu', '-1').split('|')
   1.640 -            cpumap = sxp.child_value(info, 'cpumap', [])
   1.641 -            mask = ((int(sxp.child_value(info, 'vcpus', '0')))**2) - 1
   1.642 -            count = 0
   1.643 -            for cpu in vcpu_to_cpu:
   1.644 -                d = {}
   1.645 -                d['name']   = sxp.child_value(info, 'name', '??')
   1.646 -                d['dom']    = int(sxp.child_value(info, 'id', '-1'))
   1.647 -                d['vcpu']   = int(count)
   1.648 -                d['cpu']    = int(cpu)
   1.649 -                d['cpumap'] = int(cpumap[count])&mask
   1.650 -                count = count + 1
   1.651 -                print ("%(name)-16s %(dom)3d  %(vcpu)4d  %(cpu)3d  0x%(cpumap)x" % d)
   1.652 +    # ugly hack because the opt parser apparently wants
   1.653 +    # the subcommand name just to throw it away!
   1.654 +    args.insert(0,"bogus")
   1.655 +    from xen.xm import shutdown
   1.656 +    shutdown.main(args)
   1.657 +
   1.658 +def xm_sysrq(args):
   1.659 +    from xen.xm import sysrq
   1.660 +    # ugly hack because the opt parser apparently wants
   1.661 +    # the subcommand name just to throw it away!
   1.662 +    args.insert(0,"bogus")
   1.663 +    sysrq.main(args)
   1.664  
   1.665 -    def long_list(self, doms):
   1.666 -        for dom in doms:
   1.667 -            info = server.xend_domain(dom)
   1.668 -            PrettyPrint.prettyprint(info)
   1.669 -
   1.670 -xm.prog(ProgList)
   1.671 +def xm_pause(args):
   1.672 +    arg_check(args, 1, "pause")
   1.673 +    dom = args[0]
   1.674  
   1.675 -class ProgDestroy(Prog):
   1.676 -    group = 'domain'
   1.677 -    name = "destroy"
   1.678 -    info = """Terminate a domain immediately."""
   1.679 -
   1.680 -    def help(self, args):
   1.681 -        destroy.main([args[0], '-h'])
   1.682 -
   1.683 -    def main(self, args):
   1.684 -        destroy.main(args)
   1.685 -
   1.686 -xm.prog(ProgDestroy)
   1.687 +    from xen.xend.XendClient import server
   1.688 +    server.xend_domain_pause(dom)
   1.689  
   1.690 -class ProgShutdown(Prog):
   1.691 -    group = 'domain'
   1.692 -    name = "shutdown"
   1.693 -    info = """Shutdown a domain."""
   1.694 -
   1.695 -    def help(self, args):
   1.696 -        shutdown.main([args[0], '-h'])
   1.697 -    
   1.698 -    def main(self, args):
   1.699 -        shutdown.main(args)
   1.700 +def xm_unpause(args):
   1.701 +    arg_check(args, 1, "unpause")
   1.702 +    dom = args[0]
   1.703  
   1.704 -xm.prog(ProgShutdown)
   1.705 +    from xen.xend.XendClient import server
   1.706 +    server.xend_domain_unpause(dom)
   1.707  
   1.708 -class ProgSysrq(Prog):
   1.709 -    group = 'domain'
   1.710 -    name = "sysrq"
   1.711 -    info = """Send a sysrq to a domain."""
   1.712 -
   1.713 -    def help(self, args):
   1.714 -        sysrq.main([args[0], '-h'])
   1.715 -    
   1.716 -    def main(self, args):
   1.717 -        sysrq.main(args)
   1.718 +#############################################################
   1.719  
   1.720 -xm.prog(ProgSysrq)
   1.721 -
   1.722 -class ProgPause(Prog):
   1.723 -    group = 'domain'
   1.724 -    name = "pause"
   1.725 -    info = """Pause execution of a domain."""
   1.726 -
   1.727 -    def help(self, args):
   1.728 -        print args[0], 'DOM'
   1.729 -        print '\nPause execution of domain DOM.'
   1.730 -
   1.731 -    def main(self, args):
   1.732 -        if len(args) < 2: self.err("%s: Missing domain" % args[0])
   1.733 -        dom = args[1]
   1.734 -        server.xend_domain_pause(dom)
   1.735 -
   1.736 -xm.prog(ProgPause)
   1.737 +def cpu_make_map(cpulist):
   1.738 +    cpus = []
   1.739 +    cpumap = 0
   1.740 +    for c in cpulist.split(','):
   1.741 +        if c.find('-') != -1:
   1.742 +            (x,y) = c.split('-')
   1.743 +            for i in range(int(x),int(y)+1):
   1.744 +                cpus.append(int(i))
   1.745 +        else:
   1.746 +            cpus.append(int(c))
   1.747 +    cpus.sort()
   1.748 +    for c in cpus:
   1.749 +        cpumap = cpumap | 1<<c
   1.750  
   1.751 -class ProgUnpause(Prog):
   1.752 -    group = 'domain'
   1.753 -    name = "unpause"
   1.754 -    info = """Unpause a paused domain."""
   1.755 -
   1.756 -    def help(self, args):
   1.757 -        print args[0], 'DOM'
   1.758 -        print '\nUnpause execution of domain DOM.'
   1.759 -
   1.760 -    def main(self, args):
   1.761 -        if len(args) < 2: self.err("%s: Missing domain" % args[0])
   1.762 -        dom = args[1]
   1.763 -        server.xend_domain_unpause(dom)
   1.764 -
   1.765 -xm.prog(ProgUnpause)
   1.766 -
   1.767 -class ProgPincpu(Prog):
   1.768 -    group = 'domain'
   1.769 -    name = "pincpu"
   1.770 -    info = """Set which cpus a VCPU can use. """
   1.771 -
   1.772 -    def help(self, args):
   1.773 -        print args[0],'DOM VCPU CPUS'
   1.774 -        print '\nSet which cpus VCPU in domain DOM can use.'
   1.775 +    return cpumap
   1.776  
   1.777 -    # convert list of cpus to bitmap integer value
   1.778 -    def make_map(self, cpulist):
   1.779 -        cpus = []
   1.780 -        cpumap = 0
   1.781 -        for c in cpulist.split(','):
   1.782 -            if c.find('-') != -1:
   1.783 -                (x,y) = c.split('-')
   1.784 -                for i in range(int(x),int(y)+1):
   1.785 -                    cpus.append(int(i))
   1.786 -            else:
   1.787 -                cpus.append(int(c))
   1.788 -        cpus.sort()
   1.789 -        for c in cpus:
   1.790 -            cpumap = cpumap | 1<<c
   1.791 -
   1.792 -        return cpumap
   1.793 +def xm_cpus_set(args):
   1.794 +    arg_check(args, 3, "cpus-set")
   1.795 +    
   1.796 +    dom  = args[0]
   1.797 +    vcpu = int(args[1])
   1.798 +    cpumap = cpu_make_map(args[2])
   1.799 +    
   1.800 +    from xen.xend.XendClient import server
   1.801 +    server.xend_domain_pincpu(dom, vcpu, cpumap)
   1.802  
   1.803 -    def main(self, args):
   1.804 -        if len(args) != 4: self.err("%s: Invalid argument(s)" % args[0])
   1.805 -        dom  = args[1]
   1.806 -        vcpu = int(args[2])
   1.807 -        cpumap  = self.make_map(args[3]);
   1.808 -        server.xend_domain_pincpu(dom, vcpu, cpumap)
   1.809 -
   1.810 -xm.prog(ProgPincpu)
   1.811 +def xm_mem_max(args):
   1.812 +    arg_check(args, 2, "mem-max")
   1.813 +    
   1.814 +    dom = args[0]
   1.815 +    mem = int_unit(args[1], 'm')
   1.816  
   1.817 -class ProgMaxmem(Prog):
   1.818 -    group = 'domain'
   1.819 -    name = 'maxmem'
   1.820 -    info = """Set domain memory limit."""
   1.821 -
   1.822 -    def help(self, args):
   1.823 -        print args[0], "DOM MEMORY"
   1.824 -        print "\nSet the memory limit for domain DOM to MEMORY megabytes."
   1.825 -
   1.826 -    def main(self, args):
   1.827 -        if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
   1.828 -        dom = args[1]
   1.829 -        mem = int_unit(args[2], 'm')
   1.830 -        server.xend_domain_maxmem_set(dom, mem)
   1.831 -
   1.832 -xm.prog(ProgMaxmem)
   1.833 +    from xen.xend.XendClient import server
   1.834 +    server.xend_domain_maxmem_set(dom, mem)
   1.835 +    
   1.836 +def xm_mem_set(args):
   1.837 +    arg_check(args, 2, "mem-set")
   1.838 +    
   1.839 +    dom = args[0]
   1.840 +    mem_target = int_unit(args[1], 'm')
   1.841  
   1.842 -class ProgSetMem(Prog):
   1.843 -    group = 'domain'
   1.844 -    name  = 'set-mem'
   1.845 -    info  = """Set the domain's memory footprint using the balloon driver."""
   1.846 -
   1.847 -    def help(self, args):
   1.848 -        print args[0], "DOM MEMORY_TARGET"
   1.849 -        print """\nRequest domain DOM to adjust its memory footprint to
   1.850 -MEMORY_TARGET megabytes"""
   1.851 -
   1.852 -    def main(self, args):
   1.853 -        if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
   1.854 -        dom = args[1]
   1.855 -        mem_target = int_unit(args[2], 'm')
   1.856 -        server.xend_domain_mem_target_set(dom, mem_target)
   1.857 -
   1.858 -xm.prog(ProgSetMem)
   1.859 -
   1.860 -class ProgVcpuhotplug(Prog):
   1.861 -    group = 'domain'
   1.862 -    name  = 'vcpu-hotplug'
   1.863 -    info  = """Enable or disable a VCPU in a domain."""
   1.864 -
   1.865 -    def help(self, args):
   1.866 -        print args[0], "DOM VCPU [0|1]"
   1.867 -        print """\nRequest virtual processor VCPU to be disabled or enabled in
   1.868 -domain DOM"""
   1.869 -
   1.870 -    def main(self, args):
   1.871 -        if len(args) != 4: self.err("%s: Invalid arguments(s)" % args[0])
   1.872 -        name = args[1]
   1.873 -        vcpu = int(args[2])
   1.874 -        state = int(args[3])
   1.875 -        dom = server.xend_domain(name)
   1.876 -        id = sxp.child_value(dom, 'id')
   1.877 -        server.xend_domain_vcpu_hotplug(id, vcpu, state)
   1.878 -
   1.879 -xm.prog(ProgVcpuhotplug)
   1.880 -
   1.881 -class ProgDomid(Prog):
   1.882 -    group = 'domain'
   1.883 -    name = 'domid'
   1.884 -    info = 'Convert a domain name to a domain id.'
   1.885 +    from xen.xend.XendClient import server
   1.886 +    server.xend_domain_mem_target_set(dom, mem_target)
   1.887 +    
   1.888 +# TODO: why does this lookup by name?  and what if that fails!?
   1.889 +def xm_vcpu_enable(args):
   1.890 +    arg_check(args, 2, "vcpu-enable")
   1.891 +    
   1.892 +    name = args[0]
   1.893 +    vcpu = int(args[1])
   1.894 +    
   1.895 +    from xen.xend.XendClient import server
   1.896 +    dom = server.xend_domain(name)
   1.897 +    id = sxp.child_value(dom, 'id')
   1.898 +    server.xend_domain_vcpu_hotplug(id, vcpu, 1)
   1.899  
   1.900 -    def help(self, args):
   1.901 -        print args[0], "DOM"
   1.902 -        print '\nGet the domain id for the domain with name DOM.'
   1.903 -        
   1.904 -    def main (self, args):
   1.905 -        if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
   1.906 -        name = args[1]
   1.907 -        dom = server.xend_domain(name)
   1.908 -        print sxp.child_value(dom, 'id')
   1.909 -
   1.910 -xm.prog(ProgDomid)
   1.911 -
   1.912 -class ProgDomname(Prog):
   1.913 -    group = 'domain'
   1.914 -    name = 'domname'
   1.915 -    info = 'Convert a domain id to a domain name.'
   1.916 +def xm_vcpu_disable(args):
   1.917 +    arg_check(args, 2, "vcpu-disable")
   1.918 +    
   1.919 +    name = args[0]
   1.920 +    vcpu = int(args[1])
   1.921 +    
   1.922 +    from xen.xend.XendClient import server
   1.923 +    dom = server.xend_domain(name)
   1.924 +    id = sxp.child_value(dom, 'id')
   1.925 +    server.xend_domain_vcpu_hotplug(id, vcpu, 0)
   1.926  
   1.927 -    def help(self, args):
   1.928 -        print args[0], "DOM"
   1.929 -        print '\nGet the name for the domain with id DOM.'
   1.930 -        
   1.931 -    def main (self, args):
   1.932 -        if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
   1.933 -        name = args[1]
   1.934 -        dom = server.xend_domain(name)
   1.935 -        print sxp.child_value(dom, 'name')
   1.936 -
   1.937 -xm.prog(ProgDomname)
   1.938 +def xm_domid(args):
   1.939 +    name = args[0]
   1.940  
   1.941 -class ProgBvt(Prog):
   1.942 -    group = 'scheduler'
   1.943 -    name = "bvt"
   1.944 -    info = """Set BVT scheduler parameters."""
   1.945 +    from xen.xend.XendClient import server
   1.946 +    dom = server.xend_domain(name)
   1.947 +    print sxp.child_value(dom, 'id')
   1.948      
   1.949 -    def help(self, args):
   1.950 -        print args[0], "DOM MCUADV WARPBACK WARPVALUE WARPL WARPU"
   1.951 -        print '\nSet Borrowed Virtual Time scheduler parameters.'
   1.952 +def xm_domname(args):
   1.953 +    name = args[0]
   1.954  
   1.955 -    def main(self, args):
   1.956 -        if len(args) != 7: self.err("%s: Invalid argument(s)" % args[0])
   1.957 -        dom = args[1]
   1.958 -        v = map(long, args[2:7])
   1.959 -        server.xend_domain_cpu_bvt_set(dom, *v)
   1.960 +    from xen.xend.XendClient import server
   1.961 +    dom = server.xend_domain(name)
   1.962 +    print sxp.child_value(dom, 'name')
   1.963  
   1.964 -xm.prog(ProgBvt)
   1.965 -
   1.966 -class ProgBvtslice(Prog):
   1.967 -    group = 'scheduler'
   1.968 -    name = "bvt_ctxallow"
   1.969 -    info = """Set the BVT scheduler context switch allowance."""
   1.970 +def xm_bvt(args):
   1.971 +    arg_check(args, 6, "bvt")
   1.972 +    dom = args[0]
   1.973 +    v = map(long, args[1:6])
   1.974 +    from xen.xend.XendClient import server
   1.975 +    server.xend_domain_cpu_bvt_set(dom, *v)
   1.976  
   1.977 -    def help(self, args):
   1.978 -        print args[0], 'CTX_ALLOW'
   1.979 -        print '\nSet Borrowed Virtual Time scheduler context switch allowance.'
   1.980 -
   1.981 -    def main(self, args):
   1.982 -        if len(args) < 2: self.err('%s: Missing context switch allowance'
   1.983 -                                                            % args[0])
   1.984 -        slice = int(args[1])
   1.985 -        server.xend_node_cpu_bvt_slice_set(slice)
   1.986 -
   1.987 -xm.prog(ProgBvtslice)
   1.988 +def xm_bvt_ctxallow(args):
   1.989 +    arg_check(args, 1, "bvt_ctxallow")
   1.990  
   1.991 -class ProgSedf(Prog):
   1.992 -    group = 'scheduler'
   1.993 -    name= "sedf"
   1.994 -    info = """Set simple EDF parameters."""
   1.995 -
   1.996 -    def help(self, args):
   1.997 -        print args[0], "DOM PERIOD SLICE LATENCY EXTRATIME WEIGHT"
   1.998 -        print "\nSet simple EDF parameters."
   1.999 +    slice = int(args[0])
  1.1000 +    from xen.xend.XendClient import server
  1.1001 +    server.xend_node_cpu_bvt_slice_set(slice)
  1.1002  
  1.1003 -    def main(self, args):
  1.1004 -	if len(args) != 7: self.err("%s: Invalid argument(s)" % args[0])
  1.1005 -	dom = args[1]
  1.1006 -	v = map(int, args[2:7])
  1.1007 -	server.xend_domain_cpu_sedf_set(dom, *v)
  1.1008 -
  1.1009 -xm.prog(ProgSedf)
  1.1010 -
  1.1011 -class ProgInfo(Prog):
  1.1012 -    group = 'host'
  1.1013 -    name = "info"
  1.1014 -    info = """Get information about the xen host."""
  1.1015 +def xm_sedf(args):
  1.1016 +    arg_check(args, 6, "sedf")
  1.1017 +    
  1.1018 +    dom = args[0]
  1.1019 +    v = map(int, args[1:5])
  1.1020 +    from xen.xend.XendClient import server
  1.1021 +    server.xend_domain_cpu_sedf_set(dom, *v)
  1.1022  
  1.1023 -    def main(self, args):
  1.1024 -        info = server.xend_node()
  1.1025 -        for x in info[1:]:
  1.1026 -            print "%-23s:" % x[0], x[1]
  1.1027 -
  1.1028 -xm.prog(ProgInfo)
  1.1029 -
  1.1030 -class ProgConsole(Prog):
  1.1031 -    group = 'console'
  1.1032 -    name = "console"
  1.1033 -    info = """Open a console to a domain."""
  1.1034 +def xm_info(args):
  1.1035 +    from xen.xend.XendClient import server
  1.1036 +    info = server.xend_node()
  1.1037      
  1.1038 -    def help(self, args):
  1.1039 -        print args[0], "DOM"
  1.1040 -        print "\nOpen a console to domain DOM."
  1.1041 +    for x in info[1:]:
  1.1042 +        print "%-23s:" % x[0], x[1]
  1.1043  
  1.1044 -    def main(self, args):
  1.1045 -        if len(args) < 2: self.err("%s: Missing domain" % args[0])
  1.1046 -        dom = args[1]
  1.1047 -        info = server.xend_domain(dom)
  1.1048 -        domid = int(sxp.child_value(info, 'id', '-1'))
  1.1049 -        cmd = "/usr/libexec/xen/xenconsole %d" % domid
  1.1050 -        os.execvp('/usr/libexec/xen/xenconsole', cmd.split())
  1.1051 +# TODO: remove as soon as console server shows up
  1.1052 +def xm_console(args):
  1.1053 +    arg_check(args,1,"console")
  1.1054  
  1.1055 -xm.prog(ProgConsole)
  1.1056 -
  1.1057 -class ProgCall(Prog):
  1.1058 -    name = "call"
  1.1059 -    info = "Call xend api functions."
  1.1060 +    dom = args[0]
  1.1061 +    from xen.xend.XendClient import server
  1.1062 +    info = server.xend_domain(dom)
  1.1063 +    domid = int(sxp.child_value(info, 'id', '-1'))
  1.1064 +    cmd = "/usr/libexec/xen/xenconsole %d" % domid
  1.1065 +    os.execvp('/usr/libexec/xen/xenconsole', cmd.split())
  1.1066 +    console = sxp.child(info, "console")
  1.1067  
  1.1068 -    def help (self, args):
  1.1069 -        print args[0], "function args..."
  1.1070 -        print """
  1.1071 -        Call a xend HTTP API function. The leading 'xend_' on the function
  1.1072 -can be omitted. See xen.xend.XendClient for the API functions.
  1.1073 -"""
  1.1074 -
  1.1075 -    def main(self, args):
  1.1076 -        xend_client_main(args)
  1.1077 -
  1.1078 -xm.prog(ProgCall)
  1.1079 -
  1.1080 -class ProgDmesg(Prog):
  1.1081 -    group = 'host'
  1.1082 -    name  =  "dmesg"
  1.1083 -    info  = """Read or clear Xen's message buffer."""
  1.1084 -
  1.1085 +def xm_dmesg(args):
  1.1086 +    
  1.1087      gopts = Opts(use="""[-c|--clear]
  1.1088  
  1.1089  Read Xen's message buffer (boot output, warning and error messages) or clear
  1.1090 @@ -744,161 +455,212 @@ its contents if the [-c|--clear] flag is
  1.1091      gopts.opt('clear', short='c',
  1.1092                fn=set_true, default=0,
  1.1093                use="Clear the contents of the Xen message buffer.")
  1.1094 -
  1.1095 -    short_options = ['-c']
  1.1096 -    long_options = ['--clear']
  1.1097 +    # Work around for gopts
  1.1098 +    args.insert(0,"bogus")
  1.1099 +    gopts.parse(args)
  1.1100 +    if not (1 <= len(args) <= 2):
  1.1101 +        err('Invalid arguments: ' + str(args))
  1.1102  
  1.1103 -    def help(self, args):
  1.1104 -        self.gopts.argv = args
  1.1105 -        self.gopts.usage()
  1.1106 -
  1.1107 -    def main(self, args):
  1.1108 -        self.gopts.parse(args)
  1.1109 -        if not (1 <= len(args) <=2):
  1.1110 -            self.gopts.err('Invalid arguments: ' + str(args))
  1.1111 +    from xen.xend.XendClient import server
  1.1112 +    if not gopts.vals.clear:
  1.1113 +        print server.xend_node_get_dmesg()
  1.1114 +    else:
  1.1115 +        server.xend_node_clear_dmesg()
  1.1116  
  1.1117 -        if not self.gopts.vals.clear:
  1.1118 -            print server.xend_node_get_dmesg()
  1.1119 -        else:
  1.1120 -            server.xend_node_clear_dmesg()
  1.1121 -
  1.1122 -xm.prog(ProgDmesg)
  1.1123 +def xm_log(args):
  1.1124 +    from xen.xend.XendClient import server
  1.1125 +    print server.xend_node_log()
  1.1126  
  1.1127 -class ProgLog(Prog):
  1.1128 -    group = 'host'
  1.1129 -    name  =  "log"
  1.1130 -    info  = """Print the xend log."""
  1.1131 +def xm_network_limit(args):
  1.1132 +    arg_check(args,4,"network-limit")
  1.1133 +    dom = args[0]
  1.1134 +    v = map(int, args[1:4])
  1.1135 +    from xen.xend.XendClient import server
  1.1136 +    server.xend_domain_vif_limit(dom, *v)
  1.1137  
  1.1138 -    def main(self, args):
  1.1139 -        print server.xend_node_log()
  1.1140 -
  1.1141 -xm.prog(ProgLog)
  1.1142 +def xm_network_list(args):
  1.1143 +    arg_check(args,1,"network-list")
  1.1144 +    dom = args[0]
  1.1145 +    from xen.xend.XendClient import server
  1.1146 +    for x in server.xend_domain_devices(dom, 'vif'):
  1.1147 +        sxp.show(x)
  1.1148 +        print
  1.1149  
  1.1150 -class ProgVifCreditLimit(Prog):
  1.1151 -    group = 'vif'
  1.1152 -    name= "vif-limit"
  1.1153 -    info = """Limit the transmission rate of a virtual network interface."""
  1.1154 +def xm_block_list(args):
  1.1155 +    arg_check(args,1,"block-list")
  1.1156 +    dom = args[0]
  1.1157 +    from xen.xend.XendClient import server
  1.1158 +    for x in server.xend_domain_devices(dom, 'vbd'):
  1.1159 +        sxp.show(x)
  1.1160 +        print
  1.1161  
  1.1162 -    def help(self, args):
  1.1163 -        print args[0], "DOMAIN VIF CREDIT_IN_BYTES PERIOD_IN_USECS"
  1.1164 -        print "\nSet the credit limit of a virtual network interface."
  1.1165 -
  1.1166 -    def main(self, args):
  1.1167 -        if len(args) != 5: self.err("%s: Invalid argument(s)" % args[0])
  1.1168 -        dom = args[1]
  1.1169 -        v = map(int, args[2:5])
  1.1170 -        server.xend_domain_vif_limit(dom, *v)
  1.1171 -
  1.1172 -xm.prog(ProgVifCreditLimit)
  1.1173 +def xm_block_create(args):
  1.1174 +    n = len(args)
  1.1175 +    if n < 4 or n > 5:
  1.1176 +        err("%s: Invalid argument(s)" % args[0])
  1.1177 +        usage("block-create")
  1.1178  
  1.1179 -class ProgVifList(Prog):
  1.1180 -    group = 'vif'
  1.1181 -    name  = 'vif-list'
  1.1182 -    info  = """List virtual network interfaces for a domain."""
  1.1183 +    dom = args[0]
  1.1184 +    vbd = ['vbd',
  1.1185 +           ['uname', args[1]],
  1.1186 +           ['dev',   args[2]],
  1.1187 +           ['mode',  args[3]]]
  1.1188 +    if n == 5:
  1.1189 +        vbd.append(['backend', args[4]])
  1.1190  
  1.1191 -    def help(self, args):
  1.1192 -        print args[0], "DOM"
  1.1193 -        print "\nList virtual network interfaces for domain DOM"
  1.1194 +    from xen.xend.XendClient import server
  1.1195 +    server.xend_domain_device_create(dom, vbd)
  1.1196 +
  1.1197 +def xm_block_refresh(args):
  1.1198 +    arg_check(args,2,"block-refresh")
  1.1199  
  1.1200 -    def main(self, args):
  1.1201 -        if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
  1.1202 -        dom = args[1]
  1.1203 -        for x in server.xend_domain_devices(dom, 'vif'):
  1.1204 -            sxp.show(x)
  1.1205 -            print
  1.1206 +    dom = args[0]
  1.1207 +    dev = args[1]
  1.1208 +
  1.1209 +    from xen.xend.XendClient import server
  1.1210 +    server.xend_domain_device_refresh(dom, 'vbd', dev)
  1.1211  
  1.1212 -xm.prog(ProgVifList)
  1.1213 +def xm_block_destroy(args):
  1.1214 +    arg_check(args,2,"block-destroy")
  1.1215 +
  1.1216 +    dom = args[0]
  1.1217 +    dev = args[1]
  1.1218 +
  1.1219 +    from xen.xend.XendClient import server
  1.1220 +    server.xend_domain_device_destroy(dom, 'vbd', dev)
  1.1221  
  1.1222 -class ProgVbdList(Prog):
  1.1223 -    group = 'vbd'
  1.1224 -    name  = 'vbd-list'
  1.1225 -    info  = """List virtual block devices for a domain."""
  1.1226 -
  1.1227 -    def help(self, args):
  1.1228 -        print args[0], "DOM"
  1.1229 -        print "\nList virtual block devices for domain DOM"
  1.1230 -
  1.1231 -    def main(self, args):
  1.1232 -        if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
  1.1233 -        dom = args[1]
  1.1234 -        for x in server.xend_domain_devices(dom, 'vbd'):
  1.1235 -            sxp.show(x)
  1.1236 -            print
  1.1237 +commands = {
  1.1238 +    # console commands
  1.1239 +    "console": xm_console,
  1.1240 +    # domain commands
  1.1241 +    "domid": xm_domid,
  1.1242 +    "domname": xm_domname,
  1.1243 +    "create": xm_create,
  1.1244 +    "destroy": xm_destroy,
  1.1245 +    "restore": xm_restore,
  1.1246 +    "save": xm_save,
  1.1247 +    "shutdown": xm_shutdown,
  1.1248 +    "reboot": xm_reboot,
  1.1249 +    "list": xm_list,
  1.1250 +    # memory commands
  1.1251 +    "mem-max": xm_mem_max,
  1.1252 +    "mem-set": xm_mem_set,
  1.1253 +    # cpu commands
  1.1254 +    "cpus-set": xm_cpus_set,
  1.1255 +#    "cpus-list": xm_cpus_list,
  1.1256 +    "vcpu-enable": xm_vcpu_enable,
  1.1257 +    "vcpu-disable": xm_vcpu_disable,
  1.1258 +    "vcpu-list": xm_vcpu_list,
  1.1259 +    # migration
  1.1260 +    "migrate": xm_migrate,
  1.1261 +    # special
  1.1262 +    "sysrq": xm_sysrq,
  1.1263 +    "pause": xm_pause,
  1.1264 +    "unpause": xm_unpause,
  1.1265 +    # host commands
  1.1266 +    "dmesg": xm_dmesg,
  1.1267 +    "info": xm_info,
  1.1268 +    "log": xm_log,
  1.1269 +    # scheduler
  1.1270 +    "bvt": xm_bvt,
  1.1271 +    "bvt_ctxallow": xm_bvt_ctxallow,
  1.1272 +    "sedf": xm_sedf,
  1.1273 +    # block
  1.1274 +    "block-create": xm_block_create,
  1.1275 +    "block-destroy": xm_block_destroy,
  1.1276 +    "block-list": xm_block_list,
  1.1277 +    "block-refresh": xm_block_refresh,
  1.1278 +    # network
  1.1279 +    "network-limit": xm_network_limit,
  1.1280 +    "network-list": xm_network_list
  1.1281 +    }
  1.1282  
  1.1283 -xm.prog(ProgVbdList)
  1.1284 -
  1.1285 -class ProgVbdCreate(Prog):
  1.1286 -    group = 'vbd'
  1.1287 -    name  = 'vbd-create'
  1.1288 -    info = """Create a new virtual block device for a domain"""
  1.1289 +aliases = {
  1.1290 +    "balloon": "mem-set",
  1.1291 +    "vif-list": "network-list",
  1.1292 +    "vif-limit": "network-limit",
  1.1293 +    "vbd-create": "block-create",
  1.1294 +    "vbd-destroy": "block-destroy",
  1.1295 +    "vbd-list": "block-list",
  1.1296 +    "vbd-refresh": "block-refresh",
  1.1297 +    }
  1.1298  
  1.1299 -    def help(self, args):
  1.1300 -        print args[0], "DOM UNAME DEV MODE [BACKEND]"
  1.1301 -        print """
  1.1302 -Create a virtual block device for a domain.
  1.1303 -
  1.1304 -  UNAME   - device to export, e.g. phy:hda2
  1.1305 -  DEV     - device name in the domain, e.g. sda1
  1.1306 -  MODE    - access mode: r for read, w for read-write
  1.1307 -  BACKEND - backend driver domain
  1.1308 -"""
  1.1309 +help = {
  1.1310 +    "--long": longhelp
  1.1311 +   }
  1.1312  
  1.1313 -    def main(self, args):
  1.1314 -        n = len(args)
  1.1315 -        if n < 5 or n > 6: self.err("%s: Invalid argument(s)" % args[0])
  1.1316 -        dom = args[1]
  1.1317 -        vbd = ['vbd',
  1.1318 -               ['uname', args[2]],
  1.1319 -               ['dev',   args[3]],
  1.1320 -               ['mode',  args[4]]]
  1.1321 -        if n == 6:
  1.1322 -            vbd.append(['backend', args[5]])
  1.1323 -        server.xend_domain_device_create(dom, vbd)
  1.1324 +def xm_lookup_cmd(cmd):
  1.1325 +    if commands.has_key(cmd):
  1.1326 +        return commands[cmd]
  1.1327 +    elif aliases.has_key(cmd):
  1.1328 +        deprecated(cmd,aliases[cmd])
  1.1329 +        return commands[aliases[cmd]]
  1.1330 +    else:
  1.1331 +        err('Sub Command %s not found!' % cmd)
  1.1332 +        usage()
  1.1333 +
  1.1334 +def deprecated(old,new):
  1.1335 +    err('Option %s is deprecated, and will be removed in future!!!' % old)
  1.1336 +    err('Option %s is the new replacement, see "xm help %s" for more info' % (new, new))
  1.1337  
  1.1338 -xm.prog(ProgVbdCreate)
  1.1339 +def usage(cmd=None):
  1.1340 +    if cmd == "full":
  1.1341 +        print fullhelp
  1.1342 +    elif help.has_key(cmd):
  1.1343 +        print help[cmd]
  1.1344 +    else:
  1.1345 +        print shorthelp
  1.1346 +    sys.exit(1)
  1.1347 +
  1.1348 +def main(argv=sys.argv):
  1.1349 +    if len(argv) < 2:
  1.1350 +        usage()
  1.1351 +    
  1.1352 +    if re.compile('-*help').match(argv[1]):
  1.1353 +	if len(argv) > 2 and help.has_key(argv[2]):
  1.1354 +	    usage(argv[2])
  1.1355 +	else:
  1.1356 +	    usage()
  1.1357 +	sys.exit(0)
  1.1358 +
  1.1359 +    cmd = xm_lookup_cmd(argv[1])
  1.1360  
  1.1361 -class ProgVbdRefresh(Prog):
  1.1362 -    group = 'vbd'
  1.1363 -    name  = 'vbd-refresh'
  1.1364 -    info = """Refresh a virtual block device for a domain"""
  1.1365 -
  1.1366 -    def help(self, args):
  1.1367 -        print args[0], "DOM DEV"
  1.1368 -        print """
  1.1369 -Refresh a virtual block device for a domain.
  1.1370 +    # strip off prog name and subcmd
  1.1371 +    args = argv[2:]
  1.1372 +    if cmd:
  1.1373 +        try:
  1.1374 +            from xen.xend.XendClient import XendError
  1.1375 +            rc = cmd(args)
  1.1376 +            if rc:
  1.1377 +                usage()
  1.1378 +        except socket.error, ex:
  1.1379 +            print >>sys.stderr, ex
  1.1380 +            err("Error connecting to xend, is xend running?")
  1.1381 +            sys.exit(1)
  1.1382 +        except IOError:
  1.1383 +            err("Most commands need root access.  Please try again as root")
  1.1384 +            sys.exit(1)
  1.1385 +        except XendError, ex:
  1.1386 +            if len(args) > 0:
  1.1387 +                handle_xend_error(argv[1], args[0], ex)
  1.1388 +            else:
  1.1389 +                print "Unexpected error:", sys.exc_info()[0]
  1.1390 +                print
  1.1391 +                print "Please report to xen-devel@lists.xensource.com"
  1.1392 +                raise
  1.1393 +        except SystemExit:
  1.1394 +            sys.exit(1)
  1.1395 +        except:
  1.1396 +            print "Unexpected error:", sys.exc_info()[0]
  1.1397 +            print
  1.1398 +            print "Please report to xen-devel@lists.xensource.com"
  1.1399 +            raise
  1.1400 +                
  1.1401 +    else:
  1.1402 +        usage()
  1.1403  
  1.1404 -  DEV     - idx field in the device information
  1.1405 -"""
  1.1406 -
  1.1407 -    def main(self, args):
  1.1408 -        if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
  1.1409 -        dom = args[1]
  1.1410 -        dev = args[2]
  1.1411 -        server.xend_domain_device_refresh(dom, 'vbd', dev)
  1.1412 -
  1.1413 -xm.prog(ProgVbdRefresh)
  1.1414 +if __name__ == "__main__":
  1.1415 +    main()
  1.1416  
  1.1417  
  1.1418 -class ProgVbdDestroy(Prog):
  1.1419 -    group = 'vbd'
  1.1420 -    name = 'vbd-destroy'
  1.1421 -    info = """Destroy a domain's virtual block device"""
  1.1422  
  1.1423 -    def help(self, args):
  1.1424 -        print args[0], "DOM DEV"
  1.1425 -        print """
  1.1426 -Destroy vbd DEV attached to domain DOM. Detaches the device
  1.1427 -from the domain, but does not destroy the device contents.
  1.1428 -The device indentifier DEV is the idx field in the device
  1.1429 -information. This is visible in 'xm vbd-list'."""
  1.1430 -
  1.1431 -    def main(self, args):
  1.1432 -        if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
  1.1433 -        dom = args[1]
  1.1434 -        dev = args[2]
  1.1435 -        server.xend_domain_device_destroy(dom, 'vbd', dev)
  1.1436 -
  1.1437 -xm.prog(ProgVbdDestroy)
  1.1438 -
  1.1439 -def main(args):
  1.1440 -    xm.main(args)