diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 8a4deacf57..cdb4c1c6f3 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -640,46 +640,84 @@ class XendConfig(dict): else: cfg['cpus'] = str(cfg['cpu']) - # Convert 'cpus' to list of ints + # Convert 'cpus' to list of list of ints + cpus_list = [] if 'cpus' in cfg: - cpus = [] - if type(cfg['cpus']) == list: - # If sxp_cfg was created from config.sxp, - # the form of 'cpus' is list of string. - # Convert 'cpus' to list of ints. - # ['1'] -> [1] - # ['0','2','3'] -> [0,2,3] - try: - for c in cfg['cpus']: - cpus.append(int(c)) - - cfg['cpus'] = cpus - except ValueError, e: - raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e)) - else: - # Convert 'cpus' string to list of ints - # 'cpus' supports a list of ranges (0-3), - # seperated by commas, and negation, (^1). - # Precedence is settled by order of the - # string: - # "0-3,^1" -> [0,2,3] - # "0-3,^1,1" -> [0,1,2,3] - try: - for c in cfg['cpus'].split(','): - if c.find('-') != -1: - (x, y) = c.split('-') - for i in range(int(x), int(y)+1): - cpus.append(int(i)) + # Convert the following string to list of ints. + # The string supports a list of ranges (0-3), + # seperated by commas, and negation (^1). + # Precedence is settled by order of the string: + # "0-3,^1" -> [0,2,3] + # "0-3,^1,1" -> [0,1,2,3] + def cnv(s): + l = [] + for c in s.split(','): + if c.find('-') != -1: + (x, y) = c.split('-') + for i in range(int(x), int(y)+1): + l.append(int(i)) + else: + # remove this element from the list + if c[0] == '^': + l = [x for x in l if x != int(c[1:])] else: - # remove this element from the list - if c[0] == '^': - cpus = [x for x in cpus if x != int(c[1:])] - else: - cpus.append(int(c)) - - cfg['cpus'] = cpus + l.append(int(c)) + return l + + if type(cfg['cpus']) == list: + if len(cfg['cpus']) > 0 and type(cfg['cpus'][0]) == list: + # If sxp_cfg was created from config.sxp, + # the form of 'cpus' is list of list of string. + # Convert 'cpus' to list of list of ints. + # Conversion examples: + # [['1']] -> [[1]] + # [['0','2'],['1','3']] -> [[0,2],[1,3]] + try: + for c1 in cfg['cpus']: + cpus = [] + for c2 in c1: + cpus.append(int(c2)) + cpus_list.append(cpus) + except ValueError, e: + raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e)) + else: + # Conversion examples: + # ["1"] -> [[1]] + # ["0,2","1,3"] -> [[0,2],[1,3]] + # ["0-3,^1","1-4,^2"] -> [[0,2,3],[1,3,4]] + try: + for c in cfg['cpus']: + cpus = cnv(c) + cpus_list.append(cpus) + except ValueError, e: + raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e)) + + if len(cpus_list) != cfg['vcpus']: + raise XendConfigError('vcpus and the item number of cpus are not same') + else: + # Conversion examples: + # vcpus=1: + # "1" -> [[1]] + # "0-3,^1" -> [[0,2,3]] + # vcpus=2: + # "1" -> [[1],[1]] + # "0-3,^1" -> [[0,2,3],[0,2,3]] + try: + cpus = cnv(cfg['cpus']) + for v in range(0, cfg['vcpus']): + cpus_list.append(cpus) except ValueError, e: raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e)) + else: + # Generation examples: + # vcpus=1: + # -> [[]] + # vcpus=2: + # -> [[],[]] + for v in range(0, cfg['vcpus']): + cpus_list.append(list()) + + cfg['cpus'] = cpus_list # Parse cpuid if 'cpuid' in cfg: diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 6e93795675..39e49d13ac 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -1365,28 +1365,25 @@ class XendDomain: raise XendInvalidDomain(str(domid)) # if vcpu is keyword 'all', apply the cpumap to all vcpus - vcpus = [ vcpu ] if str(vcpu).lower() == "all": vcpus = range(0, int(dominfo.getVCpuCount())) + else: + vcpus = [ int(vcpu) ] # set the same cpumask for all vcpus rc = 0 - if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED): - for v in vcpus: - try: - rc = xc.vcpu_setaffinity(dominfo.getDomid(), int(v), cpumap) - except Exception, ex: - log.exception(ex) - raise XendError("Cannot pin vcpu: %s to cpu: %s - %s" % \ - (v, cpumap, str(ex))) - else: - # FIXME: if we could define cpu affinity definitions to - # each vcpu, reprogram the following processing. - if str(vcpu).lower() != "all": - raise XendError("Must specify 'all' to VCPU " - "for inactive managed domains") - dominfo.setCpus(cpumap) - self.managed_config_save(dominfo) + cpus = dominfo.getCpus() + for v in vcpus: + try: + if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED): + rc = xc.vcpu_setaffinity(dominfo.getDomid(), v, cpumap) + cpus[v] = cpumap + except Exception, ex: + log.exception(ex) + raise XendError("Cannot pin vcpu: %d to cpu: %s - %s" % \ + (v, cpumap, str(ex))) + dominfo.setCpus(cpus) + self.managed_config_save(dominfo) return rc diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index f121cdb6fc..607a97aef5 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1051,8 +1051,8 @@ class XendDomainInfo: ['running', 0], ['cpu_time', 0.0], ['cpu', -1], - ['cpumap', self.info['cpus'] and \ - self.info['cpus'] or range(64)]]) + ['cpumap', self.info['cpus'][i] and \ + self.info['cpus'][i] or range(64)]]) return sxpr @@ -1477,6 +1477,13 @@ class XendDomainInfo: self.info['VCPUs_live'] = vcpus self._writeDom(self._vcpuDomDetails()) else: + if self.info['VCPUs_max'] > vcpus: + # decreasing + del self.info['cpus'][vcpus:] + elif self.info['VCPUs_max'] < vcpus: + # increasing + for c in range(self.info['VCPUs_max'], vcpus): + self.info['cpus'].append(list()) self.info['VCPUs_max'] = vcpus xen.xend.XendDomain.instance().managed_config_save(self) log.info("Set VCPU count on domain %s to %d", self.info['name_label'], @@ -2071,9 +2078,17 @@ class XendDomainInfo: # repin domain vcpus if a restricted cpus list is provided # this is done prior to memory allocation to aide in memory # distribution for NUMA systems. - if self.info['cpus'] is not None and len(self.info['cpus']) > 0: + def has_cpus(): + if self.info['cpus'] is not None: + for c in self.info['cpus']: + if c: + return True + return False + + if has_cpus(): for v in range(0, self.info['VCPUs_max']): - xc.vcpu_setaffinity(self.domid, v, self.info['cpus']) + if self.info['cpus'][v]: + xc.vcpu_setaffinity(self.domid, v, self.info['cpus'][v]) else: def find_relaxed_node(node_list): import sys