From 21a07f92e8d757c96528b0425064b297bb807637 Mon Sep 17 00:00:00 2001 From: Vladik Romanovsky Date: Fri, 17 Oct 2014 17:53:17 -0400 Subject: [PATCH] libvirt: set guest cpu_shares value as a multiple of guest vCPUs Currently, a default value of cpu_shares is being assigned to all guest instances, regardless of the number of vCPUs has been configured for each guest. As cpu_shares are specifying the weight to provide CPU time, this reduces the amount of time each vCPU gets, for instances with a higher number of vCPUs. Setting the default value of guest cpu.shares to be a multiple of the number of guest vcpus. Closes-Bug: #1383377 Change-Id: I3a669da3536061919e3673da88c102a868999902 --- nova/tests/unit/virt/libvirt/test_driver.py | 27 ++++++++++++++++++--- nova/virt/libvirt/driver.py | 24 ++++++++++++------ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index 3a2086e2ac..4a060286a6 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -1205,7 +1205,7 @@ class LibvirtConnTestCase(test.NoDBTestCase): random, 'choice', side_effect=lambda cells: cells[0])): cfg = conn._get_guest_config(instance_ref, [], {}, disk_info) self.assertEqual(set([0, 1]), cfg.cpuset) - self.assertIsNone(cfg.cputune) + self.assertEqual(0, len(cfg.cputune.vcpupin)) self.assertIsNone(cfg.cpu.numa) @mock.patch.object(objects.Flavor, 'get_by_id') @@ -1237,7 +1237,7 @@ class LibvirtConnTestCase(test.NoDBTestCase): cfg = conn._get_guest_config(instance_ref, [], {}, disk_info) self.assertFalse(choice_mock.called) self.assertEqual(set([3]), cfg.cpuset) - self.assertIsNone(cfg.cputune) + self.assertEqual(0, len(cfg.cputune.vcpupin)) self.assertIsNone(cfg.cpu.numa) @mock.patch.object(objects.Flavor, 'get_by_id') @@ -1275,7 +1275,7 @@ class LibvirtConnTestCase(test.NoDBTestCase): # when choosing viable cells choice_mock.assert_called_once_with([set([2, 3])]) self.assertEqual(set([2, 3]), cfg.cpuset) - self.assertIsNone(cfg.cputune) + self.assertEqual(0, len(cfg.cputune.vcpupin)) self.assertIsNone(cfg.cpu.numa) @mock.patch.object(objects.Flavor, 'get_by_id') @@ -1312,7 +1312,7 @@ class LibvirtConnTestCase(test.NoDBTestCase): conn, "_get_host_capabilities", return_value=caps)): cfg = conn._get_guest_config(instance_ref, [], {}, disk_info) self.assertIsNone(cfg.cpuset) - self.assertIsNone(cfg.cputune) + self.assertEqual(0, len(cfg.cputune.vcpupin)) self.assertIsNone(cfg.numatune) self.assertIsNotNone(cfg.cpu.numa) for instance_cell, numa_cfg_cell in zip( @@ -3024,6 +3024,25 @@ class LibvirtConnTestCase(test.NoDBTestCase): [], image_meta, disk_info) + @mock.patch.object(objects.Flavor, 'get_by_id') + def test_guest_cpu_shares_with_multi_vcpu(self, mock_flavor): + self.flags(virt_type='kvm', group='libvirt') + + conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) + + instance_ref = objects.Instance(**self.test_instance) + flavor = instance_ref.get_flavor() + flavor.extra_specs = {} + flavor.vcpus = 4 + mock_flavor.return_value = flavor + + disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type, + instance_ref) + + cfg = conn._get_guest_config(instance_ref, [], {}, disk_info) + + self.assertEqual(4096, cfg.cputune.shares) + @mock.patch.object(objects.Flavor, 'get_by_id') def test_get_guest_config_with_cpu_quota(self, mock_flavor): self.flags(virt_type='kvm', group='libvirt') diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 2f2cc0e312..b8a0277560 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -3427,6 +3427,21 @@ class LibvirtDriver(driver.ComputeDriver): id_maps.extend(gid_maps) return id_maps + def _update_guest_cputune(self, guest, flavor, virt_type): + if virt_type in ('lxc', 'kvm', 'qemu'): + if guest.cputune is None: + guest.cputune = vconfig.LibvirtConfigGuestCPUTune() + # Setting the default cpu.shares value to be a value + # dependent on the number of vcpus + guest.cputune.shares = 1024 * guest.vcpus + + cputuning = ['shares', 'period', 'quota'] + for name in cputuning: + key = "quota:cpu_" + name + if key in flavor.extra_specs: + setattr(guest.cputune, name, + int(flavor.extra_specs[key])) + def _get_cpu_numa_config_from_instance(self, instance_numa_topology): if instance_numa_topology: guest_cpu_numa = vconfig.LibvirtConfigGuestCPUNUMA() @@ -3771,14 +3786,7 @@ class LibvirtDriver(driver.ComputeDriver): flavor)) guest.idmaps = self._get_guest_idmaps() - cputuning = ['shares', 'period', 'quota'] - for name in cputuning: - key = "quota:cpu_" + name - if key in flavor.extra_specs: - if guest.cputune is None: - guest.cputune = vconfig.LibvirtConfigGuestCPUTune() - setattr(guest.cputune, name, - int(flavor.extra_specs[key])) + self._update_guest_cputune(guest, flavor, virt_type) guest.cpu = self._get_guest_cpu_config( flavor, image_meta, guest_cpu_numa)