Merge "Move PXE instance level parameters to instance_info"
This commit is contained in:
commit
76b2244c5e
@ -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):
|
||||
|
@ -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:
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
|
@ -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',
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
||||
|
@ -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(
|
||||
|
Loading…
x
Reference in New Issue
Block a user