Source code for ironic.drivers.modules.inspector.hooks.raid_device
# 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 oslo_log import log as logging
from ironic.common import exception
from ironic.drivers.modules.inspector.hooks import base
from ironic.objects import node_inventory
LOG = logging.getLogger(__name__)
[docs]
class RaidDeviceHook(base.InspectionHook):
"""Hook for learning the root device after RAID creation.
This hook can figure out the root device in 2 runs. In the first run, the
node's inventory is saved as usual, and the hook does not do anything.
The second run will check the difference between the recently discovered
block devices (as reported by the inspection results) and the previously
saved ones (from the previously saved inventory). If there is exactly one
new block device, its serial number is saved in node.properties under the
'root_device' key.
This way, it helps to figure out the root device hint in cases when Ironic
doesn't have enough information to do so otherwise. One such usecase is
DRAC RAID configuration, where the BMC doesn't provide any useful
information about the created RAID disks. Using this hook immediately
before and after creating the root RAID device will solve the issue of
root device hints.
"""
def _get_serials(self, inventory):
if inventory.get('disks'):
return [x['serial'] for x in inventory.get('disks')
if x.get('serial')]
[docs]
def __call__(self, task, inventory, plugin_data):
node = task.node
if 'root_device' in node.properties:
LOG.info('Root device is already known for node %s', node.uuid)
return
current_devices = self._get_serials(inventory)
if not current_devices:
LOG.warning('No block device information was received from the '
'ramdisk for node %s', node.uuid)
return
try:
previous_inventory = node_inventory.NodeInventory.get_by_node_id(
task.context, node.id)
except exception.NodeInventoryNotFound:
LOG.debug('Inventory for node %s not found in the database. Raid '
'device hook exiting.', task.node.uuid)
return
previous_devices = self._get_serials(previous_inventory.get(
'inventory_data'))
# Compare previously discovered devices with the current ones
new_devices = [device for device in current_devices
if device not in previous_devices]
if len(new_devices) > 1:
LOG.warning('Root device cannot be identified because multiple '
'new devices were found for node %s', node.uuid)
return
elif len(new_devices) == 0:
LOG.warning('No new devices were found for node %s', node.uuid)
return
node.set_property('root_device', {'serial': new_devices[0]})
node.save()
LOG.info('"root_device" property set for node %s', node.uuid)