Domain Groups - Tools Support
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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