summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShivanand Tendulker <stendulker@gmail.com>2015-09-18 04:43:35 -0700
committerShivanand Tendulker <stendulker@gmail.com>2016-09-18 23:28:02 -0700
commit1027c1bc44912fcbfb9f842fedef39c9067632f8 (patch)
treec96e4b1c5fcfbccbe412547a650fb2c129ac6afd
parent53f8b173ae91b141bae1b5dbe872baedc45f7866 (diff)
downloadironic-1027c1bc44912fcbfb9f842fedef39c9067632f8.tar.gz
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
-rw-r--r--ironic/drivers/modules/agent.py2
-rw-r--r--ironic/drivers/modules/deploy_utils.py9
-rw-r--r--ironic/drivers/modules/iscsi_deploy.py5
-rw-r--r--ironic/tests/unit/drivers/modules/test_agent.py1
-rw-r--r--ironic/tests/unit/drivers/modules/test_deploy_utils.py51
-rw-r--r--ironic/tests/unit/drivers/modules/test_iscsi_deploy.py11
-rw-r--r--releasenotes/notes/config-drive-support-for-whole-disk-images-in-iscsi-deploy-0193c5222a7cd129.yaml7
7 files changed, 80 insertions, 6 deletions
diff --git a/ironic/drivers/modules/agent.py b/ironic/drivers/modules/agent.py
index 1b045974c..eda5e6f17 100644
--- a/ironic/drivers/modules/agent.py
+++ b/ironic/drivers/modules/agent.py
@@ -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)
diff --git a/ironic/drivers/modules/deploy_utils.py b/ironic/drivers/modules/deploy_utils.py
index ce4be5c9e..f8354647d 100644
--- a/ironic/drivers/modules/deploy_utils.py
+++ b/ironic/drivers/modules/deploy_utils.py
@@ -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:
diff --git a/ironic/drivers/modules/iscsi_deploy.py b/ironic/drivers/modules/iscsi_deploy.py
index 3cecb4482..74d67f896 100644
--- a/ironic/drivers/modules/iscsi_deploy.py
+++ b/ironic/drivers/modules/iscsi_deploy.py
@@ -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
diff --git a/ironic/tests/unit/drivers/modules/test_agent.py b/ironic/tests/unit/drivers/modules/test_agent.py
index ca8cb474b..ad88994b1 100644
--- a/ironic/tests/unit/drivers/modules/test_agent.py
+++ b/ironic/tests/unit/drivers/modules/test_agent.py
@@ -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',
diff --git a/ironic/tests/unit/drivers/modules/test_deploy_utils.py b/ironic/tests/unit/drivers/modules/test_deploy_utils.py
index ceb8c4ab2..683d60b46 100644
--- a/ironic/tests/unit/drivers/modules/test_deploy_utils.py
+++ b/ironic/tests/unit/drivers/modules/test_deploy_utils.py
@@ -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)
diff --git a/ironic/tests/unit/drivers/modules/test_iscsi_deploy.py b/ironic/tests/unit/drivers/modules/test_iscsi_deploy.py
index 423839c97..7ca3771fa 100644
--- a/ironic/tests/unit/drivers/modules/test_iscsi_deploy.py
+++ b/ironic/tests/unit/drivers/modules/test_iscsi_deploy.py
@@ -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)
diff --git a/releasenotes/notes/config-drive-support-for-whole-disk-images-in-iscsi-deploy-0193c5222a7cd129.yaml b/releasenotes/notes/config-drive-support-for-whole-disk-images-in-iscsi-deploy-0193c5222a7cd129.yaml
new file mode 100644
index 000000000..f043b1032
--- /dev/null
+++ b/releasenotes/notes/config-drive-support-for-whole-disk-images-in-iscsi-deploy-0193c5222a7cd129.yaml
@@ -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.