diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index 49b4baf91ee5..32ed18715c50 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -9264,6 +9264,10 @@ class LibvirtConnTestCase(test.NoDBTestCase, etree.tostring(config, encoding='unicode')) def test_live_migration_uri(self): + addresses = ('127.0.0.1', '127.0.0.1:4444', '[::1]:4444', + '[0:0:0:0:0:0:0:1]:4444', u'127.0.0.1', u'destination', + ) + hypervisor_uri_map = ( ('xen', 'xenmigr://%s/system'), ('kvm', 'qemu+tcp://%s/system'), @@ -9272,17 +9276,42 @@ class LibvirtConnTestCase(test.NoDBTestCase, # anything else will return None ('lxc', None), ) - dest = 'destination' - for hyperv, uri in hypervisor_uri_map: - self.flags(virt_type=hyperv, group='libvirt') - drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) - if uri is not None: - uri = uri % dest - self.assertEqual(uri, drvr._live_migration_uri(dest)) - else: - self.assertRaises(exception.LiveMigrationURINotAvailable, - drvr._live_migration_uri, - dest) + + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) + for dest in addresses: + for hyperv, uri in hypervisor_uri_map: + self.flags(virt_type=hyperv, group='libvirt') + if uri is not None: + uri = uri % dest + self.assertEqual(uri, drvr._live_migration_uri(dest)) + else: + self.assertRaises(exception.LiveMigrationURINotAvailable, + drvr._live_migration_uri, + dest) + + def test_live_migration_uri_ipv6(self): + addresses = ('::1', '0:0:0:0:0:0:0:1', u'::1') + + hypervisor_uri_map = ( + ('xen', 'xenmigr://[%s]/system'), + ('kvm', 'qemu+tcp://[%s]/system'), + ('qemu', 'qemu+tcp://[%s]/system'), + ('parallels', 'parallels+tcp://[%s]/system'), + # anything else will return None + ('lxc', None), + ) + + for dest in addresses: + for hyperv, uri in hypervisor_uri_map: + self.flags(virt_type=hyperv, group='libvirt') + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) + if uri is not None: + uri = uri % dest + self.assertEqual(uri, drvr._live_migration_uri(dest)) + else: + self.assertRaises(exception.LiveMigrationURINotAvailable, + drvr._live_migration_uri, + dest) def test_live_migration_uri_forced(self): dest = 'destination' @@ -9338,12 +9367,26 @@ class LibvirtConnTestCase(test.NoDBTestCase, self.flags(virt_type='kvm', group='libvirt') drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) - addresses = ('127.0.0.1', '127.0.0.1:4444', - '0:0:0:0:0:0:0:1', '[0:0:0:0:0:0:0:1]:4444', - u'127.0.0.1', u'destination') + addresses = ('127.0.0.1', '127.0.0.1:4444', '[::1]:4444', + '[0:0:0:0:0:0:0:1]:4444', u'127.0.0.1', u'destination', + ) + for dest in addresses: + uri = 'tcp://%s' result = drvr._migrate_uri(dest) - self.assertEqual('tcp://%s' % dest, result) + self.assertEqual(uri % dest, result) + self.assertIsInstance(result, str) + + def test_migrate_uri_forced_live_migration_inboud_addr_ipv6(self): + self.flags(virt_type='kvm', group='libvirt') + + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) + addresses = ('::1', '0:0:0:0:0:0:0:1', u'::1') + + for dest in addresses: + uri = 'tcp://[%s]' + result = drvr._migrate_uri(dest) + self.assertEqual(uri % dest, result) self.assertIsInstance(result, str) def test_update_volume_xml_no_serial(self): diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 25d528208dd5..db6f1b199ee6 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -59,6 +59,7 @@ from oslo_utils import encodeutils from oslo_utils import excutils from oslo_utils import fileutils from oslo_utils import importutils +from oslo_utils import netutils as oslo_netutils from oslo_utils import strutils from oslo_utils import timeutils from oslo_utils import units @@ -741,6 +742,8 @@ class LibvirtDriver(driver.ComputeDriver): 'xen': 'xenmigr://%s/system', 'parallels': 'parallels+tcp://%s/system', } + dest = oslo_netutils.escape_ipv6(dest) + virt_type = CONF.libvirt.virt_type # TODO(pkoniszewski): Remove fetching live_migration_uri in Pike uri = CONF.libvirt.live_migration_uri @@ -760,6 +763,8 @@ class LibvirtDriver(driver.ComputeDriver): @staticmethod def _migrate_uri(dest): uri = None + dest = oslo_netutils.escape_ipv6(dest) + # Only QEMU live migrations supports migrate-uri parameter virt_type = CONF.libvirt.virt_type if virt_type in ('qemu', 'kvm'): diff --git a/releasenotes/notes/libvirt_fix_ipv6_live_migration-bbcde8f3b7d17921.yaml b/releasenotes/notes/libvirt_fix_ipv6_live_migration-bbcde8f3b7d17921.yaml new file mode 100644 index 000000000000..7171f73a5588 --- /dev/null +++ b/releasenotes/notes/libvirt_fix_ipv6_live_migration-bbcde8f3b7d17921.yaml @@ -0,0 +1,4 @@ +--- +fixes: + - A change has been introduced in the libvirt driver to correctly handle + IPv6 addresses for live migration.