Jay Faulkner 36e5993a04 [codespell] Fix spelling issues in IPA
This fixes several spelling issues identified by codepsell. In some
cases, I may have manually modified a line to make the output more clear
or to correct grammatical issues which were obvious in the codespell
output.

Later changes in this chain will provide the codespell config used to
generate this, as well as adding this commit's SHA, once landed, to a
.git-blame-ignore-revs file to ensure it will not pollute git historys
for modern clients.

Related-Bug: 2047654
Change-Id: I240cf8484865c9b748ceb51f3c7b9fd973cb5ada
2023-12-28 10:54:46 -08:00

518 lines
21 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 ironic_lib import utils
from oslo_concurrency import processutils
from tooz import coordination
from ironic_python_agent import burnin
from ironic_python_agent import errors
from ironic_python_agent import hardware
from ironic_python_agent.tests.unit import base
SMART_OUTPUT_JSON_COMPLETED = ("""
{
"ata_smart_data": {
"self_test": {
"status": {
"value": 0,
"string": "completed without error",
"passed": true
},
"polling_minutes": {
"short": 1,
"extended": 2,
"conveyance": 2
}
}
}
}
""")
SMART_OUTPUT_JSON_MISSING = ("""
{
"ata_smart_data": {
"self_test": {
"status": {
"value": 0,
"passed": true
}
}
}
}
""")
@mock.patch.object(utils, 'execute', autospec=True)
class TestBurnin(base.IronicAgentTest):
def test_stress_ng_cpu_default(self, mock_execute):
node = {'driver_info': {}}
mock_execute.return_value = (['out', 'err'])
burnin.stress_ng_cpu(node)
mock_execute.assert_called_once_with(
'stress-ng', '--cpu', 0, '--timeout', 86400, '--metrics-brief')
def test_stress_ng_cpu_non_default(self, mock_execute):
node = {'driver_info': {
'agent_burnin_cpu_cpu': 3,
'agent_burnin_cpu_timeout': 2911,
'agent_burnin_cpu_outputfile': '/var/log/burnin.cpu'}}
mock_execute.return_value = (['out', 'err'])
burnin.stress_ng_cpu(node)
mock_execute.assert_called_once_with(
'stress-ng', '--cpu', 3, '--timeout', 2911, '--metrics-brief',
'--log-file', '/var/log/burnin.cpu')
def test_stress_ng_cpu_no_stress_ng(self, mock_execute):
node = {'driver_info': {}}
mock_execute.side_effect = (['out', 'err'],
processutils.ProcessExecutionError())
burnin.stress_ng_cpu(node)
self.assertRaises(errors.CommandExecutionError,
burnin.stress_ng_cpu, node)
def test_stress_ng_vm_default(self, mock_execute):
node = {'driver_info': {}}
mock_execute.return_value = (['out', 'err'])
burnin.stress_ng_vm(node)
mock_execute.assert_called_once_with(
'stress-ng', '--vm', 0, '--vm-bytes', '98%',
'--timeout', 86400, '--metrics-brief')
def test_stress_ng_vm_non_default(self, mock_execute):
node = {'driver_info': {
'agent_burnin_vm_vm': 2,
'agent_burnin_vm_vm-bytes': '25%',
'agent_burnin_vm_timeout': 120,
'agent_burnin_vm_outputfile': '/var/log/burnin.vm'}}
mock_execute.return_value = (['out', 'err'])
burnin.stress_ng_vm(node)
mock_execute.assert_called_once_with(
'stress-ng', '--vm', 2, '--vm-bytes', '25%',
'--timeout', 120, '--metrics-brief',
'--log-file', '/var/log/burnin.vm')
def test_stress_ng_vm_no_stress_ng(self, mock_execute):
node = {'driver_info': {}}
mock_execute.side_effect = (['out', 'err'],
processutils.ProcessExecutionError())
burnin.stress_ng_vm(node)
self.assertRaises(errors.CommandExecutionError,
burnin.stress_ng_vm, node)
@mock.patch.object(hardware, 'list_all_block_devices', autospec=True)
def test_fio_disk_default(self, mock_list, mock_execute):
node = {'driver_info': {}}
mock_list.return_value = [
hardware.BlockDevice('/dev/sdj', 'big', 1073741824, True),
hardware.BlockDevice('/dev/hdaa', 'small', 65535, False),
]
mock_execute.return_value = (['out', 'err'])
burnin.fio_disk(node)
mock_execute.assert_called_once_with(
'fio', '--rw', 'readwrite', '--bs', '4k', '--direct', 1,
'--ioengine', 'libaio', '--iodepth', '32', '--verify',
'crc32c', '--verify_dump', 1, '--continue_on_error', 'verify',
'--loops', 4, '--runtime', 0, '--time_based', '--name',
'/dev/sdj', '--name', '/dev/hdaa')
@mock.patch.object(hardware, 'list_all_block_devices', autospec=True)
def test_fio_disk_no_default(self, mock_list, mock_execute):
node = {'driver_info': {
'agent_burnin_fio_disk_runtime': 600,
'agent_burnin_fio_disk_loops': 5,
'agent_burnin_fio_disk_outputfile': '/var/log/burnin.disk'}}
mock_list.return_value = [
hardware.BlockDevice('/dev/sdj', 'big', 1073741824, True),
hardware.BlockDevice('/dev/hdaa', 'small', 65535, False),
]
mock_execute.return_value = (['out', 'err'])
burnin.fio_disk(node)
mock_execute.assert_called_once_with(
'fio', '--rw', 'readwrite', '--bs', '4k', '--direct', 1,
'--ioengine', 'libaio', '--iodepth', '32', '--verify',
'crc32c', '--verify_dump', 1, '--continue_on_error', 'verify',
'--loops', 5, '--runtime', 600, '--time_based', '--output-format',
'json', '--output', '/var/log/burnin.disk', '--name', '/dev/sdj',
'--name', '/dev/hdaa', )
def test__smart_test_status(self, mock_execute):
device = hardware.BlockDevice('/dev/sdj', 'big', 1073741824, True)
mock_execute.return_value = ([SMART_OUTPUT_JSON_COMPLETED, 'err'])
status = burnin._smart_test_status(device)
mock_execute.assert_called_once_with('smartctl', '-ja', '/dev/sdj')
self.assertEqual(status, "completed without error")
def test__smart_test_status_missing(self, mock_execute):
device = hardware.BlockDevice('/dev/sdj', 'big', 1073741824, True)
mock_execute.return_value = ([SMART_OUTPUT_JSON_MISSING, 'err'])
status = burnin._smart_test_status(device)
mock_execute.assert_called_once_with('smartctl', '-ja', '/dev/sdj')
self.assertIsNone(status)
@mock.patch.object(burnin, '_smart_test_status', autospec=True)
@mock.patch.object(hardware, 'list_all_block_devices', autospec=True)
def test_fio_disk_smart_test(self, mock_list, mock_status, mock_execute):
node = {'driver_info': {'agent_burnin_fio_disk_smart_test': True}}
mock_list.return_value = [
hardware.BlockDevice('/dev/sdj', 'big', 1073741824, True),
hardware.BlockDevice('/dev/hdaa', 'small', 65535, False),
]
mock_status.return_value = "completed without error"
mock_execute.return_value = (['out', 'err'])
burnin.fio_disk(node)
expected_calls = [
mock.call('fio', '--rw', 'readwrite', '--bs', '4k', '--direct', 1,
'--ioengine', 'libaio', '--iodepth', '32', '--verify',
'crc32c', '--verify_dump', 1, '--continue_on_error',
'verify', '--loops', 4, '--runtime', 0, '--time_based',
'--name', '/dev/sdj', '--name', '/dev/hdaa'),
mock.call('smartctl', '-t', 'long', '/dev/sdj'),
mock.call('smartctl', '-t', 'long', '/dev/hdaa')
]
mock_execute.assert_has_calls(expected_calls)
@mock.patch.object(hardware, 'list_all_block_devices', autospec=True)
def test_fio_disk_no_fio(self, mock_list, mock_execute):
node = {'driver_info': {}}
mock_execute.side_effect = (['out', 'err'],
processutils.ProcessExecutionError())
burnin.fio_disk(node)
self.assertRaises(errors.CommandExecutionError,
burnin.fio_disk, node)
def test_fio_network_reader(self, mock_execute):
node = {'driver_info': {'agent_burnin_fio_network_runtime': 600,
'agent_burnin_fio_network_config':
{'partner': 'host-002',
'role': 'reader'}}}
mock_execute.return_value = (['out', 'err'])
burnin.fio_network(node)
expected_calls = [
mock.call('fio', '--ioengine', 'net', '--port', '9000',
'--fill_device', 1, '--group_reporting',
'--gtod_reduce', 1, '--numjobs', 16, '--name',
'reader', '--rw', 'read', '--hostname', 'host-002'),
mock.call('fio', '--ioengine', 'net', '--port', '9000',
'--fill_device', 1, '--group_reporting',
'--gtod_reduce', 1, '--numjobs', 16, '--name', 'writer',
'--rw', 'write', '--runtime', 600, '--time_based',
'--listen')]
mock_execute.assert_has_calls(expected_calls)
def test_fio_network_reader_w_logfile(self, mock_execute):
node = {'driver_info': {
'agent_burnin_fio_network_runtime': 600,
'agent_burnin_fio_network_config':
{'partner': 'host-002',
'role': 'reader'},
'agent_burnin_fio_network_outputfile': '/var/log/burnin.network'}}
mock_execute.return_value = (['out', 'err'])
burnin.fio_network(node)
expected_calls = [
mock.call('fio', '--ioengine', 'net', '--port', '9000',
'--fill_device', 1, '--group_reporting',
'--gtod_reduce', 1, '--numjobs', 16, '--name',
'reader', '--rw', 'read', '--hostname', 'host-002',
'--output-format', 'json', '--output',
'/var/log/burnin.network.reader'),
mock.call('fio', '--ioengine', 'net', '--port', '9000',
'--fill_device', 1, '--group_reporting',
'--gtod_reduce', 1, '--numjobs', 16, '--name', 'writer',
'--rw', 'write', '--runtime', 600, '--time_based',
'--listen', '--output-format', 'json', '--output',
'/var/log/burnin.network.writer')]
mock_execute.assert_has_calls(expected_calls)
def test_fio_network_writer(self, mock_execute):
node = {'driver_info': {'agent_burnin_fio_network_runtime': 600,
'agent_burnin_fio_network_config':
{'partner': 'host-001',
'role': 'writer'}}}
mock_execute.return_value = (['out', 'err'])
burnin.fio_network(node)
expected_calls = [
mock.call('fio', '--ioengine', 'net', '--port', '9000',
'--fill_device', 1, '--group_reporting',
'--gtod_reduce', 1, '--numjobs', 16, '--name', 'writer',
'--rw', 'write', '--runtime', 600, '--time_based',
'--listen'),
mock.call('fio', '--ioengine', 'net', '--port', '9000',
'--fill_device', 1, '--group_reporting',
'--gtod_reduce', 1, '--numjobs', 16, '--name',
'reader', '--rw', 'read', '--hostname', 'host-001')]
mock_execute.assert_has_calls(expected_calls)
def test_fio_network_writer_w_logfile(self, mock_execute):
node = {'driver_info': {
'agent_burnin_fio_network_runtime': 600,
'agent_burnin_fio_network_config':
{'partner': 'host-001',
'role': 'writer'},
'agent_burnin_fio_network_outputfile': '/var/log/burnin.network'}}
mock_execute.return_value = (['out', 'err'])
burnin.fio_network(node)
expected_calls = [
mock.call('fio', '--ioengine', 'net', '--port', '9000',
'--fill_device', 1, '--group_reporting',
'--gtod_reduce', 1, '--numjobs', 16, '--name', 'writer',
'--rw', 'write', '--runtime', 600, '--time_based',
'--listen', '--output-format', 'json', '--output',
'/var/log/burnin.network.writer'),
mock.call('fio', '--ioengine', 'net', '--port', '9000',
'--fill_device', 1, '--group_reporting',
'--gtod_reduce', 1, '--numjobs', 16, '--name',
'reader', '--rw', 'read', '--hostname', 'host-001',
'--output-format', 'json', '--output',
'/var/log/burnin.network.reader')]
mock_execute.assert_has_calls(expected_calls)
def test_fio_network_no_fio(self, mock_execute):
node = {'driver_info': {'agent_burnin_fio_network_config':
{'partner': 'host-003', 'role': 'reader'}}}
mock_execute.side_effect = processutils.ProcessExecutionError('boom')
self.assertRaises(errors.CommandExecutionError,
burnin.fio_network, node)
def test_fio_network_unknown_role(self, mock_execute):
node = {'driver_info': {'agent_burnin_fio_network_config':
{'partner': 'host-003', 'role': 'read'}}}
self.assertRaises(errors.CleaningError, burnin.fio_network, node)
def test_fio_network_no_role(self, mock_execute):
node = {'driver_info': {'agent_burnin_fio_network_config':
{'partner': 'host-003'}}}
self.assertRaises(errors.CleaningError, burnin.fio_network, node)
def test_fio_network_no_partner(self, mock_execute):
node = {'driver_info': {'agent_burnin_fio_network_config':
{'role': 'reader'}}}
self.assertRaises(errors.CleaningError, burnin.fio_network, node)
@mock.patch('time.sleep', autospec=True)
def test_fio_network_reader_loop(self, mock_time, mock_execute):
node = {'driver_info': {'agent_burnin_fio_network_config':
{'partner': 'host-004', 'role': 'reader'}}}
# mock the infinite loop
mock_execute.side_effect = (processutils.ProcessExecutionError(
'Connection timeout', exit_code=16),
processutils.ProcessExecutionError(
'Connection timeout', exit_code=16),
processutils.ProcessExecutionError(
'Connection refused', exit_code=16),
['out', 'err'], # connected!
['out', 'err']) # reversed roles
burnin.fio_network(node)
# we loop 3 times, then do the 2 fio calls
self.assertEqual(5, mock_execute.call_count)
self.assertEqual(3, mock_time.call_count)
def test_fio_network_dynamic_pairing_raise_missing_config(self,
mock_execute):
node = {'driver_info': {}}
self.assertRaises(errors.CleaningError, burnin.fio_network, node)
def test_fio_network_dynamic_pairing_raise_wrong_config(self,
mock_execute):
node = {'driver_info': {
'backend_url': 'zookeeper://zookeeper-host-01:2181',
'group_name': 'ironic.dynamic-network-burnin',
'timeout': 600}}
self.assertRaises(errors.CleaningError, burnin.fio_network, node)
@mock.patch.object(burnin, '_find_network_burnin_partner_and_role',
autospec=True)
def test_fio_network_dynamic_pairing_defaults(self, mock_find,
mock_execute):
node = {'driver_info': {
'agent_burnin_fio_network_pairing_backend_url':
'zookeeper://zookeeper-host-01:2181'}}
mock_find.return_value = ['partner-host', 'reader']
mock_execute.return_value = (['out', 'err'])
burnin.fio_network(node)
mock_find.assert_called_once_with(
backend_url='zookeeper://zookeeper-host-01:2181',
group_name='ironic.network-burnin',
timeout=900)
@mock.patch.object(burnin, '_find_network_burnin_partner_and_role',
autospec=True)
def test_fio_network_dynamic_pairing_no_defaults(self, mock_find,
mock_execute):
node = {'driver_info': {
'agent_burnin_fio_network_pairing_backend_url':
'zookeeper://zookeeper-host-01:2181',
'agent_burnin_fio_network_pairing_group_name':
'ironic.special-group',
'agent_burnin_fio_network_pairing_timeout': 600}}
mock_find.return_value = ['partner-host', 'reader']
mock_execute.return_value = (['out', 'err'])
burnin.fio_network(node)
mock_find.assert_called_once_with(
backend_url='zookeeper://zookeeper-host-01:2181',
group_name='ironic.special-group',
timeout=600)
@mock.patch.object(coordination, 'get_coordinator', autospec=True)
def test_fio_network_dynamic_find_timeout(self, mock_get_coordinator,
mock_execute):
mock_coordinator = mock.MagicMock()
mock_get_coordinator.return_value = mock_coordinator
# timeout since no other node is joining
self.assertRaises(errors.CleaningError,
burnin._find_network_burnin_partner_and_role,
"zk://xyz", 'group', 2)
# group did not exist, so we created it
mock_coordinator.create_group.assert_called_once_with('group')
mock_coordinator.join_group.assert_called_once()
# get_members is called initially, then every second
# up to the timeout
self.assertEqual(3, mock_coordinator.get_members.call_count)
@mock.patch.object(coordination, 'get_coordinator', autospec=True)
def test_fio_network_dynamic_find_pair_1st(self, mock_get_coordinator,
mock_execute):
mock_coordinator = mock.MagicMock()
mock_get_coordinator.return_value = mock_coordinator
class Members:
def __init__(self, members=[]):
self.members = members
def get(self):
return self.members
# we are the first node to enter, so no other host
# initially until the second one appears after some
# iterations
mock_coordinator.get_members.side_effect = \
[Members(), Members([b'host1']), Members([b'host1']),
Members([b'host1']), Members([b'host1', b'host2'])]
(partner, role) = \
burnin._find_network_burnin_partner_and_role("zk://xyz",
"group", 10)
# ... so we will leave first and be the writer
self.assertEqual((partner, role), ("host2", "writer"))
# group did not exist, so we created it
mock_coordinator.create_group.assert_called_once_with('group')
mock_coordinator.join_group.assert_called_once()
# get_members is called initially, then every second
# up to the timeout
self.assertEqual(5, mock_coordinator.get_members.call_count)
@mock.patch.object(coordination, 'get_coordinator', autospec=True)
def test_fio_network_dynamic_find_pair_2nd(self, mock_get_coordinator,
mock_execute):
mock_coordinator = mock.MagicMock()
mock_get_coordinator.return_value = mock_coordinator
class Members:
def __init__(self, members=[]):
self.members = members
def get(self):
return self.members
# we are the second node to enter, host1 is there before us ...
mock_coordinator.get_members.side_effect = \
[Members([b'host1']),
Members([b'host1', b'host2']),
Members([b'host2'])]
(partner, role) = \
burnin._find_network_burnin_partner_and_role("zk://xyz",
"group", 10)
# ... so we will leave second and be the reader
self.assertEqual((partner, role), ("host1", "reader"))
# group did not exist, so we created it
mock_coordinator.create_group.assert_called_once_with('group')
mock_coordinator.join_group.assert_called_once()
# get_members is called initially, then every second until the
# other node appears
self.assertEqual(3, mock_coordinator.get_members.call_count)