[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] The following patch is a major restructuring of main.py to be more straight forward, and remove as much code as possible.



# HG changeset patch
# User cl349@xxxxxxxxxxxxxxxxxxxx
# Node ID 3cd4f2c38aaf8e3b2fd01452db3f5aed5f7c2482
# Parent  663f0fb1e444239bae280d2867b80cea3f4bf7c1
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@xxxxxxxxx>
Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>

diff -r 663f0fb1e444 -r 3cd4f2c38aaf tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Tue Aug  9 09:34:06 2005
+++ b/tools/python/xen/xm/main.py       Tue Aug  9 12:50:22 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()
+
+
+

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.