WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-tools

[Xen-tools] [PATCH] restructure xen/xm/main.py to be more straight forwa

To: xen-tools@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-tools] [PATCH] restructure xen/xm/main.py to be more straight forward
From: Sean Dague <sean@xxxxxxxxx>
Date: Mon, 8 Aug 2005 20:17:02 -0400
Delivery-date: Tue, 09 Aug 2005 00:15:13 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-tools-request@lists.xensource.com?subject=help>
List-id: Xen control tools developers <xen-tools.lists.xensource.com>
List-post: <mailto:xen-tools@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-tools>, <mailto:xen-tools-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-tools>, <mailto:xen-tools-request@lists.xensource.com?subject=unsubscribe>
Mail-followup-to: xen-tools@xxxxxxxxxxxxxxxxxxx
Sender: xen-tools-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.5.6i
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.

This is a forward port to the current tree with new console exec support. 

Signed-off-by: Sean Dague <sean@xxxxxxxxx>

Diffstat output:
 main.py | 1468 ++++++++++++++++++++++++++--------------------------------------
 1 files changed, 615 insertions(+), 853 deletions(-)

diff -r 0229efe8ffe4 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Mon Aug  8 18:43:57 2005
+++ b/tools/python/xen/xm/main.py       Mon Aug  8 17:45:18 2005
@@ -1,28 +1,113 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@xxxxxx>
+# (C) Copyright IBM Corp. 2005
+# Copyright (C) 2004 Mike Wray
+#
+# Authors:
+#     Sean Dague <sean at dague dot net>
+#     Mike Wray <mike dot wray at hp dot com>
+#
+# This software may be used and distributed according to the terms
+# of the GNU General Public License v2.  Full details on license
+# terms and conditions are included with this distribution
+
 """Grand unified management application for Xen.
 """
 import os
 import os.path
 import sys
 import commands
+import re
 from getopt import getopt
 import socket
 import warnings
 warnings.filterwarnings('ignore', category=FutureWarning)
-
 from xen.xend import PrettyPrint
 from xen.xend import sxp
-# this is a nasty place to stick this in, but required because
-# log file access is set up via a 5 deep import chain.  This
-# ensures the user sees a useful message instead of a stack trace
-if os.getuid() != 0:
-    print "xm requires root access to execute, please try again as root"
-    sys.exit(1)
-
-from xen.xend.XendClient import XendError, server
-from xen.xend.XendClient import main as xend_client_main
-from xen.xm import create, destroy, migrate, shutdown, sysrq
 from xen.xm.opts import *
+shorthelp = """Usage: xm <subcommand> [args]
+    Control, list, and manipulate Xen guest instances
+
+xm common subcommands:
+    console <DomId>         attach to console of DomId
+    create <CfgFile>        create a domain based on Config File
+    destroy <DomId>         terminate a domain immediately
+    help                    display this message
+    list [DomId, ...]       list information about domains
+    mem-max <DomId> <Mem>   set the maximum memory reservation for a domain
+    mem-set <DomId> <Mem>   adjust the current memory usage for a domain
+    migrate <DomId> <Host>  migrate a domain to another machine
+    pause <DomId>           pause execution of a domain
+    reboot <DomId>          reboot a domain
+    restore <File>          create a domain from a saved state file
+    save <DomId> <File>     save domain state (and config) to file
+    shutdown <DomId>        shutdown a domain
+    unpause <DomId>         unpause a paused domain
+
+For a complete list of subcommands run 'xm help --long'
+For more help on xm see the xm(1) man page
+For more help on xm create, see the xmdomain.cfg(5) man page"""
+
+longhelp = """Usage: xm <subcommand> [args]
+    Control, list, and manipulate Xen guest instances
+
+xm full list of subcommands:
+
+  Domain Commands:
+    console <DomId>         attach to console of DomId
+    cpus-list <DomId> <VCpu>          get the list of cpus for a VCPU
+    cpus-set <DomId> <VCpu> <CPUS>    set which cpus a VCPU can use. 
+    create  <ConfigFile>      create a domain
+    destroy <DomId>           terminate a domain immediately
+    domid   <DomName>         convert a domain name to a domain id
+    domname <DomId>           convert a domain id to a domain name
+    list                      list information about domains
+    mem-max <DomId> <Mem>     set domain maximum memory limit
+    mem-set <DomId> <Mem>     set the domain's memory dynamically
+    migrate <DomId> <Host>    migrate a domain to another machine
+    pause   <DomId>           pause execution of a domain
+    reboot   [-w|-a] <DomId>  reboot a domain
+    restore <File>            create a domain from a saved state file
+    save    <DomId> <File>    save domain state (and config) to file
+    shutdown [-w|-a] <DomId>  shutdown a domain
+    sysrq   <DomId> <letter>  send a sysrq to a domain
+    unpause <DomId>           unpause a paused domain
+    vcpu-enable <DomId> <VCPU>        disable VCPU in a domain
+    vcpu-disable <DomId> <VCPU>       enable VCPU in a domain
+    vcpu-list <DomId>                 get the list of VCPUs for a domain
+
+  Xen Host Commands:
+    dmesg   [--clear]         read or clear Xen's message buffer
+    info                      get information about the xen host
+    log                       print the xend log
+
+  Scheduler Commands:
+    bvt <options>             set BVT scheduler parameters
+    bvt_ctxallow <Allow>      set the BVT scheduler context switch allowance
+    sedf <options>            set simple EDF parameters
+
+  Virtual Device Commands:
+    block-create <DomId> <BackDev> <FrontDev> <Mode> [BackDomId]
+        Create a new virtual block device 
+    block-destroy <DomId> <DevId>  Destroy a domain's virtual block device
+    block-list    <DomId>          List virtual block devices for a domain
+    block-refresh <DomId> <DevId>  Refresh a virtual block device for a domain
+    network-limit   <DomId> <Vif> <Credit> <Period>
+        Limit the transmission rate of a virtual network interface
+    network-list    <DomId>        List virtual network interfaces for a domain
+
+For a short list of subcommands run 'xm help'
+For more help on xm see the xm(1) man page
+For more help on xm create, see the xmdomain.cfg(5) man page"""
+
+####################################################################
+#
+#  Utility functions
+#
+####################################################################
+
+def arg_check(args,num,name):
+    if len(args) < num:
+        err("'xm %s' requires %s argument(s)!\n" % (name, num))
+        usage(name)
 
 def unit(c):
     if not c.isalpha():
@@ -49,692 +134,318 @@
     else:
         return value * (base / dst_base)
 
-class Group:
-
-    name = ""
-    info = ""
-    
-    def __init__(self, xm):
-        self.xm = xm
-        self.progs = {}
-
-    def addprog(self, prog):
-        self.progs[prog.name] = prog
-
-    def getprog(self, name):
-        return self.progs.get(name)
-
-    def proglist(self):
-        kl = self.progs.keys()
-        kl.sort()
-        return [ self.getprog(k) for k in kl ]
-
-    def help(self, args):
-        if self.info:
-            print 
-            print self.info
-            print
+def err(msg):
+    print >>sys.stderr, "Error:", msg
+
+def handle_xend_error(cmd, dom, ex):
+    error = str(ex)
+    if error == "Not found" and dom != None:
+        err("Domain '%s' not found when running 'xm %s'" % (dom, cmd))
+        sys.exit(1)
+    else:
+        raise ex
+    
+
+#########################################################################
+#
+#  Main xm functions
+#
+#########################################################################
+
+def xm_create(args):
+    from xen.xm import create
+    # ugly hack because the opt parser apparently wants
+    # the subcommand name just to throw it away!
+    args.insert(0,"bogus")
+    create.main(args)
+
+def xm_save(args):
+    arg_check(args,2,"save")
+
+    dom = args[0] # TODO: should check if this exists
+    savefile = os.path.abspath(args[1])
+    
+    from xen.xend.XendClient import server
+    server.xend_domain_save(dom, savefile)
+    
+def xm_restore(args):
+    arg_check(args,1,"restore")
+
+    savefile = os.path.abspath(args[0])
+
+    from xen.xend.XendClient import server
+    info = server.xend_domain_restore(savefile)
+    PrettyPrint.prettyprint(info)
+    id = sxp.child_value(info, 'id')
+    if id is not None:
+        server.xend_domain_unpause(id)
+
+def xm_migrate(args):
+    # TODO: arg_check
+    from xen.xm import migrate
+    # ugly hack because the opt parser apparently wants
+    # the subcommand name just to throw it away!
+    args.insert(0,"bogus")
+    migrate.main(args)
+
+def xm_list(args):
+    use_long = 0
+    show_vcpus = 0
+    (options, params) = getopt(args, 'lv', ['long','vcpus'])
+    
+    n = len(params)
+    for (k, v) in options:
+        if k in ['-l', '--long']:
+            use_long = 1
+        if k in ['-v', '--vcpus']:
+            show_vcpus = 1
+
+    domsinfo = []
+    from xen.xend.XendClient import server
+    if n == 0:
+        doms = server.xend_domains()
+        doms.sort()
+    else:
+        doms = params
+    for dom in doms:
+        info = server.xend_domain(dom)
+        domsinfo.append(parse_doms_info(info))
+               
+    if use_long:
+        # this actually seems like a bad idea, as it just dumps sexp out
+        PrettyPrint.prettyprint(info)
+    elif show_vcpus:
+        xm_show_vcpus(domsinfo)
+    else:
+        xm_brief_list(domsinfo)
+
+def parse_doms_info(info):
+    dominfo = {}
+    dominfo['dom'] = int(sxp.child_value(info, 'id', '-1'))
+    dominfo['name'] = sxp.child_value(info, 'name', '??')
+    dominfo['mem'] = int(sxp.child_value(info, 'memory', '0'))
+    dominfo['cpu'] = str(sxp.child_value(info, 'cpu', '0'))
+    dominfo['vcpus'] = int(sxp.child_value(info, 'vcpus', '0'))
+    # if there is more than 1 cpu, the value doesn't mean much
+    if dominfo['vcpus'] > 1:
+        dominfo['cpu'] = '-'
+    dominfo['state'] = sxp.child_value(info, 'state', '??')
+    dominfo['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
+    # security identifiers
+    if ((int(sxp.child_value(info, 'ssidref', '0'))) != 0):
+        dominfo['ssidref1'] =  int(sxp.child_value(info, 'ssidref', '0')) & 
0xffff
+        dominfo['ssidref2'] = (int(sxp.child_value(info, 'ssidref', '0')) >> 
16) & 0xffff
+    # get out the vcpu information
+    dominfo['vcpulist'] = []
+    vcpu_to_cpu = sxp.child_value(info, 'vcpu_to_cpu', '-1').split('|')
+    cpumap = sxp.child_value(info, 'cpumap', [])
+    mask = ((int(sxp.child_value(info, 'vcpus', '0')))**2) - 1
+    count = 0
+    for cpu in vcpu_to_cpu:
+        vcpuinfo = {}
+        vcpuinfo['name']   = sxp.child_value(info, 'name', '??')
+        vcpuinfo['dom']    = int(sxp.child_value(info, 'id', '-1'))
+        vcpuinfo['vcpu']   = int(count)
+        vcpuinfo['cpu']    = int(cpu)
+        vcpuinfo['cpumap'] = int(cpumap[count])&mask
+        count = count + 1
+        dominfo['vcpulist'].append(vcpuinfo)
+    return dominfo
+        
+def xm_brief_list(domsinfo):
+    print 'Name              Id  Mem(MB)  CPU VCPU(s)  State  Time(s)'
+    for dominfo in domsinfo:
+        if dominfo.has_key("ssidref1"):
+            print ("%(name)-16s %(dom)3d  %(mem)7d  %(cpu)3s  %(vcpus)5d   
%(state)5s  %(cpu_time)7.1f     %s:%(ssidref2)02x/p:%(ssidref1)02x" % dominfo)
         else:
-            print
-        
-    def shortHelp(self, args):
-        self.help(args)
-        for p in self.proglist():
-            p.shortHelp(args)
-
-class Prog:
-    """Base class for sub-programs.
-    """
-
-    """Program group it belongs to"""
-    group = 'all'
-    """Program name."""
-    name = '??'
-    """Short program info."""
-    info = ''
-
-    def __init__(self, xm):
-        self.xm = xm
-
-    def err(self, msg):
-        self.xm.err(msg)
-
-    def help(self, args):
-        self.shortHelp(args)
-
-    def shortHelp(self, args):
-        print "%-14s %s" % (self.name, self.info)
-
-    def main(self, args):
-        """Program main entry point.
-        """
-        pass
-
-
-class ProgUnknown(Prog):
-
-    name = 'unknown'
-    info = ''
-    
-    def help(self, args):
-        self.xm.err("Unknown command: %s\nTry '%s help' for more information."
-                    % (args[0], self.xm.name))
-
-    main = help
-
-class Xm:
-    """Main application.
-    """
-
-    def __init__(self):
-        self.name = 'xm'
-        self.unknown = ProgUnknown(self)
-        self.progs = {}
-        self.groups = {}
-
-    def err(self, msg):
-        print >>sys.stderr, "Error:", msg
-        sys.exit(1)
-
-    def main(self, args):
-        try:
-            self.main_call(args)
-        except socket.error, ex:
-            print >>sys.stderr, ex
-            self.err("Error connecting to xend, is xend running?")
-        except XendError, ex:
-            self.err(str(ex))
-
-    def main_call(self, args):
-        """Main entry point. Dispatches to the progs.
-        """
-        self.name = args[0]
-        if len(args) < 2:
-               args.append('help')
-       help = self.helparg(args)
-        p = self.getprog(args[1], self.unknown)
-        if help or len(args) < 2: 
-            p.help(args[1:])
+            print ("%(name)-16s %(dom)3d  %(mem)7d  %(cpu)3s  %(vcpus)5d   
%(state)5s  %(cpu_time)7.1f" % dominfo)
+
+def xm_show_vcpus(domsinfo):
+    print 'Name              Id  VCPU  CPU  CPUMAP'
+    for dominfo in domsinfo:
+        for vcpuinfo in dominfo['vcpulist']:
+            print ("%(name)-16s %(dom)3d  %(vcpu)4d  %(cpu)3d  0x%(cpumap)x" %
+                   vcpuinfo)
+
+def xm_vcpu_list(args):
+    args.insert(0,"-v")
+    xm_list(args)
+
+def xm_destroy(args):
+    arg_check(args,1,"destroy")
+
+    from xen.xm import destroy
+    # ugly hack because the opt parser apparently wants
+    # the subcommand name just to throw it away!
+    args.insert(0,"bogus")
+    destroy.main(args)
+            
+# TODO: make reboot do the right thing, right now
+# reboot and shutdown are exactly the same
+def xm_reboot(args):
+    arg_check(args,1,"reboot")
+    # ugly hack because the opt parser apparently wants
+    # the subcommand name just to throw it away!
+    args.insert(0,"bogus")
+    from xen.xm import shutdown
+    shutdown.main(args)
+
+def xm_shutdown(args):
+    arg_check(args,1,"shutdown")
+
+    # ugly hack because the opt parser apparently wants
+    # the subcommand name just to throw it away!
+    args.insert(0,"bogus")
+    from xen.xm import shutdown
+    shutdown.main(args)
+
+def xm_sysrq(args):
+    from xen.xm import sysrq
+    # ugly hack because the opt parser apparently wants
+    # the subcommand name just to throw it away!
+    args.insert(0,"bogus")
+    sysrq.main(args)
+
+def xm_pause(args):
+    arg_check(args, 1, "pause")
+    dom = args[0]
+
+    from xen.xend.XendClient import server
+    server.xend_domain_pause(dom)
+
+def xm_unpause(args):
+    arg_check(args, 1, "unpause")
+    dom = args[0]
+
+    from xen.xend.XendClient import server
+    server.xend_domain_unpause(dom)
+
+#############################################################
+
+def cpu_make_map(cpulist):
+    cpus = []
+    cpumap = 0
+    for c in cpulist.split(','):
+        if c.find('-') != -1:
+            (x,y) = c.split('-')
+            for i in range(int(x),int(y)+1):
+                cpus.append(int(i))
         else:
-            p.main(args[1:])
-
-    def helparg(self, args):
-        for a in args:
-            if a in ['-h', '--help']:
-                return 1
-        return 0
-
-    def prog(self, pklass):
-        """Add a sub-program.
-
-        pklass  program class (Prog subclass)
-        """
-        p = pklass(self)
-        self.progs[p.name] = p
-        self.getgroup(p.group).addprog(p)
-        return p
-
-    def getprog(self, name, val=None):
-        """Get a sub-program.
-        name  Name of the sub-program (or optionally, an unambiguous
-              prefix of its name)
-        val   Default return value if no (unique) match is found
-        """
-
-        match = None
-        for progname in self.progs.keys():
-            if progname == name:
-                match = progname
-                break
-            if progname.startswith(name):
-                if not match:
-                    match = progname
-                else:
-                    return val # name is ambiguous - bail out
-
-        return self.progs.get(match, val)
-
-    def group(self, klass):
-        g = klass(self)
-        self.groups[g.name] = g
-        return g
-
-    def getgroup(self, name):
-        return self.groups[name]
-
-    def grouplist(self):
-        kl = self.groups.keys()
-        kl.sort()
-        return [ self.getgroup(k) for k in kl ]
-        
-# Create the application object, then add the sub-program classes.
-xm = Xm()
-
-class GroupAll(Group):
-
-    name = "all"
-    info = ""
-
-xm.group(GroupAll)
-
-class GroupDomain(Group):
-
-    name = "domain"
-    info = "Commands on domains:"
-    
-xm.group(GroupDomain)
-
-class GroupScheduler(Group):
-
-    name = "scheduler"
-    info = "Comands controlling scheduling:"
-
-xm.group(GroupScheduler)
-
-class GroupHost(Group):
-
-    name = "host"
-    info = "Commands related to the xen host (node):"
-
-xm.group(GroupHost)
-
-class GroupConsole(Group):
-
-    name = "console"
-    info = "Commands related to consoles:"
-
-xm.group(GroupConsole)
-
-class GroupVbd(Group):
-
-    name = "vbd"
-    info = "Commands related to virtual block devices:"
-
-xm.group(GroupVbd)
-
-class GroupVif(Group):
-
-    name = "vif"
-    info = "Commands related to virtual network interfaces:"
-
-xm.group(GroupVif)
-
-class ProgHelp(Prog):
-
-    name = "help"
-    info = "Print help."
-    
-    def help(self, args):
-        if len(args) == 2:
-            name = args[1]
-            p = self.xm.getprog(name)
-            if p:
-                p.help(args[1:])
-            else:
-                print '%s: Unknown command: %s' % (self.name, name)
-        else:
-            for g in self.xm.grouplist():
-                g.shortHelp(args)
-            print "\nTry '%s help CMD' for help on CMD" % self.xm.name
-
-    main = help
-
-xm.prog(ProgHelp)
-
-class ProgCreate(Prog):
-
-    group = 'domain'
-    name = "create"
-    info = """Create a domain."""
-
-    def help(self, args):
-        create.main([args[0], '-h'])
-
-    def main(self, args):
-        create.main(args)
-
-xm.prog(ProgCreate)
-
-class ProgSave(Prog):
-    group = 'domain'
-    name = "save"
-    info = """Save domain state (and config) to file."""
-
-    def help(self, args):
-        print args[0], "DOM FILE"
-        print """\nSave domain with id DOM to FILE."""
-        
-    def main(self, args):
-        if len(args) < 3: self.err("%s: Missing arguments" % args[0])
-        dom = args[1]
-        savefile = os.path.abspath(args[2])
-        server.xend_domain_save(dom, savefile)
-
-xm.prog(ProgSave)
-
-class ProgRestore(Prog):
-    group = 'domain'
-    name = "restore"
-    info = """Create a domain from a saved state."""
-
-    def help(self, args):
-        print args[0], "FILE"
-        print "\nRestore a domain from FILE."
-    
-    def main(self, args):
-        if len(args) < 2: self.err("%s: Missing arguments" % args[0])
-        savefile = os.path.abspath(args[1])
-        info = server.xend_domain_restore(savefile)
-        PrettyPrint.prettyprint(info)
-        id = sxp.child_value(info, 'id')
-        if id is not None:
-            server.xend_domain_unpause(id)
-
-xm.prog(ProgRestore)
-
-class ProgMigrate(Prog):
-    group = 'domain'
-    name = "migrate"
-    info = """Migrate a domain to another machine."""
-
-    def help(self, args):
-        migrate.help([self.name] + args)
-    
-    def main(self, args):
-        migrate.main(args)
-
-xm.prog(ProgMigrate)
-
-class ProgList(Prog):
-    group = 'domain'
-    name = "list"
-    info = """List information about domains."""
-
-    short_options = 'lv'
-    long_options = ['long','vcpus']
-
-    def help(self, args):
-        if help:
-            print args[0], '[options] [DOM...]'
-            print """\nGet information about domains.
-            Either all domains or the domains given.
-
-            -l, --long   Get more detailed information.
-            -v, --vcpus  Show VCPU to CPU mapping.
-            """
-            return
-        
-    def main(self, args):
-        use_long = 0
-        show_vcpus = 0
-        (options, params) = getopt(args[1:],
-                                   self.short_options,
-                                   self.long_options)
-        n = len(params)
-        for (k, v) in options:
-            if k in ['-l', '--long']:
-                use_long = 1
-            if k in ['-v', '--vcpus']:
-                show_vcpus = 1
-                
-        if n == 0:
-            doms = server.xend_domains()
-            doms.sort()
-        else:
-            doms = params
-            
-        if use_long:
-            self.long_list(doms)
-        elif show_vcpus:
-            self.show_vcpus(doms)
-        else:
-            self.brief_list(doms)
-
-    def brief_list(self, doms):
-        print 'Name              Id  Mem(MB)  CPU VCPU(s)  State  Time(s)'
-        for dom in doms:
-            info = server.xend_domain(dom)
-            d = {}
-            d['dom'] = int(sxp.child_value(info, 'id', '-1'))
-            d['name'] = sxp.child_value(info, 'name', '??')
-            d['mem'] = int(sxp.child_value(info, 'memory', '0'))
-            d['cpu'] = str(sxp.child_value(info, 'cpu', '0'))
-            d['vcpus'] = int(sxp.child_value(info, 'vcpus', '0'))
-            d['state'] = sxp.child_value(info, 'state', '??')
-            d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
-            if d['vcpus'] > 1:
-                d['cpu'] = '-'
-            if ((int(sxp.child_value(info, 'ssidref', '0'))) != 0):
-                d['ssidref1'] =  int(sxp.child_value(info, 'ssidref', '0')) & 
0xffff
-                d['ssidref2'] = (int(sxp.child_value(info, 'ssidref', '0')) >> 
16) & 0xffff
-                print ("%(name)-16s %(dom)3d  %(mem)7d  %(cpu)3s  %(vcpus)5d   
%(state)5s  %(cpu_time)7.1f     %s:%(ssidref2)02x/p:%(ssidref1)02x" % d)
-            else:
-                print ("%(name)-16s %(dom)3d  %(mem)7d  %(cpu)3s  %(vcpus)5d   
%(state)5s  %(cpu_time)7.1f" % d)
-
-    def show_vcpus(self, doms):
-        print 'Name              Id  VCPU  CPU  CPUMAP'
-        for dom in doms:
-            info = server.xend_domain(dom)
-            vcpu_to_cpu = sxp.child_value(info, 'vcpu_to_cpu', '-1').split('|')
-            cpumap = sxp.child_value(info, 'cpumap', [])
-            mask = ((int(sxp.child_value(info, 'vcpus', '0')))**2) - 1
-            count = 0
-            for cpu in vcpu_to_cpu:
-                d = {}
-                d['name']   = sxp.child_value(info, 'name', '??')
-                d['dom']    = int(sxp.child_value(info, 'id', '-1'))
-                d['vcpu']   = int(count)
-                d['cpu']    = int(cpu)
-                d['cpumap'] = int(cpumap[count])&mask
-                count = count + 1
-                print ("%(name)-16s %(dom)3d  %(vcpu)4d  %(cpu)3d  
0x%(cpumap)x" % d)
-
-    def long_list(self, doms):
-        for dom in doms:
-            info = server.xend_domain(dom)
-            PrettyPrint.prettyprint(info)
-
-xm.prog(ProgList)
-
-class ProgDestroy(Prog):
-    group = 'domain'
-    name = "destroy"
-    info = """Terminate a domain immediately."""
-
-    def help(self, args):
-        destroy.main([args[0], '-h'])
-
-    def main(self, args):
-        destroy.main(args)
-
-xm.prog(ProgDestroy)
-
-class ProgShutdown(Prog):
-    group = 'domain'
-    name = "shutdown"
-    info = """Shutdown a domain."""
-
-    def help(self, args):
-        shutdown.main([args[0], '-h'])
-    
-    def main(self, args):
-        shutdown.main(args)
-
-xm.prog(ProgShutdown)
-
-class ProgSysrq(Prog):
-    group = 'domain'
-    name = "sysrq"
-    info = """Send a sysrq to a domain."""
-
-    def help(self, args):
-        sysrq.main([args[0], '-h'])
-    
-    def main(self, args):
-        sysrq.main(args)
-
-xm.prog(ProgSysrq)
-
-class ProgPause(Prog):
-    group = 'domain'
-    name = "pause"
-    info = """Pause execution of a domain."""
-
-    def help(self, args):
-        print args[0], 'DOM'
-        print '\nPause execution of domain DOM.'
-
-    def main(self, args):
-        if len(args) < 2: self.err("%s: Missing domain" % args[0])
-        dom = args[1]
-        server.xend_domain_pause(dom)
-
-xm.prog(ProgPause)
-
-class ProgUnpause(Prog):
-    group = 'domain'
-    name = "unpause"
-    info = """Unpause a paused domain."""
-
-    def help(self, args):
-        print args[0], 'DOM'
-        print '\nUnpause execution of domain DOM.'
-
-    def main(self, args):
-        if len(args) < 2: self.err("%s: Missing domain" % args[0])
-        dom = args[1]
-        server.xend_domain_unpause(dom)
-
-xm.prog(ProgUnpause)
-
-class ProgPincpu(Prog):
-    group = 'domain'
-    name = "pincpu"
-    info = """Set which cpus a VCPU can use. """
-
-    def help(self, args):
-        print args[0],'DOM VCPU CPUS'
-        print '\nSet which cpus VCPU in domain DOM can use.'
-
-    # convert list of cpus to bitmap integer value
-    def make_map(self, cpulist):
-        cpus = []
-        cpumap = 0
-        for c in cpulist.split(','):
-            if c.find('-') != -1:
-                (x,y) = c.split('-')
-                for i in range(int(x),int(y)+1):
-                    cpus.append(int(i))
-            else:
-                cpus.append(int(c))
-        cpus.sort()
-        for c in cpus:
-            cpumap = cpumap | 1<<c
-
-        return cpumap
-
-    def main(self, args):
-        if len(args) != 4: self.err("%s: Invalid argument(s)" % args[0])
-        dom  = args[1]
-        vcpu = int(args[2])
-        cpumap  = self.make_map(args[3]);
-        server.xend_domain_pincpu(dom, vcpu, cpumap)
-
-xm.prog(ProgPincpu)
-
-class ProgMaxmem(Prog):
-    group = 'domain'
-    name = 'maxmem'
-    info = """Set domain memory limit."""
-
-    def help(self, args):
-        print args[0], "DOM MEMORY"
-        print "\nSet the memory limit for domain DOM to MEMORY megabytes."
-
-    def main(self, args):
-        if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
-        dom = args[1]
-        mem = int_unit(args[2], 'm')
-        server.xend_domain_maxmem_set(dom, mem)
-
-xm.prog(ProgMaxmem)
-
-class ProgSetMem(Prog):
-    group = 'domain'
-    name  = 'set-mem'
-    info  = """Set the domain's memory footprint using the balloon driver."""
-
-    def help(self, args):
-        print args[0], "DOM MEMORY_TARGET"
-        print """\nRequest domain DOM to adjust its memory footprint to
-MEMORY_TARGET megabytes"""
-
-    def main(self, args):
-        if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
-        dom = args[1]
-        mem_target = int_unit(args[2], 'm')
-        server.xend_domain_mem_target_set(dom, mem_target)
-
-xm.prog(ProgSetMem)
-
-class ProgVcpuhotplug(Prog):
-    group = 'domain'
-    name  = 'vcpu-hotplug'
-    info  = """Enable or disable a VCPU in a domain."""
-
-    def help(self, args):
-        print args[0], "DOM VCPU [0|1]"
-        print """\nRequest virtual processor VCPU to be disabled or enabled in
-domain DOM"""
-
-    def main(self, args):
-        if len(args) != 4: self.err("%s: Invalid arguments(s)" % args[0])
-        name = args[1]
-        vcpu = int(args[2])
-        state = int(args[3])
-        dom = server.xend_domain(name)
-        id = sxp.child_value(dom, 'id')
-        server.xend_domain_vcpu_hotplug(id, vcpu, state)
-
-xm.prog(ProgVcpuhotplug)
-
-class ProgDomid(Prog):
-    group = 'domain'
-    name = 'domid'
-    info = 'Convert a domain name to a domain id.'
-
-    def help(self, args):
-        print args[0], "DOM"
-        print '\nGet the domain id for the domain with name DOM.'
-        
-    def main (self, args):
-        if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
-        name = args[1]
-        dom = server.xend_domain(name)
-        print sxp.child_value(dom, 'id')
-
-xm.prog(ProgDomid)
-
-class ProgDomname(Prog):
-    group = 'domain'
-    name = 'domname'
-    info = 'Convert a domain id to a domain name.'
-
-    def help(self, args):
-        print args[0], "DOM"
-        print '\nGet the name for the domain with id DOM.'
-        
-    def main (self, args):
-        if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
-        name = args[1]
-        dom = server.xend_domain(name)
-        print sxp.child_value(dom, 'name')
-
-xm.prog(ProgDomname)
-
-class ProgBvt(Prog):
-    group = 'scheduler'
-    name = "bvt"
-    info = """Set BVT scheduler parameters."""
-    
-    def help(self, args):
-        print args[0], "DOM MCUADV WARPBACK WARPVALUE WARPL WARPU"
-        print '\nSet Borrowed Virtual Time scheduler parameters.'
-
-    def main(self, args):
-        if len(args) != 7: self.err("%s: Invalid argument(s)" % args[0])
-        dom = args[1]
-        v = map(long, args[2:7])
-        server.xend_domain_cpu_bvt_set(dom, *v)
-
-xm.prog(ProgBvt)
-
-class ProgBvtslice(Prog):
-    group = 'scheduler'
-    name = "bvt_ctxallow"
-    info = """Set the BVT scheduler context switch allowance."""
-
-    def help(self, args):
-        print args[0], 'CTX_ALLOW'
-        print '\nSet Borrowed Virtual Time scheduler context switch allowance.'
-
-    def main(self, args):
-        if len(args) < 2: self.err('%s: Missing context switch allowance'
-                                                            % args[0])
-        slice = int(args[1])
-        server.xend_node_cpu_bvt_slice_set(slice)
-
-xm.prog(ProgBvtslice)
-
-class ProgSedf(Prog):
-    group = 'scheduler'
-    name= "sedf"
-    info = """Set simple EDF parameters."""
-
-    def help(self, args):
-        print args[0], "DOM PERIOD SLICE LATENCY EXTRATIME WEIGHT"
-        print "\nSet simple EDF parameters."
-
-    def main(self, args):
-       if len(args) != 7: self.err("%s: Invalid argument(s)" % args[0])
-       dom = args[1]
-       v = map(int, args[2:7])
-       server.xend_domain_cpu_sedf_set(dom, *v)
-
-xm.prog(ProgSedf)
-
-class ProgInfo(Prog):
-    group = 'host'
-    name = "info"
-    info = """Get information about the xen host."""
-
-    def main(self, args):
-        info = server.xend_node()
-        for x in info[1:]:
-            print "%-23s:" % x[0], x[1]
-
-xm.prog(ProgInfo)
-
-class ProgConsole(Prog):
-    group = 'console'
-    name = "console"
-    info = """Open a console to a domain."""
-    
-    def help(self, args):
-        print args[0], "DOM"
-        print "\nOpen a console to domain DOM."
-
-    def main(self, args):
-        if len(args) < 2: self.err("%s: Missing domain" % args[0])
-        dom = args[1]
-        info = server.xend_domain(dom)
-        domid = int(sxp.child_value(info, 'id', '-1'))
-        cmd = "/usr/libexec/xen/xenconsole %d" % domid
-        os.execvp('/usr/libexec/xen/xenconsole', cmd.split())
-
-xm.prog(ProgConsole)
-
-class ProgCall(Prog):
-    name = "call"
-    info = "Call xend api functions."
-
-    def help (self, args):
-        print args[0], "function args..."
-        print """
-        Call a xend HTTP API function. The leading 'xend_' on the function
-can be omitted. See xen.xend.XendClient for the API functions.
-"""
-
-    def main(self, args):
-        xend_client_main(args)
-
-xm.prog(ProgCall)
-
-class ProgDmesg(Prog):
-    group = 'host'
-    name  =  "dmesg"
-    info  = """Read or clear Xen's message buffer."""
-
+            cpus.append(int(c))
+    cpus.sort()
+    for c in cpus:
+        cpumap = cpumap | 1<<c
+
+    return cpumap
+
+def xm_cpus_set(args):
+    arg_check(args, 3, "cpus-set")
+    
+    dom  = args[0]
+    vcpu = int(args[1])
+    cpumap = cpu_make_map(args[2])
+    
+    from xen.xend.XendClient import server
+    server.xend_domain_pincpu(dom, vcpu, cpumap)
+
+def xm_mem_max(args):
+    arg_check(args, 2, "mem-max")
+    
+    dom = args[0]
+    mem = int_unit(args[1], 'm')
+
+    from xen.xend.XendClient import server
+    server.xend_domain_maxmem_set(dom, mem)
+    
+def xm_mem_set(args):
+    arg_check(args, 2, "mem-set")
+    
+    dom = args[0]
+    mem_target = int_unit(args[1], 'm')
+
+    from xen.xend.XendClient import server
+    server.xend_domain_mem_target_set(dom, mem_target)
+    
+# TODO: why does this lookup by name?  and what if that fails!?
+def xm_vcpu_enable(args):
+    arg_check(args, 2, "vcpu-enable")
+    
+    name = args[0]
+    vcpu = int(args[1])
+    
+    from xen.xend.XendClient import server
+    dom = server.xend_domain(name)
+    id = sxp.child_value(dom, 'id')
+    server.xend_domain_vcpu_hotplug(id, vcpu, 1)
+
+def xm_vcpu_disable(args):
+    arg_check(args, 2, "vcpu-disable")
+    
+    name = args[0]
+    vcpu = int(args[1])
+    
+    from xen.xend.XendClient import server
+    dom = server.xend_domain(name)
+    id = sxp.child_value(dom, 'id')
+    server.xend_domain_vcpu_hotplug(id, vcpu, 0)
+
+def xm_domid(args):
+    name = args[0]
+
+    from xen.xend.XendClient import server
+    dom = server.xend_domain(name)
+    print sxp.child_value(dom, 'id')
+    
+def xm_domname(args):
+    name = args[0]
+
+    from xen.xend.XendClient import server
+    dom = server.xend_domain(name)
+    print sxp.child_value(dom, 'name')
+
+def xm_bvt(args):
+    arg_check(args, 6, "bvt")
+    dom = args[0]
+    v = map(long, args[1:6])
+    from xen.xend.XendClient import server
+    server.xend_domain_cpu_bvt_set(dom, *v)
+
+def xm_bvt_ctxallow(args):
+    arg_check(args, 1, "bvt_ctxallow")
+
+    slice = int(args[0])
+    from xen.xend.XendClient import server
+    server.xend_node_cpu_bvt_slice_set(slice)
+
+def xm_sedf(args):
+    arg_check(args, 6, "sedf")
+    
+    dom = args[0]
+    v = map(int, args[1:5])
+    from xen.xend.XendClient import server
+    server.xend_domain_cpu_sedf_set(dom, *v)
+
+def xm_info(args):
+    from xen.xend.XendClient import server
+    info = server.xend_node()
+    
+    for x in info[1:]:
+        print "%-23s:" % x[0], x[1]
+
+# TODO: remove as soon as console server shows up
+def xm_console(args):
+    arg_check(args,1,"console")
+
+    dom = args[0]
+    from xen.xend.XendClient import server
+    info = server.xend_domain(dom)
+    domid = int(sxp.child_value(info, 'id', '-1'))
+    cmd = "/usr/libexec/xen/xenconsole %d" % domid
+    os.execvp('/usr/libexec/xen/xenconsole', cmd.split())
+    console = sxp.child(info, "console")
+
+def xm_dmesg(args):
+    
     gopts = Opts(use="""[-c|--clear]
 
 Read Xen's message buffer (boot output, warning and error messages) or clear
@@ -744,161 +455,212 @@
     gopts.opt('clear', short='c',
               fn=set_true, default=0,
               use="Clear the contents of the Xen message buffer.")
-
-    short_options = ['-c']
-    long_options = ['--clear']
-
-    def help(self, args):
-        self.gopts.argv = args
-        self.gopts.usage()
-
-    def main(self, args):
-        self.gopts.parse(args)
-        if not (1 <= len(args) <=2):
-            self.gopts.err('Invalid arguments: ' + str(args))
-
-        if not self.gopts.vals.clear:
-            print server.xend_node_get_dmesg()
-        else:
-            server.xend_node_clear_dmesg()
-
-xm.prog(ProgDmesg)
-
-class ProgLog(Prog):
-    group = 'host'
-    name  =  "log"
-    info  = """Print the xend log."""
-
-    def main(self, args):
-        print server.xend_node_log()
-
-xm.prog(ProgLog)
-
-class ProgVifCreditLimit(Prog):
-    group = 'vif'
-    name= "vif-limit"
-    info = """Limit the transmission rate of a virtual network interface."""
-
-    def help(self, args):
-        print args[0], "DOMAIN VIF CREDIT_IN_BYTES PERIOD_IN_USECS"
-        print "\nSet the credit limit of a virtual network interface."
-
-    def main(self, args):
-        if len(args) != 5: self.err("%s: Invalid argument(s)" % args[0])
-        dom = args[1]
-        v = map(int, args[2:5])
-        server.xend_domain_vif_limit(dom, *v)
-
-xm.prog(ProgVifCreditLimit)
-
-class ProgVifList(Prog):
-    group = 'vif'
-    name  = 'vif-list'
-    info  = """List virtual network interfaces for a domain."""
-
-    def help(self, args):
-        print args[0], "DOM"
-        print "\nList virtual network interfaces for domain DOM"
-
-    def main(self, args):
-        if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
-        dom = args[1]
-        for x in server.xend_domain_devices(dom, 'vif'):
-            sxp.show(x)
+    # Work around for gopts
+    args.insert(0,"bogus")
+    gopts.parse(args)
+    if not (1 <= len(args) <= 2):
+        err('Invalid arguments: ' + str(args))
+
+    from xen.xend.XendClient import server
+    if not gopts.vals.clear:
+        print server.xend_node_get_dmesg()
+    else:
+        server.xend_node_clear_dmesg()
+
+def xm_log(args):
+    from xen.xend.XendClient import server
+    print server.xend_node_log()
+
+def xm_network_limit(args):
+    arg_check(args,4,"network-limit")
+    dom = args[0]
+    v = map(int, args[1:4])
+    from xen.xend.XendClient import server
+    server.xend_domain_vif_limit(dom, *v)
+
+def xm_network_list(args):
+    arg_check(args,1,"network-list")
+    dom = args[0]
+    from xen.xend.XendClient import server
+    for x in server.xend_domain_devices(dom, 'vif'):
+        sxp.show(x)
+        print
+
+def xm_block_list(args):
+    arg_check(args,1,"block-list")
+    dom = args[0]
+    from xen.xend.XendClient import server
+    for x in server.xend_domain_devices(dom, 'vbd'):
+        sxp.show(x)
+        print
+
+def xm_block_create(args):
+    n = len(args)
+    if n < 4 or n > 5:
+        err("%s: Invalid argument(s)" % args[0])
+        usage("block-create")
+
+    dom = args[0]
+    vbd = ['vbd',
+           ['uname', args[1]],
+           ['dev',   args[2]],
+           ['mode',  args[3]]]
+    if n == 5:
+        vbd.append(['backend', args[4]])
+
+    from xen.xend.XendClient import server
+    server.xend_domain_device_create(dom, vbd)
+
+def xm_block_refresh(args):
+    arg_check(args,2,"block-refresh")
+
+    dom = args[0]
+    dev = args[1]
+
+    from xen.xend.XendClient import server
+    server.xend_domain_device_refresh(dom, 'vbd', dev)
+
+def xm_block_destroy(args):
+    arg_check(args,2,"block-destroy")
+
+    dom = args[0]
+    dev = args[1]
+
+    from xen.xend.XendClient import server
+    server.xend_domain_device_destroy(dom, 'vbd', dev)
+
+commands = {
+    # console commands
+    "console": xm_console,
+    # domain commands
+    "domid": xm_domid,
+    "domname": xm_domname,
+    "create": xm_create,
+    "destroy": xm_destroy,
+    "restore": xm_restore,
+    "save": xm_save,
+    "shutdown": xm_shutdown,
+    "reboot": xm_reboot,
+    "list": xm_list,
+    # memory commands
+    "mem-max": xm_mem_max,
+    "mem-set": xm_mem_set,
+    # cpu commands
+    "cpus-set": xm_cpus_set,
+#    "cpus-list": xm_cpus_list,
+    "vcpu-enable": xm_vcpu_enable,
+    "vcpu-disable": xm_vcpu_disable,
+    "vcpu-list": xm_vcpu_list,
+    # migration
+    "migrate": xm_migrate,
+    # special
+    "sysrq": xm_sysrq,
+    "pause": xm_pause,
+    "unpause": xm_unpause,
+    # host commands
+    "dmesg": xm_dmesg,
+    "info": xm_info,
+    "log": xm_log,
+    # scheduler
+    "bvt": xm_bvt,
+    "bvt_ctxallow": xm_bvt_ctxallow,
+    "sedf": xm_sedf,
+    # block
+    "block-create": xm_block_create,
+    "block-destroy": xm_block_destroy,
+    "block-list": xm_block_list,
+    "block-refresh": xm_block_refresh,
+    # network
+    "network-limit": xm_network_limit,
+    "network-list": xm_network_list
+    }
+
+aliases = {
+    "balloon": "mem-set",
+    "vif-list": "network-list",
+    "vif-limit": "network-limit",
+    "vbd-create": "block-create",
+    "vbd-destroy": "block-destroy",
+    "vbd-list": "block-list",
+    "vbd-refresh": "block-refresh",
+    }
+
+help = {
+    "--long": longhelp
+   }
+
+def xm_lookup_cmd(cmd):
+    if commands.has_key(cmd):
+        return commands[cmd]
+    elif aliases.has_key(cmd):
+        deprecated(cmd,aliases[cmd])
+        return commands[aliases[cmd]]
+    else:
+        err('Sub Command %s not found!' % cmd)
+        usage()
+
+def deprecated(old,new):
+    err('Option %s is deprecated, and will be removed in future!!!' % old)
+    err('Option %s is the new replacement, see "xm help %s" for more info' % 
(new, new))
+
+def usage(cmd=None):
+    if cmd == "full":
+        print fullhelp
+    elif help.has_key(cmd):
+        print help[cmd]
+    else:
+        print shorthelp
+    sys.exit(1)
+
+def main(argv=sys.argv):
+    if len(argv) < 2:
+        usage()
+    
+    if re.compile('-*help').match(argv[1]):
+       if len(argv) > 2 and help.has_key(argv[2]):
+           usage(argv[2])
+       else:
+           usage()
+       sys.exit(0)
+
+    cmd = xm_lookup_cmd(argv[1])
+
+    # strip off prog name and subcmd
+    args = argv[2:]
+    if cmd:
+        try:
+            from xen.xend.XendClient import XendError
+            rc = cmd(args)
+            if rc:
+                usage()
+        except socket.error, ex:
+            print >>sys.stderr, ex
+            err("Error connecting to xend, is xend running?")
+            sys.exit(1)
+        except IOError:
+            err("Most commands need root access.  Please try again as root")
+            sys.exit(1)
+        except XendError, ex:
+            if len(args) > 0:
+                handle_xend_error(argv[1], args[0], ex)
+            else:
+                print "Unexpected error:", sys.exc_info()[0]
+                print
+                print "Please report to xen-devel@xxxxxxxxxxxxxxxxxxx"
+                raise
+        except SystemExit:
+            sys.exit(1)
+        except:
+            print "Unexpected error:", sys.exc_info()[0]
             print
-
-xm.prog(ProgVifList)
-
-class ProgVbdList(Prog):
-    group = 'vbd'
-    name  = 'vbd-list'
-    info  = """List virtual block devices for a domain."""
-
-    def help(self, args):
-        print args[0], "DOM"
-        print "\nList virtual block devices for domain DOM"
-
-    def main(self, args):
-        if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
-        dom = args[1]
-        for x in server.xend_domain_devices(dom, 'vbd'):
-            sxp.show(x)
-            print
-
-xm.prog(ProgVbdList)
-
-class ProgVbdCreate(Prog):
-    group = 'vbd'
-    name  = 'vbd-create'
-    info = """Create a new virtual block device for a domain"""
-
-    def help(self, args):
-        print args[0], "DOM UNAME DEV MODE [BACKEND]"
-        print """
-Create a virtual block device for a domain.
-
-  UNAME   - device to export, e.g. phy:hda2
-  DEV     - device name in the domain, e.g. sda1
-  MODE    - access mode: r for read, w for read-write
-  BACKEND - backend driver domain
-"""
-
-    def main(self, args):
-        n = len(args)
-        if n < 5 or n > 6: self.err("%s: Invalid argument(s)" % args[0])
-        dom = args[1]
-        vbd = ['vbd',
-               ['uname', args[2]],
-               ['dev',   args[3]],
-               ['mode',  args[4]]]
-        if n == 6:
-            vbd.append(['backend', args[5]])
-        server.xend_domain_device_create(dom, vbd)
-
-xm.prog(ProgVbdCreate)
-
-class ProgVbdRefresh(Prog):
-    group = 'vbd'
-    name  = 'vbd-refresh'
-    info = """Refresh a virtual block device for a domain"""
-
-    def help(self, args):
-        print args[0], "DOM DEV"
-        print """
-Refresh a virtual block device for a domain.
-
-  DEV     - idx field in the device information
-"""
-
-    def main(self, args):
-        if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
-        dom = args[1]
-        dev = args[2]
-        server.xend_domain_device_refresh(dom, 'vbd', dev)
-
-xm.prog(ProgVbdRefresh)
-
-
-class ProgVbdDestroy(Prog):
-    group = 'vbd'
-    name = 'vbd-destroy'
-    info = """Destroy a domain's virtual block device"""
-
-    def help(self, args):
-        print args[0], "DOM DEV"
-        print """
-Destroy vbd DEV attached to domain DOM. Detaches the device
-from the domain, but does not destroy the device contents.
-The device indentifier DEV is the idx field in the device
-information. This is visible in 'xm vbd-list'."""
-
-    def main(self, args):
-        if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
-        dom = args[1]
-        dev = args[2]
-        server.xend_domain_device_destroy(dom, 'vbd', dev)
-
-xm.prog(ProgVbdDestroy)
-
-def main(args):
-    xm.main(args)
+            print "Please report to xen-devel@xxxxxxxxxxxxxxxxxxx"
+            raise
+                
+    else:
+        usage()
+
+if __name__ == "__main__":
+    main()
+
+
+


-- 
__________________________________________________________________

Sean Dague                                       Mid-Hudson Valley
sean at dague dot net                            Linux Users Group
http://dague.net                                 http://mhvlug.org

There is no silver bullet.  Plus, werewolves make better neighbors
than zombies, and they tend to keep the vampire population down.
__________________________________________________________________

Attachment: pgpoxVr8KtzVE.pgp
Description: PGP signature

_______________________________________________
Xen-tools mailing list
Xen-tools@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-tools
<Prev in Thread] Current Thread [Next in Thread>