diff options
| author | Jenkins <jenkins@review.openstack.org> | 2013-04-04 15:33:27 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2013-04-04 15:33:27 +0000 |
| commit | f4a062f890e44798253a684378ab0a8bc15d1edf (patch) | |
| tree | 5a606ffaae05c62667a21f922b8a254bce422014 | |
| parent | f96c9ab31700bc37792de0b3bec97edd7d99aa29 (diff) | |
| parent | e9c88b7d3657d83ab84c081fbd56183061ed09c7 (diff) | |
Merge "Fallback to conductor if types are not stashed."
| -rw-r--r-- | nova/compute/resource_tracker.py | 41 | ||||
| -rw-r--r-- | nova/tests/compute/test_resource_tracker.py | 26 |
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): |
