summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorÉdouard Thuleau <edouard.thuleau@orange.com>2012-11-08 16:14:37 +0100
committerÉdouard Thuleau <edouard.thuleau@orange.com>2012-11-21 22:44:57 +0100
commitd32d5b252fc6c71a19b5372defb468fee9c57d3a (patch)
treea27f41bd3e3e11a0faa18a32a16e9dc755465062 /nova
parent5582d203b77741a005687a87673d9fce11b5ee09 (diff)
Compute doesn't set the 'host' field in instance
When an instance starts, compute ask the resource manager to check the compute capabilities. If the compute resources are sufficient, the resource manager updates the 'host' instance field in the database. But the local variable 'instance' use by compute manger isn't updated. So, when compute manager asks the network manager to allocate a network for the instance, the 'host' instance field is null. Some compute tests doesn't update the local variable instance when they change some parameter on instance and failed with this patch. Fixes LP bug #1073600 Change-Id: I842d4814b9eabc6222c68118d8a244b20bb68164
Diffstat (limited to 'nova')
-rw-r--r--nova/compute/manager.py5
-rw-r--r--nova/compute/resource_tracker.py21
-rw-r--r--nova/tests/compute/test_compute.py91
-rw-r--r--nova/tests/compute/test_resource_tracker.py12
4 files changed, 88 insertions, 41 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index eab4906b0..5d5a4b582 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -1762,6 +1762,11 @@ class ComputeManager(manager.SchedulerDependentManager):
if not filter_properties:
filter_properties = {}
+ if not instance['host']:
+ self._set_instance_error_state(context, instance['uuid'])
+ msg = _('Instance has no source host')
+ raise exception.MigrationError(msg)
+
same_host = instance['host'] == self.host
if same_host and not CONF.allow_resize_to_same_host:
self._set_instance_error_state(context, instance['uuid'])
diff --git a/nova/compute/resource_tracker.py b/nova/compute/resource_tracker.py
index 17d0869ad..7bb402916 100644
--- a/nova/compute/resource_tracker.py
+++ b/nova/compute/resource_tracker.py
@@ -83,22 +83,20 @@ class ResourceTracker(object):
if self.disabled:
# compute_driver doesn't support resource tracking, just
# set the 'host' field and continue the build:
- instance_ref = self._set_instance_host(context,
- instance_ref['uuid'])
+ self._set_instance_host(context, instance_ref)
return claims.NopClaim()
# sanity check:
if instance_ref['host']:
- LOG.warning(_("Host field should be not be set on the instance "
- "until resources have been claimed."),
+ LOG.warning(_("Host field should not be set on the instance until "
+ "resources have been claimed."),
instance=instance_ref)
claim = claims.Claim(instance_ref, self)
if claim.test(self.compute_node, limits):
- instance_ref = self._set_instance_host(context,
- instance_ref['uuid'])
+ self._set_instance_host(context, instance_ref)
# Mark resources in-use and update stats
self._update_usage_from_instance(self.compute_node, instance_ref)
@@ -170,16 +168,17 @@ class ResourceTracker(object):
'new_instance_type_id': instance_type['id'],
'status': 'pre-migrating'})
- def _set_instance_host(self, context, instance_uuid):
+ def _set_instance_host(self, context, instance_ref):
"""Tag the instance as belonging to this host. This should be done
while the COMPUTE_RESOURCES_SEMPAHORE is held so the resource claim
will not be lost if the audit process starts.
"""
values = {'host': self.host, 'launched_on': self.host}
- (old_ref, instance_ref) = db.instance_update_and_get_original(context,
- instance_uuid, values)
- notifications.send_update(context, old_ref, instance_ref)
- return instance_ref
+ (old_ref, new_ref) = db.instance_update_and_get_original(context,
+ instance_ref['uuid'], values)
+ notifications.send_update(context, old_ref, new_ref)
+ instance_ref['host'] = self.host
+ instance_ref['launched_on'] = self.host
def abort_instance_claim(self, instance):
"""Remove usage from the given instance"""
diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py
index 264566d7a..206c5d694 100644
--- a/nova/tests/compute/test_compute.py
+++ b/nova/tests/compute/test_compute.py
@@ -1771,21 +1771,23 @@ class ComputeTestCase(BaseTestCase):
new_type_id = new_type['id']
self.compute.run_instance(self.context, instance=instance)
- db.instance_update(self.context, instance['uuid'], {'host': 'foo'})
- db.instance_update(self.context, instance["uuid"],
+ new_instance = db.instance_update(self.context, instance['uuid'],
+ {'host': 'foo'})
+ new_instance = jsonutils.to_primitive(new_instance)
+ db.instance_update(self.context, new_instance["uuid"],
{"task_state": task_states.RESIZE_PREP})
- self.compute.prep_resize(self.context, instance=instance,
+ self.compute.prep_resize(self.context, instance=new_instance,
instance_type=new_type, image={})
migration_ref = db.migration_get_by_instance_and_status(
- self.context.elevated(), instance['uuid'], 'pre-migrating')
- self.compute.resize_instance(self.context, instance=instance,
+ self.context.elevated(), new_instance['uuid'], 'pre-migrating')
+ self.compute.resize_instance(self.context, instance=new_instance,
migration=migration_ref, image={}, instance_type=new_type)
timeutils.set_time_override(cur_time)
test_notifier.NOTIFICATIONS = []
self.compute.finish_resize(self.context,
migration=jsonutils.to_primitive(migration_ref),
- disk_info={}, image={}, instance=instance)
+ disk_info={}, image={}, instance=new_instance)
self.assertEquals(len(test_notifier.NOTIFICATIONS), 2)
msg = test_notifier.NOTIFICATIONS[0]
@@ -1798,7 +1800,7 @@ class ComputeTestCase(BaseTestCase):
payload = msg['payload']
self.assertEquals(payload['tenant_id'], self.project_id)
self.assertEquals(payload['user_id'], self.user_id)
- self.assertEquals(payload['instance_id'], instance['uuid'])
+ self.assertEquals(payload['instance_id'], new_instance['uuid'])
self.assertEquals(payload['instance_type'], 'm1.small')
self.assertEquals(str(payload['instance_type_id']), str(new_type_id))
self.assertTrue('display_name' in payload)
@@ -1808,7 +1810,7 @@ class ComputeTestCase(BaseTestCase):
image_ref_url = utils.generate_image_url(FAKE_IMAGE_REF)
self.assertEquals(payload['image_ref_url'], image_ref_url)
self.compute.terminate_instance(self.context,
- instance=jsonutils.to_primitive(instance))
+ instance=jsonutils.to_primitive(new_instance))
def test_resize_instance_notification(self):
"""Ensure notifications on instance migrate/resize"""
@@ -1821,12 +1823,14 @@ class ComputeTestCase(BaseTestCase):
timeutils.set_time_override(cur_time)
test_notifier.NOTIFICATIONS = []
- db.instance_update(self.context, instance['uuid'], {'host': 'foo'})
+ new_instance = db.instance_update(self.context, instance['uuid'],
+ {'host': 'foo'})
+ new_instance = jsonutils.to_primitive(new_instance)
instance_type = instance_types.get_default_instance_type()
- self.compute.prep_resize(self.context, instance=instance,
+ self.compute.prep_resize(self.context, instance=new_instance,
instance_type=instance_type, image={})
db.migration_get_by_instance_and_status(self.context.elevated(),
- instance['uuid'],
+ new_instance['uuid'],
'pre-migrating')
self.assertEquals(len(test_notifier.NOTIFICATIONS), 3)
@@ -1843,7 +1847,7 @@ class ComputeTestCase(BaseTestCase):
payload = msg['payload']
self.assertEquals(payload['tenant_id'], self.project_id)
self.assertEquals(payload['user_id'], self.user_id)
- self.assertEquals(payload['instance_id'], instance['uuid'])
+ self.assertEquals(payload['instance_id'], new_instance['uuid'])
self.assertEquals(payload['instance_type'], 'm1.tiny')
type_id = instance_types.get_instance_type_by_name('m1.tiny')['id']
self.assertEquals(str(payload['instance_type_id']), str(type_id))
@@ -1852,10 +1856,12 @@ class ComputeTestCase(BaseTestCase):
self.assertTrue('launched_at' in payload)
image_ref_url = utils.generate_image_url(FAKE_IMAGE_REF)
self.assertEquals(payload['image_ref_url'], image_ref_url)
- self.compute.terminate_instance(self.context, instance=instance)
+ self.compute.terminate_instance(self.context, instance=new_instance)
- def test_prep_resize_instance_migration_error(self):
- """Ensure prep_resize raise a migration error"""
+ def test_prep_resize_instance_migration_error_on_same_host(self):
+ """Ensure prep_resize raise a migration error if destination is set on
+ the same source host and allow_resize_to_same_host is false
+ """
self.flags(host="foo", allow_resize_to_same_host=False)
instance = jsonutils.to_primitive(self._create_fake_instance())
@@ -1874,6 +1880,26 @@ class ComputeTestCase(BaseTestCase):
reservations=reservations)
self.compute.terminate_instance(self.context, instance=new_instance)
+ def test_prep_resize_instance_migration_error_on_none_host(self):
+ """Ensure prep_resize raise a migration error if destination host is
+ not defined
+ """
+ instance = jsonutils.to_primitive(self._create_fake_instance())
+
+ reservations = self._ensure_quota_reservations_rolledback()
+
+ self.compute.run_instance(self.context, instance=instance)
+ new_instance = db.instance_update(self.context, instance['uuid'],
+ {'host': None})
+ new_instance = jsonutils.to_primitive(new_instance)
+ instance_type = instance_types.get_default_instance_type()
+
+ self.assertRaises(exception.MigrationError, self.compute.prep_resize,
+ self.context, instance=new_instance,
+ instance_type=instance_type, image={},
+ reservations=reservations)
+ self.compute.terminate_instance(self.context, instance=new_instance)
+
def test_resize_instance_driver_error(self):
"""Ensure instance status set to Error on resize error"""
@@ -1889,22 +1915,24 @@ class ComputeTestCase(BaseTestCase):
reservations = self._ensure_quota_reservations_rolledback()
self.compute.run_instance(self.context, instance=instance)
- db.instance_update(self.context, instance['uuid'], {'host': 'foo'})
- self.compute.prep_resize(self.context, instance=instance,
+ new_instance = db.instance_update(self.context, instance['uuid'],
+ {'host': 'foo'})
+ new_instance = jsonutils.to_primitive(new_instance)
+ self.compute.prep_resize(self.context, instance=new_instance,
instance_type=instance_type, image={},
reservations=reservations)
migration_ref = db.migration_get_by_instance_and_status(
- self.context.elevated(), instance['uuid'], 'pre-migrating')
+ self.context.elevated(), new_instance['uuid'], 'pre-migrating')
- db.instance_update(self.context, instance['uuid'],
+ db.instance_update(self.context, new_instance['uuid'],
{"task_state": task_states.RESIZE_PREP})
#verify
self.assertRaises(test.TestingException, self.compute.resize_instance,
- self.context, instance=instance,
+ self.context, instance=new_instance,
migration=migration_ref, image={},
reservations=reservations,
instance_type=jsonutils.to_primitive(instance_type))
- instance = db.instance_get_by_uuid(self.context, instance['uuid'])
+ instance = db.instance_get_by_uuid(self.context, new_instance['uuid'])
self.assertEqual(instance['vm_state'], vm_states.ERROR)
self.compute.terminate_instance(self.context,
@@ -1916,22 +1944,23 @@ class ComputeTestCase(BaseTestCase):
instance_type = instance_types.get_default_instance_type()
self.compute.run_instance(self.context, instance=instance)
- db.instance_update(self.context, instance['uuid'],
- {'host': 'foo'})
- self.compute.prep_resize(self.context, instance=instance,
+ new_instance = db.instance_update(self.context, instance['uuid'],
+ {'host': 'foo'})
+ new_instance = jsonutils.to_primitive(new_instance)
+ self.compute.prep_resize(self.context, instance=new_instance,
instance_type=instance_type, image={})
migration_ref = db.migration_get_by_instance_and_status(
- self.context.elevated(), instance['uuid'], 'pre-migrating')
- db.instance_update(self.context, instance['uuid'],
+ self.context.elevated(), new_instance['uuid'], 'pre-migrating')
+ db.instance_update(self.context, new_instance['uuid'],
{"task_state": task_states.RESIZE_PREP})
- self.compute.resize_instance(self.context, instance=instance,
+ self.compute.resize_instance(self.context, instance=new_instance,
migration=migration_ref, image={},
instance_type=jsonutils.to_primitive(instance_type))
- inst = db.instance_get_by_uuid(self.context, instance['uuid'])
+ inst = db.instance_get_by_uuid(self.context, new_instance['uuid'])
self.assertEqual(migration_ref['dest_compute'], inst['host'])
self.compute.terminate_instance(self.context,
- instance=jsonutils.to_primitive(instance))
+ instance=jsonutils.to_primitive(inst))
def test_finish_revert_resize(self):
"""Ensure that the flavor is reverted to the original on revert"""
@@ -2052,7 +2081,9 @@ class ComputeTestCase(BaseTestCase):
instance_type = instance_types.get_default_instance_type()
self.compute.run_instance(self.context, instance=inst_ref)
- db.instance_update(self.context, inst_ref['uuid'], {'host': 'foo'})
+ inst_ref = db.instance_update(self.context, inst_ref['uuid'],
+ {'host': 'foo'})
+ inst_ref = jsonutils.to_primitive(inst_ref)
self.compute.prep_resize(self.context, instance=inst_ref,
instance_type=instance_type,
image={}, reservations=reservations)
diff --git a/nova/tests/compute/test_resource_tracker.py b/nova/tests/compute/test_resource_tracker.py
index 5a7fcac2b..b9fd738fa 100644
--- a/nova/tests/compute/test_resource_tracker.py
+++ b/nova/tests/compute/test_resource_tracker.py
@@ -155,6 +155,7 @@ class BaseTestCase(test.TestCase):
'vcpus': 1,
'host': None,
'instance_type_id': 1,
+ 'launched_on': None,
}
instance.update(kwargs)
@@ -799,3 +800,14 @@ class ResizeClaimTestCase(BaseTrackerTestCase):
self.tracker.update_available_resource(self.context)
self.assertEqual(1, len(self.tracker.tracked_migrations))
+
+ def test_set_instance_host(self):
+ instance = self._fake_instance()
+ self.assertEqual(None, instance['host'])
+ self.assertEqual(None, instance['launched_on'])
+
+ claim = self.tracker.instance_claim(self.context, instance)
+ self.assertNotEqual(0, claim.memory_mb)
+
+ self.assertEqual('fakehost', instance['host'])
+ self.assertEqual('fakehost', instance['launched_on'])