Skip to content

Commit

Permalink
Update hypervisor_hostname after live migration
Browse files Browse the repository at this point in the history
After a live migration, the OS-EXT-SRV-ATTR:hypervisor_hostname
attribute of the instance is not updated correctly.  This change
adds a parameter to the call to _instance_update that fixes the
problem.

Fixes bug 1173376

Change-Id: I40f1ead2d93c7a9979a914e0fb96e3e5bb287b48
(cherry picked from commit 8c8e44c)
  • Loading branch information
Ben Nemec authored and russellb committed May 6, 2013
1 parent 43004ba commit 158f003
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 28 deletions.
16 changes: 12 additions & 4 deletions nova/compute/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -3268,10 +3268,18 @@ def post_live_migration_at_destination(self, context, instance,
block_migration, block_device_info)
# Restore instance state
current_power_state = self._get_power_state(context, instance)
instance = self._instance_update(context, instance['uuid'],
host=self.host, power_state=current_power_state,
vm_state=vm_states.ACTIVE, task_state=None,
expected_task_state=task_states.MIGRATING)
node_name = None
try:
compute_node = self._get_compute_info(context, self.host)
node_name = compute_node['hypervisor_hostname']
except exception.NotFound:
LOG.exception(_('Failed to get compute_info for %s') % self.host)
finally:
instance = self._instance_update(context, instance['uuid'],
host=self.host, power_state=current_power_state,
vm_state=vm_states.ACTIVE, task_state=None,
expected_task_state=task_states.MIGRATING,
node=node_name)

# NOTE(vish): this is necessary to update dhcp
self.network_api.setup_networks_on_host(context, instance, self.host)
Expand Down
71 changes: 47 additions & 24 deletions nova/tests/compute/test_compute.py
Original file line number Diff line number Diff line change
Expand Up @@ -3260,51 +3260,74 @@ def test_post_live_migration_working_correctly(self):
self.mox.ReplayAll()
self.compute._post_live_migration(c, inst_ref, dest)

def test_post_live_migration_at_destination(self):
def _begin_post_live_migration_at_destination(self):
self.mox.StubOutWithMock(self.compute.network_api,
'setup_networks_on_host')
self.mox.StubOutWithMock(self.compute.conductor_api,
'network_migrate_instance_finish')
self.mox.StubOutWithMock(self.compute, '_get_power_state')
self.mox.StubOutWithMock(self.compute, '_instance_update')
self.mox.StubOutWithMock(self.compute, '_get_compute_info')

params = {'task_state': task_states.MIGRATING,
'power_state': power_state.PAUSED, }
instance = jsonutils.to_primitive(self._create_fake_instance(params))
self.instance = jsonutils.to_primitive(
self._create_fake_instance(params))

admin_ctxt = context.get_admin_context()
instance = db.instance_get_by_uuid(admin_ctxt, instance['uuid'])
self.admin_ctxt = context.get_admin_context()
self.instance = db.instance_get_by_uuid(self.admin_ctxt,
self.instance['uuid'])

self.compute.network_api.setup_networks_on_host(admin_ctxt, instance,
self.compute.network_api.setup_networks_on_host(self.admin_ctxt,
self.instance,
self.compute.host)
migration = {'source_compute': instance['host'],
migration = {'source_compute': self.instance['host'],
'dest_compute': self.compute.host, }
self.compute.conductor_api.network_migrate_instance_finish(admin_ctxt,
instance, migration)
self.compute.conductor_api.network_migrate_instance_finish(
self.admin_ctxt, self.instance, migration)
fake_net_info = []
fake_block_dev_info = {'foo': 'bar'}
self.compute.driver.post_live_migration_at_destination(admin_ctxt,
instance,
self.compute.driver.post_live_migration_at_destination(self.admin_ctxt,
self.instance,
fake_net_info,
False,
fake_block_dev_info)
self.compute._get_power_state(admin_ctxt, instance).AndReturn(
'fake_power_state')
self.compute._get_power_state(self.admin_ctxt,
self.instance).AndReturn(
'fake_power_state')

updated_instance = 'fake_updated_instance'
self.compute._instance_update(admin_ctxt, instance['uuid'],
host=self.compute.host,
power_state='fake_power_state',
vm_state=vm_states.ACTIVE,
task_state=None,
expected_task_state=task_states.MIGRATING).AndReturn(
updated_instance)
self.compute.network_api.setup_networks_on_host(admin_ctxt,
updated_instance, self.compute.host)
def _finish_post_live_migration_at_destination(self):
self.compute.network_api.setup_networks_on_host(self.admin_ctxt,
mox.IgnoreArg(), self.compute.host)

self.mox.ReplayAll()

self.compute.post_live_migration_at_destination(admin_ctxt, instance)
self.compute.post_live_migration_at_destination(self.admin_ctxt,
self.instance)

return self.compute.conductor_api.instance_get_by_uuid(self.admin_ctxt,
self.instance['uuid'])

def test_post_live_migration_at_destination_with_compute_info(self):
"""The instance's node property should be updated correctly."""
self._begin_post_live_migration_at_destination()
hypervisor_hostname = 'fake_hypervisor_hostname'
fake_compute_info = {'hypervisor_hostname': hypervisor_hostname}
self.compute._get_compute_info(mox.IgnoreArg(),
mox.IgnoreArg()).AndReturn(
fake_compute_info)
updated = self._finish_post_live_migration_at_destination()
self.assertEqual(updated['node'], hypervisor_hostname)

def test_post_live_migration_at_destination_without_compute_info(self):
"""The instance's node property should be set to None if we fail to
get compute_info.
"""
self._begin_post_live_migration_at_destination()
self.compute._get_compute_info(mox.IgnoreArg(),
mox.IgnoreArg()).AndRaise(
exception.NotFound())
updated = self._finish_post_live_migration_at_destination()
self.assertIsNone(updated['node'])

def test_run_kill_vm(self):
# Detect when a vm is terminated behind the scenes.
Expand Down

0 comments on commit 158f003

Please sign in to comment.