From a7e2a4114a4adbdb0273603515ecfe688e2231dd Mon Sep 17 00:00:00 2001 From: Russell Bryant Date: Thu, 5 Dec 2013 14:44:32 -0500 Subject: [PATCH] Allow compute manager to accept 3.0 messages We are currently trying to support live upgrades from havana to icehouse. This change is required to make that happen. In a live upgrade situation, you have icehouse nova infrastructure, with a mix of havana and icehouse compute nodes as you roll through and upgrade them. While in this situation, the havana compute nodes must be able to accept 3.0 messages. Accepting 3.0 messages is trivial to do and extremely low risk. It does not change the behavior of a havana-only deployment at all. The only additions is some pass-through code to the current compute manager. This code will only get hit during a live upgrade situation. Note that there is one other change needed to complete this. With only this patch, live upgrades are supported, but any operations that require compute nodes to talk to each other will not work. This includes resizes and migrates. That would be unfortunate, since live migrations are something that people *definitely* want to be able to do during an upgrade procedure. The additional changes needed to allow resizes and migrates during live upgrades are included in another patch. Partial-bug: #1258253 Change-Id: Ia801609b6b3fe88e0d0b16f4c0d37bf25dbfa842 --- nova/compute/manager.py | 93 ++++++++++++++++++++++++++++++ nova/tests/compute/test_compute.py | 15 +++++ 2 files changed, 108 insertions(+) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 3faf907e7617..385f955463fa 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -451,6 +451,12 @@ class ComputeManager(manager.SchedulerDependentManager): self.use_legacy_block_device_info = \ self.driver.need_legacy_block_device_info + def create_rpc_dispatcher(self, backdoor_port=None, additional_apis=None): + additional_apis = additional_apis or [] + additional_apis.append(ComputeV3Proxy(self)) + return super(ComputeManager, self).create_rpc_dispatcher( + backdoor_port, additional_apis) + def _get_resource_tracker(self, nodename): rt = self._resource_tracker_dict.get(nodename) if not rt: @@ -5086,3 +5092,90 @@ class ComputeManager(manager.SchedulerDependentManager): instance.cleaned = True with utils.temporary_mutation(context, read_deleted='yes'): instance.save(context) + + +class ComputeV3Proxy(object): + + # NOTE(russellb) The compute rpc API version 3.0 is exactly the same as + # 2.latest used in Havana, so we can safely pass it through directly to the + # 2.x implementation compute manager. + RPC_API_VERSION = '3.0' + + supported_methods = ( + 'add_aggregate_host', + 'add_fixed_ip_to_instance', + 'attach_interface', + 'attach_volume', + 'change_instance_metadata', + 'check_can_live_migrate_destination', + 'check_can_live_migrate_source', + 'check_instance_shared_storage', + 'confirm_resize', + 'detach_interface', + 'detach_volume', + 'finish_resize', + 'finish_revert_resize', + 'get_console_output', + 'get_console_pool_info', + 'get_console_topic', + 'get_diagnostics', + 'get_vnc_console', + 'get_spice_console', + 'validate_console_port', + 'host_maintenance_mode', + 'host_power_action', + 'inject_file', + 'inject_network_info', + 'live_migration', + 'pause_instance', + 'post_live_migration_at_destination', + 'power_off_instance', + 'power_on_instance', + 'pre_live_migration', + 'prep_resize', + 'reboot_instance', + 'rebuild_instance', + 'refresh_provider_fw_rules', + 'remove_aggregate_host', + 'remove_fixed_ip_from_instance', + 'remove_volume_connection', + 'rescue_instance', + 'reset_network', + 'resize_instance', + 'resume_instance', + 'revert_resize', + 'rollback_live_migration_at_destination', + 'run_instance', + 'set_admin_password', + 'set_host_enabled', + 'swap_volume', + 'get_host_uptime', + 'reserve_block_device_name', + 'live_snapshot_instance', + 'backup_instance', + 'snapshot_instance', + 'start_instance', + 'stop_instance', + 'suspend_instance', + 'terminate_instance', + 'unpause_instance', + 'unrescue_instance', + 'soft_delete_instance', + 'restore_instance', + 'shelve_instance', + 'shelve_offload_instance', + 'unshelve_instance', + 'volume_snapshot_create', + 'volume_snapshot_delete', + 'refresh_security_group_rules', + 'refresh_security_group_members', + 'refresh_instance_security_rules', + ) + + def __init__(self, manager): + self.manager = manager + + def __getattr__(self, attr): + if attr not in self.supported_methods: + raise AttributeError() + return getattr(self.manager, attr) diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index 60470d330141..b2b88ee52f7a 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -9532,3 +9532,18 @@ class ComputeAPIClassNameTestCase(test.TestCase): self.flags(cell_type='fake_cell_type', group='cells') self.assertRaises(exception.InvalidInput, compute._get_compute_api_class_name) + + +class ComputeManagerV3TestCase(test.TestCase): + def test_v3_passes_through_to_v2(self): + self.count = 0 + + def _fake(*args, **kwargs): + self.count += 1 + + manager = compute_manager.ComputeManager() + proxy = compute_manager.ComputeV3Proxy(manager) + for m in proxy.supported_methods: + self.stubs.Set(manager, m, _fake) + getattr(proxy, m)() + self.assertEqual(self.count, len(proxy.supported_methods))