summaryrefslogtreecommitdiffstats
path: root/nova/virt
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2013-05-13 07:09:49 +0000
committerGerrit Code Review <review@openstack.org>2013-05-13 07:09:49 +0000
commit72da62feb2596fc32a0f3f349db042c10f13fa0d (patch)
tree3ad1bd41b902882c7ce8487eb5b36cc4251e76c6 /nova/virt
parent5dba32a23e67341bfdc03a00781ab491238e21f4 (diff)
parent37b4ae369f3a086990d3c1499bf8b741c7226107 (diff)
Merge "Add cpuset attr to vcpu conf in libvirt xml"
Diffstat (limited to 'nova/virt')
-rw-r--r--nova/virt/libvirt/config.py8
-rwxr-xr-xnova/virt/libvirt/driver.py75
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.