diff options
author | John Garbutt <john.garbutt@rackspace.com> | 2013-11-15 15:44:26 +0000 |
---|---|---|
committer | John Garbutt <john.garbutt@rackspace.com> | 2014-01-03 13:27:50 +0000 |
commit | 3c25a3fe3ffeb899d6a8c93549988ea38750468b (patch) | |
tree | d33c28e5b4776c0ca0b666116b7943d461068c7e | |
parent | 01f85bdc057376708a1c1cca65bbcc85af494bfa (diff) | |
download | nova-3c25a3fe3ffeb899d6a8c93549988ea38750468b.tar.gz |
xenapi: add support for vcpu_pin_set
This moves vcpu_pin_set config from the libvirt driver into a place that
can be shared between drivers, nova.virt.cpu
At the same time, the utility function that converts the configuration
value into a list of integers has also been moved into nova.virt.cpu
This new code is then used in the XenAPI driver to apply a CPU mask that
implements the currently configured value for vcpu_pin_set
The main use case for this setting is to ensure all guest VMs are not
using the physical CPUs that Dom0 are configured to use.
DocImpact
Completes blueprint xenapi-vcpu-pin-set
Change-Id: I9d53d93db0c5f2a11ad685d3fc335f0cd6b1f79b
-rw-r--r-- | etc/nova/nova.conf.sample | 13 | ||||
-rw-r--r-- | nova/tests/virt/libvirt/test_libvirt.py | 100 | ||||
-rw-r--r-- | nova/tests/virt/test_cpu.py | 110 | ||||
-rw-r--r-- | nova/tests/virt/xenapi/test_vm_utils.py | 94 | ||||
-rw-r--r-- | nova/virt/cpu.py | 88 | ||||
-rw-r--r-- | nova/virt/libvirt/driver.py | 62 | ||||
-rw-r--r-- | nova/virt/xenapi/vm_utils.py | 6 |
7 files changed, 280 insertions, 193 deletions
diff --git a/etc/nova/nova.conf.sample b/etc/nova/nova.conf.sample index 5856a03d36..efcec13a73 100644 --- a/etc/nova/nova.conf.sample +++ b/etc/nova/nova.conf.sample @@ -1884,6 +1884,15 @@ # +# Options defined in nova.virt.cpu +# + +# Which pcpus can be used by vcpus of instance e.g: +# "4-12,^8,15" (string value) +#vcpu_pin_set=<None> + + +# # Options defined in nova.virt.disk.api # @@ -2593,10 +2602,6 @@ # file=directsync,block=none (list value) #disk_cachemodes= -# Which pcpus can be used by vcpus of instance e.g: -# "4-12,^8,15" (string value) -#vcpu_pin_set=<None> - # # Options defined in nova.virt.libvirt.imagebackend diff --git a/nova/tests/virt/libvirt/test_libvirt.py b/nova/tests/virt/libvirt/test_libvirt.py index 754a5d0a3d..e6370dec2e 100644 --- a/nova/tests/virt/libvirt/test_libvirt.py +++ b/nova/tests/virt/libvirt/test_libvirt.py @@ -7494,106 +7494,6 @@ class LibvirtDriverTestCase(test.TestCase): self.libvirtconnection.get_instance_disk_info, instance_name) - def test_get_cpuset_ids(self): - # correct syntax - self.flags(vcpu_pin_set="1", group='libvirt') - cpuset_ids = self.libvirtconnection._get_cpuset_ids() - self.assertEqual([1], cpuset_ids) - - self.flags(vcpu_pin_set="1,2", group='libvirt') - cpuset_ids = self.libvirtconnection._get_cpuset_ids() - self.assertEqual([1, 2], cpuset_ids) - - self.flags(vcpu_pin_set=", , 1 , ,, 2, ,", group='libvirt') - cpuset_ids = self.libvirtconnection._get_cpuset_ids() - self.assertEqual([1, 2], cpuset_ids) - - self.flags(vcpu_pin_set="1-1", group='libvirt') - cpuset_ids = self.libvirtconnection._get_cpuset_ids() - self.assertEqual([1], cpuset_ids) - - self.flags(vcpu_pin_set=" 1 - 1, 1 - 2 , 1 -3", group='libvirt') - cpuset_ids = self.libvirtconnection._get_cpuset_ids() - self.assertEqual([1, 2, 3], cpuset_ids) - - self.flags(vcpu_pin_set="1,^2", group='libvirt') - cpuset_ids = self.libvirtconnection._get_cpuset_ids() - self.assertEqual([1], cpuset_ids) - - self.flags(vcpu_pin_set="1-2, ^1", group='libvirt') - cpuset_ids = self.libvirtconnection._get_cpuset_ids() - self.assertEqual([2], cpuset_ids) - - self.flags(vcpu_pin_set="1-3,5,^2", group='libvirt') - cpuset_ids = self.libvirtconnection._get_cpuset_ids() - self.assertEqual([1, 3, 5], cpuset_ids) - - self.flags(vcpu_pin_set=" 1 - 3 , ^2, 5", - group='libvirt') - cpuset_ids = self.libvirtconnection._get_cpuset_ids() - self.assertEqual([1, 3, 5], cpuset_ids) - - # invalid syntax - self.flags(vcpu_pin_set=" -1-3,5,^2", group='libvirt') - self.assertRaises(exception.Invalid, - self.libvirtconnection._get_cpuset_ids) - - self.flags(vcpu_pin_set="1-3-,5,^2", group='libvirt') - self.assertRaises(exception.Invalid, - self.libvirtconnection._get_cpuset_ids) - - self.flags(vcpu_pin_set="-3,5,^2", group='libvirt') - self.assertRaises(exception.Invalid, - self.libvirtconnection._get_cpuset_ids) - - self.flags(vcpu_pin_set="1-,5,^2", group='libvirt') - self.assertRaises(exception.Invalid, - self.libvirtconnection._get_cpuset_ids) - - self.flags(vcpu_pin_set="1-3,5,^2^", group='libvirt') - self.assertRaises(exception.Invalid, - self.libvirtconnection._get_cpuset_ids) - - self.flags(vcpu_pin_set="1-3,5,^2-", group='libvirt') - self.assertRaises(exception.Invalid, - self.libvirtconnection._get_cpuset_ids) - - self.flags(vcpu_pin_set="--13,^^5,^2", group='libvirt') - self.assertRaises(exception.Invalid, - self.libvirtconnection._get_cpuset_ids) - - self.flags(vcpu_pin_set="a-3,5,^2", group='libvirt') - self.assertRaises(exception.Invalid, - self.libvirtconnection._get_cpuset_ids) - - self.flags(vcpu_pin_set="1-a,5,^2", group='libvirt') - self.assertRaises(exception.Invalid, - self.libvirtconnection._get_cpuset_ids) - - self.flags(vcpu_pin_set="1-3,b,^2", group='libvirt') - self.assertRaises(exception.Invalid, - self.libvirtconnection._get_cpuset_ids) - - self.flags(vcpu_pin_set="1-3,5,^c", group='libvirt') - self.assertRaises(exception.Invalid, - self.libvirtconnection._get_cpuset_ids) - - self.flags(vcpu_pin_set="3 - 1, 5 , ^ 2 ", group='libvirt') - self.assertRaises(exception.Invalid, - self.libvirtconnection._get_cpuset_ids) - - self.flags(vcpu_pin_set=" 1,1, ^1", group='libvirt') - self.assertRaises(exception.Invalid, - self.libvirtconnection._get_cpuset_ids) - - self.flags(vcpu_pin_set=" 1,^1,^1,2, ^2", group='libvirt') - self.assertRaises(exception.Invalid, - self.libvirtconnection._get_cpuset_ids) - - self.flags(vcpu_pin_set="^2", group='libvirt') - self.assertRaises(exception.Invalid, - self.libvirtconnection._get_cpuset_ids) - class LibvirtVolumeUsageTestCase(test.TestCase): """Test for LibvirtDriver.get_all_volume_usage.""" diff --git a/nova/tests/virt/test_cpu.py b/nova/tests/virt/test_cpu.py new file mode 100644 index 0000000000..fb97c408a9 --- /dev/null +++ b/nova/tests/virt/test_cpu.py @@ -0,0 +1,110 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# 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.assertEqual(None, 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) diff --git a/nova/tests/virt/xenapi/test_vm_utils.py b/nova/tests/virt/xenapi/test_vm_utils.py index 2a5d7c361a..2e878f7039 100644 --- a/nova/tests/virt/xenapi/test_vm_utils.py +++ b/nova/tests/virt/xenapi/test_vm_utils.py @@ -1430,42 +1430,72 @@ class ScanSrTestCase(VMUtilsTestBase): mock_sleep.assert_called_once_with(2) -class AllowVSSProviderTest(VMUtilsTestBase): - def setUp(self): - super(AllowVSSProviderTest, self).setUp() - self.flags(disable_process_locking=True, - instance_name_template='%d', - firewall_driver='nova.virt.xenapi.firewall.' - 'Dom0IptablesFirewallDriver') - self.flags(connection_url='test_url', - connection_password='test_pass', - group='xenserver') - stubs.stubout_session(self.stubs, fake.SessionBase) - driver = xenapi_conn.XenAPIDriver(False) - self.session = driver._session - self.session.is_local_connection = False - self.instance = { - 'uuid': 'fakeinstance', - 'kernel_id': 'kernel', +@mock.patch.object(flavors, 'extract_flavor', + return_value={ + 'memory_mb': 1024, + 'vcpus': 1, + 'vcpu_weight': 1.0, + }) +class CreateVmTestCase(VMUtilsTestBase): + def test_vss_provider(self, mock_extract): + self.flags(vcpu_pin_set="2,3") + session = mock.Mock() + instance = { + "uuid": "uuid", } - def test_allow_vss_provider(self): - def fake_extract_flavor(inst): - return { - 'memory_mb': 1024, - 'vcpus': 1, - 'vcpu_weight': 1.0, - } - - def fake_call_xenapi(command, rec): - xenstore_data = rec.get('xenstore_data') - self.assertIn('vm-data/allowvssprovider', xenstore_data) - - self.stubs.Set(flavors, 'extract_flavor', fake_extract_flavor) - self.stubs.Set(self.session, 'call_xenapi', fake_call_xenapi) - vm_utils.create_vm(self.session, self.instance, "label", + vm_utils.create_vm(session, instance, "label", "kernel", "ramdisk") + vm_rec = { + 'VCPUs_params': {'cap': '0', 'mask': '2,3', 'weight': '1.0'}, + 'PV_args': '', + 'memory_static_min': '0', + 'ha_restart_priority': '', + 'HVM_boot_policy': 'BIOS order', + 'PV_bootloader': '', 'tags': [], + 'VCPUs_max': '1', + 'memory_static_max': '1073741824', + 'actions_after_shutdown': 'destroy', + 'memory_dynamic_max': '1073741824', + 'user_version': '0', + 'xenstore_data': {'vm-data/allowvssprovider': 'false'}, + 'blocked_operations': {}, + 'is_a_template': False, + 'name_description': '', + 'memory_dynamic_min': '1073741824', + 'actions_after_crash': 'destroy', + 'memory_target': '1073741824', + 'PV_ramdisk': '', + 'PV_bootloader_args': '', + 'PCI_bus': '', + 'other_config': {'nova_uuid': 'uuid'}, + 'name_label': 'label', + 'actions_after_reboot': 'restart', + 'VCPUs_at_startup': '1', + 'HVM_boot_params': {'order': 'dc'}, + 'platform': {'nx': 'true', 'pae': 'true', 'apic': 'true', + 'timeoffset': '0', 'viridian': 'true', + 'acpi': 'true'}, + 'PV_legacy_args': '', + 'PV_kernel': '', + 'affinity': '', + 'recommendations': '', + 'ha_always_run': False + } + session.call_xenapi.assert_called_once_with("VM.create", vm_rec) + + def test_invalid_cpu_mask_raises(self, mock_extract): + self.flags(vcpu_pin_set="asdf") + session = mock.Mock() + instance = { + "uuid": "uuid", + } + self.assertRaises(exception.Invalid, + vm_utils.create_vm, + session, instance, "label", + "kernel", "ramdisk") + class DetermineVmModeTestCase(VMUtilsTestBase): def test_determine_vm_mode_returns_xen_mode(self): diff --git a/nova/virt/cpu.py b/nova/virt/cpu.py new file mode 100644 index 0000000000..6be25b7c75 --- /dev/null +++ b/nova/virt/cpu.py @@ -0,0 +1,88 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# 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='Which pcpus can be used by vcpus of instance ' + 'e.g: "4-12,^8,15"', + deprecated_group='libvirt'), +] + +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) diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 5c557febe6..eec7120475 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -91,6 +91,7 @@ from nova import unit from nova import utils from nova import version 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 @@ -248,10 +249,6 @@ libvirt_opts = [ help='Specific cachemodes to use for different disk types ' 'e.g: file=directsync,block=none', deprecated_group='DEFAULT'), - cfg.StrOpt('vcpu_pin_set', - help='Which pcpus can be used by vcpus of instance ' - 'e.g: "4-12,^8,15"', - deprecated_group='DEFAULT'), ] CONF = cfg.CONF @@ -263,6 +260,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') DEFAULT_FIREWALL_DRIVER = "%s.%s" % ( libvirt_firewall.__name__, @@ -2991,7 +2989,7 @@ class LibvirtDriver(driver.ComputeDriver): guest.uuid = instance['uuid'] guest.memory = inst_type['memory_mb'] * 1024 guest.vcpus = inst_type['vcpus'] - guest.cpuset = CONF.libvirt.vcpu_pin_set + guest.cpuset = CONF.vcpu_pin_set quota_items = ['cpu_shares', 'cpu_period', 'cpu_quota'] for key, value in inst_type['extra_specs'].iteritems(): @@ -3498,56 +3496,6 @@ 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.libvirt.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.libvirt.vcpu_pin_set) - # This will convert the set to a sorted list for us - return sorted(cpuset_ids) - def get_vcpu_total(self): """Get available vcpu number of physical computer. @@ -3564,11 +3512,11 @@ class LibvirtDriver(driver.ComputeDriver): "function is not implemented for this platform. ")) return 0 - if CONF.libvirt.vcpu_pin_set is None: + if CONF.vcpu_pin_set is None: self._vcpu_total = total_pcpus return self._vcpu_total - available_ids = self._get_cpuset_ids() + available_ids = cpu.get_cpuset_ids() if available_ids[-1] >= total_pcpus: raise exception.Invalid(_("Invalid vcpu_pin_set config, " "out of hypervisor cpu range.")) diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index fea691aab3..580f9fcd59 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -52,6 +52,7 @@ from nova.openstack.common import xmlutils from nova import unit 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.xenapi import agent @@ -267,6 +268,11 @@ 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() + if cpu_mask_list: + cpu_mask = ",".join(str(cpu_id) for cpu_id in cpu_mask_list) + vcpu_params["mask"] = cpu_mask + rec = { 'actions_after_crash': 'destroy', 'actions_after_reboot': 'restart', |