From dc5ce8080b38764a5298cba1680d6d967d5b0727 Mon Sep 17 00:00:00 2001 From: Pavlo Shchelokovskyy Date: Fri, 23 Sep 2016 20:43:11 +0300 Subject: [PATCH] Move build_instance_info_for_deploy to deploy_utils this function is not using any agent-specific logic and sets pretty common instance_info fields any deployment driver would need. To facilitate code reuse and not impose dependency of third-party drivers on agent driver module, move this code to deploy_utils. In case this is actually already used by a third-party driver, the old location is left in place but will log a deprecation warning. This patch also amends this function to store more image information in instance_info, namely list if image tags and full image properties as returned by Glance API. Change-Id: I0ce425325ad01455c72a96e013114509bbd74a66 --- ironic/drivers/modules/agent.py | 62 +----- ironic/drivers/modules/deploy_utils.py | 55 +++++ .../tests/unit/drivers/modules/test_agent.py | 189 +----------------- .../unit/drivers/modules/test_deploy_utils.py | 189 ++++++++++++++++++ 4 files changed, 265 insertions(+), 230 deletions(-) diff --git a/ironic/drivers/modules/agent.py b/ironic/drivers/modules/agent.py index eda5e6f175..1d0ffe6ada 100644 --- a/ironic/drivers/modules/agent.py +++ b/ironic/drivers/modules/agent.py @@ -14,15 +14,13 @@ from ironic_lib import metrics_utils from oslo_log import log -from oslo_utils import excutils from oslo_utils import units import six.moves.urllib_parse as urlparse from ironic.common import dhcp_factory from ironic.common import exception from ironic.common.glance_service import service_utils -from ironic.common.i18n import _, _LE, _LI, _LW -from ironic.common import image_service +from ironic.common.i18n import _, _LI, _LW from ironic.common import images from ironic.common import raid from ironic.common import states @@ -68,54 +66,15 @@ PARTITION_IMAGE_LABELS = ('kernel', 'ramdisk', 'root_gb', 'root_mb', 'swap_mb', 'deploy_boot_mode') -@METRICS.timer('build_instance_info_for_deploy') def build_instance_info_for_deploy(task): - """Build instance_info necessary for deploying to a node. - - :param task: a TaskManager object containing the node - :returns: a dictionary containing the properties to be updated - in instance_info - :raises: exception.ImageRefValidationFailed if image_source is not - Glance href and is not HTTP(S) URL. - """ - node = task.node - instance_info = node.instance_info - iwdi = node.driver_internal_info.get('is_whole_disk_image') - image_source = instance_info['image_source'] - if service_utils.is_glance_image(image_source): - glance = image_service.GlanceImageService(version=2, - context=task.context) - image_info = glance.show(image_source) - swift_temp_url = glance.swift_temp_url(image_info) - LOG.debug('Got image info: %(info)s for node %(node)s.', - {'info': image_info, 'node': node.uuid}) - instance_info['image_url'] = swift_temp_url - instance_info['image_checksum'] = image_info['checksum'] - instance_info['image_disk_format'] = image_info['disk_format'] - instance_info['image_container_format'] = ( - image_info['container_format']) - - if not iwdi: - instance_info['kernel'] = image_info['properties']['kernel_id'] - instance_info['ramdisk'] = image_info['properties']['ramdisk_id'] - else: - try: - image_service.HttpImageService().validate_href(image_source) - except exception.ImageRefValidationFailed: - with excutils.save_and_reraise_exception(): - LOG.error(_LE("Agent deploy supports only HTTP(S) URLs as " - "instance_info['image_source']. Either %s " - "is not a valid HTTP(S) URL or " - "is not reachable."), image_source) - instance_info['image_url'] = image_source - - if not iwdi: - instance_info['image_type'] = 'partition' - i_info = deploy_utils.parse_instance_info(node) - instance_info.update(i_info) - else: - instance_info['image_type'] = 'whole-disk-image' - return instance_info + # TODO(pas-ha) remove this at the end of Ocata release + LOG.warning(_LW("This function is moved to " + "'ironic.drivers.modules.deploy_utils' module. " + "Using it from 'ironic.drivers.modules.agent' module " + "is deprecated and will be impossible in Ocata release. " + "Please update your driver to use this function " + "from its new location.")) + return deploy_utils.build_instance_info_for_deploy(task) @METRICS.timer('check_image_size') @@ -462,7 +421,8 @@ class AgentDeploy(AgentDeployMixin, base.DeployInterface): manager_utils.node_power_action(task, states.POWER_OFF) task.driver.network.add_provisioning_network(task) if node.provision_state not in [states.ACTIVE, states.ADOPTING]: - node.instance_info = build_instance_info_for_deploy(task) + node.instance_info = deploy_utils.build_instance_info_for_deploy( + task) node.save() if CONF.agent.manage_agent_boot: deploy_opts = deploy_utils.build_agent_options(node) diff --git a/ironic/drivers/modules/deploy_utils.py b/ironic/drivers/modules/deploy_utils.py index 32bb16deb1..114f66c6ec 100644 --- a/ironic/drivers/modules/deploy_utils.py +++ b/ironic/drivers/modules/deploy_utils.py @@ -20,6 +20,7 @@ import re import time from ironic_lib import disk_utils +from ironic_lib import metrics_utils from oslo_concurrency import processutils from oslo_log import log as logging from oslo_serialization import jsonutils @@ -54,6 +55,8 @@ if CONF.rootwrap_config != '/etc/ironic/rootwrap.conf': LOG = logging.getLogger(__name__) +METRICS = metrics_utils.get_metrics_logger(__name__) + VALID_ROOT_DEVICE_HINTS = set(('size', 'model', 'wwn', 'serial', 'vendor', 'wwn_with_extension', 'wwn_vendor_extension', 'name', 'rotational')) @@ -1260,3 +1263,55 @@ def _check_disk_layout_unchanged(node, i_info): "from previous deployment:%(error_msg)s") raise exception.InvalidParameterValue(err_msg_invalid % {'error_msg': error_msg}) + + +@METRICS.timer('build_instance_info_for_deploy') +def build_instance_info_for_deploy(task): + """Build instance_info necessary for deploying to a node. + + :param task: a TaskManager object containing the node + :returns: a dictionary containing the properties to be updated + in instance_info + :raises: exception.ImageRefValidationFailed if image_source is not + Glance href and is not HTTP(S) URL. + """ + node = task.node + instance_info = node.instance_info + iwdi = node.driver_internal_info.get('is_whole_disk_image') + image_source = instance_info['image_source'] + if service_utils.is_glance_image(image_source): + glance = image_service.GlanceImageService(version=2, + context=task.context) + image_info = glance.show(image_source) + swift_temp_url = glance.swift_temp_url(image_info) + LOG.debug('Got image info: %(info)s for node %(node)s.', + {'info': image_info, 'node': node.uuid}) + instance_info['image_url'] = swift_temp_url + instance_info['image_checksum'] = image_info['checksum'] + instance_info['image_disk_format'] = image_info['disk_format'] + instance_info['image_container_format'] = ( + image_info['container_format']) + instance_info['image_tags'] = image_info.get('tags', []) + instance_info['image_properties'] = image_info['properties'] + + if not iwdi: + instance_info['kernel'] = image_info['properties']['kernel_id'] + instance_info['ramdisk'] = image_info['properties']['ramdisk_id'] + else: + try: + image_service.HttpImageService().validate_href(image_source) + except exception.ImageRefValidationFailed: + with excutils.save_and_reraise_exception(): + LOG.error(_LE("Agent deploy supports only HTTP(S) URLs as " + "instance_info['image_source']. Either %s " + "is not a valid HTTP(S) URL or " + "is not reachable."), image_source) + instance_info['image_url'] = image_source + + if not iwdi: + instance_info['image_type'] = 'partition' + i_info = parse_instance_info(node) + instance_info.update(i_info) + else: + instance_info['image_type'] = 'whole-disk-image' + return instance_info diff --git a/ironic/tests/unit/drivers/modules/test_agent.py b/ironic/tests/unit/drivers/modules/test_agent.py index ad88994b16..0919bd44d3 100644 --- a/ironic/tests/unit/drivers/modules/test_agent.py +++ b/ironic/tests/unit/drivers/modules/test_agent.py @@ -19,7 +19,6 @@ from oslo_config import cfg from ironic.common import dhcp_factory from ironic.common import exception -from ironic.common import image_service from ironic.common import images from ironic.common import raid from ironic.common import states @@ -52,184 +51,16 @@ class TestAgentMethods(db_base.DbTestCase): driver='fake_agent') dhcp_factory.DHCPFactory._dhcp_provider = None - @mock.patch.object(image_service, 'GlanceImageService', autospec=True) - def test_build_instance_info_for_deploy_glance_image(self, glance_mock): - i_info = self.node.instance_info - i_info['image_source'] = '733d1c44-a2ea-414b-aca7-69decf20d810' - driver_internal_info = self.node.driver_internal_info - driver_internal_info['is_whole_disk_image'] = True - self.node.driver_internal_info = driver_internal_info - self.node.instance_info = i_info - self.node.save() - - image_info = {'checksum': 'aa', 'disk_format': 'qcow2', - 'container_format': 'bare'} - glance_mock.return_value.show = mock.MagicMock(spec_set=[], - return_value=image_info) - + @mock.patch.object(agent.LOG, 'warning', autospec=True) + @mock.patch.object(deploy_utils, 'build_instance_info_for_deploy', + autospec=True) + def test_build_instance_info_for_deploy_warn(self, build_mock, warn_mock): mgr_utils.mock_the_extension_manager(driver='fake_agent') with task_manager.acquire( self.context, self.node.uuid, shared=False) as task: - agent.build_instance_info_for_deploy(task) - - glance_mock.assert_called_once_with(version=2, - context=task.context) - glance_mock.return_value.show.assert_called_once_with( - self.node.instance_info['image_source']) - glance_mock.return_value.swift_temp_url.assert_called_once_with( - image_info) - - @mock.patch.object(deploy_utils, 'parse_instance_info', autospec=True) - @mock.patch.object(image_service, 'GlanceImageService', autospec=True) - def test_build_instance_info_for_deploy_glance_partition_image( - self, glance_mock, parse_instance_info_mock): - i_info = {} - i_info['image_source'] = '733d1c44-a2ea-414b-aca7-69decf20d810' - i_info['kernel'] = '13ce5a56-1de3-4916-b8b2-be778645d003' - i_info['ramdisk'] = 'a5a370a8-1b39-433f-be63-2c7d708e4b4e' - i_info['root_gb'] = 5 - i_info['swap_mb'] = 4 - i_info['ephemeral_gb'] = 0 - i_info['ephemeral_format'] = None - i_info['configdrive'] = 'configdrive' - driver_internal_info = self.node.driver_internal_info - driver_internal_info['is_whole_disk_image'] = False - self.node.driver_internal_info = driver_internal_info - self.node.instance_info = i_info - self.node.save() - - image_info = {'checksum': 'aa', 'disk_format': 'qcow2', - 'container_format': 'bare', - 'properties': {'kernel_id': 'kernel', - 'ramdisk_id': 'ramdisk'}} - glance_mock.return_value.show = mock.MagicMock(spec_set=[], - return_value=image_info) - glance_obj_mock = glance_mock.return_value - glance_obj_mock.swift_temp_url.return_value = 'temp-url' - parse_instance_info_mock.return_value = {'swap_mb': 4} - image_source = '733d1c44-a2ea-414b-aca7-69decf20d810' - expected_i_info = {'root_gb': 5, - 'swap_mb': 4, - 'ephemeral_gb': 0, - 'ephemeral_format': None, - 'configdrive': 'configdrive', - 'image_source': image_source, - 'image_url': 'temp-url', - 'kernel': 'kernel', - 'ramdisk': 'ramdisk', - 'image_type': 'partition', - 'image_checksum': 'aa', - 'image_container_format': 'bare', - 'image_disk_format': 'qcow2'} - mgr_utils.mock_the_extension_manager(driver='fake_agent') - with task_manager.acquire( - self.context, self.node.uuid, shared=False) as task: - - info = agent.build_instance_info_for_deploy(task) - - glance_mock.assert_called_once_with(version=2, - context=task.context) - glance_mock.return_value.show.assert_called_once_with( - self.node.instance_info['image_source']) - glance_mock.return_value.swift_temp_url.assert_called_once_with( - image_info) - image_type = task.node.instance_info['image_type'] - self.assertEqual('partition', image_type) - self.assertEqual('kernel', info['kernel']) - self.assertEqual('ramdisk', info['ramdisk']) - self.assertEqual(expected_i_info, info) - parse_instance_info_mock.assert_called_once_with(task.node) - - @mock.patch.object(image_service.HttpImageService, 'validate_href', - autospec=True) - def test_build_instance_info_for_deploy_nonglance_image( - self, validate_href_mock): - i_info = self.node.instance_info - driver_internal_info = self.node.driver_internal_info - i_info['image_source'] = 'http://image-ref' - i_info['image_checksum'] = 'aa' - i_info['root_gb'] = 10 - i_info['image_checksum'] = 'aa' - driver_internal_info['is_whole_disk_image'] = True - self.node.instance_info = i_info - self.node.driver_internal_info = driver_internal_info - self.node.save() - - mgr_utils.mock_the_extension_manager(driver='fake_agent') - with task_manager.acquire( - self.context, self.node.uuid, shared=False) as task: - - info = agent.build_instance_info_for_deploy(task) - - self.assertEqual(self.node.instance_info['image_source'], - info['image_url']) - validate_href_mock.assert_called_once_with( - mock.ANY, 'http://image-ref') - - @mock.patch.object(deploy_utils, 'parse_instance_info', autospec=True) - @mock.patch.object(image_service.HttpImageService, 'validate_href', - autospec=True) - def test_build_instance_info_for_deploy_nonglance_partition_image( - self, validate_href_mock, parse_instance_info_mock): - i_info = {} - driver_internal_info = self.node.driver_internal_info - i_info['image_source'] = 'http://image-ref' - i_info['kernel'] = 'http://kernel-ref' - i_info['ramdisk'] = 'http://ramdisk-ref' - i_info['image_checksum'] = 'aa' - i_info['root_gb'] = 10 - i_info['configdrive'] = 'configdrive' - driver_internal_info['is_whole_disk_image'] = False - self.node.instance_info = i_info - self.node.driver_internal_info = driver_internal_info - self.node.save() - - mgr_utils.mock_the_extension_manager(driver='fake_agent') - validate_href_mock.side_effect = ['http://image-ref', - 'http://kernel-ref', - 'http://ramdisk-ref'] - parse_instance_info_mock.return_value = {'swap_mb': 5} - expected_i_info = {'image_source': 'http://image-ref', - 'image_url': 'http://image-ref', - 'image_type': 'partition', - 'kernel': 'http://kernel-ref', - 'ramdisk': 'http://ramdisk-ref', - 'image_checksum': 'aa', - 'root_gb': 10, - 'swap_mb': 5, - 'configdrive': 'configdrive'} - with task_manager.acquire( - self.context, self.node.uuid, shared=False) as task: - - info = agent.build_instance_info_for_deploy(task) - - self.assertEqual(self.node.instance_info['image_source'], - info['image_url']) - validate_href_mock.assert_called_once_with( - mock.ANY, 'http://image-ref') - self.assertEqual('partition', info['image_type']) - self.assertEqual(expected_i_info, info) - parse_instance_info_mock.assert_called_once_with(task.node) - - @mock.patch.object(image_service.HttpImageService, 'validate_href', - autospec=True) - def test_build_instance_info_for_deploy_nonsupported_image( - self, validate_href_mock): - validate_href_mock.side_effect = exception.ImageRefValidationFailed( - image_href='file://img.qcow2', reason='fail') - i_info = self.node.instance_info - i_info['image_source'] = 'file://img.qcow2' - i_info['image_checksum'] = 'aa' - self.node.instance_info = i_info - self.node.save() - - mgr_utils.mock_the_extension_manager(driver='fake_agent') - with task_manager.acquire( - self.context, self.node.uuid, shared=False) as task: - - self.assertRaises(exception.ImageRefValidationFailed, - agent.build_instance_info_for_deploy, task) + build_mock.assert_called_once_with(task) + self.assertTrue(warn_mock.called) @mock.patch.object(images, 'image_show', autospec=True) def test_check_image_size(self, show_mock): @@ -452,7 +283,7 @@ class TestAgentDeploy(db_base.DbTestCase): @mock.patch.object(pxe.PXEBoot, 'prepare_ramdisk') @mock.patch.object(deploy_utils, 'build_agent_options') - @mock.patch.object(agent, 'build_instance_info_for_deploy') + @mock.patch.object(deploy_utils, 'build_instance_info_for_deploy') @mock.patch('ironic.drivers.modules.network.flat.FlatNetwork.' 'add_provisioning_network', autospec=True) def test_prepare(self, add_provisioning_net_mock, build_instance_info_mock, @@ -476,7 +307,7 @@ class TestAgentDeploy(db_base.DbTestCase): @mock.patch.object(pxe.PXEBoot, 'prepare_ramdisk') @mock.patch.object(deploy_utils, 'build_agent_options') - @mock.patch.object(agent, 'build_instance_info_for_deploy') + @mock.patch.object(deploy_utils, 'build_instance_info_for_deploy') def test_prepare_manage_agent_boot_false( self, build_instance_info_mock, build_options_mock, pxe_prepare_ramdisk_mock): @@ -499,7 +330,7 @@ class TestAgentDeploy(db_base.DbTestCase): 'add_provisioning_network', autospec=True) @mock.patch.object(pxe.PXEBoot, 'prepare_ramdisk') @mock.patch.object(deploy_utils, 'build_agent_options') - @mock.patch.object(agent, 'build_instance_info_for_deploy') + @mock.patch.object(deploy_utils, 'build_instance_info_for_deploy') def test_prepare_active( self, build_instance_info_mock, build_options_mock, pxe_prepare_ramdisk_mock, add_provisioning_net_mock): @@ -518,7 +349,7 @@ class TestAgentDeploy(db_base.DbTestCase): 'add_provisioning_network', autospec=True) @mock.patch.object(pxe.PXEBoot, 'prepare_ramdisk') @mock.patch.object(deploy_utils, 'build_agent_options') - @mock.patch.object(agent, 'build_instance_info_for_deploy') + @mock.patch.object(deploy_utils, 'build_instance_info_for_deploy') def test_prepare_adopting( self, build_instance_info_mock, build_options_mock, pxe_prepare_ramdisk_mock, add_provisioning_net_mock): diff --git a/ironic/tests/unit/drivers/modules/test_deploy_utils.py b/ironic/tests/unit/drivers/modules/test_deploy_utils.py index 683d60b465..2f174b19f2 100644 --- a/ironic/tests/unit/drivers/modules/test_deploy_utils.py +++ b/ironic/tests/unit/drivers/modules/test_deploy_utils.py @@ -2520,3 +2520,192 @@ class InstanceInfoTestCase(db_base.DbTestCase): node = obj_utils.create_test_node(self.context, instance_info=info) self.assertRaises(exception.InvalidParameterValue, utils.parse_instance_info, node) + + +class TestBuildInstanceInfoForDeploy(db_base.DbTestCase): + def setUp(self): + super(TestBuildInstanceInfoForDeploy, self).setUp() + self.node = obj_utils.create_test_node(self.context, + driver='fake_agent') + + @mock.patch.object(image_service, 'GlanceImageService', autospec=True) + def test_build_instance_info_for_deploy_glance_image(self, glance_mock): + i_info = self.node.instance_info + i_info['image_source'] = '733d1c44-a2ea-414b-aca7-69decf20d810' + driver_internal_info = self.node.driver_internal_info + driver_internal_info['is_whole_disk_image'] = True + self.node.driver_internal_info = driver_internal_info + self.node.instance_info = i_info + self.node.save() + + image_info = {'checksum': 'aa', 'disk_format': 'qcow2', + 'container_format': 'bare', 'properties': {}} + glance_mock.return_value.show = mock.MagicMock(spec_set=[], + return_value=image_info) + + mgr_utils.mock_the_extension_manager(driver='fake_agent') + with task_manager.acquire( + self.context, self.node.uuid, shared=False) as task: + + utils.build_instance_info_for_deploy(task) + + glance_mock.assert_called_once_with(version=2, + context=task.context) + glance_mock.return_value.show.assert_called_once_with( + self.node.instance_info['image_source']) + glance_mock.return_value.swift_temp_url.assert_called_once_with( + image_info) + + @mock.patch.object(utils, 'parse_instance_info', autospec=True) + @mock.patch.object(image_service, 'GlanceImageService', autospec=True) + def test_build_instance_info_for_deploy_glance_partition_image( + self, glance_mock, parse_instance_info_mock): + i_info = {} + i_info['image_source'] = '733d1c44-a2ea-414b-aca7-69decf20d810' + i_info['kernel'] = '13ce5a56-1de3-4916-b8b2-be778645d003' + i_info['ramdisk'] = 'a5a370a8-1b39-433f-be63-2c7d708e4b4e' + i_info['root_gb'] = 5 + i_info['swap_mb'] = 4 + i_info['ephemeral_gb'] = 0 + i_info['ephemeral_format'] = None + i_info['configdrive'] = 'configdrive' + driver_internal_info = self.node.driver_internal_info + driver_internal_info['is_whole_disk_image'] = False + self.node.driver_internal_info = driver_internal_info + self.node.instance_info = i_info + self.node.save() + + image_info = {'checksum': 'aa', 'disk_format': 'qcow2', + 'container_format': 'bare', + 'properties': {'kernel_id': 'kernel', + 'ramdisk_id': 'ramdisk'}} + glance_mock.return_value.show = mock.MagicMock(spec_set=[], + return_value=image_info) + glance_obj_mock = glance_mock.return_value + glance_obj_mock.swift_temp_url.return_value = 'temp-url' + parse_instance_info_mock.return_value = {'swap_mb': 4} + image_source = '733d1c44-a2ea-414b-aca7-69decf20d810' + expected_i_info = {'root_gb': 5, + 'swap_mb': 4, + 'ephemeral_gb': 0, + 'ephemeral_format': None, + 'configdrive': 'configdrive', + 'image_source': image_source, + 'image_url': 'temp-url', + 'kernel': 'kernel', + 'ramdisk': 'ramdisk', + 'image_type': 'partition', + 'image_tags': [], + 'image_properties': {'kernel_id': 'kernel', + 'ramdisk_id': 'ramdisk'}, + 'image_checksum': 'aa', + 'image_container_format': 'bare', + 'image_disk_format': 'qcow2'} + mgr_utils.mock_the_extension_manager(driver='fake_agent') + with task_manager.acquire( + self.context, self.node.uuid, shared=False) as task: + + info = utils.build_instance_info_for_deploy(task) + + glance_mock.assert_called_once_with(version=2, + context=task.context) + glance_mock.return_value.show.assert_called_once_with( + self.node.instance_info['image_source']) + glance_mock.return_value.swift_temp_url.assert_called_once_with( + image_info) + image_type = task.node.instance_info['image_type'] + self.assertEqual('partition', image_type) + self.assertEqual('kernel', info['kernel']) + self.assertEqual('ramdisk', info['ramdisk']) + self.assertEqual(expected_i_info, info) + parse_instance_info_mock.assert_called_once_with(task.node) + + @mock.patch.object(image_service.HttpImageService, 'validate_href', + autospec=True) + def test_build_instance_info_for_deploy_nonglance_image( + self, validate_href_mock): + i_info = self.node.instance_info + driver_internal_info = self.node.driver_internal_info + i_info['image_source'] = 'http://image-ref' + i_info['image_checksum'] = 'aa' + i_info['root_gb'] = 10 + i_info['image_checksum'] = 'aa' + driver_internal_info['is_whole_disk_image'] = True + self.node.instance_info = i_info + self.node.driver_internal_info = driver_internal_info + self.node.save() + + mgr_utils.mock_the_extension_manager(driver='fake_agent') + with task_manager.acquire( + self.context, self.node.uuid, shared=False) as task: + + info = utils.build_instance_info_for_deploy(task) + + self.assertEqual(self.node.instance_info['image_source'], + info['image_url']) + validate_href_mock.assert_called_once_with( + mock.ANY, 'http://image-ref') + + @mock.patch.object(utils, 'parse_instance_info', autospec=True) + @mock.patch.object(image_service.HttpImageService, 'validate_href', + autospec=True) + def test_build_instance_info_for_deploy_nonglance_partition_image( + self, validate_href_mock, parse_instance_info_mock): + i_info = {} + driver_internal_info = self.node.driver_internal_info + i_info['image_source'] = 'http://image-ref' + i_info['kernel'] = 'http://kernel-ref' + i_info['ramdisk'] = 'http://ramdisk-ref' + i_info['image_checksum'] = 'aa' + i_info['root_gb'] = 10 + i_info['configdrive'] = 'configdrive' + driver_internal_info['is_whole_disk_image'] = False + self.node.instance_info = i_info + self.node.driver_internal_info = driver_internal_info + self.node.save() + + mgr_utils.mock_the_extension_manager(driver='fake_agent') + validate_href_mock.side_effect = ['http://image-ref', + 'http://kernel-ref', + 'http://ramdisk-ref'] + parse_instance_info_mock.return_value = {'swap_mb': 5} + expected_i_info = {'image_source': 'http://image-ref', + 'image_url': 'http://image-ref', + 'image_type': 'partition', + 'kernel': 'http://kernel-ref', + 'ramdisk': 'http://ramdisk-ref', + 'image_checksum': 'aa', + 'root_gb': 10, + 'swap_mb': 5, + 'configdrive': 'configdrive'} + with task_manager.acquire( + self.context, self.node.uuid, shared=False) as task: + + info = utils.build_instance_info_for_deploy(task) + + self.assertEqual(self.node.instance_info['image_source'], + info['image_url']) + validate_href_mock.assert_called_once_with( + mock.ANY, 'http://image-ref') + self.assertEqual('partition', info['image_type']) + self.assertEqual(expected_i_info, info) + parse_instance_info_mock.assert_called_once_with(task.node) + + @mock.patch.object(image_service.HttpImageService, 'validate_href', + autospec=True) + def test_build_instance_info_for_deploy_nonsupported_image( + self, validate_href_mock): + validate_href_mock.side_effect = exception.ImageRefValidationFailed( + image_href='file://img.qcow2', reason='fail') + i_info = self.node.instance_info + i_info['image_source'] = 'file://img.qcow2' + i_info['image_checksum'] = 'aa' + self.node.instance_info = i_info + self.node.save() + + mgr_utils.mock_the_extension_manager(driver='fake_agent') + with task_manager.acquire( + self.context, self.node.uuid, shared=False) as task: + + self.assertRaises(exception.ImageRefValidationFailed, + utils.build_instance_info_for_deploy, task)