diff --git a/ironic/conductor/manager.py b/ironic/conductor/manager.py index a693582615..33a084f1ad 100644 --- a/ironic/conductor/manager.py +++ b/ironic/conductor/manager.py @@ -479,6 +479,8 @@ class ConductorManager(periodic_task.PeriodicTasks): else: node.provision_state = new_state finally: + # Clean the instance_info + node.instance_info = {} node.save(context) def _conductor_service_record_keepalive(self): diff --git a/ironic/drivers/modules/pxe.py b/ironic/drivers/modules/pxe.py index ba95244f48..cfd10b1e3c 100644 --- a/ironic/drivers/modules/pxe.py +++ b/ironic/drivers/modules/pxe.py @@ -84,61 +84,100 @@ CONF.register_opts(pxe_opts, group='pxe') CONF.import_opt('use_ipv6', 'ironic.netconf') -def _parse_driver_info(node): - """Gets the driver-specific Node deployment info. - - This method validates whether the 'driver_info' property of the - supplied node contains the required information for this driver to - deploy images to the node. - - :param node: a single Node to validate. - :returns: A dict with the driver_info values. - """ - - info = node.driver_info or {} - d_info = {} - d_info['image_source'] = info.get('pxe_image_source') - d_info['deploy_kernel'] = info.get('pxe_deploy_kernel') - d_info['deploy_ramdisk'] = info.get('pxe_deploy_ramdisk') - d_info['root_gb'] = info.get('pxe_root_gb') - +def _check_for_missing_params(info_dict, param_prefix=''): missing_info = [] - for label in d_info: - if not d_info[label]: - missing_info.append("pxe_%s" % label) + for label, value in info_dict.items(): + if not value: + missing_info.append(param_prefix + label) + if missing_info: raise exception.InvalidParameterValue(_( "Can not validate PXE bootloader. The following parameters " "were not passed to ironic: %s") % missing_info) - # Internal use only - d_info['deploy_key'] = info.get('pxe_deploy_key') - d_info['swap_mb'] = info.get('pxe_swap_mb', 0) - d_info['ephemeral_gb'] = info.get('pxe_ephemeral_gb', 0) - d_info['ephemeral_format'] = info.get('pxe_ephemeral_format') +def _parse_driver_info(node): + """Gets the driver specific Node deployment info. + + This method validates whether the 'driver_info' property of the + supplied node contains the required information for this driver to + deploy images to the node. + + :param node: a single Node. + :returns: A dict with the driver_info values. + """ + info = node.driver_info + d_info = {} + d_info['deploy_kernel'] = info.get('pxe_deploy_kernel') + d_info['deploy_ramdisk'] = info.get('pxe_deploy_ramdisk') + + _check_for_missing_params(d_info, 'pxe_') + + return d_info + + +def _parse_instance_info(node): + """Gets the instance specific Node deployment info. + + This method validates whether the 'instance_info' property of the + supplied node contains the required information for this driver to + deploy images to the node. + + :param node: a single Node. + :returns: A dict with the instance_info values. + """ + + info = node.instance_info + i_info = {} + i_info['image_source'] = info.get('image_source') + i_info['root_gb'] = info.get('root_gb') + + _check_for_missing_params(i_info) + + # Internal use only + i_info['deploy_key'] = info.get('deploy_key') + + i_info['swap_mb'] = info.get('swap_mb', 0) + i_info['ephemeral_gb'] = info.get('ephemeral_gb', 0) + i_info['ephemeral_format'] = info.get('ephemeral_format') err_msg_invalid = _("Can not validate PXE bootloader. Invalid parameter " - "pxe_%(param)s. Reason: %(reason)s") + "%(param)s. Reason: %(reason)s") for param in ('root_gb', 'swap_mb', 'ephemeral_gb'): try: - int(d_info[param]) + int(i_info[param]) except ValueError: - reason = _("'%s' is not an integer value.") % d_info[param] + reason = _("'%s' is not an integer value.") % i_info[param] raise exception.InvalidParameterValue(err_msg_invalid % {'param': param, 'reason': reason}) - if d_info['ephemeral_gb'] and not d_info['ephemeral_format']: - d_info['ephemeral_format'] = CONF.pxe.default_ephemeral_format + if i_info['ephemeral_gb'] and not i_info['ephemeral_format']: + i_info['ephemeral_format'] = CONF.pxe.default_ephemeral_format - preserve_ephemeral = info.get('pxe_preserve_ephemeral', False) + preserve_ephemeral = info.get('preserve_ephemeral', False) try: - d_info['preserve_ephemeral'] = strutils.bool_from_string( + i_info['preserve_ephemeral'] = strutils.bool_from_string( preserve_ephemeral, strict=True) except ValueError as e: raise exception.InvalidParameterValue(err_msg_invalid % {'param': 'preserve_ephemeral', 'reason': e}) - return d_info + return i_info + + +def _parse_deploy_info(node): + """Gets the instance and driver specific Node deployment info. + + This method validates whether the 'instance_info' and 'driver_info' + property of the supplied node contains the required information for + this driver to deploy images to the node. + + :param node: a single Node. + :returns: A dict with the instance_info and driver_info values. + """ + info = {} + info.update(_parse_instance_info(node)) + info.update(_parse_driver_info(node)) + return info def _build_pxe_config_options(node, pxe_info, ctx): @@ -150,7 +189,9 @@ def _build_pxe_config_options(node, pxe_info, ctx): The options should then be passed to tftp.create_pxe_config to create the actual config files. - :param pxe_options: A dict of values to set on the configuration file + :param node: a single Node. + :param pxe_info: a dict of values to set on the configuration file + :param ctx: security context :returns: A dictionary of pxe options to be used in the pxe bootfile template. """ @@ -160,13 +201,12 @@ def _build_pxe_config_options(node, pxe_info, ctx): keystone.get_service_url()).rstrip('/') deploy_key = utils.random_alnum(32) - driver_info = node['driver_info'] - driver_info['pxe_deploy_key'] = deploy_key - node['driver_info'] = driver_info + i_info = node.instance_info + i_info['deploy_key'] = deploy_key + node.instance_info = i_info node.save(ctx) pxe_options = { - 'deployment_id': node['uuid'], 'deployment_key': deploy_key, 'deployment_iscsi_iqn': "iqn-%s" % node.uuid, @@ -295,10 +335,10 @@ def _cache_instance_image(ctx, node): fetch from Glance directly, and write its own last-mile configuration. """ - d_info = _parse_driver_info(node) + i_info = _parse_instance_info(node) fileutils.ensure_tree(_get_image_dir_path(node.uuid)) image_path = _get_image_file_path(node.uuid) - uuid = d_info['image_source'] + uuid = i_info['image_source'] LOG.debug("Fetching image %(ami)s for node %(uuid)s" % {'ami': uuid, 'uuid': node.uuid}) @@ -317,7 +357,7 @@ def _get_tftp_image_info(node, ctx): driver_info and defaults are not set """ - d_info = _parse_driver_info(node) + d_info = _parse_deploy_info(node) image_info = {} for label in ('deploy_kernel', 'deploy_ramdisk'): @@ -326,20 +366,19 @@ def _get_tftp_image_info(node, ctx): os.path.join(CONF.tftp.tftp_root, node.uuid, label) ) - driver_info = node.driver_info + i_info = node.instance_info labels = ('kernel', 'ramdisk') - if not (driver_info.get('pxe_kernel') and driver_info.get('pxe_ramdisk')): + if not (i_info.get('kernel') and i_info.get('ramdisk')): glance_service = service.Service(version=1, context=ctx) iproperties = glance_service.show(d_info['image_source'])['properties'] for label in labels: - driver_info['pxe_' + label] = str(iproperties[label + - '_id']).split('/')[-1] - node.driver_info = driver_info + i_info[label] = str(iproperties[label + '_id']).split('/')[-1] + node.instance_info = i_info node.save(ctx) for label in labels: image_info[label] = ( - driver_info['pxe_' + label], + i_info[label], os.path.join(CONF.tftp.tftp_root, node.uuid, label) ) @@ -369,22 +408,12 @@ def _destroy_token_file(node): utils.unlink_without_raise(token_file_path) -def _remove_internal_attrs(task): - """Remove internal attributes from driver_info.""" - internal_attrs = ('pxe_deploy_key', 'pxe_kernel', 'pxe_ramdisk') - driver_info = task.node.driver_info - for attr in internal_attrs: - driver_info.pop(attr, None) - task.node.driver_info = driver_info - task.node.save(task.context) - - def _check_image_size(task): """Check if the requested image is larger than the root partition size.""" - driver_info = _parse_driver_info(task.node) + i_info = _parse_instance_info(task.node) image_path = _get_image_file_path(task.node.uuid) image_mb = deploy_utils.get_image_mb(image_path) - root_mb = 1024 * int(driver_info['root_gb']) + root_mb = 1024 * int(i_info['root_gb']) if image_mb > root_mb: msg = (_('Root partition is too small for requested image. ' 'Image size: %(image_mb)d MB, Root size: %(root_mb)d MB') @@ -392,7 +421,7 @@ def _check_image_size(task): raise exception.InstanceDeployFailure(msg) -def _validate_glance_image(ctx, driver_info): +def _validate_glance_image(ctx, deploy_info): """Validate the image in Glance. Check if the image exist in Glance and if it contains the @@ -400,7 +429,7 @@ def _validate_glance_image(ctx, driver_info): :raises: InvalidParameterValue. """ - image_id = driver_info['image_source'] + image_id = deploy_info['image_source'] try: glance_service = service.Service(version=1, context=ctx) image_props = glance_service.show(image_id)['properties'] @@ -430,7 +459,7 @@ class PXEDeploy(base.DeployInterface): """PXE Deploy Interface: just a stub until the real driver is ported.""" def validate(self, task): - """Validate the driver-specific Node deployment info. + """Validate the deployment information for the task's node. :param task: a TaskManager instance containing the node to act on. :raises: InvalidParameterValue. @@ -439,7 +468,8 @@ class PXEDeploy(base.DeployInterface): if not driver_utils.get_node_mac_addresses(task): raise exception.InvalidParameterValue(_("Node %s does not have " "any port associated with it.") % node.uuid) - d_info = _parse_driver_info(node) + + d_info = _parse_deploy_info(node) # Try to get the URL of the Ironic API try: @@ -491,8 +521,6 @@ class PXEDeploy(base.DeployInterface): :returns: deploy state DELETED. """ manager_utils.node_power_action(task, states.POWER_OFF) - _remove_internal_attrs(task) - return states.DELETED def prepare(self, task): @@ -522,7 +550,7 @@ class PXEDeploy(base.DeployInterface): """ node = task.node pxe_info = _get_tftp_image_info(node, task.context) - d_info = _parse_driver_info(node) + d_info = _parse_deploy_info(node) for label in pxe_info: path = pxe_info[label][1] utils.unlink_without_raise(path) @@ -541,7 +569,7 @@ class VendorPassthru(base.VendorInterface): """Interface to mix IPMI and PXE vendor-specific interfaces.""" def _get_deploy_info(self, node, **kwargs): - d_info = _parse_driver_info(node) + d_info = _parse_deploy_info(node) deploy_key = kwargs.get('key') if d_info['deploy_key'] != deploy_key: diff --git a/ironic/nova/tests/virt/ironic/test_patcher.py b/ironic/nova/tests/virt/ironic/test_patcher.py index aa30d61086..81c2197536 100644 --- a/ironic/nova/tests/virt/ironic/test_patcher.py +++ b/ironic/nova/tests/virt/ironic/test_patcher.py @@ -45,13 +45,13 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase): {'path': '/driver_info/pxe_deploy_ramdisk', 'value': extra_specs['baremetal:deploy_ramdisk_id'], 'op': 'add'}, - {'path': '/driver_info/pxe_image_source', + {'path': '/instance_info/image_source', 'value': self.image_meta['id'], 'op': 'add'}, - {'path': '/driver_info/pxe_root_gb', + {'path': '/instance_info/root_gb', 'value': str(instance['root_gb']), 'op': 'add'}, - {'path': '/driver_info/pxe_swap_mb', + {'path': '/instance_info/swap_mb', 'value': str(self.flavor['swap']), 'op': 'add'}] patch = patcher.create(node).get_deploy_patch( @@ -65,9 +65,9 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase): CONF.set_override('default_ephemeral_format', 'testfmt') patch = patcher.create(node).get_deploy_patch( instance, self.image_meta, self.flavor) - expected1 = {'path': '/driver_info/pxe_ephemeral_gb', + expected1 = {'path': '/instance_info/ephemeral_gb', 'value': '10', 'op': 'add'} - expected2 = {'path': '/driver_info/pxe_ephemeral_format', + expected2 = {'path': '/instance_info/ephemeral_format', 'value': 'testfmt', 'op': 'add'} self.assertIn(expected1, patch) self.assertIn(expected2, patch) @@ -81,29 +81,14 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase): instance, self.image_meta, self.flavor) def test_pxe_get_cleanup_patch(self): - driver_info = {'pxe_image_source': 'fake-image-id', - 'pxe_deploy_kernel': 'fake-kernel-id', - 'pxe_deploy_ramdisk': 'fake-ramdisk-id', - 'pxe_root_gb': '1024', - 'pxe_swap_mb': '512', - 'pxe_preserve_ephemeral': True, - 'pxe_ephemeral_format': 'fake-format'} + driver_info = {'pxe_deploy_kernel': 'fake-kernel-id', + 'pxe_deploy_ramdisk': 'fake-ramdisk-id'} node = ironic_utils.get_test_node(driver='pxe_fake', driver_info=driver_info) instance = fake_instance.fake_instance_obj(self.ctx, node=node.uuid) patch = patcher.create(node).get_cleanup_patch(instance, None) - expected = [{'path': '/driver_info/pxe_image_source', - 'op': 'remove'}, - {'path': '/driver_info/pxe_deploy_kernel', + expected = [{'path': '/driver_info/pxe_deploy_kernel', 'op': 'remove'}, {'path': '/driver_info/pxe_deploy_ramdisk', - 'op': 'remove'}, - {'path': '/driver_info/pxe_root_gb', - 'op': 'remove'}, - {'path': '/driver_info/pxe_swap_mb', - 'op': 'remove'}, - {'path': '/driver_info/pxe_preserve_ephemeral', - 'op': 'remove'}, - {'path': '/driver_info/pxe_ephemeral_format', 'op': 'remove'}] self.assertEqual(sorted(expected), sorted(patch)) diff --git a/ironic/nova/virt/ironic/driver.py b/ironic/nova/virt/ironic/driver.py index 90d9d37229..d29dc9eaa4 100644 --- a/ironic/nova/virt/ironic/driver.py +++ b/ironic/nova/virt/ironic/driver.py @@ -662,9 +662,9 @@ class IronicDriver(virt_driver.ComputeDriver): icli = client_wrapper.IronicClientWrapper() - # Update driver_info for the ephemeral preservation value. + # Update instance_info for the ephemeral preservation value. patch = [] - patch.append({'path': '/driver_info/pxe_preserve_ephemeral', + patch.append({'path': '/instance_info/preserve_ephemeral', 'op': 'add', 'value': str(preserve_ephemeral)}) try: icli.call('node.update', node_uuid, patch) diff --git a/ironic/nova/virt/ironic/patcher.py b/ironic/nova/virt/ironic/patcher.py index 4fbf20f676..14c144ee07 100644 --- a/ironic/nova/virt/ironic/patcher.py +++ b/ironic/nova/virt/ironic/patcher.py @@ -89,19 +89,19 @@ class PXEDriverFields(GenericDriverFields): 'value': deploy_kernel}) patch.append({'path': '/driver_info/pxe_deploy_ramdisk', 'op': 'add', 'value': deploy_ramdisk}) - patch.append({'path': '/driver_info/pxe_image_source', 'op': 'add', + patch.append({'path': '/instance_info/image_source', 'op': 'add', 'value': image_meta['id']}) - patch.append({'path': '/driver_info/pxe_root_gb', 'op': 'add', + patch.append({'path': '/instance_info/root_gb', 'op': 'add', 'value': str(instance['root_gb'])}) - patch.append({'path': '/driver_info/pxe_swap_mb', 'op': 'add', + patch.append({'path': '/instance_info/swap_mb', 'op': 'add', 'value': str(flavor['swap'])}) if instance.get('ephemeral_gb'): - patch.append({'path': '/driver_info/pxe_ephemeral_gb', + patch.append({'path': '/instance_info/ephemeral_gb', 'op': 'add', 'value': str(instance['ephemeral_gb'])}) if CONF.default_ephemeral_format: - patch.append({'path': '/driver_info/pxe_ephemeral_format', + patch.append({'path': '/instance_info/ephemeral_format', 'op': 'add', 'value': CONF.default_ephemeral_format}) return patch @@ -110,7 +110,9 @@ class PXEDriverFields(GenericDriverFields): """Build a patch to clean up the fields. Build a json-patch to remove the fields used to deploy a node - using the PXE driver. + using the PXE driver. Note that the fields added to the Node's + instance_info don't need to be removed because they are purged + during the Node's tear down. :param instance: the instance object. :param network_info: the instance network information. @@ -119,10 +121,7 @@ class PXEDriverFields(GenericDriverFields): """ patch = [] driver_info = self.node.driver_info - fields = ['pxe_image_source', 'pxe_root_gb', 'pxe_swap_mb', - 'pxe_deploy_kernel', 'pxe_deploy_ramdisk', - 'pxe_ephemeral_gb', 'pxe_ephemeral_format', - 'pxe_preserve_ephemeral'] + fields = ['pxe_deploy_kernel', 'pxe_deploy_ramdisk'] for field in fields: if field in driver_info: patch.append({'op': 'remove', diff --git a/ironic/tests/conductor/test_manager.py b/ironic/tests/conductor/test_manager.py index 9bce9badbe..42d00c4be0 100644 --- a/ironic/tests/conductor/test_manager.py +++ b/ironic/tests/conductor/test_manager.py @@ -676,7 +676,8 @@ class ManagerTestCase(tests_db_base.DbTestCase): def test_do_node_tear_down_driver_raises_error(self, mock_tear_down): # test when driver.deploy.tear_down raises exception node = obj_utils.create_test_node(self.context, driver='fake', - provision_state=states.ACTIVE) + provision_state=states.ACTIVE, + instance_info={'foo': 'bar'}) task = task_manager.TaskManager(self.context, node.uuid) self._start_service() @@ -688,13 +689,16 @@ class ManagerTestCase(tests_db_base.DbTestCase): self.assertEqual(states.ERROR, node.provision_state) self.assertEqual(states.NOSTATE, node.target_provision_state) self.assertIsNotNone(node.last_error) + # Assert instance_info was erased + self.assertEqual({}, node.instance_info) mock_tear_down.assert_called_once_with(mock.ANY) @mock.patch('ironic.drivers.modules.fake.FakeDeploy.tear_down') def test_do_node_tear_down_ok(self, mock_tear_down): # test when driver.deploy.tear_down returns DELETED node = obj_utils.create_test_node(self.context, driver='fake', - provision_state=states.ACTIVE) + provision_state=states.ACTIVE, + instance_info={'foo': 'bar'}) task = task_manager.TaskManager(self.context, node.uuid) self._start_service() @@ -704,13 +708,15 @@ class ManagerTestCase(tests_db_base.DbTestCase): self.assertEqual(states.NOSTATE, node.provision_state) self.assertEqual(states.NOSTATE, node.target_provision_state) self.assertIsNone(node.last_error) + self.assertEqual({}, node.instance_info) mock_tear_down.assert_called_once_with(mock.ANY) @mock.patch('ironic.drivers.modules.fake.FakeDeploy.tear_down') def test_do_node_tear_down_partial_ok(self, mock_tear_down): # test when driver.deploy.tear_down doesn't return DELETED node = obj_utils.create_test_node(self.context, driver='fake', - provision_state=states.ACTIVE) + provision_state=states.ACTIVE, + instance_info={'foo': 'bar'}) self._start_service() task = task_manager.TaskManager(self.context, node.uuid) @@ -719,12 +725,15 @@ class ManagerTestCase(tests_db_base.DbTestCase): node.refresh() self.assertEqual(states.DELETING, node.provision_state) self.assertIsNone(node.last_error) + self.assertEqual({}, node.instance_info) mock_tear_down.assert_called_once_with(mock.ANY) @mock.patch('ironic.conductor.manager.ConductorManager._spawn_worker') def test_do_node_tear_down_worker_pool_full(self, mock_spawn): + fake_instance_info = {'foo': 'bar'} node = obj_utils.create_test_node(self.context, driver='fake', - provision_state=states.ACTIVE) + provision_state=states.ACTIVE, + instance_info=fake_instance_info) self._start_service() mock_spawn.side_effect = exception.NoFreeConductorWorker() @@ -738,6 +747,8 @@ class ManagerTestCase(tests_db_base.DbTestCase): node.refresh() # This is a sync operation last_error should be None. self.assertIsNone(node.last_error) + # Assert instance_info was not touched + self.assertEqual(fake_instance_info, node.instance_info) # Verify reservation has been cleared. self.assertIsNone(node.reservation) diff --git a/ironic/tests/db/utils.py b/ironic/tests/db/utils.py index 68e8764cdb..9b1a6d32c8 100644 --- a/ironic/tests/db/utils.py +++ b/ironic/tests/db/utils.py @@ -47,12 +47,17 @@ def get_test_ssh_info(auth_type='password'): return result -def get_test_pxe_info(): +def get_test_pxe_driver_info(): return { - "pxe_image_source": "glance://image_uuid", "pxe_deploy_kernel": "glance://deploy_kernel_uuid", "pxe_deploy_ramdisk": "glance://deploy_ramdisk_uuid", - "pxe_root_gb": 100, + } + + +def get_test_pxe_instance_info(): + return { + "image_source": "glance://image_uuid", + "root_gb": 100, } diff --git a/ironic/tests/drivers/test_pxe.py b/ironic/tests/drivers/test_pxe.py index 44cfe24c58..ca73aa4d27 100644 --- a/ironic/tests/drivers/test_pxe.py +++ b/ironic/tests/drivers/test_pxe.py @@ -49,7 +49,8 @@ from ironic.tests.objects import utils as obj_utils CONF = cfg.CONF -INFO_DICT = db_utils.get_test_pxe_info() +INST_INFO_DICT = db_utils.get_test_pxe_instance_info() +DRV_INFO_DICT = db_utils.get_test_pxe_driver_info() class PXEValidateParametersTestCase(base.TestCase): @@ -59,30 +60,22 @@ class PXEValidateParametersTestCase(base.TestCase): self.context = context.get_admin_context() self.dbapi = dbapi.get_instance() - def test__parse_driver_info_good(self): + def test__parse_deploy_info(self): # make sure we get back the expected things node = obj_utils.create_test_node(self.context, driver='fake_pxe', - driver_info=INFO_DICT) - info = pxe._parse_driver_info(node) - self.assertIsNotNone(info.get('image_source')) - self.assertIsNotNone(info.get('deploy_kernel')) + instance_info=INST_INFO_DICT, + driver_info=DRV_INFO_DICT) + info = pxe._parse_deploy_info(node) self.assertIsNotNone(info.get('deploy_ramdisk')) + self.assertIsNotNone(info.get('deploy_kernel')) + self.assertIsNotNone(info.get('image_source')) self.assertIsNotNone(info.get('root_gb')) self.assertEqual(0, info.get('ephemeral_gb')) - def test__parse_driver_info_missing_instance_source(self): - # make sure error is raised when info is missing - info = dict(INFO_DICT) - del info['pxe_image_source'] - node = obj_utils.create_test_node(self.context, driver_info=info) - self.assertRaises(exception.InvalidParameterValue, - pxe._parse_driver_info, - node) - def test__parse_driver_info_missing_deploy_kernel(self): # make sure error is raised when info is missing - info = dict(INFO_DICT) + info = dict(DRV_INFO_DICT) del info['pxe_deploy_kernel'] node = obj_utils.create_test_node(self.context, driver_info=info) self.assertRaises(exception.InvalidParameterValue, @@ -91,89 +84,117 @@ class PXEValidateParametersTestCase(base.TestCase): def test__parse_driver_info_missing_deploy_ramdisk(self): # make sure error is raised when info is missing - info = dict(INFO_DICT) + info = dict(DRV_INFO_DICT) del info['pxe_deploy_ramdisk'] node = obj_utils.create_test_node(self.context, driver_info=info) self.assertRaises(exception.InvalidParameterValue, pxe._parse_driver_info, node) - def test__parse_driver_info_missing_root_gb(self): + def test__parse_driver_info_good(self): + # make sure we get back the expected things + node = obj_utils.create_test_node(self.context, + driver='fake_pxe', + driver_info=DRV_INFO_DICT) + info = pxe._parse_driver_info(node) + self.assertIsNotNone(info.get('deploy_ramdisk')) + self.assertIsNotNone(info.get('deploy_kernel')) + + def test__parse_instance_info_good(self): + # make sure we get back the expected things + node = obj_utils.create_test_node(self.context, + driver='fake_pxe', + instance_info=INST_INFO_DICT) + info = pxe._parse_instance_info(node) + self.assertIsNotNone(info.get('image_source')) + self.assertIsNotNone(info.get('root_gb')) + self.assertEqual(0, info.get('ephemeral_gb')) + + def test__parse_instance_info_missing_instance_source(self): # make sure error is raised when info is missing - info = dict(INFO_DICT) - del info['pxe_root_gb'] - node = obj_utils.create_test_node(self.context, driver_info=info) + info = dict(INST_INFO_DICT) + del info['image_source'] + node = obj_utils.create_test_node(self.context, instance_info=info) self.assertRaises(exception.InvalidParameterValue, - pxe._parse_driver_info, + pxe._parse_instance_info, node) - def test__parse_driver_info_invalid_root_gb(self): - info = dict(INFO_DICT) - info['pxe_root_gb'] = 'foobar' - node = obj_utils.create_test_node(self.context, driver_info=info) + def test__parse_instance_info_missing_root_gb(self): + # make sure error is raised when info is missing + info = dict(INST_INFO_DICT) + del info['root_gb'] + node = obj_utils.create_test_node(self.context, instance_info=info) self.assertRaises(exception.InvalidParameterValue, - pxe._parse_driver_info, + pxe._parse_instance_info, node) - def test__parse_driver_info_valid_ephemeral_gb(self): + def test__parse_instance_info_invalid_root_gb(self): + info = dict(INST_INFO_DICT) + info['root_gb'] = 'foobar' + node = obj_utils.create_test_node(self.context, instance_info=info) + self.assertRaises(exception.InvalidParameterValue, + pxe._parse_instance_info, + node) + + def test__parse_instance_info_valid_ephemeral_gb(self): ephemeral_gb = 10 ephemeral_fmt = 'test-fmt' - info = dict(INFO_DICT) - info['pxe_ephemeral_gb'] = ephemeral_gb - info['pxe_ephemeral_format'] = ephemeral_fmt - node = obj_utils.create_test_node(self.context, driver_info=info) - data = pxe._parse_driver_info(node) + info = dict(INST_INFO_DICT) + info['ephemeral_gb'] = ephemeral_gb + info['ephemeral_format'] = ephemeral_fmt + node = obj_utils.create_test_node(self.context, instance_info=info) + data = pxe._parse_instance_info(node) self.assertEqual(ephemeral_gb, data.get('ephemeral_gb')) self.assertEqual(ephemeral_fmt, data.get('ephemeral_format')) - def test__parse_driver_info_invalid_ephemeral_gb(self): - info = dict(INFO_DICT) - info['pxe_ephemeral_gb'] = 'foobar' - info['pxe_ephemeral_format'] = 'exttest' - node = obj_utils.create_test_node(self.context, driver_info=info) + def test__parse_instance_info_invalid_ephemeral_gb(self): + info = dict(INST_INFO_DICT) + info['ephemeral_gb'] = 'foobar' + info['ephemeral_format'] = 'exttest' + node = obj_utils.create_test_node(self.context, instance_info=info) self.assertRaises(exception.InvalidParameterValue, - pxe._parse_driver_info, + pxe._parse_instance_info, node) - def test__parse_driver_info_valid_ephemeral_missing_format(self): + def test__parse_instance_info_valid_ephemeral_missing_format(self): ephemeral_gb = 10 ephemeral_fmt = 'test-fmt' - info = dict(INFO_DICT) - info['pxe_ephemeral_gb'] = ephemeral_gb - info['pxe_ephemeral_format'] = None + info = dict(INST_INFO_DICT) + info['ephemeral_gb'] = ephemeral_gb + info['ephemeral_format'] = None self.config(default_ephemeral_format=ephemeral_fmt, group='pxe') - node = obj_utils.create_test_node(self.context, driver_info=info) - driver_info = pxe._parse_driver_info(node) - self.assertEqual(ephemeral_fmt, driver_info['ephemeral_format']) + node = obj_utils.create_test_node(self.context, instance_info=info) + instance_info = pxe._parse_instance_info(node) + self.assertEqual(ephemeral_fmt, instance_info['ephemeral_format']) - def test__parse_driver_info_valid_preserve_ephemeral_true(self): - info = dict(INFO_DICT) + def test__parse_instance_info_valid_preserve_ephemeral_true(self): + info = dict(INST_INFO_DICT) for _id, opt in enumerate(['true', 'TRUE', 'True', 't', 'on', 'yes', 'y', '1']): - info['pxe_preserve_ephemeral'] = opt + info['preserve_ephemeral'] = opt node = obj_utils.create_test_node(self.context, id=_id, uuid=utils.generate_uuid(), - driver_info=info) - data = pxe._parse_driver_info(node) + instance_info=info) + data = pxe._parse_instance_info(node) self.assertTrue(data.get('preserve_ephemeral')) - def test__parse_driver_info_valid_preserve_ephemeral_false(self): - info = dict(INFO_DICT) + def test__parse_instance_info_valid_preserve_ephemeral_false(self): + info = dict(INST_INFO_DICT) for _id, opt in enumerate(['false', 'FALSE', 'False', 'f', 'off', 'no', 'n', '0']): - info['pxe_preserve_ephemeral'] = opt + info['preserve_ephemeral'] = opt node = obj_utils.create_test_node(self.context, id=_id, uuid=utils.generate_uuid(), - driver_info=info) - data = pxe._parse_driver_info(node) + instance_info=info) + data = pxe._parse_instance_info(node) self.assertFalse(data.get('preserve_ephemeral')) - def test__parse_driver_info_invalid_preserve_ephemeral(self): - info = dict(INFO_DICT) - info['pxe_preserve_ephemeral'] = 'foobar' - node = obj_utils.create_test_node(self.context, driver_info=info) + def test__parse_instance_info_invalid_preserve_ephemeral(self): + info = dict(INST_INFO_DICT) + info['preserve_ephemeral'] = 'foobar' + node = obj_utils.create_test_node(self.context, instance_info=info) self.assertRaises(exception.InvalidParameterValue, - pxe._parse_driver_info, + pxe._parse_instance_info, node) @@ -183,7 +204,8 @@ class PXEPrivateMethodsTestCase(db_base.DbTestCase): super(PXEPrivateMethodsTestCase, self).setUp() n = { 'driver': 'fake_pxe', - 'driver_info': INFO_DICT + 'instance_info': INST_INFO_DICT, + 'driver_info': DRV_INFO_DICT, } mgr_utils.mock_the_extension_manager(driver="fake_pxe") self.dbapi = dbapi.get_instance() @@ -231,9 +253,9 @@ class PXEPrivateMethodsTestCase(db_base.DbTestCase): self.assertEqual(expected_info, image_info) self.assertFalse(show_mock.called) self.assertEqual('instance_kernel_uuid', - self.node.driver_info.get('pxe_kernel')) + self.node.instance_info.get('kernel')) self.assertEqual('instance_ramdisk_uuid', - self.node.driver_info.get('pxe_ramdisk')) + self.node.instance_info.get('ramdisk')) @mock.patch.object(utils, 'random_alnum') @mock.patch.object(tftp, 'build_pxe_config') @@ -289,7 +311,7 @@ class PXEPrivateMethodsTestCase(db_base.DbTestCase): # test that deploy_key saved db_node = self.dbapi.get_node_by_uuid(self.node.uuid) - db_key = db_node['driver_info'].get('pxe_deploy_key') + db_key = db_node.instance_info.get('deploy_key') self.assertEqual(fake_key, db_key) def test__get_image_dir_path(self): @@ -475,11 +497,12 @@ class PXEDriverTestCase(db_base.DbTestCase): self.temp_dir = tempfile.mkdtemp() self.config(images_path=self.temp_dir, group='pxe') mgr_utils.mock_the_extension_manager(driver="fake_pxe") - driver_info = INFO_DICT - driver_info['pxe_deploy_key'] = 'fake-56789' + instance_info = INST_INFO_DICT + instance_info['deploy_key'] = 'fake-56789' self.node = obj_utils.create_test_node(self.context, driver='fake_pxe', - driver_info=driver_info) + instance_info=instance_info, + driver_info=DRV_INFO_DICT) self.dbapi = dbapi.get_instance() self.port = self.dbapi.create_port(db_utils.get_test_port( node_id=self.node.id)) @@ -499,12 +522,12 @@ class PXEDriverTestCase(db_base.DbTestCase): task.driver.deploy.validate(task) def test_validate_fail(self): - info = dict(INFO_DICT) - del info['pxe_image_source'] - self.node['driver_info'] = json.dumps(info) + info = dict(INST_INFO_DICT) + del info['image_source'] + self.node.instance_info = json.dumps(info) with task_manager.acquire(self.context, self.node.uuid, shared=True) as task: - task.node['driver_info'] = json.dumps(info) + task.node['instance_info'] = json.dumps(info) self.assertRaises(exception.InvalidParameterValue, task.driver.deploy.validate, task) @@ -512,7 +535,8 @@ class PXEDriverTestCase(db_base.DbTestCase): new_node = obj_utils.create_test_node( self.context, id=321, uuid='aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee', - driver='fake_pxe', driver_info=INFO_DICT) + driver='fake_pxe', instance_info=INST_INFO_DICT, + driver_info=DRV_INFO_DICT) with task_manager.acquire(self.context, new_node.uuid, shared=True) as task: self.assertRaises(exception.InvalidParameterValue, @@ -692,24 +716,6 @@ class PXEDriverTestCase(db_base.DbTestCase): self.assertEqual(states.DELETED, state) node_power_mock.assert_called_once_with(task, states.POWER_OFF) - @mock.patch.object(manager_utils, 'node_power_action') - def test_tear_down_removes_internal_attrs(self, mock_npa): - self.assertIn('pxe_deploy_key', self.node.driver_info) - # add internal image info - info = self.node.driver_info - info['pxe_kernel'] = 'fake-123' - info['pxe_ramdisk'] = 'fake-345' - self.node.driver_info = info - self.node.save() - with task_manager.acquire(self.context, self.node.uuid) as task: - task.driver.deploy.tear_down(task) - mock_npa.assert_called_once_with(task, states.POWER_OFF) - - self.node.refresh() - self.assertNotIn('pxe_deploy_key', self.node.driver_info) - self.assertNotIn('pxe_kernel', self.node.driver_info) - self.assertNotIn('pxe_ramdisk', self.node.driver_info) - @mock.patch.object(neutron, 'update_neutron') def test_take_over(self, update_neutron_mock): with task_manager.acquire(