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

[Xen-devel] [PATCH 1/8] [xm] Domain Groups: xm group commands



xm:

1. Add the following commands: grp-create, grp-shutdown, grp-destroy,
grp-join, grp-pause, grp-unpause, grp-reboot, grp-save, grp-restore,
grp-migrate, grp-list

2. Add example group configuration file and parsing mechanism.




diff -r ecb6cd61a9cf tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Tue Feb 20 12:27:03 2007 +0000
+++ b/tools/python/xen/xm/create.py     Tue Feb 20 12:59:11 2007 -0500
@@ -489,6 +489,11 @@ gopts.var('on_xend_stop', val='continue|
           - shutdown:       Domain is shutdown;
           - suspend:        Domain is suspended;
           """)
+
+gopts.var('dgid', val='NUM',
+          fn=set_int, default=32767,
+          use='Default domain group to join.')
+
 
 def err(msg):
     """Print an error to stderr and exit.
@@ -749,6 +754,8 @@ def make_config(vals):
         config.append(['backend', ['tpmif']])
     if vals.localtime:
         config.append(['localtime', vals.localtime])
+    if vals.dgid is not None:
+        config.append(['dgid', vals.dgid])
 
     config_image = configure_image(vals)
     if vals.bootloader:
@@ -1268,6 +1275,7 @@ def main(argv):
                     print("Could not start console\n");
                     sys.exit(0)
             dom = make_domain(opts, config)
+            return dom
 
 
 if __name__ == '__main__':
diff -r ecb6cd61a9cf tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Tue Feb 20 12:27:03 2007 +0000
+++ b/tools/python/xen/xm/main.py       Tue Feb 20 12:59:11 2007 -0500
@@ -50,6 +50,7 @@ from xen.xm import console
 from xen.xm import console
 from xen.util import security
 from xen.util.xmlrpclib2 import ServerProxy
+from xen.xm import group
 
 import XenAPI
 
@@ -184,6 +185,25 @@ SUBCOMMAND_HELP = {
     'labels'        :  ('[policy] [type=dom|res|any]',
                         'List <type> labels for (active) policy.'),
     'serve'         :  ('', 'Proxy Xend XMLRPC over stdio.'),
+
+    # domain groups
+
+    'grp-create'    :  ('<config> [--managed | -m]','Create a domain group'),
+    'grp-shutdown'  :  ('<grp> [--keep| -k]','Shutdown all domains in group'),
+    'grp-destroy'   :  ('<grp> [--force | -f]','Destroy group'),
+    'grp-reboot'    :  ('<grp>','Reboot all domains in group'),
+    'grp-pause'     :  ('<grp>','Pause all domains in group'),
+    'grp-unpause'   :  ('<grp>','Unpause all domains in group'),
+    'grp-save'      :  ('<grp> <prefix>','Save all domains in group to ' 
+                        'files with the specified prefix'),
+    'grp-restore'   :  ('<CheckpointFile> [CheckpointFile ...]',
+                        'Restore all domains in group from file(s)'),
+    'grp-suspend'   :  ('<grp>','Suspend all domains in group'),
+    'grp-resume'    :  ('<grp>','Resume all domains in group'),
+    'grp-migrate'   :  ('<grp> <host> [--live | -l]',
+                        'Migrate all domains in group to host'),
+    'grp-join'      :  ('<dom> <grp>','Add domain to group'),
+    'grp-list'      :  ('','List groups and their members'),
 }
 
 SUBCOMMAND_OPTIONS = {
@@ -292,6 +312,20 @@ domain_commands = [
     "vcpu-set",
     ]
 
+group_commands = [
+    "grp-create",
+    "grp-shutdown",
+    "grp-destroy",
+    "grp-reboot",
+    "grp-pause",
+    "grp-unpause",
+    "grp-suspend",
+    "grp-resume",
+    "grp-migrate",
+    "grp-join",
+    "grp-list",
+]
+
 host_commands = [
     "dmesg",
     "info",
@@ -335,7 +369,8 @@ acm_commands = [
     ]
 
 all_commands = (domain_commands + host_commands + scheduler_commands +
-                device_commands + vnet_commands + acm_commands + ['shell'])
+                device_commands + vnet_commands + acm_commands + ['shell'] +
+                group_commands )
 
 
 ##
@@ -482,12 +517,17 @@ def usage(cmd = None):
 #
 ####################################################################
 
-def arg_check(args, name, lo, hi = -1):
+def arg_check(args, name, lo, hi = None):
     n = len([i for i in args if i != '--'])
     
-    if hi == -1:
+    if hi == None:
         if n != lo:
             err("'xm %s' requires %d argument%s.\n" % (name, lo,
+                                                       lo == 1 and '' or 's'))
+            usage(name)
+    elif hi == -1:
+        if n < lo:
+            err("'xm %s' requires at least %d argument%s.\n" % (name, lo,
                                                        lo == 1 and '' or 's'))
             usage(name)
     else:
@@ -694,6 +734,7 @@ def parse_doms_info(info):
 
     return {
         'domid'    : get_info('domid',              str,   ''),
+        'dgid'     : get_info('dgid',               int,   -1),
         'name'     : get_info('name',               str,   '??'),
         'mem'      : get_info('memory_dynamic_min', int,   0),
         'state'    : get_info('state',              str,   ''),
@@ -733,6 +774,7 @@ def domid_match(domid, info):
     return domid is None or domid == info['name'] or \
            domid == str(info['domid'])
 
+
 def xm_brief_list(doms):
     print '%-40s %3s %5s %5s %10s %9s' % \
           ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)')
@@ -744,13 +786,14 @@ def xm_brief_list(doms):
         d = parse_doms_info(dom)
         print format % d
 
+
 def xm_label_list(doms):
-    print '%-32s %3s %5s %5s %5s %9s %-8s' % \
+    print '%-32s %3s %5s %5s %5s %9s %-8s %7s' % \
           ('Name', 'ID', 'Mem', 'VCPUs', 'State', 'Time(s)', 'Label')
     
     output = []
     format = '%(name)-32s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \
-             '%(cpu_time)8.1f %(seclabel)9s'
+             '%(cpu_time)8.1f %(seclabel)9s %(dgid)7d'
     
     for dom in doms:
         d = parse_doms_info(dom)
@@ -1647,6 +1690,100 @@ def xm_vnet_delete(args):
     arg_check(args, "vnet-delete", 1)
     vnet = args[0]
     server.xend_vnet_delete(vnet)
+
+def xm_grp_create(args):
+    arg_check(args, "grp-create", 1)
+
+    CONFIG_ROOT = '/etc/xen/'
+    config_path = args[0]
+
+    if ( os.path.exists( config_path ) ):
+        verified_config_path = config_path
+    elif ( os.path.exists(CONFIG_ROOT + config_path ) ):
+        verified_config_path = CONFIG_ROOT + config_path
+    else:
+        err( "configuration file [%s] not found" % config_path )
+        return 1
+
+    return group.grp_create( verified_config_path )
+
+def xm_grp_destroy(args):
+    force = False
+    arg_check(args, "grp-destroy", 1, 2)
+    dgid = args[0]
+    for clflag in ['--force', '-f']:
+        if clflag in args:
+            force = True
+    return group.grp_destroy(dgid, force)
+
+def xm_grp_shutdown(args):
+    keep = False
+    arg_check(args, "grp-shutdown", 1, 2)
+    dgid = args[0]
+    for clflag in ['--keep', '-k']:
+        if clflag in args:
+            keep = True
+    return group.grp_shutdown(dgid, "poweroff", keep)
+
+def xm_grp_reboot(args):
+    arg_check(args, "grp-reboot", 1)
+    dgid = args[0]
+    return group.grp_shutdown(dgid, "reboot", True)
+
+def xm_grp_pause(args):
+    arg_check(args, "grp-pause", 1)
+    dgid = args[0]
+    return group.grp_pause(dgid)
+
+def xm_grp_unpause(args):
+    arg_check(args, "grp-unpause", 1)
+    dgid = args[0]
+    return group.grp_unpause(dgid)
+
+def xm_grp_save(args):
+    arg_check(args, "grp-save", 2)
+    dgid = args[0]
+    prefix = args[1]
+    return group.grp_save(dgid, prefix)
+
+def xm_grp_restore(args):
+    arg_check(args, "grp-restore", 1, -1)
+    return group.grp_restore(args)
+
+def xm_grp_suspend(args):
+    print "Not yet implemented"
+    #arg_check(args, "grp-suspend", 1)
+    #dgid = args[0]
+    #return group.grp_suspend(dgid)
+
+def xm_grp_resume(args):
+    print "Not yet implemented"
+    #arg_check(args, "grp-resume", 1)
+    #dgid = args[0]
+    #return group.grp_resume(dgid)
+
+def xm_grp_migrate(args):
+    live = False
+    arg_check(args, "grp-migrate", 2, 3)
+    dgid = args[0]
+    dst = args[1]
+    for clflag in ['--live', '-l']:
+        if clflag in args:
+            live = True
+    # hardcode these options for now
+    resource = 0
+    port = 0
+    return group.grp_migrate(dgid,dst,live,resource,port)
+
+def xm_grp_join(args):
+    arg_check(args, "grp-join", 2)
+    domid = args[0]
+    dgid = args[1]
+    return group.grp_join(domid, dgid)
+
+def xm_grp_list(args):
+    arg_check(args, "grp-list", 0)
+    return group.grp_list()
 
 commands = {
     "shell": xm_shell,
@@ -1704,6 +1841,20 @@ commands = {
     "vnet-delete": xm_vnet_delete,
     # vtpm
     "vtpm-list": xm_vtpm_list,
+    # group
+    "grp-create": xm_grp_create,
+    "grp-shutdown": xm_grp_shutdown,
+    "grp-destroy": xm_grp_destroy,
+    "grp-reboot": xm_grp_reboot,
+    "grp-pause": xm_grp_pause,
+    "grp-unpause": xm_grp_unpause,
+    "grp-save": xm_grp_save,
+    "grp-restore": xm_grp_restore,
+    "grp-suspend": xm_grp_suspend,
+    "grp-resume": xm_grp_resume,
+    "grp-migrate": xm_grp_migrate,
+    "grp-join": xm_grp_join,
+    "grp-list": xm_grp_list,
     }
 
 ## The commands supported by a separate argument parser in xend.xm.
diff -r ecb6cd61a9cf tools/python/xen/xm/group.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/xm/group.py      Tue Feb 20 12:59:11 2007 -0500
@@ -0,0 +1,274 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#============================================================================
+# Author: Chris Bookholt <hap10@xxxxxxxxxxxxxx>
+#============================================================================
+import os.path
+import sys
+import xmlrpclib
+import time
+from xen.xm.opts import Opts
+from xen.xend import sxp
+from xen.xend.XendClient import server
+from sets import Set
+
+opts = Opts()
+
+# print an error to stderr and exit.
+def err(msg):
+    print >>sys.stderr, "Error:", msg
+    sys.exit(1)
+
+
+def get_grp(dgid):
+    grpinfo = server.xend.group(dgid)
+    if not grpinfo:
+        err("group %s does not exist" % dgid)
+    return grpinfo
+
+
+def idCheck(dgid, op):
+    dgid = int(dgid)
+    if (dgid == 0 or dgid == 32767):
+        err("cannot %s group %d" % (op,dgid))
+
+
+def wait_create(domname, timeout):
+    counter = 0
+    while counter < timeout:
+        domains = server.xend.domains(0)
+        if domname in domains:
+            return
+        counter += 1
+        time.sleep(1)
+    err("timeout reached; problem starting group member dom: %s" % domname)
+
+
+# read and parse sxp config from file
+def make_config(config_file_path):
+    try:
+        fin = file(config_file_path, 'rb')
+        try:
+            config = sxp.parse(fin)
+        finally:
+            fin.close()
+        if config is None:
+            config = ['grp_config']
+        else:
+            config.insert(0, 'grp_config')
+    except Exception, ex:
+        print("Error: %s" % str(ex))
+        raise Exception
+    return config
+
+
+# create a domain group
+def make_domain_group(config):
+    try:
+        grpinfo = server.xend.group.create(config)
+    except xmlrpclib.Fault, ex:
+        err(str(ex))
+    except Exception, ex:
+        print("Error: %s" % str(ex))
+        raise Exception
+    return grpinfo
+
+
+# start the group members
+def populate_group(grpinfo, managed):
+    if managed:
+        from xen.xm import new
+    else:
+        from xen.xm import create
+
+    for domdata in grpinfo['member_list']:
+        domdata_list = domdata.split(":")
+        domname = domdata_list[0]
+        dom_config_path = domdata_list[1]
+        if managed:
+            #print "creating managed domain %s from file: %s" % 
(domname,dom_config_path)
+            new.main([None,dom_config_path])
+            #print "starting managed domain %s" % domname
+            server.xend.domain.start(domname, False)
+            domid = sxp.child_value(server.xend.domain(domname), 'domid')
+        else:
+            domid = create.main([None,dom_config_path])
+        wait_create(domname, 10)
+        dgid = grpinfo['dgid']
+        grp_join(domid, dgid)
+    #grp_unpause(grp.dgid)
+
+
+def grp_create(config_file_path, managed = False):
+    config = make_config(config_file_path)
+    grpinfo = make_domain_group(config)
+    populate_group(grpinfo, managed)
+
+
+# shutdown or reboot a group of domains
+def grp_shutdown(dgid, reason, keep):
+    grpinfo = get_grp(dgid)
+    idCheck(grpinfo['dgid'],"shutdown or reboot")
+    try:
+        server.xend.group.shutdown(dgid, reason)
+        if reason == "poweroff" and not keep:
+            print "waiting for group members to shutdown..."
+            from xen.xm.shutdown import wait_shutdown
+            wait_shutdown(opts, grpinfo['members'])
+            grp_destroy(dgid, force = False)
+    except xmlrpclib.Fault, ex:
+        err(str(ex))
+    except Exception, ex:
+        print("Error: %s" % str(ex))
+        raise Exception
+
+
+# destroy a domain group
+def grp_destroy(dgid, force = False):
+    grpinfo = get_grp(dgid)
+    idCheck(grpinfo['dgid'],"destroy")
+    try:
+        if force:
+            grp_pause(dgid)
+            for domid in grpinfo['members']:
+                server.xend.domain.destroy(domid)
+            print "waiting for group members to be destroyed..."
+            from xen.xm.shutdown import wait_shutdown
+            wait_shutdown(opts, grpinfo['members'])
+        server.xend.group.destroy(grpinfo['dgid'])
+    except xmlrpclib.Fault, ex:
+        err(str(ex))
+    except Exception, ex:
+        print("Error: %s" % str(ex))
+        raise Exception
+    return
+
+
+# save a group of running domains
+def grp_save(dgid, prefix):
+    grpinfo = get_grp(dgid)
+    idCheck(grpinfo['dgid'],"save")
+    try:
+        server.xend.group.save(dgid, prefix)
+    except xmlrpclib.Fault, ex:
+        err(str(ex))
+    except Exception, ex:
+        print("Error: %s" % str(ex))
+        raise Exception
+
+
+# retore a group of running domains
+def grp_restore(srcs):
+    try:
+        server.xend.group.restore(srcs)
+    except xmlrpclib.Fault, ex:
+        err(str(ex))
+    except Exception, ex:
+        print("Error: %s" % str(ex))
+        raise Exception
+
+
+# suspend a group of running, managed domains
+#def grp_suspend(dgid):
+#    grpinfo = get_grp(dgid)
+#    idCheck(grpinfo['dgid'],"suspend")
+#    try:
+#        server.xend.group.suspend(dgid)
+#    except xmlrpclib.Fault, ex:
+#        err(str(ex))
+#    except Exception, ex:
+#        print("Error: %s" % str(ex))
+#        raise Exception
+    
+
+# resume a suspended domain group
+#def grp_resume(dgid):
+#    try:
+#        server.xend.group.resume(dgid)
+#    except xmlrpclib.Fault, ex:
+#        err(str(ex))
+#    except Exception, ex:
+#        print("Error: %s" % str(ex))
+#        raise Exception
+    
+
+# pause a domain group
+def grp_pause(dgid):
+    grpinfo = get_grp(dgid)
+    idCheck(grpinfo['dgid'],"pause")
+    try:
+        server.xend.group.pause(grpinfo['dgid'])
+    except xmlrpclib.Fault, ex:
+        err(str(ex))
+    except Exception, ex:
+        print("Error: %s" % str(ex))
+        raise Exception
+
+
+# unpause a domain group
+def grp_unpause(dgid):
+    grpinfo = get_grp(dgid)
+    idCheck(grpinfo['dgid'],"unpause")
+    try:
+        server.xend.group.unpause(grpinfo['dgid'])
+    except xmlrpclib.Fault, ex:
+        err(str(ex))
+    except Exception, ex:
+        print("Error: %s" % str(ex))
+        raise Exception
+
+
+# migrate a domain group
+def grp_migrate(dgid, dst, live, resource, port):
+    grpinfo = get_grp(dgid)
+    idCheck(grpinfo['dgid'],"unpause")
+    try:
+        server.xend.group.migrate(grpinfo['dgid'], dst, live, resource, port)
+    except xmlrpclib.Fault, ex:
+       err(str(ex))
+    except Exception, ex:
+        print("Error: %s" % str(ex))
+        raise Exception
+
+
+# cause a domain to join a group
+def grp_join( dom, dgid ):
+    grpinfo = get_grp(dgid)
+    domid = sxp.child_value(server.xend.domain(dom), 'domid')
+    try:
+        server.xend.group.join(domid, grpinfo['dgid'])
+    except xmlrpclib.Fault, ex:
+       err(str(ex))
+    except Exception, ex:
+        print("Error: %s" % str(ex))
+        raise Exception
+
+
+# print list of domain group stats
+def grp_list():
+    try:
+        domgrps = server.xend.group.list()
+        format = "%-20s %-6s %-5s %-46s"
+        print format % ('Name', 'ID', 'Size', 'Members')
+        for grpinfo in domgrps:
+            name = grpinfo['grp_name']
+            dgid = grpinfo['dgid']
+            size = grpinfo['size']
+            members = ", ".join(grpinfo['members'])
+            print format % (name, dgid, size, members)
+    except xmlrpclib.Fault, ex:
+        err(str(ex))
+    except Exception, ex:
+        print("Error: %s" % str(ex))
+        raise Exception




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

 


Rackspace

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