Add boot information into the inventory
Adds a new BootInfo object with 2 fields: * current_boot_mode - bios or uefi, detected from presence of /sys/firmware/efi as per the following answer: http://askubuntu.com/a/162896 This field will be used for setting the boot_mode capability in ironic-inspector * pxe_interface - PXE booting interface, if it can be detected. This fields is already used by ironic-inspector, added here for consistency. Change-Id: Ib36b592ffaba3bfa055d65c9526607867d302584 Partial-Bug: #1571580
This commit is contained in:
parent
962ee1afb5
commit
53b187a4c3
@ -117,6 +117,11 @@ fields:
|
|||||||
system vendor information from SMBIOS as reported by ``dmidecode``:
|
system vendor information from SMBIOS as reported by ``dmidecode``:
|
||||||
``product_name``, ``serial_number`` and ``manufacturer``.
|
``product_name``, ``serial_number`` and ``manufacturer``.
|
||||||
|
|
||||||
|
``boot``
|
||||||
|
boot information with fields: ``current_boot_mode`` (boot mode used for
|
||||||
|
the current boot - BIOS or UEFI) and ``pxe_interface`` (interface used
|
||||||
|
for PXE booting, if any).
|
||||||
|
|
||||||
Image Builders
|
Image Builders
|
||||||
--------------
|
--------------
|
||||||
Unlike most other python software, you must build an IPA ramdisk image before
|
Unlike most other python software, you must build an IPA ramdisk image before
|
||||||
|
@ -220,6 +220,14 @@ class SystemVendorInfo(encoding.SerializableComparable):
|
|||||||
self.manufacturer = manufacturer
|
self.manufacturer = manufacturer
|
||||||
|
|
||||||
|
|
||||||
|
class BootInfo(encoding.SerializableComparable):
|
||||||
|
serializable_fields = ('current_boot_mode', 'pxe_interface')
|
||||||
|
|
||||||
|
def __init__(self, current_boot_mode, pxe_interface=None):
|
||||||
|
self.current_boot_mode = current_boot_mode
|
||||||
|
self.pxe_interface = pxe_interface
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
class HardwareManager(object):
|
class HardwareManager(object):
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
@ -244,6 +252,9 @@ class HardwareManager(object):
|
|||||||
def get_bmc_address(self):
|
def get_bmc_address(self):
|
||||||
raise errors.IncompatibleHardwareMethodError()
|
raise errors.IncompatibleHardwareMethodError()
|
||||||
|
|
||||||
|
def get_boot_info(self):
|
||||||
|
raise errors.IncompatibleHardwareMethodError()
|
||||||
|
|
||||||
def erase_block_device(self, node, block_device):
|
def erase_block_device(self, node, block_device):
|
||||||
"""Attempt to erase a block device.
|
"""Attempt to erase a block device.
|
||||||
|
|
||||||
@ -305,6 +316,7 @@ class HardwareManager(object):
|
|||||||
hardware_info['memory'] = self.get_memory()
|
hardware_info['memory'] = self.get_memory()
|
||||||
hardware_info['bmc_address'] = self.get_bmc_address()
|
hardware_info['bmc_address'] = self.get_bmc_address()
|
||||||
hardware_info['system_vendor'] = self.get_system_vendor_info()
|
hardware_info['system_vendor'] = self.get_system_vendor_info()
|
||||||
|
hardware_info['boot'] = self.get_boot_info()
|
||||||
return hardware_info
|
return hardware_info
|
||||||
|
|
||||||
def get_clean_steps(self, node, ports):
|
def get_clean_steps(self, node, ports):
|
||||||
@ -597,6 +609,13 @@ class GenericHardwareManager(HardwareManager):
|
|||||||
serial_number=serial_number,
|
serial_number=serial_number,
|
||||||
manufacturer=manufacturer)
|
manufacturer=manufacturer)
|
||||||
|
|
||||||
|
def get_boot_info(self):
|
||||||
|
boot_mode = 'uefi' if os.path.isdir('/sys/firmware/efi') else 'bios'
|
||||||
|
LOG.debug('The current boot mode is %s', boot_mode)
|
||||||
|
pxe_interface = utils.get_agent_params().get('BOOTIF')
|
||||||
|
return BootInfo(current_boot_mode=boot_mode,
|
||||||
|
pxe_interface=pxe_interface)
|
||||||
|
|
||||||
def erase_block_device(self, node, block_device):
|
def erase_block_device(self, node, block_device):
|
||||||
|
|
||||||
# Check if the block device is virtual media and skip the device.
|
# Check if the block device is virtual media and skip the device.
|
||||||
|
@ -306,7 +306,7 @@ def collect_default(data, failures):
|
|||||||
LOG.debug('default root device is %s', root_disk.name)
|
LOG.debug('default root device is %s', root_disk.name)
|
||||||
# Both boot interface and IPMI address might not be present,
|
# Both boot interface and IPMI address might not be present,
|
||||||
# we don't count it as failure
|
# we don't count it as failure
|
||||||
data['boot_interface'] = utils.get_agent_params().get('BOOTIF')
|
data['boot_interface'] = inventory['boot'].pxe_interface
|
||||||
LOG.debug('boot devices was %s', data['boot_interface'])
|
LOG.debug('boot devices was %s', data['boot_interface'])
|
||||||
data['ipmi_address'] = inventory.get('bmc_address')
|
data['ipmi_address'] = inventory.get('bmc_address')
|
||||||
LOG.debug('BMC IP address: %s', data['ipmi_address'])
|
LOG.debug('BMC IP address: %s', data['ipmi_address'])
|
||||||
|
@ -500,6 +500,10 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
|
|||||||
hardware.BlockDevice('/dev/hdaa', 'small', 65535, False),
|
hardware.BlockDevice('/dev/hdaa', 'small', 65535, False),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
self.hardware.get_boot_info = mock.Mock()
|
||||||
|
self.hardware.get_boot_info.return_value = hardware.BootInfo(
|
||||||
|
current_boot_mode='bios', pxe_interface='boot:if')
|
||||||
|
|
||||||
hardware_info = self.hardware.list_hardware_info()
|
hardware_info = self.hardware.list_hardware_info()
|
||||||
self.assertEqual(self.hardware.get_memory(), hardware_info['memory'])
|
self.assertEqual(self.hardware.get_memory(), hardware_info['memory'])
|
||||||
self.assertEqual(self.hardware.get_cpus(), hardware_info['cpu'])
|
self.assertEqual(self.hardware.get_cpus(), hardware_info['cpu'])
|
||||||
@ -507,6 +511,8 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
|
|||||||
hardware_info['disks'])
|
hardware_info['disks'])
|
||||||
self.assertEqual(self.hardware.list_network_interfaces(),
|
self.assertEqual(self.hardware.list_network_interfaces(),
|
||||||
hardware_info['interfaces'])
|
hardware_info['interfaces'])
|
||||||
|
self.assertEqual(self.hardware.get_boot_info(),
|
||||||
|
hardware_info['boot'])
|
||||||
|
|
||||||
@mock.patch.object(hardware, 'list_all_block_devices')
|
@mock.patch.object(hardware, 'list_all_block_devices')
|
||||||
def test_list_block_devices(self, list_mock):
|
def test_list_block_devices(self, list_mock):
|
||||||
@ -1120,6 +1126,30 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
|
|||||||
mocked_root_dev.call_count)
|
mocked_root_dev.call_count)
|
||||||
mocked_sleep.assert_called_with(hardware._DISK_WAIT_DELAY)
|
mocked_sleep.assert_called_with(hardware._DISK_WAIT_DELAY)
|
||||||
|
|
||||||
|
@mock.patch.object(utils, 'get_agent_params',
|
||||||
|
lambda: {'BOOTIF': 'boot:if'})
|
||||||
|
@mock.patch.object(os.path, 'isdir', autospec=True)
|
||||||
|
def test_get_boot_info_pxe_interface(self, mocked_isdir):
|
||||||
|
mocked_isdir.return_value = False
|
||||||
|
result = self.hardware.get_boot_info()
|
||||||
|
self.assertEqual(hardware.BootInfo(current_boot_mode='bios',
|
||||||
|
pxe_interface='boot:if'),
|
||||||
|
result)
|
||||||
|
|
||||||
|
@mock.patch.object(os.path, 'isdir', autospec=True)
|
||||||
|
def test_get_boot_info_bios(self, mocked_isdir):
|
||||||
|
mocked_isdir.return_value = False
|
||||||
|
result = self.hardware.get_boot_info()
|
||||||
|
self.assertEqual(hardware.BootInfo(current_boot_mode='bios'), result)
|
||||||
|
mocked_isdir.assert_called_once_with('/sys/firmware/efi')
|
||||||
|
|
||||||
|
@mock.patch.object(os.path, 'isdir', autospec=True)
|
||||||
|
def test_get_boot_info_uefi(self, mocked_isdir):
|
||||||
|
mocked_isdir.return_value = True
|
||||||
|
result = self.hardware.get_boot_info()
|
||||||
|
self.assertEqual(hardware.BootInfo(current_boot_mode='uefi'), result)
|
||||||
|
mocked_isdir.assert_called_once_with('/sys/firmware/efi')
|
||||||
|
|
||||||
|
|
||||||
@mock.patch.object(utils, 'execute', autospec=True)
|
@mock.patch.object(utils, 'execute', autospec=True)
|
||||||
class TestModuleFunctions(test_base.BaseTestCase):
|
class TestModuleFunctions(test_base.BaseTestCase):
|
||||||
|
@ -258,6 +258,8 @@ class BaseDiscoverTest(unittest.TestCase):
|
|||||||
rotational=True)
|
rotational=True)
|
||||||
],
|
],
|
||||||
'bmc_address': '1.2.3.4',
|
'bmc_address': '1.2.3.4',
|
||||||
|
'boot': hardware.BootInfo(current_boot_mode='bios',
|
||||||
|
pxe_interface='boot:if')
|
||||||
}
|
}
|
||||||
self.failures = utils.AccumulatedFailures()
|
self.failures = utils.AccumulatedFailures()
|
||||||
self.data = {}
|
self.data = {}
|
||||||
@ -327,8 +329,6 @@ class TestDiscoverSchedulingProperties(BaseDiscoverTest):
|
|||||||
self.data)
|
self.data)
|
||||||
|
|
||||||
|
|
||||||
@mock.patch.object(utils, 'get_agent_params',
|
|
||||||
lambda: {'BOOTIF': 'boot:if'})
|
|
||||||
@mock.patch.object(inspector, 'wait_for_dhcp', autospec=True)
|
@mock.patch.object(inspector, 'wait_for_dhcp', autospec=True)
|
||||||
@mock.patch.object(inspector, 'discover_scheduling_properties', autospec=True)
|
@mock.patch.object(inspector, 'discover_scheduling_properties', autospec=True)
|
||||||
@mock.patch.object(inspector, 'discover_network_properties', autospec=True)
|
@mock.patch.object(inspector, 'discover_network_properties', autospec=True)
|
||||||
|
4
releasenotes/notes/boot-info-f18336ada089f6dd.yaml
Normal file
4
releasenotes/notes/boot-info-f18336ada089f6dd.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Introduced "boot" field into the inventory, with "current_boot_mode" and
|
||||||
|
"pxe_interface" fields. Both will be used for inspection.
|
Loading…
Reference in New Issue
Block a user