virt: move get_cpuset_ids into nova.virt.hardware
The nova.virt.cpu module has a single helper method for getting the instance vCPU pin list. The new module nova.virt.hardware is intended to be a single place for all helpers related to guest hardware configuration, so it is a natural place for the get_cpuset_ids method. Rename it to 'get_vcpu_pin_set' to slightly clarify its purpose too. Blueprint: virt-driver-numa-placement Blueprint: virt-driver-cpu-pinning Change-Id: Id106737dc40471e8d31fbc002256b70e0b6ad5f6
This commit is contained in:
@@ -1,108 +0,0 @@
|
||||
# Copyright 2013 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from nova import exception
|
||||
from nova import test
|
||||
from nova.virt import cpu
|
||||
|
||||
|
||||
class CpuSetTestCase(test.NoDBTestCase):
|
||||
def test_get_cpuset_ids_none_returns_none(self):
|
||||
self.flags(vcpu_pin_set=None)
|
||||
cpuset_ids = cpu.get_cpuset_ids()
|
||||
self.assertIsNone(cpuset_ids)
|
||||
|
||||
def test_get_cpuset_ids_valid_syntax_works(self):
|
||||
self.flags(vcpu_pin_set="1")
|
||||
cpuset_ids = cpu.get_cpuset_ids()
|
||||
self.assertEqual([1], cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="1,2")
|
||||
cpuset_ids = cpu.get_cpuset_ids()
|
||||
self.assertEqual([1, 2], cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set=", , 1 , ,, 2, ,")
|
||||
cpuset_ids = cpu.get_cpuset_ids()
|
||||
self.assertEqual([1, 2], cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="1-1")
|
||||
cpuset_ids = cpu.get_cpuset_ids()
|
||||
self.assertEqual([1], cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set=" 1 - 1, 1 - 2 , 1 -3")
|
||||
cpuset_ids = cpu.get_cpuset_ids()
|
||||
self.assertEqual([1, 2, 3], cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="1,^2")
|
||||
cpuset_ids = cpu.get_cpuset_ids()
|
||||
self.assertEqual([1], cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="1-2, ^1")
|
||||
cpuset_ids = cpu.get_cpuset_ids()
|
||||
self.assertEqual([2], cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="1-3,5,^2")
|
||||
cpuset_ids = cpu.get_cpuset_ids()
|
||||
self.assertEqual([1, 3, 5], cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set=" 1 - 3 , ^2, 5")
|
||||
cpuset_ids = cpu.get_cpuset_ids()
|
||||
self.assertEqual([1, 3, 5], cpuset_ids)
|
||||
|
||||
def test_get_cpuset_ids_invalid_syntax_raises(self):
|
||||
self.flags(vcpu_pin_set=" -1-3,5,^2")
|
||||
self.assertRaises(exception.Invalid, cpu.get_cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="1-3-,5,^2")
|
||||
self.assertRaises(exception.Invalid, cpu.get_cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="-3,5,^2")
|
||||
self.assertRaises(exception.Invalid, cpu.get_cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="1-,5,^2")
|
||||
self.assertRaises(exception.Invalid, cpu.get_cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="1-3,5,^2^")
|
||||
self.assertRaises(exception.Invalid, cpu.get_cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="1-3,5,^2-")
|
||||
self.assertRaises(exception.Invalid, cpu.get_cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="--13,^^5,^2")
|
||||
self.assertRaises(exception.Invalid, cpu.get_cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="a-3,5,^2")
|
||||
self.assertRaises(exception.Invalid, cpu.get_cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="1-a,5,^2")
|
||||
self.assertRaises(exception.Invalid, cpu.get_cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="1-3,b,^2")
|
||||
self.assertRaises(exception.Invalid, cpu.get_cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="1-3,5,^c")
|
||||
self.assertRaises(exception.Invalid, cpu.get_cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="3 - 1, 5 , ^ 2 ")
|
||||
self.assertRaises(exception.Invalid, cpu.get_cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set=" 1,1, ^1")
|
||||
self.assertRaises(exception.Invalid, cpu.get_cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set=" 1,^1,^1,2, ^2")
|
||||
self.assertRaises(exception.Invalid, cpu.get_cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="^2")
|
||||
self.assertRaises(exception.Invalid, cpu.get_cpuset_ids)
|
||||
@@ -23,6 +23,96 @@ class FakeFlavor():
|
||||
self.extra_specs = extra_specs
|
||||
|
||||
|
||||
class CpuSetTestCase(test.NoDBTestCase):
|
||||
def test_get_vcpu_pin_set_none_returns_none(self):
|
||||
self.flags(vcpu_pin_set=None)
|
||||
cpuset_ids = hw.get_vcpu_pin_set()
|
||||
self.assertIsNone(cpuset_ids)
|
||||
|
||||
def test_get_vcpu_pin_set_valid_syntax_works(self):
|
||||
self.flags(vcpu_pin_set="1")
|
||||
cpuset_ids = hw.get_vcpu_pin_set()
|
||||
self.assertEqual([1], cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="1,2")
|
||||
cpuset_ids = hw.get_vcpu_pin_set()
|
||||
self.assertEqual([1, 2], cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set=", , 1 , ,, 2, ,")
|
||||
cpuset_ids = hw.get_vcpu_pin_set()
|
||||
self.assertEqual([1, 2], cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="1-1")
|
||||
cpuset_ids = hw.get_vcpu_pin_set()
|
||||
self.assertEqual([1], cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set=" 1 - 1, 1 - 2 , 1 -3")
|
||||
cpuset_ids = hw.get_vcpu_pin_set()
|
||||
self.assertEqual([1, 2, 3], cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="1,^2")
|
||||
cpuset_ids = hw.get_vcpu_pin_set()
|
||||
self.assertEqual([1], cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="1-2, ^1")
|
||||
cpuset_ids = hw.get_vcpu_pin_set()
|
||||
self.assertEqual([2], cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set="1-3,5,^2")
|
||||
cpuset_ids = hw.get_vcpu_pin_set()
|
||||
self.assertEqual([1, 3, 5], cpuset_ids)
|
||||
|
||||
self.flags(vcpu_pin_set=" 1 - 3 , ^2, 5")
|
||||
cpuset_ids = hw.get_vcpu_pin_set()
|
||||
self.assertEqual([1, 3, 5], cpuset_ids)
|
||||
|
||||
def test_get_vcpu_pin_set_invalid_syntax_raises(self):
|
||||
self.flags(vcpu_pin_set=" -1-3,5,^2")
|
||||
self.assertRaises(exception.Invalid, hw.get_vcpu_pin_set)
|
||||
|
||||
self.flags(vcpu_pin_set="1-3-,5,^2")
|
||||
self.assertRaises(exception.Invalid, hw.get_vcpu_pin_set)
|
||||
|
||||
self.flags(vcpu_pin_set="-3,5,^2")
|
||||
self.assertRaises(exception.Invalid, hw.get_vcpu_pin_set)
|
||||
|
||||
self.flags(vcpu_pin_set="1-,5,^2")
|
||||
self.assertRaises(exception.Invalid, hw.get_vcpu_pin_set)
|
||||
|
||||
self.flags(vcpu_pin_set="1-3,5,^2^")
|
||||
self.assertRaises(exception.Invalid, hw.get_vcpu_pin_set)
|
||||
|
||||
self.flags(vcpu_pin_set="1-3,5,^2-")
|
||||
self.assertRaises(exception.Invalid, hw.get_vcpu_pin_set)
|
||||
|
||||
self.flags(vcpu_pin_set="--13,^^5,^2")
|
||||
self.assertRaises(exception.Invalid, hw.get_vcpu_pin_set)
|
||||
|
||||
self.flags(vcpu_pin_set="a-3,5,^2")
|
||||
self.assertRaises(exception.Invalid, hw.get_vcpu_pin_set)
|
||||
|
||||
self.flags(vcpu_pin_set="1-a,5,^2")
|
||||
self.assertRaises(exception.Invalid, hw.get_vcpu_pin_set)
|
||||
|
||||
self.flags(vcpu_pin_set="1-3,b,^2")
|
||||
self.assertRaises(exception.Invalid, hw.get_vcpu_pin_set)
|
||||
|
||||
self.flags(vcpu_pin_set="1-3,5,^c")
|
||||
self.assertRaises(exception.Invalid, hw.get_vcpu_pin_set)
|
||||
|
||||
self.flags(vcpu_pin_set="3 - 1, 5 , ^ 2 ")
|
||||
self.assertRaises(exception.Invalid, hw.get_vcpu_pin_set)
|
||||
|
||||
self.flags(vcpu_pin_set=" 1,1, ^1")
|
||||
self.assertRaises(exception.Invalid, hw.get_vcpu_pin_set)
|
||||
|
||||
self.flags(vcpu_pin_set=" 1,^1,^1,2, ^2")
|
||||
self.assertRaises(exception.Invalid, hw.get_vcpu_pin_set)
|
||||
|
||||
self.flags(vcpu_pin_set="^2")
|
||||
self.assertRaises(exception.Invalid, hw.get_vcpu_pin_set)
|
||||
|
||||
|
||||
class VCPUTopologyTest(test.NoDBTestCase):
|
||||
|
||||
def test_validate_config(self):
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
# Copyright 2013 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo.config import cfg
|
||||
|
||||
from nova import exception
|
||||
from nova.openstack.common.gettextutils import _
|
||||
from nova.openstack.common import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
virt_cpu_opts = [
|
||||
cfg.StrOpt('vcpu_pin_set',
|
||||
help='Defines which pcpus that instance vcpus can use. '
|
||||
'For example, "4-12,^8,15"'),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(virt_cpu_opts)
|
||||
|
||||
|
||||
def get_cpuset_ids():
|
||||
"""Parsing vcpu_pin_set config.
|
||||
|
||||
Returns a list of pcpu ids can be used by instances.
|
||||
"""
|
||||
if not CONF.vcpu_pin_set:
|
||||
return None
|
||||
|
||||
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)
|
||||
@@ -14,12 +14,77 @@
|
||||
|
||||
import collections
|
||||
|
||||
from oslo.config import cfg
|
||||
|
||||
from nova import exception
|
||||
from nova.openstack.common.gettextutils import _
|
||||
from nova.openstack.common import log as logging
|
||||
|
||||
virt_cpu_opts = [
|
||||
cfg.StrOpt('vcpu_pin_set',
|
||||
help='Defines which pcpus that instance vcpus can use. '
|
||||
'For example, "4-12,^8,15"'),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(virt_cpu_opts)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_vcpu_pin_set():
|
||||
"""Parsing vcpu_pin_set config.
|
||||
|
||||
Returns a list of pcpu ids can be used by instances.
|
||||
"""
|
||||
if not CONF.vcpu_pin_set:
|
||||
return None
|
||||
|
||||
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)
|
||||
|
||||
|
||||
class VirtCPUTopology(object):
|
||||
|
||||
def __init__(self, sockets, cores, threads):
|
||||
|
||||
@@ -81,7 +81,6 @@ from nova import utils
|
||||
from nova import version
|
||||
from nova.virt import block_device as driver_block_device
|
||||
from nova.virt import configdrive
|
||||
from nova.virt import cpu
|
||||
from nova.virt.disk import api as disk
|
||||
from nova.virt import driver
|
||||
from nova.virt import event as virtevent
|
||||
@@ -225,7 +224,7 @@ CONF.import_opt('use_cow_images', 'nova.virt.driver')
|
||||
CONF.import_opt('live_migration_retry_count', 'nova.compute.manager')
|
||||
CONF.import_opt('vncserver_proxyclient_address', 'nova.vnc')
|
||||
CONF.import_opt('server_proxyclient_address', 'nova.spice', group='spice')
|
||||
CONF.import_opt('vcpu_pin_set', 'nova.virt.cpu')
|
||||
CONF.import_opt('vcpu_pin_set', 'nova.virt.hardware')
|
||||
CONF.import_opt('vif_plugging_is_fatal', 'nova.virt.driver')
|
||||
CONF.import_opt('vif_plugging_timeout', 'nova.virt.driver')
|
||||
|
||||
@@ -3762,7 +3761,7 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
self._vcpu_total = total_pcpus
|
||||
return self._vcpu_total
|
||||
|
||||
available_ids = cpu.get_cpuset_ids()
|
||||
available_ids = hardware.get_vcpu_pin_set()
|
||||
if available_ids[-1] >= total_pcpus:
|
||||
raise exception.Invalid(_("Invalid vcpu_pin_set config, "
|
||||
"out of hypervisor cpu range."))
|
||||
|
||||
@@ -50,9 +50,9 @@ from nova.openstack.common import versionutils
|
||||
from nova.openstack.common import xmlutils
|
||||
from nova import utils
|
||||
from nova.virt import configdrive
|
||||
from nova.virt import cpu
|
||||
from nova.virt.disk import api as disk
|
||||
from nova.virt.disk.vfs import localfs as vfsimpl
|
||||
from nova.virt import hardware
|
||||
from nova.virt.xenapi import agent
|
||||
from nova.virt.xenapi.image import utils as image_utils
|
||||
from nova.virt.xenapi import volume_utils
|
||||
@@ -240,7 +240,7 @@ def create_vm(session, instance, name_label, kernel, ramdisk,
|
||||
# we need to specify both weight and cap for either to apply
|
||||
vcpu_params = {"weight": str(vcpu_weight), "cap": "0"}
|
||||
|
||||
cpu_mask_list = cpu.get_cpuset_ids()
|
||||
cpu_mask_list = hardware.get_vcpu_pin_set()
|
||||
if cpu_mask_list:
|
||||
cpu_mask = ",".join(str(cpu_id) for cpu_id in cpu_mask_list)
|
||||
vcpu_params["mask"] = cpu_mask
|
||||
|
||||
Reference in New Issue
Block a user