diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 9378112045..1098417542 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -78,6 +78,25 @@ def scrub_password(data): else: return data +# +# CPU fields: +# +# vcpus_number -- the maximum number of vcpus that this domain may ever have. +# aka XendDomainInfo.getVCpuCount(). +# vcpus -- the legacy configuration name for above. +# max_vcpu_id -- vcpus_number - 1. This is given to us by Xen. +# +# cpus -- the list of pCPUs available to each vCPU. +# +# vcpu_avail: a bitmap telling the guest domain whether it may use each of +# its VCPUs. This is translated to +# /cpu//availability = {online,offline} for use +# by the guest domain. +# online_vpcus -- the number of VCPUs currently up, as reported by Xen. This +# is changed by changing vcpu_avail, and waiting for the +# domain to respond. +# + # Mapping from XendConfig configuration keys to the old # legacy configuration keys that map directly. @@ -185,7 +204,7 @@ LEGACY_CFG_TYPES = { 'uuid': str, 'name': str, 'vcpus': int, - 'vcpu_avail': int, + 'vcpu_avail': long, 'memory': int, 'shadow_memory': int, 'maxmem': int, @@ -355,9 +374,6 @@ class XendConfig(dict): 'cpu_weight': 256, 'cpu_cap': 0, 'vcpus_number': 1, - 'online_vcpus': 1, - 'max_vcpu_id': 0, - 'vcpu_avail': 1, 'console_refs': [], 'vif_refs': [], 'vbd_refs': [], @@ -389,7 +405,7 @@ class XendConfig(dict): event) def _vcpus_sanity_check(self): - if self.get('vcpus_number') != None: + if 'vcpus_number' in self and 'vcpu_avail' not in self: self['vcpu_avail'] = (1 << self['vcpus_number']) - 1 def _uuid_sanity_check(self): @@ -405,7 +421,7 @@ class XendConfig(dict): def _dominfo_to_xapi(self, dominfo): self['domid'] = dominfo['domid'] self['online_vcpus'] = dominfo['online_vcpus'] - self['max_vcpu_id'] = dominfo['max_vcpu_id'] + self['vcpus_number'] = dominfo['max_vcpu_id'] + 1 self['memory_dynamic_min'] = (dominfo['mem_kb'] + 1023)/1024 self['memory_dynamic_max'] = (dominfo['maxmem_kb'] + 1023)/1024 self['cpu_time'] = dominfo['cpu_time']/1e9 @@ -636,9 +652,6 @@ class XendConfig(dict): self['memory_dynamic_max'] = self['memory_static_max'] self['memory_dynamic_min'] = self['memory_static_min'] - # make sure max_vcpu_id is set correctly - self['max_vcpu_id'] = self['vcpus_number'] - 1 - # set device references in the configuration self['devices'] = cfg.get('devices', {}) @@ -720,13 +733,11 @@ class XendConfig(dict): _set_cfg_if_exists('on_xend_stop') _set_cfg_if_exists('on_xend_start') _set_cfg_if_exists('vcpu_avail') - _set_cfg_if_exists('max_vcpu_id') # needed for vcpuDomDetails _set_cfg_if_exists('cpu_weight') _set_cfg_if_exists('cpu_cap') # Parse and store runtime configuration _set_cfg_if_exists('start_time') - _set_cfg_if_exists('online_vcpus') _set_cfg_if_exists('cpu_time') _set_cfg_if_exists('shutdown_reason') _set_cfg_if_exists('up_time') diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index fdd571239f..27cba0049c 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -60,25 +60,6 @@ log = logging.getLogger("xend.XendDomainInfo") #log.setLevel(logging.TRACE) -# -# There are a number of CPU-related fields: -# -# vcpus: the number of virtual CPUs this domain is configured to use. -# vcpu_avail: a bitmap telling the guest domain whether it may use each of -# its VCPUs. This is translated to -# /cpu//availability = {online,offline} for use -# by the guest domain. -# cpumap: a list of bitmaps, one for each VCPU, giving the physical -# CPUs that that VCPU may use. -# cpu: a configuration setting requesting that VCPU 0 is pinned to -# the specified physical CPU. -# -# vcpus and vcpu_avail settings persist with the VM (i.e. they are persistent -# across save, restore, migrate, and restart). The other settings are only -# specific to the domain, so are lost when the VM moves. -# - - def create(config): """Creates and start a VM using the supplied configuration. @@ -624,7 +605,7 @@ class XendDomainInfo: ['name', self.info['name_label']], ['vcpu_count', self.info['vcpus_number']]] - for i in range(0, self.info['max_vcpu_id']+1): + for i in range(0, self.info['vcpus_number']): info = xc.vcpu_getinfo(self.domid, i) sxpr.append(['vcpu', @@ -908,8 +889,9 @@ class XendDomainInfo: self._writeDom(self._vcpuDomDetails()) else: self.info['vcpus_number'] = vcpus - self.info['online_vcpus'] = vcpus xen.xend.XendDomain.instance().managed_config_save(self) + log.info("Set VCPU count on domain %s to %d", self.info['name_label'], + vcpus) def getLabel(self): return security.get_security_info(self.info, 'label') @@ -1394,7 +1376,7 @@ class XendDomainInfo: # 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: - for v in range(0, self.info['max_vcpu_id']+1): + for v in range(0, self.info['vcpus_number']): xc.vcpu_setaffinity(self.domid, v, self.info['cpus']) # Use architecture- and image-specific calculations to determine @@ -2052,8 +2034,8 @@ class XendDomainInfo: # TODO: spec says that key is int, however, python does not allow # non-string keys to dictionaries. vcpu_util = {} - if 'max_vcpu_id' in self.info and self.domid != None: - for i in range(0, self.info['max_vcpu_id']+1): + if 'vcpus_number' in self.info and self.domid != None: + for i in range(0, self.info['vcpus_number']): info = xc.vcpu_getinfo(self.domid, i) vcpu_util[str(i)] = info['cpu_time']/1000000000.0 diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index a7db1bf860..348590c126 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -377,11 +377,12 @@ class HVMImageHandler(ImageHandler): # xm config file def parseDeviceModelArgs(self, imageConfig, deviceConfig): dmargs = [ 'boot', 'fda', 'fdb', 'soundhw', - 'localtime', 'serial', 'stdvga', 'isa', 'vcpus', + 'localtime', 'serial', 'stdvga', 'isa', 'acpi', 'usb', 'usbdevice', 'keymap' ] - ret = [] hvmDeviceConfig = imageConfig['hvm']['devices'] - + + ret = ['-vcpus', str(self.vm.getVCpuCount())] + for a in dmargs: v = hvmDeviceConfig.get(a) diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index e0fe857885..fb42f44c64 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -190,6 +190,10 @@ gopts.var('vcpus', val='VCPUS', fn=set_int, default=1, use="# of Virtual CPUS in domain.") +gopts.var('vcpu_avail', val='VCPUS', + fn=set_long, default=None, + use="Bitmask for virtual CPUs to make available immediately.") + gopts.var('cpu_cap', val='CAP', fn=set_int, default=None, use="""Set the maximum amount of cpu. @@ -740,7 +744,7 @@ def make_config(vals): map(add_conf, ['name', 'memory', 'maxmem', 'shadow_memory', 'restart', 'on_poweroff', - 'on_reboot', 'on_crash', 'vcpus', 'features', + 'on_reboot', 'on_crash', 'vcpus', 'vcpu_avail', 'features', 'on_xend_start', 'on_xend_stop']) if vals.uuid is not None: diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 87a0602e2d..95990f8f62 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -693,12 +693,15 @@ def parse_doms_info(info): up_time = time.time() - start_time return { - 'domid' : get_info('domid', str, ''), - 'name' : get_info('name', str, '??'), + 'domid' : get_info('domid', str, ''), + 'name' : get_info('name', str, '??'), 'mem' : get_info('memory_dynamic_min', int, 0), - 'vcpus' : get_info('online_vcpus', int, 0), - 'state' : get_info('state', str, ''), - 'cpu_time' : get_info('cpu_time', float, 0), + 'state' : get_info('state', str, ''), + 'cpu_time' : get_info('cpu_time', float, 0.0), + # VCPUs is the number online when the VM is up, or the number + # configured otherwise. + 'vcpus' : get_info('online_vcpus', int, + get_info('vcpus', int, 0)), 'up_time' : up_time, 'seclabel' : security.get_security_printlabel(info), } diff --git a/tools/python/xen/xm/opts.py b/tools/python/xen/xm/opts.py index 7dd28bfa4e..1b80ceeff8 100644 --- a/tools/python/xen/xm/opts.py +++ b/tools/python/xen/xm/opts.py @@ -571,6 +571,14 @@ def set_int(opt, k, v): opt.opts.err('Invalid value: ' + str(v)) opt.set(v) +def set_long(opt, k, v): + """Set an option to a long integer value.""" + try: + v = long(v) + except: + opt.opts.err('Invalid value: ' + str(v)) + opt.set(v) + def set_float(opt, k, v): """Set an option to a float value.""" try: