summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2013-04-04 15:33:27 +0000
committerGerrit Code Review <review@openstack.org>2013-04-04 15:33:27 +0000
commitf4a062f890e44798253a684378ab0a8bc15d1edf (patch)
tree5a606ffaae05c62667a21f922b8a254bce422014
parentf96c9ab31700bc37792de0b3bec97edd7d99aa29 (diff)
parente9c88b7d3657d83ab84c081fbd56183061ed09c7 (diff)
Merge "Fallback to conductor if types are not stashed."
-rw-r--r--nova/compute/resource_tracker.py41
-rw-r--r--nova/tests/compute/test_resource_tracker.py26
2 files changed, 53 insertions, 14 deletions
diff --git a/nova/compute/resource_tracker.py b/nova/compute/resource_tracker.py
index 69b5eb61f..44168b6b8 100644
--- a/nova/compute/resource_tracker.py
+++ b/nova/compute/resource_tracker.py
@@ -145,8 +145,8 @@ class ResourceTracker(object):
# Mark the resources in-use for the resize landing on this
# compute host:
- self._update_usage_from_migration(instance_ref, self.compute_node,
- migration_ref)
+ self._update_usage_from_migration(context, instance_ref,
+ self.compute_node, migration_ref)
elevated = context.elevated()
self._update(elevated, self.compute_node)
@@ -263,7 +263,7 @@ class ResourceTracker(object):
migrations = capi.migration_get_in_progress_by_host_and_node(context,
self.host, self.nodename)
- self._update_usage_from_migrations(resources, migrations)
+ self._update_usage_from_migrations(context, resources, migrations)
# Detect and account for orphaned instances that may exist on the
# hypervisor, but are not in the DB:
@@ -387,7 +387,8 @@ class ResourceTracker(object):
resources['running_vms'] = self.stats.num_instances
resources['vcpus_used'] = self.stats.num_vcpus_used
- def _update_usage_from_migration(self, instance, resources, migration):
+ def _update_usage_from_migration(self, context, instance, resources,
+ migration):
"""Update usage for a single migration. The record may
represent an incoming or outbound migration.
"""
@@ -408,19 +409,23 @@ class ResourceTracker(object):
# instance is *not* in:
if (instance['instance_type_id'] ==
migration['old_instance_type_id']):
- itype = instance_types.extract_instance_type(instance)
+ itype = self._get_instance_type(context, instance, 'new_',
+ migration['new_instance_type_id'])
else:
# instance record already has new flavor, hold space for a
# possible revert to the old instance type:
- itype = instance_types.extract_instance_type(instance, 'old_')
+ itype = self._get_instance_type(context, instance, 'old_',
+ migration['old_instance_type_id'])
elif incoming and not record:
# instance has not yet migrated here:
- itype = instance_types.extract_instance_type(instance, 'new_')
+ itype = self._get_instance_type(context, instance, 'new_',
+ migration['new_instance_type_id'])
elif outbound and not record:
# instance migrated, but record usage for a possible revert:
- itype = instance_types.extract_instance_type(instance, 'old_')
+ itype = self._get_instance_type(context, instance, 'old_',
+ migration['old_instance_type_id'])
if itype:
self.stats.update_stats_for_migration(itype)
@@ -428,7 +433,7 @@ class ResourceTracker(object):
resources['stats'] = self.stats
self.tracked_migrations[uuid] = (migration, itype)
- def _update_usage_from_migrations(self, resources, migrations):
+ def _update_usage_from_migrations(self, context, resources, migrations):
self.tracked_migrations.clear()
@@ -460,7 +465,7 @@ class ResourceTracker(object):
for migration in filtered.values():
instance = migration['instance']
try:
- self._update_usage_from_migration(instance, resources,
+ self._update_usage_from_migration(context, instance, resources,
migration)
except exception.InstanceTypeNotFound:
LOG.warn(_("InstanceType could not be found, skipping "
@@ -576,3 +581,19 @@ class ResourceTracker(object):
return True
return False
+
+ def _get_instance_type(self, context, instance, prefix,
+ instance_type_id=None):
+ """Get the instance type from sys metadata if it's stashed. If not,
+ fall back to fetching it via the conductor API.
+
+ See bug 1164110
+ """
+ if not instance_type_id:
+ instance_type_id = instance['instance_type_id']
+
+ try:
+ return instance_types.extract_instance_type(instance, prefix)
+ except KeyError:
+ return self.conductor_api.instance_type_get(context,
+ instance_type_id)
diff --git a/nova/tests/compute/test_resource_tracker.py b/nova/tests/compute/test_resource_tracker.py
index 860ea9fab..c03ccbe28 100644
--- a/nova/tests/compute/test_resource_tracker.py
+++ b/nova/tests/compute/test_resource_tracker.py
@@ -161,14 +161,18 @@ class BaseTestCase(test.TestCase):
'value': instance_type[key]})
return sys_meta
- def _fake_instance(self, *args, **kwargs):
+ def _fake_instance(self, stash=True, **kwargs):
# Default to an instance ready to resize to or from the same
# instance_type
itype = self._fake_instance_type_create()
- sys_meta = (self._fake_instance_system_metadata(itype) +
- self._fake_instance_system_metadata(itype, 'new_') +
- self._fake_instance_system_metadata(itype, 'old_'))
+ sys_meta = self._fake_instance_system_metadata(itype)
+
+ if stash:
+ # stash instance types in system metadata.
+ sys_meta = (sys_meta +
+ self._fake_instance_system_metadata(itype, 'new_') +
+ self._fake_instance_system_metadata(itype, 'old_'))
instance_uuid = str(uuid.uuid1())
instance = {
@@ -876,6 +880,20 @@ class ResizeClaimTestCase(BaseTrackerTestCase):
self.assertEqual('fakenode', instance['node'])
+class NoInstanceTypesInSysMetadata(ResizeClaimTestCase):
+ """Make sure we handle the case where the following are true:
+ 1) Compute node C gets upgraded to code that looks for instance types in
+ system metadata. AND
+ 2) C already has instances in the process of migrating that do not have
+ stashed instance types.
+
+ bug 1164110
+ """
+ def setUp(self):
+ super(NoInstanceTypesInSysMetadata, self).setUp()
+ self.instance = self._fake_instance(stash=False)
+
+
class OrphanTestCase(BaseTrackerTestCase):
def _driver(self):
class OrphanVirtDriver(FakeVirtDriver):