cpu: make governors to be optional

Change-Id: Ifb7d001cfdb95b1b0aa29f45c0ef71c0673e1760
Closes-Bug: #2023018
(cherry picked from commit 2c4421568e)
(cherry picked from commit 891d1773a2)
This commit is contained in:
Sylvain Bauza 2023-06-06 11:56:32 +02:00 committed by Balazs Gibizer
parent bb472db2cd
commit 5c33bd4dfc
6 changed files with 74 additions and 8 deletions

View File

@ -772,6 +772,11 @@ while there could be other tools outside Nova to manage the governor, like
tuned. That being said, we also provide a way to automatically change the
governors on the fly, as explained below.
.. important::
Some OS platforms don't support `cpufreq` resources in sysfs, so the
``governor`` strategy could be not available. Please verify if your OS
supports scaling govenors before modifying the configuration option.
If the strategy is set to ``governor``, a couple of config options are provided
to define which exact CPU govenor to use for each of the up and down states :

View File

@ -39,10 +39,14 @@ class TempFileSystemFixture(fixtures.Fixture):
class SysFileSystemFixture(TempFileSystemFixture):
"""Creates a fake /sys filesystem"""
def __init__(self, cpus_supported=None, cpufreq_enabled=True):
"""Instantiates a fake sysfs.
def __init__(self, cpus_supported=None):
:param cpus_supported: number of devices/system/cpu (default: 10)
:param cpufreq_enabled: cpufreq subdir created (default: True)
"""
self.cpus_supported = cpus_supported or 10
self.cpufreq_enabled = cpufreq_enabled
def _setUp(self):
super()._setUp()
@ -73,9 +77,12 @@ class SysFileSystemFixture(TempFileSystemFixture):
for cpu_nr in range(self.cpus_supported):
cpu_dir = os.path.join(self.cpu_path_mock % {'core': cpu_nr})
os.makedirs(os.path.join(cpu_dir, 'cpufreq'))
filesystem.write_sys(
os.path.join(cpu_dir, 'cpufreq/scaling_governor'),
data='powersave')
os.makedirs(cpu_dir)
filesystem.write_sys(os.path.join(cpu_dir, 'online'), data='1')
if self.cpufreq_enabled:
os.makedirs(os.path.join(cpu_dir, 'cpufreq'))
filesystem.write_sys(
os.path.join(cpu_dir, 'cpufreq/scaling_governor'),
data='powersave')
filesystem.write_sys(core.AVAILABLE_PATH,
f'0-{self.cpus_supported - 1}')

View File

@ -220,6 +220,39 @@ class PowerManagementTestsGovernor(PowerManagementTestsBase):
self.restart_compute_service, hostname='compute1')
class PowerManagementTestsGovernorNotSupported(PowerManagementTestsBase):
"""Test suite for OS without governor support usage (same 10-core host)"""
def setUp(self):
super(PowerManagementTestsGovernorNotSupported, self).setUp()
self.useFixture(nova_fixtures.SysFileSystemFixture(
cpufreq_enabled=False))
# Definining the CPUs to be pinned.
self.flags(cpu_dedicated_set='1-9', cpu_shared_set=None,
group='compute')
self.flags(vcpu_pin_set=None)
self.flags(cpu_power_management=True, group='libvirt')
self.flags(cpu_power_management_strategy='cpu_state', group='libvirt')
self.flags(allow_resize_to_same_host=True)
self.host_info = fakelibvirt.HostInfo(cpu_nodes=1, cpu_sockets=1,
cpu_cores=5, cpu_threads=2)
def test_enabling_governor_strategy_fails(self):
self.flags(cpu_power_management_strategy='governor', group='libvirt')
self.assertRaises(exception.FileNotFound, self.start_compute,
host_info=self.host_info, hostname='compute1')
def test_enabling_cpu_state_strategy_works(self):
self.flags(cpu_power_management_strategy='cpu_state', group='libvirt')
self.compute1 = self.start_compute(host_info=self.host_info,
hostname='compute1')
cpu_dedicated_set = hardware.get_cpu_dedicated_set()
self._assert_cpu_set_state(cpu_dedicated_set, expected='offline')
class PowerManagementMixedInstances(PowerManagementTestsBase):
"""Test suite for a single host with 6 dedicated cores, 3 shared and one
OS-restricted.

View File

@ -57,6 +57,12 @@ class TestAPI(test.NoDBTestCase):
self.assertEqual('fake_governor', self.core_1.governor)
mock_get_governor.assert_called_once_with(self.core_1.ident)
@mock.patch.object(core, 'get_governor')
def test_governor_optional(self, mock_get_governor):
mock_get_governor.side_effect = exception.FileNotFound(file_path='foo')
self.assertIsNone(self.core_1.governor)
mock_get_governor.assert_called_once_with(self.core_1.ident)
@mock.patch.object(core, 'set_governor')
def test_set_governor_low(self, mock_set_governor):
self.flags(cpu_power_governor_low='fake_low_gov', group='libvirt')

View File

@ -11,6 +11,7 @@
# under the License.
from dataclasses import dataclass
import typing as ty
from oslo_log import log as logging
@ -59,8 +60,13 @@ class Core:
return str(self.ident)
@property
def governor(self) -> str:
return core.get_governor(self.ident)
def governor(self) -> ty.Optional[str]:
try:
return core.get_governor(self.ident)
# NOTE(sbauza): cpufreq/scaling_governor is not enabled for some OS
# platforms.
except exception.FileNotFound:
return None
def set_high_governor(self) -> None:
core.set_governor(self.ident, CONF.libvirt.cpu_power_governor_high)

View File

@ -0,0 +1,9 @@
---
fixes:
- |
Some OS platforms don't provide by default cpufreq resources in sysfs, so
they don't have CPU scaling governors. That's why we should let the governor
strategy to be optional for `CPU power management`_.
.. _CPU power management: https://docs.openstack.org/nova/latest/admin/cpu-topologies.html#configuring-cpu-power-management-for-dedicated-cores