Support configdrive in iscsi deploy for whole disk images
This will work for UEFI only or BIOS only images. It will not work for hybrid images; which are capable of boot from BIOS and UEFI boot mode. Partial-Bug: #1493328 Change-Id: I9a0775a147d5bac711b58b4b6cf0135ec68509f7
This commit is contained in:
parent
53f8b173ae
commit
1027c1bc44
@ -258,6 +258,7 @@ class AgentDeployMixin(agent_base_vendor.AgentDeployMixin):
|
||||
if no_proxy is not None:
|
||||
image_info['no_proxy'] = no_proxy
|
||||
|
||||
image_info['node_uuid'] = node.uuid
|
||||
iwdi = node.driver_internal_info.get('is_whole_disk_image')
|
||||
if not iwdi:
|
||||
for label in PARTITION_IMAGE_LABELS:
|
||||
@ -272,7 +273,6 @@ class AgentDeployMixin(agent_base_vendor.AgentDeployMixin):
|
||||
disk_label = deploy_utils.get_disk_label(node)
|
||||
if disk_label is not None:
|
||||
image_info['disk_label'] = disk_label
|
||||
image_info['node_uuid'] = node.uuid
|
||||
|
||||
# Tell the client to download and write the image with the given args
|
||||
self._client.prepare_image(node, image_info)
|
||||
|
@ -363,7 +363,7 @@ def deploy_partition_image(
|
||||
|
||||
|
||||
def deploy_disk_image(address, port, iqn, lun,
|
||||
image_path, node_uuid):
|
||||
image_path, node_uuid, configdrive=None):
|
||||
"""All-in-one function to deploy a whole disk image to a node.
|
||||
|
||||
:param address: The iSCSI IP address.
|
||||
@ -373,6 +373,8 @@ def deploy_disk_image(address, port, iqn, lun,
|
||||
:param image_path: Path for the instance's disk image.
|
||||
:param node_uuid: node's uuid. Used for logging. Currently not in use
|
||||
by this function but could be used in the future.
|
||||
:param configdrive: Optional. Base64 encoded Gzipped configdrive content
|
||||
or configdrive HTTP URL.
|
||||
:returns: a dictionary containing the key 'disk identifier' to identify
|
||||
the disk which was used for deployment.
|
||||
"""
|
||||
@ -381,6 +383,10 @@ def deploy_disk_image(address, port, iqn, lun,
|
||||
disk_utils.populate_image(image_path, dev)
|
||||
disk_identifier = disk_utils.get_disk_identifier(dev)
|
||||
|
||||
if configdrive:
|
||||
disk_utils.create_config_drive_partition(node_uuid, dev,
|
||||
configdrive)
|
||||
|
||||
return {'disk identifier': disk_identifier}
|
||||
|
||||
|
||||
@ -1181,6 +1187,7 @@ def parse_instance_info(node):
|
||||
# ensuring that it is possible
|
||||
i_info['swap_mb'] = info.get('swap_mb', 0)
|
||||
i_info['ephemeral_gb'] = info.get('ephemeral_gb', 0)
|
||||
i_info['configdrive'] = info.get('configdrive')
|
||||
err_msg_invalid = _("Cannot validate parameter for driver deploy. "
|
||||
"Invalid parameter %(param)s. Reason: %(reason)s")
|
||||
for param in DISK_LAYOUT_PARAMS:
|
||||
|
@ -183,12 +183,13 @@ def get_deploy_info(node, address, iqn, port=None, lun='1'):
|
||||
_("Parameters %s were not passed to ironic"
|
||||
" for deploy.") % missing)
|
||||
|
||||
# configdrive is nullable
|
||||
params['configdrive'] = i_info.get('configdrive')
|
||||
if is_whole_disk_image:
|
||||
return params
|
||||
|
||||
# configdrive and ephemeral_format are nullable
|
||||
# ephemeral_format is nullable
|
||||
params['ephemeral_format'] = i_info.get('ephemeral_format')
|
||||
params['configdrive'] = i_info.get('configdrive')
|
||||
|
||||
return params
|
||||
|
||||
|
@ -662,6 +662,7 @@ class TestAgentVendor(db_base.DbTestCase):
|
||||
expected_image_info = {
|
||||
'urls': [test_temp_url],
|
||||
'id': 'fake-image',
|
||||
'node_uuid': self.node.uuid,
|
||||
'checksum': 'checksum',
|
||||
'disk_format': 'qcow2',
|
||||
'container_format': 'bare',
|
||||
|
@ -874,8 +874,10 @@ class PhysicalWorkTestCase(tests_base.TestCase):
|
||||
self.assertEqual(root_uuid, uuid_dict_returned['root uuid'])
|
||||
mock_unlink.assert_called_once_with('configdrive-path')
|
||||
|
||||
@mock.patch.object(disk_utils, 'create_config_drive_partition',
|
||||
autospec=True)
|
||||
@mock.patch.object(disk_utils, 'get_disk_identifier', autospec=True)
|
||||
def test_deploy_whole_disk_image(self, mock_gdi):
|
||||
def test_deploy_whole_disk_image(self, mock_gdi, create_config_drive_mock):
|
||||
"""Check loosely all functions are called with right args."""
|
||||
address = '127.0.0.1'
|
||||
port = 3306
|
||||
@ -904,10 +906,55 @@ class PhysicalWorkTestCase(tests_base.TestCase):
|
||||
mock.call.populate_image(image_path, dev)]
|
||||
|
||||
uuid_dict_returned = utils.deploy_disk_image(address, port, iqn, lun,
|
||||
image_path, node_uuid)
|
||||
image_path, node_uuid,
|
||||
configdrive=None)
|
||||
|
||||
self.assertEqual(utils_calls_expected, utils_mock.mock_calls)
|
||||
self.assertEqual(disk_utils_calls_expected, disk_utils_mock.mock_calls)
|
||||
self.assertFalse(create_config_drive_mock.called)
|
||||
self.assertEqual('0x12345678', uuid_dict_returned['disk identifier'])
|
||||
|
||||
@mock.patch.object(disk_utils, 'create_config_drive_partition',
|
||||
autospec=True)
|
||||
@mock.patch.object(disk_utils, 'get_disk_identifier', autospec=True)
|
||||
def test_deploy_whole_disk_image_with_config_drive(self, mock_gdi,
|
||||
create_partition_mock):
|
||||
"""Check loosely all functions are called with right args."""
|
||||
address = '127.0.0.1'
|
||||
port = 3306
|
||||
iqn = 'iqn.xyz'
|
||||
lun = 1
|
||||
image_path = '/tmp/xyz/image'
|
||||
node_uuid = "12345678-1234-1234-1234-1234567890abcxyz"
|
||||
config_url = 'http://1.2.3.4/cd'
|
||||
|
||||
dev = '/dev/fake'
|
||||
utils_list = ['get_dev', 'discovery', 'login_iscsi', 'logout_iscsi',
|
||||
'delete_iscsi']
|
||||
|
||||
disk_utils_list = ['is_block_device', 'populate_image']
|
||||
utils_mock = self._mock_calls(utils_list, utils)
|
||||
disk_utils_mock = self._mock_calls(disk_utils_list, disk_utils)
|
||||
utils_mock.get_dev.return_value = dev
|
||||
disk_utils_mock.is_block_device.return_value = True
|
||||
mock_gdi.return_value = '0x12345678'
|
||||
utils_calls_expected = [mock.call.get_dev(address, port, iqn, lun),
|
||||
mock.call.discovery(address, port),
|
||||
mock.call.login_iscsi(address, port, iqn),
|
||||
mock.call.logout_iscsi(address, port, iqn),
|
||||
mock.call.delete_iscsi(address, port, iqn)]
|
||||
|
||||
disk_utils_calls_expected = [mock.call.is_block_device(dev),
|
||||
mock.call.populate_image(image_path, dev)]
|
||||
|
||||
uuid_dict_returned = utils.deploy_disk_image(address, port, iqn, lun,
|
||||
image_path, node_uuid,
|
||||
configdrive=config_url)
|
||||
|
||||
utils_mock.assert_has_calls(utils_calls_expected)
|
||||
disk_utils_mock.assert_has_calls(disk_utils_calls_expected)
|
||||
create_partition_mock.assert_called_once_with(node_uuid, dev,
|
||||
config_url)
|
||||
self.assertEqual('0x12345678', uuid_dict_returned['disk identifier'])
|
||||
|
||||
@mock.patch.object(common_utils, 'execute', autospec=True)
|
||||
|
@ -386,6 +386,17 @@ class IscsiDeployMethodsTestCase(db_base.DbTestCase):
|
||||
ret_val = self._test_get_deploy_info()
|
||||
self.assertEqual(3266, ret_val['port'])
|
||||
|
||||
def test_get_deploy_info_whole_disk_image(self):
|
||||
instance_info = self.node.instance_info
|
||||
instance_info['configdrive'] = 'My configdrive'
|
||||
self.node.instance_info = instance_info
|
||||
self.node.driver_internal_info['is_whole_disk_image'] = True
|
||||
kwargs = {'address': '1.1.1.1', 'iqn': 'target-iqn'}
|
||||
ret_val = iscsi_deploy.get_deploy_info(self.node, **kwargs)
|
||||
self.assertEqual('1.1.1.1', ret_val['address'])
|
||||
self.assertEqual('target-iqn', ret_val['iqn'])
|
||||
self.assertEqual('My configdrive', ret_val['configdrive'])
|
||||
|
||||
@mock.patch.object(iscsi_deploy, 'continue_deploy', autospec=True)
|
||||
def test_do_agent_iscsi_deploy_okay(self, continue_deploy_mock):
|
||||
agent_client_mock = mock.MagicMock(spec_set=agent_client.AgentClient)
|
||||
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
features:
|
||||
- Added configdrive support for whole disk images
|
||||
for iSCSI based deploy.
|
||||
This will work for UEFI only or BIOS only images.
|
||||
It will not work for hybrid images which are
|
||||
capable of booting from BIOS and UEFI boot mode.
|
Loading…
Reference in New Issue
Block a user