diff options
| author | Jenkins <jenkins@review.openstack.org> | 2013-05-13 07:09:49 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2013-05-13 07:09:49 +0000 |
| commit | 72da62feb2596fc32a0f3f349db042c10f13fa0d (patch) | |
| tree | 3ad1bd41b902882c7ce8487eb5b36cc4251e76c6 /nova/virt | |
| parent | 5dba32a23e67341bfdc03a00781ab491238e21f4 (diff) | |
| parent | 37b4ae369f3a086990d3c1499bf8b741c7226107 (diff) | |
Merge "Add cpuset attr to vcpu conf in libvirt xml"
Diffstat (limited to 'nova/virt')
| -rw-r--r-- | nova/virt/libvirt/config.py | 8 | ||||
| -rwxr-xr-x | nova/virt/libvirt/driver.py | 75 |
2 files changed, 79 insertions, 4 deletions
diff --git a/nova/virt/libvirt/config.py b/nova/virt/libvirt/config.py index 729d27ea4..08a0566dd 100644 --- a/nova/virt/libvirt/config.py +++ b/nova/virt/libvirt/config.py @@ -789,6 +789,7 @@ class LibvirtConfigGuest(LibvirtConfigObject): self.name = None self.memory = 1024 * 1024 * 500 self.vcpus = 1 + self.cpuset = None self.cpu = None self.cpu_shares = None self.cpu_quota = None @@ -812,7 +813,12 @@ class LibvirtConfigGuest(LibvirtConfigObject): root.append(self._text_node("uuid", self.uuid)) root.append(self._text_node("name", self.name)) root.append(self._text_node("memory", self.memory)) - root.append(self._text_node("vcpu", self.vcpus)) + if self.cpuset is not None: + vcpu = self._text_node("vcpu", self.vcpus) + vcpu.set("cpuset", self.cpuset) + root.append(vcpu) + else: + root.append(self._text_node("vcpu", self.vcpus)) def _format_os(self, root): os = etree.Element("os") diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 516c4eb63..6af67bde5 100755 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -211,6 +211,10 @@ libvirt_opts = [ default=[], help='Specific cachemodes to use for different disk types ' 'e.g: ["file=directsync","block=none"]'), + cfg.StrOpt('vcpu_pin_set', + default=None, + help='Which pcpus can be used by vcpus of instance ' + 'e.g: "4-12,^8,15"'), ] CONF = cfg.CONF @@ -305,6 +309,7 @@ class LibvirtDriver(driver.ComputeDriver): self._fc_wwpns = None self._wrapped_conn = None self._caps = None + self._vcpu_total = 0 self.read_only = read_only self.firewall_driver = firewall.load_driver( DEFAULT_FIREWALL_DRIVER, @@ -2146,6 +2151,7 @@ class LibvirtDriver(driver.ComputeDriver): guest.uuid = instance['uuid'] guest.memory = inst_type['memory_mb'] * 1024 guest.vcpus = inst_type['vcpus'] + guest.cpuset = CONF.vcpu_pin_set quota_items = ['cpu_shares', 'cpu_period', 'cpu_quota'] for key, value in inst_type['extra_specs'].iteritems(): @@ -2518,20 +2524,83 @@ class LibvirtDriver(driver.ComputeDriver): return interfaces + def _get_cpuset_ids(self): + """ + Parsing vcpu_pin_set config. + + Returns a list of pcpu ids can be used by instances. + """ + cpuset_ids = set() + cpuset_reject_ids = set() + for rule in CONF.vcpu_pin_set.split(','): + rule = rule.strip() + # Handle multi ',' + if len(rule) < 1: + continue + # Note the count limit in the .split() call + range_parts = rule.split('-', 1) + if len(range_parts) > 1: + # So, this was a range; start by converting the parts to ints + try: + start, end = [int(p.strip()) for p in range_parts] + except ValueError: + raise exception.Invalid(_("Invalid range expression %r") + % rule) + # Make sure it's a valid range + if start > end: + raise exception.Invalid(_("Invalid range expression %r") + % rule) + # Add available pcpu ids to set + cpuset_ids |= set(range(start, end + 1)) + elif rule[0] == '^': + # Not a range, the rule is an exclusion rule; convert to int + try: + cpuset_reject_ids.add(int(rule[1:].strip())) + except ValueError: + raise exception.Invalid(_("Invalid exclusion " + "expression %r") % rule) + else: + # OK, a single PCPU to include; convert to int + try: + cpuset_ids.add(int(rule)) + except ValueError: + raise exception.Invalid(_("Invalid inclusion " + "expression %r") % rule) + # Use sets to handle the exclusion rules for us + cpuset_ids -= cpuset_reject_ids + if not cpuset_ids: + raise exception.Invalid(_("No CPUs available after parsing %r") % + CONF.vcpu_pin_set) + # This will convert the set to a sorted list for us + return sorted(cpuset_ids) + def get_vcpu_total(self): - """Get vcpu number of physical computer. + """Get available vcpu number of physical computer. - :returns: the number of cpu core. + :returns: the number of cpu core instances can be used. """ + if self._vcpu_total != 0: + return self._vcpu_total try: - return self._conn.getInfo()[2] + total_pcpus = self._conn.getInfo()[2] except libvirt.libvirtError: LOG.warn(_("Cannot get the number of cpu, because this " "function is not implemented for this platform. ")) return 0 + if CONF.vcpu_pin_set is None: + self._vcpu_total = total_pcpus + return self._vcpu_total + + available_ids = self._get_cpuset_ids() + if available_ids[-1] >= total_pcpus: + raise exception.Invalid(_("Invalid vcpu_pin_set config, " + "out of hypervisor cpu range.")) + self._vcpu_total = len(available_ids) + return self._vcpu_total + def get_memory_mb_total(self): """Get the total memory size(MB) of physical computer. |
