nova/nova/tests/unit/virt/libvirt/cpu/test_api.py

246 lines
11 KiB
Python

# 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 unittest import mock
from nova import exception
from nova import objects
from nova import test
from nova.virt.libvirt.cpu import api
from nova.virt.libvirt.cpu import core
class TestAPI(test.NoDBTestCase):
def setUp(self):
super(TestAPI, self).setUp()
self.core_1 = api.Core(1)
# Create a fake instance with two pinned CPUs but only one is on the
# dedicated set
numa_topology = objects.InstanceNUMATopology(cells=[
objects.InstanceNUMACell(cpu_pinning_raw={'0': '0', '2': '2'}),
])
self.fake_inst = objects.Instance(numa_topology=numa_topology)
@mock.patch.object(core, 'get_online')
def test_online(self, mock_get_online):
mock_get_online.return_value = True
self.assertTrue(self.core_1.online)
mock_get_online.assert_called_once_with(self.core_1.ident)
@mock.patch.object(core, 'set_online')
def test_set_online(self, mock_set_online):
self.core_1.online = True
mock_set_online.assert_called_once_with(self.core_1.ident)
@mock.patch.object(core, 'set_offline')
def test_set_offline(self, mock_set_offline):
self.core_1.online = False
mock_set_offline.assert_called_once_with(self.core_1.ident)
def test_hash(self):
self.assertEqual(hash(self.core_1.ident), hash(self.core_1))
@mock.patch.object(core, 'get_governor')
def test_governor(self, mock_get_governor):
mock_get_governor.return_value = 'fake_governor'
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')
self.core_1.set_low_governor()
mock_set_governor.assert_called_once_with(self.core_1.ident,
'fake_low_gov')
@mock.patch.object(core, 'set_governor')
def test_set_governor_high(self, mock_set_governor):
self.flags(cpu_power_governor_high='fake_high_gov', group='libvirt')
self.core_1.set_high_governor()
mock_set_governor.assert_called_once_with(self.core_1.ident,
'fake_high_gov')
@mock.patch.object(core, 'set_online')
def test_power_up_online(self, mock_online):
self.flags(cpu_power_management=True, group='libvirt')
self.flags(cpu_dedicated_set='1-2', group='compute')
api.power_up(self.fake_inst)
# only core #2 can be set as core #0 is not on the dedicated set
# As a reminder, core(i).online calls set_online(i)
mock_online.assert_called_once_with(2)
@mock.patch.object(core, 'set_governor')
def test_power_up_governor(self, mock_set_governor):
self.flags(cpu_power_management=True, group='libvirt')
self.flags(cpu_power_management_strategy='governor', group='libvirt')
self.flags(cpu_dedicated_set='1-2', group='compute')
api.power_up(self.fake_inst)
# only core #2 can be set as core #1 is not on the dedicated set
# As a reminder, core(i).set_high_governor calls set_governor(i)
mock_set_governor.assert_called_once_with(2, 'performance')
@mock.patch.object(core, 'set_online')
def test_power_up_skipped(self, mock_online):
self.flags(cpu_power_management=False, group='libvirt')
api.power_up(self.fake_inst)
mock_online.assert_not_called()
@mock.patch.object(core, 'set_online')
def test_power_up_skipped_if_standard_instance(self, mock_online):
self.flags(cpu_power_management=True, group='libvirt')
api.power_up(objects.Instance(numa_topology=None))
mock_online.assert_not_called()
@mock.patch.object(core, 'set_offline')
def test_power_down_offline(self, mock_offline):
self.flags(cpu_power_management=True, group='libvirt')
self.flags(cpu_dedicated_set='1-2', group='compute')
api.power_down(self.fake_inst)
# only core #2 can be set as core #1 is not on the dedicated set
# As a reminder, core(i).online calls set_online(i)
mock_offline.assert_called_once_with(2)
@mock.patch.object(core, 'set_governor')
def test_power_down_governor_cpu0_ignored(self, mock_set_governor):
self.flags(cpu_power_management=True, group='libvirt')
self.flags(cpu_power_management_strategy='governor', group='libvirt')
self.flags(cpu_dedicated_set='0-1', group='compute')
api.power_down(self.fake_inst)
# Make sure that core #0 is ignored, since it is special and cannot
# be powered down.
mock_set_governor.assert_not_called()
@mock.patch.object(core, 'set_governor')
def test_power_down_governor(self, mock_set_governor):
self.flags(cpu_power_management=True, group='libvirt')
self.flags(cpu_power_management_strategy='governor', group='libvirt')
self.flags(cpu_dedicated_set='1-2', group='compute')
api.power_down(self.fake_inst)
# only core #2 can be set as core #0 is not on the dedicated set
# As a reminder, core(i).set_high_governor calls set_governor(i)
mock_set_governor.assert_called_once_with(2, 'powersave')
@mock.patch.object(core, 'set_offline')
def test_power_down_skipped(self, mock_offline):
self.flags(cpu_power_management=False, group='libvirt')
api.power_down(self.fake_inst)
mock_offline.assert_not_called()
@mock.patch.object(core, 'set_offline')
def test_power_down_skipped_if_standard_instance(self, mock_offline):
self.flags(cpu_power_management=True, group='libvirt')
api.power_down(objects.Instance(numa_topology=None))
mock_offline.assert_not_called()
@mock.patch.object(core, 'set_offline')
def test_power_down_all_dedicated_cpus_offline(self, mock_offline):
self.flags(cpu_power_management=True, group='libvirt')
self.flags(cpu_dedicated_set='0-2', group='compute')
api.power_down_all_dedicated_cpus()
# All dedicated CPUs are turned offline, except CPU0
mock_offline.assert_has_calls([mock.call(1), mock.call(2)])
@mock.patch.object(core, 'set_governor')
def test_power_down_all_dedicated_cpus_governor(self, mock_set_governor):
self.flags(cpu_power_management=True, group='libvirt')
self.flags(cpu_power_management_strategy='governor', group='libvirt')
self.flags(cpu_dedicated_set='0-2', group='compute')
api.power_down_all_dedicated_cpus()
# All dedicated CPUs are turned offline, except CPU0
mock_set_governor.assert_has_calls([mock.call(1, 'powersave'),
mock.call(2, 'powersave')])
@mock.patch.object(core, 'set_offline')
def test_power_down_all_dedicated_cpus_skipped(self, mock_offline):
self.flags(cpu_power_management=False, group='libvirt')
api.power_down_all_dedicated_cpus()
mock_offline.assert_not_called()
@mock.patch.object(core, 'set_offline')
def test_power_down_all_dedicated_cpus_no_dedicated_cpus_configured(
self, mock_offline
):
self.flags(cpu_power_management=True, group='libvirt')
self.flags(cpu_dedicated_set=None, group='compute')
api.power_down_all_dedicated_cpus()
mock_offline.assert_not_called()
@mock.patch.object(core, 'get_governor')
@mock.patch.object(core, 'get_online')
def test_validate_all_dedicated_cpus_for_governor(self, mock_get_online,
mock_get_governor):
self.flags(cpu_power_management=True, group='libvirt')
self.flags(cpu_dedicated_set='0-1', group='compute')
self.flags(cpu_power_management_strategy='governor', group='libvirt')
mock_get_governor.return_value = 'performance'
mock_get_online.side_effect = (True, False)
self.assertRaises(exception.InvalidConfiguration,
api.validate_all_dedicated_cpus)
@mock.patch.object(core, 'get_governor')
@mock.patch.object(core, 'get_online')
def test_validate_all_dedicated_cpus_for_cpu_state(self, mock_get_online,
mock_get_governor):
self.flags(cpu_power_management=True, group='libvirt')
self.flags(cpu_dedicated_set='1-2', group='compute')
self.flags(cpu_power_management_strategy='cpu_state', group='libvirt')
mock_get_online.return_value = True
mock_get_governor.side_effect = ('powersave', 'performance')
self.assertRaises(exception.InvalidConfiguration,
api.validate_all_dedicated_cpus)
@mock.patch.object(core, 'get_governor')
@mock.patch.object(core, 'get_online')
@mock.patch.object(api.LOG, 'warning')
def test_validate_all_dedicated_cpus_for_cpu_state_warning(
self, mock_warning, mock_get_online, mock_get_governor):
self.flags(cpu_power_management=True, group='libvirt')
self.flags(cpu_dedicated_set='0-2', group='compute')
self.flags(cpu_power_management_strategy='cpu_state', group='libvirt')
mock_get_online.return_value = True
mock_get_governor.return_value = 'performance'
api.validate_all_dedicated_cpus()
# Make sure we skipped CPU0
mock_get_online.assert_has_calls([mock.call(1), mock.call(2)])
# Make sure we logged a warning about CPU0
mock_warning.assert_called_once_with(
'CPU0 is in cpu_dedicated_set, but it is not eligible for '
'state management and will be ignored')
def test_validate_all_dedicated_cpus_no_cpu(self):
self.flags(cpu_power_management=True, group='libvirt')
self.flags(cpu_dedicated_set=None, group='compute')
api.validate_all_dedicated_cpus()
# no assert we want to make sure the validation won't raise if
# no dedicated cpus are configured