Skip to contentSkip to conversation

Domain Groups - Tools Support

RFC In review Chris 1 participant 1 message Dec 18, 2007 Arm/actions semi architecture

lore
Share & tools
lore

Chris

author
#0 lore raw

RFC 2/2 Domain Groups - Tools Support

diffstat domgrps-tools.patch

 examples/Makefile                      |    1
 examples/xmexample.grp                 |   21 +
 libxc/Makefile                         |    1
 libxc/xc_domain.c                      |    4
 libxc/xc_domain_group.c                |  100 +++++++++
 libxc/xc_private.h                     |   31 ++
 libxc/xenctrl.h                        |   31 ++
 python/xen/lowlevel/xc/xc.c            |  241 ++++++++++++++++++++--
 python/xen/xend/XendCheckpoint.py      |   54 ++++-
 python/xen/xend/XendClient.py          |    1
 python/xen/xend/XendConfig.py          |   27 ++
 python/xen/xend/XendConstants.py       |   11 +
 python/xen/xend/XendDomain.py          |   15 +
 python/xen/xend/XendDomainGroup.py     |  347 +++++++++++++++++++++++++++++++++
 python/xen/xend/XendDomainGroupInfo.py |  238 ++++++++++++++++++++++
 python/xen/xend/XendDomainInfo.py      |   37 ++-
 python/xen/xend/XendError.py           |    4
 python/xen/xend/server/XMLRPCServer.py |   34 ++-
 python/xen/xm/create.py                |    8
 python/xen/xm/group.py                 |  275 ++++++++++++++++++++++++++
 python/xen/xm/main.py                  |  166 +++++++++++++++
21 files changed, 1595 insertions(+), 52 deletions(-)
tools/examples/Makefile +1 -0
diff -urN xen-unstable/tools/examples/Makefile xen-unstable-trp-domgrps-rebase-tip/tools/examples/Makefile
@@ -16,6 +16,7 @@
 XEN_CONFIGS += xmexample2
 XEN_CONFIGS += xmexample.hvm
 XEN_CONFIGS += xmexample.vti
+XEN_CONFIGS += xmexample.grp
 XEN_CONFIGS += xend-pci-quirks.sxp
 XEN_CONFIGS += xend-pci-permissive.sxp
 
tools/examples/xmexample.grp +21 -0
diff -urN xen-unstable/tools/examples/xmexample.grp xen-unstable-trp-domgrps-rebase-tip/tools/examples/xmexample.grp
@@ -0,0 +1,21 @@
+################################################################################
+#
+# Defines a group of domains
+#
+################################################################################
+# grp_name must be unique (within the scope of a xend instance)
+#
+# member_list contains names and paths to configuration files for each
+# member of the domain group  
+# 
+# Note: The domain name in member_list must match the 'name' attribute in the 
+# corresponding VM configuration file.
+################################################################################
+
+(grp_name "TestGroup")
+
+(member_list
+       ('fc5-1:/etc/xen/vmconfig-1'
+        'fc5-2:/etc/xen/vmconfig-2'
+        'fc5-3:/etc/xen/vmconfig-3')
+)
tools/libxc/Makefile +1 -0
diff -urN xen-unstable/tools/libxc/Makefile xen-unstable-trp-domgrps-rebase-tip/tools/libxc/Makefile
@@ -10,6 +10,7 @@
 CTRL_SRCS-$(CONFIG_IA64) += xc_core_ia64.c
 CTRL_SRCS-$(CONFIG_POWERPC) += xc_core_powerpc.c
 CTRL_SRCS-y       += xc_domain.c
+CTRL_SRCS-y       += xc_domain_group.c
 CTRL_SRCS-y       += xc_evtchn.c
 CTRL_SRCS-y       += xc_misc.c
 CTRL_SRCS-y       += xc_acm.c
tools/libxc/xc_domain.c +4 -0
diff -urN xen-unstable/tools/libxc/xc_domain.c xen-unstable-trp-domgrps-rebase-tip/tools/libxc/xc_domain.c
@@ -197,6 +197,7 @@
             info->crashed  = 1;
         }
 
+        info->grpid = domctl.u.getdomaininfo.group;
         info->ssidref  = domctl.u.getdomaininfo.ssidref;
         info->nr_pages = domctl.u.getdomaininfo.tot_pages;
         info->max_memkb = domctl.u.getdomaininfo.max_pages << (PAGE_SHIFT-10);
@@ -208,6 +209,9 @@
         memcpy(info->handle, domctl.u.getdomaininfo.handle,
                sizeof(xen_domain_handle_t));
 
+        memcpy(info->dg_handle, domctl.u.getdomaininfo.dg_handle,
+               sizeof(xen_domain_group_handle_t));
+
         next_domid = (uint16_t)domctl.domain + 1;
         info++;
     }
tools/libxc/xc_domain_group.c +100 -0

100 lines not on this page · raw message

tools/libxc/xc_private.h +31 -0
diff -urN xen-unstable/tools/libxc/xc_private.h xen-unstable-trp-domgrps-rebase-tip/tools/libxc/xc_private.h
@@ -23,10 +23,12 @@
 #ifdef VALGRIND
 #define DECLARE_HYPERCALL privcmd_hypercall_t hypercall = { 0 }
 #define DECLARE_DOMCTL struct xen_domctl domctl = { 0 }
+#define DECLARE_DOMGRPCTL struct xen_domgrpctl domgrpctl = { 0 }
 #define DECLARE_SYSCTL struct xen_sysctl sysctl = { 0 }
 #else
 #define DECLARE_HYPERCALL privcmd_hypercall_t hypercall
 #define DECLARE_DOMCTL struct xen_domctl domctl
+#define DECLARE_DOMGRPCTL struct xen_domgrpctl domgrpctl
 #define DECLARE_SYSCTL struct xen_sysctl sysctl
 #endif
 
@@ -125,6 +127,35 @@
     return ret;
 }
 
+static inline int do_domgrpctl(int xc_handle, struct xen_domgrpctl *domgrpctl)
+{
+    int ret = -1;
+    DECLARE_HYPERCALL;
+
+    domgrpctl->interface_version = XEN_DOMGRPCTL_INTERFACE_VERSION;
+
+    hypercall.op     = __HYPERVISOR_domgrpctl;
+    hypercall.arg[0] = (unsigned long)domgrpctl;
+
+    if ( mlock(domgrpctl, sizeof(*domgrpctl)) != 0 )
+    {
+        PERROR("Could not lock memory for Xen hypercall");
+        goto out1;
+    }
+
+    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
+    {
+        if ( errno == EACCES )
+            DPRINTF("domgrpctl operation failed -- need to"
+                    " rebuild the user-space tool set?\n");
+    }
+
+    safe_munlock(domgrpctl, sizeof(*domgrpctl));
+
+ out1:
+    return ret;
+}
+
 static inline int do_sysctl(int xc_handle, struct xen_sysctl *sysctl)
 {
     int ret = -1;
tools/libxc/xenctrl.h +31 -0
diff -urN xen-unstable/tools/libxc/xenctrl.h xen-unstable-trp-domgrps-rebase-tip/tools/libxc/xenctrl.h
@@ -21,6 +21,7 @@
 #include <stdint.h>
 #include <xen/xen.h>
 #include <xen/domctl.h>
+#include <xen/domgrpctl.h>
 #include <xen/sysctl.h>
 #include <xen/version.h>
 #include <xen/event_channel.h>
@@ -151,6 +152,7 @@
 
 typedef struct xc_dominfo {
     uint32_t      domid;
+    uint32_t      grpid;
     uint32_t      ssidref;
     unsigned int  dying:1, crashed:1, shutdown:1,
                   paused:1, blocked:1, running:1,
@@ -163,8 +165,16 @@
     unsigned int  nr_online_vcpus;
     unsigned int  max_vcpu_id;
     xen_domain_handle_t handle;
+    xen_domain_group_handle_t dg_handle;
 } xc_dominfo_t;
 
+typedef struct{
+    dgid_t        dgid;
+    uint16_t      size;
+    domid_t       member_list[MAX_GROUP_SIZE];
+    xen_domain_group_handle_t handle;
+} xc_grpinfo_t;
+
 typedef xen_domctl_getdomaininfo_t xc_domaininfo_t;
 int xc_domain_create(int xc_handle,
                      uint32_t ssidref,
@@ -298,6 +308,27 @@
                       unsigned int max_doms,
                       xc_dominfo_t *info);
 
+int xc_domain_group_getinfo(int xc_handle,
+                            uint32_t first_dgid,
+			    unsigned int max_grps,
+			    xc_grpinfo_t *info);
+
+int xc_domain_group_create(int xc_handle,
+                           xen_domain_group_handle_t handle,
+                           uint32_t *pdgid);
+
+int xc_domain_group_pause(int xc_handle,
+                          uint32_t dgid);
+
+int xc_domain_group_unpause(int xc_handle,
+                            uint32_t dgid);
+
+int xc_domain_group_destroy(int xc_handle,
+                            uint32_t dgid);
+
+int xc_domain_group_join(int xc_handle,
+                         uint32_t domid,
+                         uint32_t dgid);
 
 /**
  * This function will set the execution context for the specified vcpu.
tools/python/xen/lowlevel/xc/xc.c +217 -24

343 lines not on this page · raw message

tools/python/xen/xend/server/XMLRPCServer.py +30 -4
diff -urN xen-unstable/tools/python/xen/xend/server/XMLRPCServer.py xen-unstable-trp-domgrps-rebase-tip/tools/python/xen/xend/server/XMLRPCServer.py
@@ -29,10 +29,11 @@
 
 from xen.xend import XendAPI, XendDomain, XendDomainInfo, XendNode
 from xen.xend import XendLogging, XendDmesg
+from xen.xend import XendDomainGroup
 from xen.xend.XendClient import XML_RPC_SOCKET
 from xen.xend.XendConstants import DOM_STATE_RUNNING
 from xen.xend.XendLogging import log
-from xen.xend.XendError import XendInvalidDomain
+from xen.xend.XendError import XendInvalidDomain, XendInvalidDomainGroup
 
 # vcpu_avail is a long and is not needed by the clients.  It's far easier
 # to just remove it then to try and marshal the long.
@@ -46,16 +47,16 @@
             ret.append(k)
     return ret
 
-def lookup(domid):
+def lookup_dom(domid):
     info = XendDomain.instance().domain_lookup(domid)
     return info
 
 def dispatch(domid, fn, args):
-    info = lookup(domid)
+    info = lookup_dom(domid)
     return getattr(info, fn)(*args)
 
 def domain(domid, full = 0):
-    info = lookup(domid)
+    info = lookup_dom(domid)
     return fixup_sxpr(info.sxpr(not full))
 
 def domains(detail = True, full = False):
@@ -76,6 +77,19 @@
     info = XendDomain.instance().domain_restore(src, paused)
     return fixup_sxpr(info.sxpr())
 
+def lookup_grp(dgid):
+    grpinfo = XendDomainGroup.instance().grp_lookup(dgid)
+    if not grpinfo:
+        raise XendInvalidDomainGroup("Invalid group: %s" % str(dgid))
+    return grpinfo
+
+def group(dgid):
+    return lookup_grp(dgid)
+
+def group_create(config):
+    info = XendDomainGroup.instance().grp_create(config)
+    return info.sxpr()
+
 def get_log():
     f = open(XendLogging.getLogFilename(), 'r')
     try:
@@ -91,6 +105,10 @@
 
 exclude = ['domain_create', 'domain_restore']
 
+grp_methods = ['grp_destroy', 'grp_pause', 'grp_unpause', 'grp_members', 
+               'grp_join', 'grp_migrate', 'grp_list', 'grp_suspend', 
+               'grp_resume', 'grp_save', 'grp_restore', 'grp_shutdown']
+
 class XMLRPCServer:
     def __init__(self, auth, use_xenapi, use_tcp = False,
                  ssl_key_file = None, ssl_cert_file = None,
@@ -190,6 +208,12 @@
                 if name not in exclude:
                     self.server.register_function(fn, "xend.domain.%s" % name[7:])
 
+        # Domain Group Operations
+        xdg_inst = XendDomainGroup.instance()
+        for name in grp_methods:
+            fn = getattr(xdg_inst, name)
+            self.server.register_function(fn, "xend.group.%s" % name[4:])
+
         # Functions in XendNode and XendDmesg
         for type, lst, n in [(XendNode, ['info', 'send_debug_keys'], 'node'),
                              (XendDmesg, ['info', 'clear'], 'node.dmesg')]:
@@ -206,6 +230,8 @@
         self.server.register_function(get_log, 'xend.node.log')
         self.server.register_function(domain_create, 'xend.domain.create')
         self.server.register_function(domain_restore, 'xend.domain.restore')
+        self.server.register_function(group, 'xend.group')
+        self.server.register_function(group_create, 'xend.group.create')
 
         # A couple of the security functions
         from xen.util.xsm import xsm as security
tools/python/xen/xend/XendCheckpoint.py +48 -6

81 lines not on this page · raw message

tools/python/xen/xend/XendClient.py +1 -0
diff -urN xen-unstable/tools/python/xen/xend/XendClient.py xen-unstable-trp-domgrps-rebase-tip/tools/python/xen/xend/XendClient.py
@@ -27,6 +27,7 @@
 ERROR_INTERNAL = 1
 ERROR_GENERIC = 2
 ERROR_INVALID_DOMAIN = 3
+ERROR_INVALID_DOMAIN_GROUP = 4
 
 uri = 'httpu:///var/run/xend/xmlrpc.sock'
 if os.environ.has_key('XM_SERVER'):
tools/python/xen/xend/XendConfig.py +24 -3
diff -urN xen-unstable/tools/python/xen/xend/XendConfig.py xen-unstable-trp-domgrps-rebase-tip/tools/python/xen/xend/XendConfig.py
@@ -27,7 +27,7 @@
 from xen.xend.XendError import VmError
 from xen.xend.XendDevices import XendDevices
 from xen.xend.PrettyPrint import prettyprintstring
-from xen.xend.XendConstants import DOM_STATE_HALTED
+from xen.xend.XendConstants import DOM_STATE_HALTED,NULL_GROUP_ID,NULL_GROUP_UUID
 from xen.xend.xenstore.xstransact import xstransact
 from xen.xend.server.BlktapController import blktap_disk_types
 from xen.xend.server.netif import randomMAC
@@ -111,6 +111,8 @@
 
 XENAPI_CFG_TO_LEGACY_CFG = {
     'uuid': 'uuid',
+    'dgid': 'dgid',
+    'dguuid': 'dguuid',
     'VCPUs_max': 'vcpus',
     'cpus': 'cpus',
     'name_label': 'name',
@@ -142,6 +144,8 @@
 
 XENAPI_CFG_TYPES = {
     'uuid': str,
+    'dguid': int,
+    'dguuid': str,
     'name_label': str,
     'name_description': str,
     'user_version': str,
@@ -197,6 +201,9 @@
 
 LEGACY_CFG_TYPES = {
     'uuid':          str,
+    'dgid':          int,
+    'dguuid':        str,
+    'grp_name':      str,
     'name':          str,
     'vcpus':         int,
     'vcpu_avail':    long,
@@ -222,6 +229,8 @@
 # xenstore.
 LEGACY_XENSTORE_VM_PARAMS = [
     'uuid',
+    'dgid',
+    'dguuid',
     'name',
     'vcpus',
     'vcpu_avail',
@@ -336,7 +345,9 @@
             'vbd_refs': [],
             'vtpm_refs': [],
             'other_config': {},
-            'platform': {}
+            'platform': {},
+            'dgid': NULL_GROUP_ID,
+            'dguuid': NULL_GROUP_UUID,
         }
         
         return defaults
@@ -388,6 +399,10 @@
             self['uuid'] = uuid.createString()
         else:
             self['uuid'] = uuid.toString(uuid.fromString(self['uuid']))
+        if 'dguuid' not in self or not self['dguuid']:
+            self['dguuid'] = uuid.createString()
+        else:
+            self['dguuid'] = uuid.toString(uuid.fromString(self['dguuid']))
 
     def _name_sanity_check(self):
         if 'name_label' not in self:
@@ -417,6 +432,7 @@
 
     def _dominfo_to_xapi(self, dominfo, update_mem = False):
         self['domid'] = dominfo['domid']
+        self['dgid'] = dominfo['dgid']
         self['online_vcpus'] = dominfo['online_vcpus']
         self['VCPUs_max'] = dominfo['max_vcpu_id'] + 1
 
@@ -448,6 +464,9 @@
 
         if 'handle' in dominfo:
             self['uuid'] = uuid.toString(dominfo['handle'])
+
+        if 'dg_handle' in dominfo:
+            self['dguuid'] = uuid.toString(dominfo['dg_handle'])
             
     def _parse_sxp(self, sxp_cfg):
         """ Populate this XendConfig using the parsed SXP.
@@ -924,6 +943,8 @@
                     sxpr.append([legacy, int(self[xenapi])])
                 else:
                     sxpr.append([legacy, self[xenapi]])
+	    else:
+                    log.debug("Unconverted key: " + xenapi)
 
         MiB = 1024*1024
 
@@ -931,7 +952,7 @@
         sxpr.append(["memory", int(self["memory_dynamic_max"])/MiB])
 
         for legacy in LEGACY_UNSUPPORTED_BY_XENAPI_CFG:
-            if legacy in ('domid', 'uuid', 'cpus'): # skip these
+            if legacy in ('domid', 'uuid', 'cpus', 'dgid', 'dguuid'): # skip these
                 continue
             if self.has_key(legacy) and self[legacy] not in (None, []):
                 sxpr.append([legacy, self[legacy]])
tools/python/xen/xend/XendConstants.py +11 -0
diff -urN xen-unstable/tools/python/xen/xend/XendConstants.py xen-unstable-trp-domgrps-rebase-tip/tools/python/xen/xend/XendConstants.py
@@ -123,4 +123,15 @@
 #
 
 XS_VMROOT = "/vm/"
+XS_GRPROOT = "/group/"
 
+#
+# Domain Group Constants
+# 
+
+GROUP0_ID = 0
+GROUP0_UUID = "00000000-0000-0000-0000-000000000000"
+GROUP0_NAME = "Group-0"
+NULL_GROUP_ID = 32767
+NULL_GROUP_UUID = "ffffffff-ffff-ffff-ffff-ffffffffffff"
+NULL_GROUP_NAME = "Null-Group"
tools/python/xen/xend/XendDomainGroupInfo.py +238 -0

238 lines not on this page · raw message

tools/python/xen/xend/XendDomainGroup.py +347 -0

347 lines not on this page · raw message

tools/python/xen/xend/XendDomainInfo.py +31 -6
diff -urN xen-unstable/tools/python/xen/xend/XendDomainInfo.py xen-unstable-trp-domgrps-rebase-tip/tools/python/xen/xend/XendDomainInfo.py
@@ -952,6 +952,8 @@
     def _storeDomDetails(self):
         to_store = {
             'domid':              str(self.domid),
+            'dgid':               str(self.info['dgid']),
+            'dguuid':             self.info['dguuid'],
             'vm':                 self.vmpath,
             'name':               self.info['name_label'],
             'console/limit':      str(xoptions.get_console_limit() * 1024),
@@ -1037,7 +1039,7 @@
         # changed in Xenstore.
         
         cfg_vm = ['name', 'on_poweroff', 'on_reboot', 'on_crash',
-                  'rtc/timeoffset']
+                  'rtc/timeoffset', 'dgid', 'dguuid', 'grp_name']
         
         vm_details = self._readVMDetails([(k,XendConfig.LEGACY_CFG_TYPES[k])
                                            for k in cfg_vm])
@@ -1086,6 +1088,9 @@
         
         reason = self.readDom('control/shutdown')
 
+        # stash current dgid for restart/resume/restore
+        self.old_dgid = self.info.get('dgid')
+
         if reason and reason != 'suspend':
             sst = self.readDom('xend/shutdown_start_time')
             now = time.time()
@@ -1113,6 +1118,12 @@
     def getDomid(self):
         return self.domid
 
+    def getDgid(self):
+        return self.info.get('dgid')
+
+    def getOldDgid(self):
+        return self.old_dgid
+
     def setName(self, name):
         self._checkName(name)
         self.info['name_label'] = name
@@ -1393,8 +1404,21 @@
 
             new_dom = None
             try:
-                new_dom = XendDomain.instance().domain_create_from_dict(
-                    self.info)
+                xd = XendDomain.instance()
+                new_dom = xd.domain_create_from_dict(self.info)
+
+                # rejoin former domain group
+                xdg = xen.xend.XendDomainGroup.instance()
+
+                # wait until both needed locks are available
+                rc = False
+                while rc == False:
+                    rc = xd.domains_lock.acquire( blocking = False )
+                    if rc == False:
+                        time.sleep(1)
+                xdg.grp_join(new_dom.domid, self.old_dgid)
+                xd.domains_lock.release()
+
                 new_dom.waitForDevices()
                 new_dom.unpause()
                 rst_cnt = self._readVm('xend/restart_count')
@@ -2845,9 +2869,10 @@
         return (dev_uuid in self.info['%s_refs' % dev_class.lower()])
 
     def __str__(self):
-        return '<domain id=%s name=%s memory=%s state=%s>' % \
-               (str(self.domid), self.info['name_label'],
-                str(self.info['memory_dynamic_max']), DOM_STATES[self._stateGet()])
+        return '<domain id=%s dgid=%s name=%s memory=%s state=%s>' % \
+               (str(self.domid), str(self.info.get('dgid')), 
+                self.info['name_label'], str(self.info['memory_dynamic_max']),
+                DOM_STATES[self._stateGet()])
 
     __repr__ = __str__
 
tools/python/xen/xend/XendDomain.py +14 -1
diff -urN xen-unstable/tools/python/xen/xend/XendDomain.py xen-unstable-trp-domgrps-rebase-tip/tools/python/xen/xend/XendDomain.py
@@ -432,6 +432,14 @@
             if domid not in running_domids and domid != DOM0_ID:
                 self._remove_domain(dom, domid)
 
+        # update group information
+        xdg = xen.xend.XendDomainGroup.instance()
+        xdg.domain_groups_lock.acquire()
+        try:
+            xdg.refresh()
+        finally:
+            xdg.domain_groups_lock.release()
+
 
     def add_domain(self, info):
         """Add a domain to the list of running domains
@@ -925,10 +933,15 @@
                     if hasattr(os, "O_LARGEFILE"):
                         oflags |= os.O_LARGEFILE
                     fd = os.open(chkpath, oflags)
-                    XendCheckpoint.restore(self,
+                    pdated_dominfo = XendCheckpoint.restore(self,
                                            fd,
                                            dominfo,
                                            paused = start_paused)
+                    domid = dominfo.getDomid()
+                    dgid = dominfo.getOldDgid()
+                    xdg = xen.xend.XendDomainGroup.instance()
+                    xdg.grp_join(domid, dgid)
+                    self.add_domain(updated_dominfo)
                     os.unlink(chkpath)
                 except OSError, ex:
                     raise XendError("Failed to read stored checkpoint file")
tools/python/xen/xend/XendError.py +4 -0
diff -urN xen-unstable/tools/python/xen/xend/XendError.py xen-unstable-trp-domgrps-rebase-tip/tools/python/xen/xend/XendError.py
@@ -24,6 +24,10 @@
     def __init__(self, value):
         Fault.__init__(self, XendClient.ERROR_INVALID_DOMAIN, value)
 
+class XendInvalidDomainGroup(Fault):
+    def __init__(self, value):
+        Fault.__init__(self, XendClient.ERROR_INVALID_DOMAIN_GROUP, value)
+
 class XendError(Fault):
     
     def __init__(self, value):
tools/python/xen/xm/create.py +8 -0
diff -urN xen-unstable/tools/python/xen/xm/create.py xen-unstable-trp-domgrps-rebase-tip/tools/python/xen/xm/create.py
@@ -521,6 +521,11 @@
           - 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.
     """
@@ -768,6 +773,8 @@
         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:
@@ -1188,6 +1195,7 @@
         map(lambda vm_ref: server.xenapi.VM.start(vm_ref, 0), vm_refs)
     elif not opts.is_xml:
         dom = make_domain(opts, config)
+	return dom
         
 def do_console(domain_name):
     cpid = os.fork() 
tools/python/xen/xm/group.py +275 -0

275 lines not on this page · raw message

tools/python/xen/xm/main.py +158 -8

228 lines not on this page · raw message

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel