Software RAID: Identify the root fs via its UUID from image metadata
In order to install the bootloader on instances with software RAID, the IPA needs to chroot into the deployed image's root fs. Currently, the IPA assumes the first partition to contain the root fs, so this breaks with images where this is not the case. The proposed change extracts the root fs UUID from the image's metadata instead and passes it to the IPA (in the same way this is done for partition images). It keeps the current behaviour to send the UUID extracted from the driver internal info in case the metadata is not set on the image. For the time being, the IPA completely ignores the UUID passed anyway, so to make this fully work the IPA will also need to be patched. Change-Id: I69bd53aa24b7b10384dc1399a0acaa21d38d6bd9 Story: #2006649 Task: #37081
This commit is contained in:
parent
2408987175
commit
defc4a8761
@ -27,6 +27,7 @@ import retrying
|
||||
from ironic.common import boot_devices
|
||||
from ironic.common import exception
|
||||
from ironic.common.i18n import _
|
||||
from ironic.common import image_service
|
||||
from ironic.common import states
|
||||
from ironic.conductor import steps as conductor_steps
|
||||
from ironic.conductor import utils as manager_utils
|
||||
@ -827,9 +828,30 @@ class AgentDeployMixin(HeartbeatMixin):
|
||||
LOG.debug('Node %s has a Software RAID configuration',
|
||||
node.uuid)
|
||||
software_raid = True
|
||||
root_uuid = internal_info.get('root_uuid_or_disk_id')
|
||||
break
|
||||
|
||||
# For software RAID try to get the UUID of the root fs from the
|
||||
# image's metadata (via Glance). Fall back to the driver internal
|
||||
# info in case it is not available (e.g. not set or there's no Glance).
|
||||
if software_raid:
|
||||
image_source = node.instance_info.get('image_source')
|
||||
try:
|
||||
context = task.context
|
||||
context.is_admin = True
|
||||
glance = image_service.GlanceImageService(
|
||||
context=context)
|
||||
image_info = glance.show(image_source)
|
||||
image_properties = image_info.get('properties')
|
||||
root_uuid = image_properties['rootfs_uuid']
|
||||
LOG.debug('Got rootfs_uuid from Glance: %s', root_uuid)
|
||||
except Exception as e:
|
||||
LOG.warning('Could not get \'rootfs_uuid\' property for '
|
||||
'image %(image)s from Glance: %(error)s.',
|
||||
{'image': image_source, 'error': e})
|
||||
root_uuid = internal_info.get('root_uuid_or_disk_id')
|
||||
LOG.debug('Got rootfs_uuid from driver internal info: '
|
||||
' %s', root_uuid)
|
||||
|
||||
whole_disk_image = internal_info.get('is_whole_disk_image')
|
||||
if software_raid or (root_uuid and not whole_disk_image):
|
||||
LOG.debug('Installing the bootloader for node %(node)s on '
|
||||
|
@ -21,6 +21,7 @@ from oslo_config import cfg
|
||||
|
||||
from ironic.common import boot_devices
|
||||
from ironic.common import exception
|
||||
from ironic.common import image_service
|
||||
from ironic.common import states
|
||||
from ironic.conductor import steps as conductor_steps
|
||||
from ironic.conductor import task_manager
|
||||
@ -1189,11 +1190,13 @@ class AgentDeployMixinTest(AgentDeployMixinBaseTest):
|
||||
try_set_boot_device_mock.assert_called_once_with(
|
||||
task, boot_devices.DISK, persistent=True)
|
||||
|
||||
@mock.patch.object(image_service, 'GlanceImageService', autospec=True)
|
||||
@mock.patch.object(deploy_utils, 'try_set_boot_device', autospec=True)
|
||||
@mock.patch.object(agent_client.AgentClient, 'install_bootloader',
|
||||
autospec=True)
|
||||
def test_configure_local_boot_on_software_raid(
|
||||
self, install_bootloader_mock, try_set_boot_device_mock):
|
||||
self, install_bootloader_mock, try_set_boot_device_mock,
|
||||
GlanceImageService_mock):
|
||||
with task_manager.acquire(self.context, self.node['uuid'],
|
||||
shared=False) as task:
|
||||
task.node.driver_internal_info['is_whole_disk_image'] = True
|
||||
@ -1211,12 +1214,48 @@ class AgentDeployMixinTest(AgentDeployMixinBaseTest):
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
self.deploy.configure_local_boot(task)
|
||||
self.assertTrue(GlanceImageService_mock.called)
|
||||
self.assertTrue(install_bootloader_mock.called)
|
||||
try_set_boot_device_mock.assert_called_once_with(
|
||||
task, boot_devices.DISK, persistent=True)
|
||||
|
||||
@mock.patch.object(image_service, 'GlanceImageService', autospec=True)
|
||||
@mock.patch.object(deploy_utils, 'try_set_boot_device', autospec=True)
|
||||
@mock.patch.object(agent_client.AgentClient, 'install_bootloader',
|
||||
autospec=True)
|
||||
def test_configure_local_boot_on_software_raid_exception(
|
||||
self, install_bootloader_mock, try_set_boot_device_mock,
|
||||
GlanceImageService_mock):
|
||||
GlanceImageService_mock.side_effect = Exception('Glance not found')
|
||||
with task_manager.acquire(self.context, self.node['uuid'],
|
||||
shared=False) as task:
|
||||
task.node.driver_internal_info['is_whole_disk_image'] = True
|
||||
root_uuid = "1efecf88-2b58-4d4e-8fbd-7bef1a40a1b0"
|
||||
task.node.driver_internal_info['root_uuid_or_disk_id'] = root_uuid
|
||||
task.node.target_raid_config = {
|
||||
"logical_disks": [
|
||||
{
|
||||
"size_gb": 100,
|
||||
"raid_level": "1",
|
||||
"controller": "software",
|
||||
},
|
||||
{
|
||||
"size_gb": 'MAX',
|
||||
"raid_level": "0",
|
||||
"controller": "software",
|
||||
}
|
||||
]
|
||||
}
|
||||
self.deploy.configure_local_boot(task)
|
||||
self.assertTrue(GlanceImageService_mock.called)
|
||||
# check if the root_uuid comes from the driver_internal_info
|
||||
install_bootloader_mock.assert_called_once_with(
|
||||
mock.ANY, task.node, root_uuid=root_uuid,
|
||||
efi_system_part_uuid=None, prep_boot_part_uuid=None)
|
||||
try_set_boot_device_mock.assert_called_once_with(
|
||||
task, boot_devices.DISK, persistent=True)
|
||||
|
||||
@mock.patch.object(deploy_utils, 'try_set_boot_device', autospec=True)
|
||||
@mock.patch.object(agent_client.AgentClient, 'install_bootloader',
|
||||
autospec=True)
|
||||
@ -1237,7 +1276,6 @@ class AgentDeployMixinTest(AgentDeployMixinBaseTest):
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
self.deploy.configure_local_boot(task)
|
||||
self.assertFalse(install_bootloader_mock.called)
|
||||
try_set_boot_device_mock.assert_called_once_with(
|
||||
|
@ -0,0 +1,13 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Software RAID is no longer limited to images which have the root file
|
||||
system in the first partition.
|
||||
upgrade:
|
||||
- |
|
||||
For Software RAID, the IPA no longer assumes that the root file system
|
||||
of the deployed image is in the first partition. Instead, it will use
|
||||
the UUID passed from the conductor. Operators need hence to make sure
|
||||
that the conductor has the correct UUID (which either comes from the
|
||||
'rootfs_uuid' field in the image metadata or from the
|
||||
'root_uuid_or_disk_id' in the nodes 'internal_driver_info'.)
|
Loading…
x
Reference in New Issue
Block a user