From 621594fc41d0e07fd63dfe7c3c5cfee9edc380ad Mon Sep 17 00:00:00 2001 From: Mark McLoughlin Date: Mon, 4 Jan 2016 20:11:18 +0000 Subject: [PATCH] libvirt: add a new live_migration_tunnelled config Add a config option which explicitly controls whether we pass the VIR_MIGRATE_TUNNELLED flag to libvirt. This is a lot more covenient than having users modify a list of obscure flags. Note that this especially makes sense as part of a longer term plan to remove the live_migration_flag and block_migration_flag config options completely, and instead have config options for controlling specific behavior choices that operators care about. Note also that review Id8b38b0978cdc80df37cb26bb69d8f4bec5bf766 essentially proposes changing the default of this config value to false. DocImpact Change-Id: I8d77596860a7803f8549cde4277e9a0509e4675a Signed-off-by: Mark McLoughlin --- nova/tests/unit/virt/libvirt/test_driver.py | 47 +++++++++++++++++++ nova/virt/libvirt/driver.py | 40 ++++++++++++++++ ...-new-tunneled-option-d7ebb1eb1e95e683.yaml | 7 +++ 3 files changed, 94 insertions(+) create mode 100644 releasenotes/notes/libvirt-live-migration-new-tunneled-option-d7ebb1eb1e95e683.yaml diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index 1d390ce137f8..ef4ef0efb4fd 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -1022,6 +1022,53 @@ class LibvirtConnTestCase(test.NoDBTestCase): msg = mock_log.warning.call_args_list[3] self.assertIn('Removing the VIR_MIGRATE_PERSIST_DEST flag', msg[0][0]) + @mock.patch('nova.virt.libvirt.driver.LOG') + def test_live_migration_tunnelled_true(self, mock_log): + self.flags(live_migration_tunnelled=True, group='libvirt') + + self._do_test_parse_migration_flags( + lm_config=('VIR_MIGRATE_PEER2PEER, VIR_MIGRATE_UNDEFINE_SOURCE, ' + 'VIR_MIGRATE_LIVE'), + bm_config=('VIR_MIGRATE_PEER2PEER, VIR_MIGRATE_UNDEFINE_SOURCE, ' + 'VIR_MIGRATE_LIVE, VIR_MIGRATE_NON_SHARED_INC'), + lm_expected=(libvirt_driver.libvirt.VIR_MIGRATE_LIVE | + libvirt_driver.libvirt.VIR_MIGRATE_PEER2PEER | + libvirt_driver.libvirt.VIR_MIGRATE_UNDEFINE_SOURCE | + libvirt_driver.libvirt.VIR_MIGRATE_TUNNELLED), + bm_expected=(libvirt_driver.libvirt.VIR_MIGRATE_LIVE | + libvirt_driver.libvirt.VIR_MIGRATE_PEER2PEER | + libvirt_driver.libvirt.VIR_MIGRATE_UNDEFINE_SOURCE | + libvirt_driver.libvirt.VIR_MIGRATE_NON_SHARED_INC | + libvirt_driver.libvirt.VIR_MIGRATE_TUNNELLED)) + + msg = mock_log.warning.call_args_list[0] + self.assertIn('does not contain the VIR_MIGRATE_TUNNELLED', msg[0][0]) + msg = mock_log.warning.call_args_list[1] + self.assertIn('does not contain the VIR_MIGRATE_TUNNELLED', msg[0][0]) + + @mock.patch('nova.virt.libvirt.driver.LOG') + def test_live_migration_tunnelled_false(self, mock_log): + self.flags(live_migration_tunnelled=False, group='libvirt') + + self._do_test_parse_migration_flags( + lm_config=('VIR_MIGRATE_PEER2PEER, VIR_MIGRATE_UNDEFINE_SOURCE, ' + 'VIR_MIGRATE_LIVE, VIR_MIGRATE_TUNNELLED'), + bm_config=('VIR_MIGRATE_PEER2PEER, VIR_MIGRATE_UNDEFINE_SOURCE, ' + 'VIR_MIGRATE_LIVE, VIR_MIGRATE_NON_SHARED_INC, ' + 'VIR_MIGRATE_TUNNELLED'), + lm_expected=(libvirt_driver.libvirt.VIR_MIGRATE_LIVE | + libvirt_driver.libvirt.VIR_MIGRATE_PEER2PEER | + libvirt_driver.libvirt.VIR_MIGRATE_UNDEFINE_SOURCE), + bm_expected=(libvirt_driver.libvirt.VIR_MIGRATE_LIVE | + libvirt_driver.libvirt.VIR_MIGRATE_PEER2PEER | + libvirt_driver.libvirt.VIR_MIGRATE_UNDEFINE_SOURCE | + libvirt_driver.libvirt.VIR_MIGRATE_NON_SHARED_INC)) + + msg = mock_log.warning.call_args_list[0] + self.assertIn('contains the VIR_MIGRATE_TUNNELLED flag', msg[0][0]) + msg = mock_log.warning.call_args_list[1] + self.assertIn('contains the VIR_MIGRATE_TUNNELLED flag', msg[0][0]) + @mock.patch('nova.utils.get_image_from_system_metadata') @mock.patch.object(host.Host, 'has_min_version', return_value=True) diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 70dfc019047b..036f909e9cc6 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -168,6 +168,16 @@ libvirt_opts = [ 'VIR_MIGRATE_LIVE, VIR_MIGRATE_TUNNELLED, ' 'VIR_MIGRATE_NON_SHARED_INC', help='Migration flags to be set for block migration'), + cfg.BoolOpt('live_migration_tunnelled', + help='Whether to use tunnelled migration, where migration ' + 'data is transported over the libvirtd connection. If ' + 'True, we use the VIR_MIGRATE_TUNNELLED migration flag, ' + 'avoiding the need to configure the network to allow ' + 'direct hypervisor to hypervisor communication. If ' + 'False, use the native transport. If not set, Nova ' + 'will choose a sensible default based on, for example ' + 'the availability of native encryption support in the ' + 'hypervisor.'), cfg.IntOpt('live_migration_bandwidth', default=0, help='Maximum bandwidth(in MiB/s) to be used during migration. ' @@ -693,6 +703,31 @@ class LibvirtDriver(driver.ComputeDriver): return (live_migration_flags, block_migration_flags) + def _handle_live_migration_tunnelled(self, migration_flags, config_name): + if CONF.libvirt.live_migration_tunnelled is None: + return migration_flags + + if CONF.libvirt.live_migration_tunnelled: + if (migration_flags & libvirt.VIR_MIGRATE_TUNNELLED) == 0: + LOG.warning(_LW('The %(config_name)s config option does not ' + 'contain the VIR_MIGRATE_TUNNELLED flag but ' + 'the live_migration_tunnelled is set to True ' + 'which causes VIR_MIGRATE_TUNNELLED to be ' + 'set'), + {'config_name': config_name}) + migration_flags |= libvirt.VIR_MIGRATE_TUNNELLED + else: + if (migration_flags & libvirt.VIR_MIGRATE_TUNNELLED) != 0: + LOG.warning(_LW('The %(config_name)s config option contains ' + 'the VIR_MIGRATE_TUNNELLED flag but the ' + 'live_migration_tunnelled is set to False ' + 'which causes VIR_MIGRATE_TUNNELLED to be ' + 'unset'), + {'config_name': config_name}) + migration_flags &= ~libvirt.VIR_MIGRATE_TUNNELLED + + return migration_flags + def _parse_migration_flags(self): def str2sum(str_val): logical_sum = 0 @@ -719,6 +754,11 @@ class LibvirtDriver(driver.ComputeDriver): block_migration_flags) = self._check_block_migration_flags( live_migration_flags, block_migration_flags) + live_migration_flags = self._handle_live_migration_tunnelled( + live_migration_flags, live_config_name) + block_migration_flags = self._handle_live_migration_tunnelled( + block_migration_flags, block_config_name) + self._live_migration_flags = live_migration_flags self._block_migration_flags = block_migration_flags diff --git a/releasenotes/notes/libvirt-live-migration-new-tunneled-option-d7ebb1eb1e95e683.yaml b/releasenotes/notes/libvirt-live-migration-new-tunneled-option-d7ebb1eb1e95e683.yaml new file mode 100644 index 000000000000..6c56365275b5 --- /dev/null +++ b/releasenotes/notes/libvirt-live-migration-new-tunneled-option-d7ebb1eb1e95e683.yaml @@ -0,0 +1,7 @@ +--- +features: + - The libvirt driver now has a live_migration_tunnelled + configuration option which should be used where the + VIR_MIGRATE_TUNNELLED flag would previously have been + set or unset in the live_migration_flag and + block_migration_flag configuration options.