summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/business-logic/example_business_logic.py7
-rw-r--r--ironic_python_agent/agent.py11
-rw-r--r--ironic_python_agent/extensions/image.py9
-rw-r--r--ironic_python_agent/extensions/standby.py34
-rw-r--r--ironic_python_agent/hardware.py37
-rw-r--r--ironic_python_agent/hardware_managers/cna.py7
-rw-r--r--ironic_python_agent/tests/unit/extensions/test_image.py38
-rw-r--r--ironic_python_agent/tests/unit/hardware_managers/test_cna.py4
-rw-r--r--ironic_python_agent/tests/unit/test_agent.py2
-rw-r--r--ironic_python_agent/tests/unit/test_hardware.py97
-rw-r--r--ironic_python_agent/utils.py3
-rw-r--r--tox.ini4
12 files changed, 129 insertions, 124 deletions
diff --git a/examples/business-logic/example_business_logic.py b/examples/business-logic/example_business_logic.py
index 4fb7fc32..eac88a59 100644
--- a/examples/business-logic/example_business_logic.py
+++ b/examples/business-logic/example_business_logic.py
@@ -190,5 +190,8 @@ class ExampleBusinessLogicHardwareManager(hardware.HardwareManager):
# Make sure to provide default values for optional arguments.
def companyx_apply_something(self, node, ports, required_value,
optional_value=None):
- LOG.info('apply_something called with required_value={} and '
- 'optional_value={}'.format(required_value, optional_value))
+ LOG.info('apply_something called with '
+ 'required_value=%(required_value)s and '
+ 'optional_value=%(optional_value)s',
+ {'required_value': required_value,
+ 'optional_value': optional_value})
diff --git a/ironic_python_agent/agent.py b/ironic_python_agent/agent.py
index a9f8077f..c5b24560 100644
--- a/ironic_python_agent/agent.py
+++ b/ironic_python_agent/agent.py
@@ -125,17 +125,16 @@ class IronicPythonAgentHeartbeater(threading.Thread):
self.heartbeat_forced = False
self.previous_heartbeat = _time()
except errors.HeartbeatConflictError:
- LOG.warning('conflict error sending heartbeat to {}'.format(
- self.agent.api_url))
+ LOG.warning('conflict error sending heartbeat to %s',
+ self.agent.api_url)
except Exception:
- LOG.exception('error sending heartbeat to {}'.format(
- self.agent.api_url))
+ LOG.exception('error sending heartbeat to %s', self.agent.api_url)
finally:
interval_multiplier = random.uniform(self.min_jitter_multiplier,
self.max_jitter_multiplier)
self.interval = self.agent.heartbeat_timeout * interval_multiplier
- log_msg = 'sleeping before next heartbeat, interval: {0}'
- LOG.info(log_msg.format(self.interval))
+ LOG.info('sleeping before next heartbeat, interval: %s',
+ self.interval)
def force_heartbeat(self):
self.heartbeat_forced = True
diff --git a/ironic_python_agent/extensions/image.py b/ironic_python_agent/extensions/image.py
index 84e86f17..1d439923 100644
--- a/ironic_python_agent/extensions/image.py
+++ b/ironic_python_agent/extensions/image.py
@@ -274,7 +274,7 @@ def _run_efibootmgr(valid_efi_bootloaders, device, efi_partition,
# Before updating let's get information about the bootorder
LOG.debug("Getting information about boot order.")
- utils.execute('efibootmgr')
+ utils.execute('efibootmgr', '-v')
# NOTE(iurygregory): regex used to identify the Warning in the stderr after
# we add the new entry. Example:
# "efibootmgr: ** Warning ** : Boot0004 has same label ironic"
@@ -303,7 +303,7 @@ def _run_efibootmgr(valid_efi_bootloaders, device, efi_partition,
'dev': device})
# Update the nvram using efibootmgr
# https://linux.die.net/man/8/efibootmgr
- cmd = utils.execute('efibootmgr', '-c', '-d', device,
+ cmd = utils.execute('efibootmgr', '-v', '-c', '-d', device,
'-p', efi_partition, '-w', '-L', label,
'-l', v_efi_bl_path)
for line in cmd[1].split('\n'):
@@ -489,8 +489,9 @@ def _prepare_boot_partitions_for_softraid(device, holders, efi_part,
# RAID the ESPs, metadata=1.0 is mandatory to be able to boot
md_device = '/dev/md/esp'
- LOG.debug("Creating md device {} for the ESPs on {}".format(
- md_device, efi_partitions))
+ LOG.debug("Creating md device %(md_device)s for the ESPs "
+ "on %(efi_partitions)s",
+ {'md_device': md_device, 'efi_partitions': efi_partitions})
utils.execute('mdadm', '--create', md_device, '--force',
'--run', '--metadata=1.0', '--level', '1',
'--raid-devices', len(efi_partitions),
diff --git a/ironic_python_agent/extensions/standby.py b/ironic_python_agent/extensions/standby.py
index 970cf7de..e63a9572 100644
--- a/ironic_python_agent/extensions/standby.py
+++ b/ironic_python_agent/extensions/standby.py
@@ -202,7 +202,7 @@ def _write_whole_disk_image(image, image_info, device):
command = ['qemu-img', 'convert',
'-t', 'directsync', '-O', 'host_device', '-W',
image, device]
- LOG.info('Writing image with command: {}'.format(' '.join(command)))
+ LOG.info('Writing image with command: %s', ' '.join(command))
try:
disk_utils.convert_image(image, device, out_format='host_device',
cache='directsync', out_of_order=True)
@@ -232,8 +232,9 @@ def _write_image(image_info, device, configdrive=None):
else:
_write_whole_disk_image(image, image_info, device)
totaltime = time.time() - starttime
- LOG.info('Image {} written to device {} in {} seconds'.format(
- image, device, totaltime))
+ LOG.info('Image %(image)s written to device %(device)s in %(totaltime)s '
+ 'seconds', {'image': image, 'device': device,
+ 'totaltime': totaltime})
try:
disk_utils.fix_gpt_partition(device, node_uuid=None)
except exception.InstanceDeployFailure:
@@ -329,7 +330,7 @@ class ImageDownload(object):
details = []
for url in image_info['urls']:
try:
- LOG.info("Attempting to download image from {}".format(url))
+ LOG.info("Attempting to download image from %s", url)
self._request = _download_with_proxy(image_info, url,
image_info['id'])
except errors.ImageDownloadError as e:
@@ -386,12 +387,16 @@ class ImageDownload(object):
not match the checksum as reported by glance in image_info.
"""
checksum = self._hash_algo.hexdigest()
- LOG.debug('Verifying image at {} against {} checksum '
- '{}'.format(image_location, self._hash_algo.name, checksum))
+ LOG.debug('Verifying image at %(image_location)s against '
+ '%(algo_name)s checksum %(checksum)s',
+ {'image_location': image_location,
+ 'algo_name': self._hash_algo.name,
+ 'checksum': checksum})
if checksum != self._expected_hash_value:
- LOG.error(errors.ImageChecksumError.details_str.format(
+ error_msg = errors.ImageChecksumError.details_str.format(
image_location, self._image_info['id'],
- self._expected_hash_value, checksum))
+ self._expected_hash_value, checksum)
+ LOG.error(error_msg)
raise errors.ImageChecksumError(image_location,
self._image_info['id'],
self._expected_hash_value,
@@ -434,8 +439,10 @@ def _download_image(image_info):
break
totaltime = time.time() - starttime
- LOG.info("Image downloaded from {} in {} seconds".format(image_location,
- totaltime))
+ LOG.info("Image downloaded from %(image_location)s "
+ "in %(totaltime)s seconds",
+ {'image_location': image_location,
+ 'totaltime': totaltime})
image_download.verify_image(image_location)
@@ -597,8 +604,8 @@ class StandbyExtension(base.BaseAgentExtension):
break
totaltime = time.time() - starttime
- LOG.info("Image streamed onto device {} in {} "
- "seconds".format(device, totaltime))
+ LOG.info("Image streamed onto device %(device)s in %(totaltime)s "
+ "seconds", {'device': device, 'totaltime': totaltime})
# Verify if the checksum of the streamed image is correct
image_download.verify_image(device)
# Fix any gpt partition
@@ -609,7 +616,8 @@ class StandbyExtension(base.BaseAgentExtension):
pass
# Fix the root partition UUID
root_uuid = disk_utils.block_uuid(device)
- LOG.info("{} UUID is now {}".format(device, root_uuid))
+ LOG.info("%(device)s UUID is now %(root_uuid)s",
+ {'device': device, 'root_uuid': root_uuid})
self.partition_uuids['root uuid'] = root_uuid
def _fix_up_partition_uuids(self, image_info, device):
diff --git a/ironic_python_agent/hardware.py b/ironic_python_agent/hardware.py
index 87e5ea82..e963059f 100644
--- a/ironic_python_agent/hardware.py
+++ b/ironic_python_agent/hardware.py
@@ -127,6 +127,17 @@ def _udev_settle():
return
+def _load_ipmi_modules():
+ """Load kernel modules required for IPMI interaction.
+
+ This is required to be called at least once before attempting to use
+ ipmitool or related tools.
+ """
+ il_utils.try_execute('modprobe', 'ipmi_msghandler')
+ il_utils.try_execute('modprobe', 'ipmi_devintf')
+ il_utils.try_execute('modprobe', 'ipmi_si')
+
+
def _check_for_iscsi():
"""Connect iSCSI shared connected via iBFT or OF.
@@ -445,13 +456,13 @@ def list_all_block_devices(block_type='disk',
# lvm, part, rom, loop
if devtype != block_type:
if devtype is None or ignore_raid:
- LOG.debug("Skipping: {!r}".format(line))
+ LOG.debug("Skipping: %s", line)
continue
elif ('raid' in devtype
and block_type in ['raid', 'disk']):
LOG.debug(
"TYPE detected to contain 'raid', signifying a "
- "RAID volume. Found: {!r}".format(line))
+ "RAID volume. Found: %s", line)
elif (devtype == 'md'
and (block_type == 'part'
or block_type == 'md')):
@@ -461,11 +472,11 @@ def list_all_block_devices(block_type='disk',
# more detail.
LOG.debug(
"TYPE detected to contain 'md', signifying a "
- "RAID partition. Found: {!r}".format(line))
+ "RAID partition. Found: %s", line)
else:
LOG.debug(
- "TYPE did not match. Wanted: {!r} but found: {!r}".format(
- block_type, line))
+ "TYPE did not match. Wanted: %(block_type)s but found: "
+ "%(line)s", {'block_type': block_type, 'line': line})
continue
# Ensure all required columns are at least present, even if blank
@@ -984,6 +995,7 @@ class GenericHardwareManager(HardwareManager):
# Do some initialization before we declare ourself ready
_check_for_iscsi()
_md_scan_and_assemble()
+ _load_ipmi_modules()
self.wait_for_disks()
return HardwareSupport.GENERIC
@@ -1765,11 +1777,6 @@ class GenericHardwareManager(HardwareManager):
:return: IP address of lan channel or 0.0.0.0 in case none of them is
configured properly
"""
- # These modules are rarely loaded automatically
- il_utils.try_execute('modprobe', 'ipmi_msghandler')
- il_utils.try_execute('modprobe', 'ipmi_devintf')
- il_utils.try_execute('modprobe', 'ipmi_si')
-
try:
# From all the channels 0-15, only 1-11 can be assigned to
# different types of communication media and protocols and
@@ -1807,11 +1814,6 @@ class GenericHardwareManager(HardwareManager):
:return: MAC address of the first LAN channel or 00:00:00:00:00:00 in
case none of them has one or is configured properly
"""
- # These modules are rarely loaded automatically
- il_utils.try_execute('modprobe', 'ipmi_msghandler')
- il_utils.try_execute('modprobe', 'ipmi_devintf')
- il_utils.try_execute('modprobe', 'ipmi_si')
-
try:
# From all the channels 0-15, only 1-11 can be assigned to
# different types of communication media and protocols and
@@ -1859,11 +1861,6 @@ class GenericHardwareManager(HardwareManager):
configured properly. May return None value if it cannot
interract with system tools or critical error occurs.
"""
- # These modules are rarely loaded automatically
- il_utils.try_execute('modprobe', 'ipmi_msghandler')
- il_utils.try_execute('modprobe', 'ipmi_devintf')
- il_utils.try_execute('modprobe', 'ipmi_si')
-
null_address_re = re.compile(r'^::(/\d{1,3})*$')
def get_addr(channel, dynamic=False):
diff --git a/ironic_python_agent/hardware_managers/cna.py b/ironic_python_agent/hardware_managers/cna.py
index 2d49d9e0..a4021c10 100644
--- a/ironic_python_agent/hardware_managers/cna.py
+++ b/ironic_python_agent/hardware_managers/cna.py
@@ -64,9 +64,10 @@ def _disable_embedded_lldp_agent_in_cna_card():
failed_dirs.append(inner_dir)
continue
if failed_dirs:
- LOG.warning('Failed to disable the embedded LLDP on Intel CNA network '
- 'card. Addresses of failed pci devices: {}'
- .format(str(failed_dirs).strip('[]')))
+ warning_msg = ('Failed to disable the embedded LLDP on Intel '
+ 'CNA network card. Addresses of failed pci '
+ 'devices: %s', str(failed_dirs).strip('[]'))
+ LOG.warning(warning_msg)
class IntelCnaHardwareManager(hardware.HardwareManager):
diff --git a/ironic_python_agent/tests/unit/extensions/test_image.py b/ironic_python_agent/tests/unit/extensions/test_image.py
index 05e937b8..33056575 100644
--- a/ironic_python_agent/tests/unit/extensions/test_image.py
+++ b/ironic_python_agent/tests/unit/extensions/test_image.py
@@ -236,8 +236,8 @@ class TestImageExtension(base.IronicAgentTest):
mock.call('udevadm', 'settle'),
mock.call('mount', self.fake_efi_system_part,
self.fake_dir + '/boot/efi'),
- mock.call('efibootmgr'),
- mock.call('efibootmgr', '-c', '-d', self.fake_dev,
+ mock.call('efibootmgr', '-v'),
+ mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
'-p', '1', '-w',
'-L', 'ironic1', '-l',
'\\EFI\\BOOT\\BOOTX64.EFI'),
@@ -283,8 +283,8 @@ class TestImageExtension(base.IronicAgentTest):
mock.call('udevadm', 'settle'),
mock.call('mount', self.fake_efi_system_part,
self.fake_dir + '/boot/efi'),
- mock.call('efibootmgr'),
- mock.call('efibootmgr', '-c', '-d', self.fake_dev,
+ mock.call('efibootmgr', '-v'),
+ mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
'-p', '1', '-w',
'-L', 'ironic1', '-l',
'\\EFI\\BOOT\\BOOTX64.EFI'),
@@ -335,8 +335,8 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
mock.call('udevadm', 'settle'),
mock.call('mount', self.fake_efi_system_part,
self.fake_dir + '/boot/efi'),
- mock.call('efibootmgr'),
- mock.call('efibootmgr', '-c', '-d', self.fake_dev,
+ mock.call('efibootmgr', '-v'),
+ mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
'-p', '1', '-w',
'-L', 'ironic1', '-l',
'\\EFI\\BOOT\\BOOTX64.EFI'),
@@ -387,12 +387,12 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
mock.call('udevadm', 'settle'),
mock.call('mount', self.fake_efi_system_part,
self.fake_dir + '/boot/efi'),
- mock.call('efibootmgr'),
- mock.call('efibootmgr', '-c', '-d', self.fake_dev,
+ mock.call('efibootmgr', '-v'),
+ mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
'-p', '1', '-w',
'-L', 'ironic1', '-l',
'\\EFI\\BOOT\\BOOTX64.EFI'),
- mock.call('efibootmgr', '-c', '-d', self.fake_dev,
+ mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
'-p', '1', '-w',
'-L', 'ironic2', '-l',
'\\WINDOWS\\system32\\winload.efi'),
@@ -2226,8 +2226,8 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
mock.call('udevadm', 'settle'),
mock.call('mount', self.fake_efi_system_part,
self.fake_dir + '/boot/efi'),
- mock.call('efibootmgr'),
- mock.call('efibootmgr', '-c', '-d', self.fake_dev,
+ mock.call('efibootmgr', '-v'),
+ mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
'-p', '1', '-w',
'-L', 'ironic1', '-l',
'\\EFI\\BOOT\\BOOTX64.EFI'),
@@ -2270,8 +2270,8 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
mock.call('udevadm', 'settle'),
mock.call('mount', self.fake_efi_system_part,
self.fake_dir + '/boot/efi'),
- mock.call('efibootmgr'),
- mock.call('efibootmgr', '-c', '-d', self.fake_dev,
+ mock.call('efibootmgr', '-v'),
+ mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
'-p', '1', '-w',
'-L', 'Vendor String', '-l',
'\\EFI\\vendor\\shimx64.efi'),
@@ -2310,8 +2310,8 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
mock.call('udevadm', 'settle'),
mock.call('mount', '/dev/fakenvme0p1',
self.fake_dir + '/boot/efi'),
- mock.call('efibootmgr'),
- mock.call('efibootmgr', '-c', '-d', '/dev/fakenvme0',
+ mock.call('efibootmgr', '-v'),
+ mock.call('efibootmgr', '-v', '-c', '-d', '/dev/fakenvme0',
'-p', '1', '-w',
'-L', 'ironic1', '-l',
'\\EFI\\BOOT\\BOOTX64.EFI'),
@@ -2350,8 +2350,8 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
mock.call('udevadm', 'settle'),
mock.call('mount', self.fake_efi_system_part,
self.fake_dir + '/boot/efi'),
- mock.call('efibootmgr'),
- mock.call('efibootmgr', '-c', '-d', self.fake_dev,
+ mock.call('efibootmgr', '-v'),
+ mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
'-p', '1', '-w',
'-L', 'ironic1', '-l',
'\\EFI\\BOOT\\BOOTX64.EFI'),
@@ -2457,8 +2457,8 @@ efibootmgr: ** Warning ** : Boot0005 has same label ironic1\n
self.fake_dev,
self.fake_efi_system_part,
self.fake_dir)
- expected = [mock.call('efibootmgr'),
- mock.call('efibootmgr', '-c', '-d', self.fake_dev,
+ expected = [mock.call('efibootmgr', '-v'),
+ mock.call('efibootmgr', '-v', '-c', '-d', self.fake_dev,
'-p', self.fake_efi_system_part, '-w',
'-L', 'ironic1', '-l',
'\\EFI\\BOOT\\BOOTX64.EFI')]
diff --git a/ironic_python_agent/tests/unit/hardware_managers/test_cna.py b/ironic_python_agent/tests/unit/hardware_managers/test_cna.py
index b38d6d20..29c456a7 100644
--- a/ironic_python_agent/tests/unit/hardware_managers/test_cna.py
+++ b/ironic_python_agent/tests/unit/hardware_managers/test_cna.py
@@ -112,8 +112,8 @@ class TestIntelCnaHardwareManager(base.IronicAgentTest):
cna._disable_embedded_lldp_agent_in_cna_card()
expected_log_message = ('Failed to disable the embedded LLDP on '
'Intel CNA network card. Addresses of '
- 'failed pci devices: {}'
- .format(str(listdir_dict).strip('[]')))
+ 'failed pci devices: %s',
+ str(listdir_dict).strip('[]'))
mock_log.warning.assert_called_once_with(expected_log_message)
@mock.patch.object(cna, 'LOG', autospec=True)
diff --git a/ironic_python_agent/tests/unit/test_agent.py b/ironic_python_agent/tests/unit/test_agent.py
index b020f692..9b95e695 100644
--- a/ironic_python_agent/tests/unit/test_agent.py
+++ b/ironic_python_agent/tests/unit/test_agent.py
@@ -159,6 +159,7 @@ class TestHeartbeater(ironic_agent_base.IronicAgentTest):
@mock.patch.object(hardware, '_md_scan_and_assemble', lambda: None)
@mock.patch.object(hardware, '_check_for_iscsi', lambda: None)
+@mock.patch.object(hardware, '_load_ipmi_modules', lambda: None)
@mock.patch.object(hardware.GenericHardwareManager, 'wait_for_disks',
lambda self: None)
class TestBaseAgent(ironic_agent_base.IronicAgentTest):
@@ -959,6 +960,7 @@ class TestAgentStandalone(ironic_agent_base.IronicAgentTest):
@mock.patch.object(hardware, '_md_scan_and_assemble', lambda: None)
@mock.patch.object(hardware, '_check_for_iscsi', lambda: None)
+@mock.patch.object(hardware, '_load_ipmi_modules', lambda: None)
@mock.patch.object(hardware.GenericHardwareManager, 'wait_for_disks',
lambda self: None)
@mock.patch.object(socket, 'gethostbyname', autospec=True)
diff --git a/ironic_python_agent/tests/unit/test_hardware.py b/ironic_python_agent/tests/unit/test_hardware.py
index 44b2a87d..143957eb 100644
--- a/ironic_python_agent/tests/unit/test_hardware.py
+++ b/ironic_python_agent/tests/unit/test_hardware.py
@@ -2246,41 +2246,35 @@ class TestGenericHardwareManager(base.IronicAgentTest):
mock_dev_file.side_effect = reads
self.assertTrue(self.hardware._is_read_only_device(device))
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_address(self, mocked_execute, mte):
+ def test_get_bmc_address(self, mocked_execute):
mocked_execute.return_value = '192.1.2.3\n', ''
self.assertEqual('192.1.2.3', self.hardware.get_bmc_address())
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_address_virt(self, mocked_execute, mte):
+ def test_get_bmc_address_virt(self, mocked_execute):
mocked_execute.side_effect = processutils.ProcessExecutionError()
self.assertIsNone(self.hardware.get_bmc_address())
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_address_zeroed(self, mocked_execute, mte):
+ def test_get_bmc_address_zeroed(self, mocked_execute):
mocked_execute.return_value = '0.0.0.0\n', ''
self.assertEqual('0.0.0.0', self.hardware.get_bmc_address())
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_address_invalid(self, mocked_execute, mte):
+ def test_get_bmc_address_invalid(self, mocked_execute):
# In case of invalid lan channel, stdout is empty and the error
# on stderr is "Invalid channel"
mocked_execute.return_value = '\n', 'Invalid channel: 55'
self.assertEqual('0.0.0.0', self.hardware.get_bmc_address())
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_address_random_error(self, mocked_execute, mte):
+ def test_get_bmc_address_random_error(self, mocked_execute):
mocked_execute.return_value = '192.1.2.3\n', 'Random error message'
self.assertEqual('192.1.2.3', self.hardware.get_bmc_address())
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_address_iterate_channels(self, mocked_execute, mte):
+ def test_get_bmc_address_iterate_channels(self, mocked_execute):
# For channel 1 we simulate unconfigured IP
# and for any other we return a correct IP address
def side_effect(*args, **kwargs):
@@ -2295,57 +2289,49 @@ class TestGenericHardwareManager(base.IronicAgentTest):
mocked_execute.side_effect = side_effect
self.assertEqual('192.1.2.3', self.hardware.get_bmc_address())
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_address_not_available(self, mocked_execute, mte):
+ def test_get_bmc_address_not_available(self, mocked_execute):
mocked_execute.return_value = '', ''
self.assertEqual('0.0.0.0', self.hardware.get_bmc_address())
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_mac_not_available(self, mocked_execute, mte):
+ def test_get_bmc_mac_not_available(self, mocked_execute):
mocked_execute.return_value = '', ''
self.assertRaises(errors.IncompatibleHardwareMethodError,
self.hardware.get_bmc_mac)
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_mac(self, mocked_execute, mte):
+ def test_get_bmc_mac(self, mocked_execute):
mocked_execute.return_value = '192.1.2.3\n01:02:03:04:05:06', ''
self.assertEqual('01:02:03:04:05:06', self.hardware.get_bmc_mac())
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_mac_virt(self, mocked_execute, mte):
+ def test_get_bmc_mac_virt(self, mocked_execute):
mocked_execute.side_effect = processutils.ProcessExecutionError()
self.assertIsNone(self.hardware.get_bmc_mac())
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_mac_zeroed(self, mocked_execute, mte):
+ def test_get_bmc_mac_zeroed(self, mocked_execute):
mocked_execute.return_value = '0.0.0.0\n00:00:00:00:00:00', ''
self.assertRaises(errors.IncompatibleHardwareMethodError,
self.hardware.get_bmc_mac)
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_mac_invalid(self, mocked_execute, mte):
+ def test_get_bmc_mac_invalid(self, mocked_execute):
# In case of invalid lan channel, stdout is empty and the error
# on stderr is "Invalid channel"
mocked_execute.return_value = '\n', 'Invalid channel: 55'
self.assertRaises(errors.IncompatibleHardwareMethodError,
self.hardware.get_bmc_mac)
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_mac_random_error(self, mocked_execute, mte):
+ def test_get_bmc_mac_random_error(self, mocked_execute):
mocked_execute.return_value = ('192.1.2.3\n00:00:00:00:00:02',
'Random error message')
self.assertEqual('00:00:00:00:00:02', self.hardware.get_bmc_mac())
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_mac_iterate_channels(self, mocked_execute, mte):
+ def test_get_bmc_mac_iterate_channels(self, mocked_execute):
# For channel 1 we simulate unconfigured IP
# and for any other we return a correct IP address
def side_effect(*args, **kwargs):
@@ -2363,15 +2349,13 @@ class TestGenericHardwareManager(base.IronicAgentTest):
mocked_execute.side_effect = side_effect
self.assertEqual('01:02:03:04:05:06', self.hardware.get_bmc_mac())
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_v6address_not_enabled(self, mocked_execute, mte):
+ def test_get_bmc_v6address_not_enabled(self, mocked_execute):
mocked_execute.side_effect = [('ipv4\n', '')] * 11
self.assertEqual('::/0', self.hardware.get_bmc_v6address())
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_v6address_dynamic_address(self, mocked_execute, mte):
+ def test_get_bmc_v6address_dynamic_address(self, mocked_execute):
mocked_execute.side_effect = [
('ipv6\n', ''),
(hws.IPMITOOL_LAN6_PRINT_DYNAMIC_ADDR, '')
@@ -2379,9 +2363,8 @@ class TestGenericHardwareManager(base.IronicAgentTest):
self.assertEqual('2001:1234:1234:1234:1234:1234:1234:1234',
self.hardware.get_bmc_v6address())
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_v6address_static_address_both(self, mocked_execute, mte):
+ def test_get_bmc_v6address_static_address_both(self, mocked_execute):
dynamic_disabled = \
hws.IPMITOOL_LAN6_PRINT_DYNAMIC_ADDR.replace('active', 'disabled')
mocked_execute.side_effect = [
@@ -2392,15 +2375,13 @@ class TestGenericHardwareManager(base.IronicAgentTest):
self.assertEqual('2001:5678:5678:5678:5678:5678:5678:5678',
self.hardware.get_bmc_v6address())
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_v6address_virt(self, mocked_execute, mte):
+ def test_get_bmc_v6address_virt(self, mocked_execute):
mocked_execute.side_effect = processutils.ProcessExecutionError()
self.assertIsNone(self.hardware.get_bmc_v6address())
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_v6address_invalid_enables(self, mocked_execute, mte):
+ def test_get_bmc_v6address_invalid_enables(self, mocked_execute):
def side_effect(*args, **kwargs):
if args[0].startswith('ipmitool lan6 print'):
return '', 'Failed to get IPv6/IPv4 Addressing Enables'
@@ -2408,9 +2389,8 @@ class TestGenericHardwareManager(base.IronicAgentTest):
mocked_execute.side_effect = side_effect
self.assertEqual('::/0', self.hardware.get_bmc_v6address())
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_v6address_invalid_get_address(self, mocked_execute, mte):
+ def test_get_bmc_v6address_invalid_get_address(self, mocked_execute):
def side_effect(*args, **kwargs):
if args[0].startswith('ipmitool lan6 print'):
if args[0].endswith('dynamic_addr') \
@@ -2422,10 +2402,9 @@ class TestGenericHardwareManager(base.IronicAgentTest):
self.assertEqual('::/0', self.hardware.get_bmc_v6address())
@mock.patch.object(hardware, 'LOG', autospec=True)
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
def test_get_bmc_v6address_ipmitool_invalid_stdout_format(
- self, mocked_execute, mte, mocked_log):
+ self, mocked_execute, mocked_log):
def side_effect(*args, **kwargs):
if args[0].startswith('ipmitool lan6 print'):
if args[0].endswith('dynamic_addr') \
@@ -2439,9 +2418,8 @@ class TestGenericHardwareManager(base.IronicAgentTest):
'command: %(e)s', mock.ANY)
mocked_log.warning.assert_has_calls([one_call] * 14)
- @mock.patch.object(il_utils, 'try_execute', autospec=True)
@mock.patch.object(utils, 'execute', autospec=True)
- def test_get_bmc_v6address_channel_7(self, mocked_execute, mte):
+ def test_get_bmc_v6address_channel_7(self, mocked_execute):
def side_effect(*args, **kwargs):
if not args[0].startswith('ipmitool lan6 print 7'):
# ipv6 is not enabled for channels 1-6
@@ -4072,6 +4050,7 @@ class TestGenericHardwareManager(base.IronicAgentTest):
self.hardware._nvme_erase, block_device)
+@mock.patch.object(hardware, '_load_ipmi_modules', autospec=True)
@mock.patch.object(hardware.GenericHardwareManager,
'get_os_install_device', autospec=True)
@mock.patch.object(hardware, '_md_scan_and_assemble', autospec=True)
@@ -4084,7 +4063,8 @@ class TestEvaluateHardwareSupport(base.IronicAgentTest):
def test_evaluate_hw_waits_for_disks(
self, mocked_sleep, mocked_check_for_iscsi,
- mocked_md_assemble, mocked_get_inst_dev):
+ mocked_md_assemble, mocked_get_inst_dev,
+ mocked_load_ipmi_modules):
mocked_get_inst_dev.side_effect = [
errors.DeviceNotFound('boom'),
None
@@ -4092,6 +4072,7 @@ class TestEvaluateHardwareSupport(base.IronicAgentTest):
result = self.hardware.evaluate_hardware_support()
+ self.assertTrue(mocked_load_ipmi_modules.called)
self.assertTrue(mocked_check_for_iscsi.called)
self.assertTrue(mocked_md_assemble.called)
self.assertEqual(hardware.HardwareSupport.GENERIC, result)
@@ -4102,7 +4083,8 @@ class TestEvaluateHardwareSupport(base.IronicAgentTest):
@mock.patch.object(hardware, 'LOG', autospec=True)
def test_evaluate_hw_no_wait_for_disks(
self, mocked_log, mocked_sleep, mocked_check_for_iscsi,
- mocked_md_assemble, mocked_get_inst_dev):
+ mocked_md_assemble, mocked_get_inst_dev,
+ mocked_load_ipmi_modules):
CONF.set_override('disk_wait_attempts', '0')
result = self.hardware.evaluate_hardware_support()
@@ -4116,7 +4098,8 @@ class TestEvaluateHardwareSupport(base.IronicAgentTest):
@mock.patch.object(hardware, 'LOG', autospec=True)
def test_evaluate_hw_waits_for_disks_nonconfigured(
self, mocked_log, mocked_sleep, mocked_check_for_iscsi,
- mocked_md_assemble, mocked_get_inst_dev):
+ mocked_md_assemble, mocked_get_inst_dev,
+ mocked_load_ipmi_modules):
mocked_get_inst_dev.side_effect = [
errors.DeviceNotFound('boom'),
errors.DeviceNotFound('boom'),
@@ -4147,7 +4130,8 @@ class TestEvaluateHardwareSupport(base.IronicAgentTest):
mocked_sleep,
mocked_check_for_iscsi,
mocked_md_assemble,
- mocked_get_inst_dev):
+ mocked_get_inst_dev,
+ mocked_load_ipmi_modules):
CONF.set_override('disk_wait_attempts', '1')
mocked_get_inst_dev.side_effect = [
@@ -4167,7 +4151,8 @@ class TestEvaluateHardwareSupport(base.IronicAgentTest):
def test_evaluate_hw_disks_timeout_unconfigured(self, mocked_sleep,
mocked_check_for_iscsi,
mocked_md_assemble,
- mocked_get_inst_dev):
+ mocked_get_inst_dev,
+ mocked_load_ipmi_modules):
mocked_get_inst_dev.side_effect = errors.DeviceNotFound('boom')
self.hardware.evaluate_hardware_support()
mocked_sleep.assert_called_with(3)
@@ -4175,7 +4160,8 @@ class TestEvaluateHardwareSupport(base.IronicAgentTest):
def test_evaluate_hw_disks_timeout_configured(self, mocked_sleep,
mocked_check_for_iscsi,
mocked_md_assemble,
- mocked_root_dev):
+ mocked_root_dev,
+ mocked_load_ipmi_modules):
CONF.set_override('disk_wait_delay', '5')
mocked_root_dev.side_effect = errors.DeviceNotFound('boom')
@@ -4184,7 +4170,8 @@ class TestEvaluateHardwareSupport(base.IronicAgentTest):
def test_evaluate_hw_disks_timeout(
self, mocked_sleep, mocked_check_for_iscsi,
- mocked_md_assemble, mocked_get_inst_dev):
+ mocked_md_assemble, mocked_get_inst_dev,
+ mocked_load_ipmi_modules):
mocked_get_inst_dev.side_effect = errors.DeviceNotFound('boom')
result = self.hardware.evaluate_hardware_support()
self.assertEqual(hardware.HardwareSupport.GENERIC, result)
@@ -4274,6 +4261,14 @@ class TestModuleFunctions(base.IronicAgentTest):
mocked_execute.assert_has_calls([
mock.call('iscsistart', '-f')])
+ @mock.patch.object(il_utils, 'try_execute', autospec=True)
+ def test__load_ipmi_modules(self, mocked_try_execute, me):
+ hardware._load_ipmi_modules()
+ mocked_try_execute.assert_has_calls([
+ mock.call('modprobe', 'ipmi_msghandler'),
+ mock.call('modprobe', 'ipmi_devintf'),
+ mock.call('modprobe', 'ipmi_si')])
+
def create_hdparm_info(supported=False, enabled=False, locked=False,
frozen=False, enhanced_erase=False):
diff --git a/ironic_python_agent/utils.py b/ironic_python_agent/utils.py
index 2fc60ff1..74ac328b 100644
--- a/ironic_python_agent/utils.py
+++ b/ironic_python_agent/utils.py
@@ -865,8 +865,7 @@ def create_partition_table(dev_name, partition_table_type):
:raises: CommandExecutionError if an error is encountered while
attempting to create the partition table.
"""
- LOG.info("Creating partition table on {}".format(
- dev_name))
+ LOG.info("Creating partition table on %s", dev_name)
try:
execute('parted', dev_name, '-s', '--',
'mklabel', partition_table_type)
diff --git a/tox.ini b/tox.ini
index 70e0af6b..ccbe9fa5 100644
--- a/tox.ini
+++ b/tox.ini
@@ -35,10 +35,10 @@ commands = stestr run {posargs}
[testenv:pep8]
usedevelop = False
deps=
- hacking>=3.1.0,<4.0.0 # Apache-2.0
+ hacking>=4.1.0,<5.0.0 # Apache-2.0
bashate>=0.5.1 # Apache-2.0
flake8-import-order>=0.17.1 # LGPLv3
- pycodestyle>=2.0.0,<2.7.0 # MIT
+ pycodestyle>=2.0.0,<3.0.0 # MIT
doc8>=0.8.1 # Apache-2.0
allowlist_externals = bash
commands =