Skip to content

Commit

Permalink
Migrate floating ip addresses in multi_host live_migration
Browse files Browse the repository at this point in the history
Make migration of floating ip addresses work and work only
in multi_host mode.
Add test case for post_live_migration_at_destination.

Fixes bug 966529 and bug 1029291

Change-Id: Ia79030e5bcfc55e5a33b20a3d6eead01fa5b255a
  • Loading branch information
wenjianhn committed Nov 13, 2012
1 parent c9a2ae6 commit 3c173a7
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 36 deletions.
29 changes: 6 additions & 23 deletions nova/compute/manager.py
Expand Up @@ -2534,29 +2534,9 @@ def _post_live_migration(self, ctxt, instance_ref,
self.driver.unfilter_instance(instance_ref,
self._legacy_nw_info(network_info))

# Database updating.
# NOTE(jkoelker) This needs to be converted to network api calls
# if nova wants to support floating_ips in
# quantum/melange
try:
# Not return if floating_ip is not found, otherwise,
# instance never be accessible..
floating_ip = self.db.instance_get_floating_address(ctxt,
instance_ref['id'])
if not floating_ip:
LOG.info(_('No floating_ip found'), instance=instance_ref)
else:
floating_ip_ref = self.db.floating_ip_get_by_address(ctxt,
floating_ip)
self.db.floating_ip_update(ctxt,
floating_ip_ref['address'],
{'host': dest})
except exception.NotFound:
LOG.info(_('No floating_ip found.'), instance=instance_ref)
except Exception, e:
LOG.error(_('Live migration: Unexpected error: cannot inherit '
'floating ip.\n%(e)s'), locals(),
instance=instance_ref)
migration = {'source_compute': self.host,
'dest_compute': dest, }
self.network_api.migrate_instance_start(ctxt, instance_ref, migration)

# Define domain at destination host, without doing it,
# pause/suspend/terminate do not work.
Expand Down Expand Up @@ -2605,6 +2585,9 @@ def post_live_migration_at_destination(self, context, instance,
# plug_vifs
self.network_api.setup_networks_on_host(context, instance,
self.host)
migration = {'source_compute': instance['host'],
'dest_compute': self.host, }
self.network_api.migrate_instance_finish(context, instance, migration)

network_info = self._get_instance_nw_info(context, instance)
self.driver.post_live_migration_at_destination(context, instance,
Expand Down
52 changes: 39 additions & 13 deletions nova/tests/compute/test_compute.py
Expand Up @@ -2321,11 +2321,12 @@ def test_live_migration_works_correctly(self):
def test_post_live_migration_working_correctly(self):
"""Confirm post_live_migration() works as expected correctly."""
dest = 'desthost'
flo_addr = '1.2.1.2'
srchost = self.compute.host

# creating testdata
c = context.get_admin_context()
inst_ref = jsonutils.to_primitive(self._create_fake_instance({
'host': srchost,
'state_description': 'migrating',
'state': power_state.PAUSED}))
inst_uuid = inst_ref['uuid']
Expand All @@ -2334,15 +2335,15 @@ def test_post_live_migration_working_correctly(self):
db.instance_update(c, inst_uuid,
{'task_state': task_states.MIGRATING,
'power_state': power_state.PAUSED})
fix_addr = db.fixed_ip_create(c, {'address': '1.1.1.1',
'instance_uuid': inst_ref['uuid']})
fix_ref = db.fixed_ip_get_by_address(c, fix_addr)
db.floating_ip_create(c, {'address': flo_addr,
'fixed_ip_id': fix_ref['id']})

# creating mocks
self.mox.StubOutWithMock(self.compute.driver, 'unfilter_instance')
self.compute.driver.unfilter_instance(inst_ref, [])
self.mox.StubOutWithMock(self.compute.network_api,
'migrate_instance_start')
migration = {'source_compute': srchost,
'dest_compute': dest, }
self.compute.network_api.migrate_instance_start(c, inst_ref, migration)
self.mox.StubOutWithMock(rpc, 'call')
rpc.call(c, rpc.queue_get_for(c, CONF.compute_topic, dest),
{"method": "post_live_migration_at_destination",
Expand All @@ -2361,14 +2362,39 @@ def test_post_live_migration_working_correctly(self):
self.mox.ReplayAll()
self.compute._post_live_migration(c, inst_ref, dest)

# make sure floating ips are rewritten to destinatioin hostname.
flo_refs = db.floating_ip_get_all_by_host(c, dest)
self.assertTrue(flo_refs)
self.assertEqual(flo_refs[0]['address'], flo_addr)
def test_post_live_migration_at_destination(self):
params = {'task_state': task_states.MIGRATING,
'power_state': power_state.PAUSED, }
instance = jsonutils.to_primitive(self._create_fake_instance(params))

# cleanup
db.instance_destroy(c, inst_uuid)
db.floating_ip_destroy(c, flo_addr)
admin_ctxt = context.get_admin_context()
instance = db.instance_get_by_uuid(admin_ctxt, instance['uuid'])
self.mox.StubOutWithMock(self.compute.network_api,
'setup_networks_on_host')
self.compute.network_api.setup_networks_on_host(admin_ctxt, instance,
self.compute.host)
self.mox.StubOutWithMock(self.compute.network_api,
'migrate_instance_finish')
migration = {'source_compute': instance['host'],
'dest_compute': self.compute.host, }
self.compute.network_api.migrate_instance_finish(admin_ctxt,
instance, migration)
self.mox.StubOutWithMock(self.compute.driver,
'post_live_migration_at_destination')
fake_net_info = []
self.compute.driver.post_live_migration_at_destination(admin_ctxt,
instance,
fake_net_info,
False)
self.compute.network_api.setup_networks_on_host(admin_ctxt, instance,
self.compute.host)

self.mox.ReplayAll()
self.compute.post_live_migration_at_destination(admin_ctxt, instance)
instance = db.instance_get_by_uuid(admin_ctxt, instance['uuid'])
self.assertEqual(instance['host'], self.compute.host)
self.assertEqual(instance['vm_state'], vm_states.ACTIVE)
self.assertEqual(instance['task_state'], None)

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

0 comments on commit 3c173a7

Please sign in to comment.