From ebfa09fa197a1d88d1b3ab1f308232c3df7dc009 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Thu, 9 Apr 2015 09:45:50 -0700 Subject: [PATCH] Add compute RPC API v4.0 This patch creates compute RPC API version 4.0, while retaining compatibility in rpcapi and manager for 3.x, allowing for continuous deployment scenarios. UpgradeImpact - Deployments doing continuous deployment should follow this process to upgrade without any downtime: 1) Set [upgrade_levels] compute=kilo in your config. 2) Upgrade to this commit. 3) Once everything has been upgraded, remove the entry in [upgrade_levels] so that all rpc clients to the nova-compute service start sending the new 4.0 messages. Change-Id: Id96e77c739e7473774e110646204520d6163d8a5 --- nova/compute/manager.py | 300 ++++++++++++++++++ nova/compute/rpcapi.py | 225 ++++++++------ nova/tests/unit/compute/test_rpcapi.py | 401 ++++++++++++++++++++++++- 3 files changed, 821 insertions(+), 105 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 6004419730e6..aa563966133e 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -690,6 +690,7 @@ class ComputeManager(manager.Manager): super(ComputeManager, self).__init__(service_name="compute", *args, **kwargs) + self.additional_endpoints.append(_ComputeV4Proxy(self)) # NOTE(russellb) Load the driver last. It may call back into the # compute manager via the virtapi, so we want it to be fully @@ -6545,3 +6546,302 @@ class ComputeManager(manager.Manager): image_meta = compute_utils.get_image_metadata( context, self.image_api, image_ref, instance) self.driver.unquiesce(context, instance, image_meta) + + +# TODO(danms): This goes away immediately in Lemming and is just +# present in Kilo so that we can receive v3.x and v4.0 messages +class _ComputeV4Proxy(object): + + target = messaging.Target(version='4.0') + + def __init__(self, manager): + self.manager = manager + + def add_aggregate_host(self, ctxt, aggregate, host, slave_info=None): + return self.manager.add_aggregate_host(ctxt, aggregate, host, + slave_info=slave_info) + + def add_fixed_ip_to_instance(self, ctxt, network_id, instance): + return self.manager.add_fixed_ip_to_instance(ctxt, + network_id, + instance) + + def attach_interface(self, ctxt, instance, network_id, port_id, + requested_ip): + return self.manager.attach_interface(ctxt, instance, network_id, + port_id, requested_ip) + + def attach_volume(self, ctxt, instance, bdm): + # NOTE(danms): In 3.x, attach_volume had mountpoint and volume_id + # parameters, which are gone from 4.x. Provide None for each to + # the 3.x manager above and remove in Lemming. + return self.manager.attach_volume(ctxt, None, None, + instance=instance, + bdm=bdm) + + def change_instance_metadata(self, ctxt, instance, diff): + return self.manager.change_instance_metadata(ctxt, instance, diff) + + def check_can_live_migrate_destination(self, ctxt, instance, destination, + block_migration, disk_over_commit): + return self.manager.check_can_live_migrate_destination( + ctxt, instance, destination, block_migration, disk_over_commit) + + def check_can_live_migrate_source(self, ctxt, instance, dest_check_data): + return self.manager.check_can_live_migrate_source(ctxt, instance, + dest_check_data) + + def check_instance_shared_storage(self, ctxt, instance, data): + return self.manager.check_instance_shared_storage(ctxt, instance, data) + + def confirm_resize(self, ctxt, instance, reservations, migration): + return self.manager.confirm_resize(ctxt, instance, + reservations, migration) + + def detach_interface(self, ctxt, instance, port_id): + return self.manager.detach_interface(ctxt, instance, port_id) + + def detach_volume(self, ctxt, volume_id, instance): + # NOTE(danms): Pass instance by kwarg to help the object_compat + # decorator, as real RPC dispatch does. + return self.manager.detach_volume(ctxt, volume_id, instance=instance) + + def finish_resize(self, ctxt, disk_info, image, instance, + reservations, migration): + return self.manager.finish_resize(ctxt, disk_info, image, instance, + reservations, migration) + + def finish_revert_resize(self, ctxt, instance, + reservations, migration): + return self.manager.finish_revert_resize(ctxt, instance, + reservations, migration) + + def get_console_output(self, ctxt, instance, tail_length): + return self.manager.get_console_output(ctxt, instance, tail_length) + + def get_console_pool_info(self, ctxt, console_type): + return self.manager.get_console_pool_info(ctxt, console_type) + + def get_console_topic(self, ctxt): + return self.manager.get_console_topic(ctxt) + + def get_diagnostics(self, ctxt, instance): + return self.manager.get_diagnostics(ctxt, instance) + + def get_instance_diagnostics(self, ctxt, instance): + return self.manager.get_instance_diagnostics(ctxt, instance) + + def get_vnc_console(self, ctxt, console_type, instance): + return self.manager.get_vnc_console(ctxt, console_type, instance) + + def get_spice_console(self, ctxt, console_type, instance): + return self.manager.get_spice_console(ctxt, console_type, instance) + + def get_rdp_console(self, ctxt, console_type, instance): + return self.manager.get_rdp_console(ctxt, console_type, instance) + + def get_serial_console(self, ctxt, console_type, instance): + return self.manager.get_serial_console(ctxt, console_type, instance) + + def validate_console_port(self, ctxt, instance, port, console_type): + return self.manager.validate_console_port(ctxt, instance, port, + console_type) + + def host_maintenance_mode(self, ctxt, host, mode): + return self.manager.host_maintenance_mode(ctxt, host, mode) + + def host_power_action(self, ctxt, action): + return self.manager.host_power_action(ctxt, action) + + def inject_network_info(self, ctxt, instance): + return self.manager.inject_network_info(ctxt, instance) + + def live_migration(self, ctxt, instance, dest, block_migration, + migrate_data=None): + return self.manager.live_migration(ctxt, instance, dest, + block_migration, + migrate_data=migrate_data) + + def pause_instance(self, ctxt, instance): + return self.manager.pause_instance(ctxt, instance) + + def post_live_migration_at_destination(self, ctxt, instance, + block_migration): + return self.manager.post_live_migration_at_destination( + ctxt, instance, block_migration) + + def pre_live_migration(self, ctxt, instance, block_migration, disk, + migrate_data=None): + return self.manager.pre_live_migration(ctxt, instance, block_migration, + disk, migrate_data=None) + + def prep_resize(self, ctxt, image, instance, instance_type, + reservations=None, request_spec=None, + filter_properties=None, node=None, clean_shutdown=True): + return self.manager.prep_resize(ctxt, image, instance, instance_type, + reservations=reservations, + request_spec=request_spec, + filter_properties=filter_properties, + node=node, + clean_shutdown=clean_shutdown) + + def reboot_instance(self, ctxt, instance, block_device_info, reboot_type): + return self.manager.reboot_instance(ctxt, instance, block_device_info, + reboot_type) + + def rebuild_instance(self, ctxt, instance, orig_image_ref, image_ref, + injected_files, new_pass, orig_sys_metadata, + bdms, recreate, on_shared_storage, + preserve_ephemeral=False): + return self.manager.rebuild_instance( + ctxt, instance, orig_image_ref, image_ref, + injected_files, new_pass, orig_sys_metadata, + bdms, recreate, on_shared_storage, + preserve_ephemeral=preserve_ephemeral) + + def refresh_provider_fw_rules(self, ctxt): + return self.manager.refresh_provider_fw_rules(ctxt) + + def remove_aggregate_host(self, ctxt, host, slave_info, aggregate): + return self.manager.remove_aggregate_host(ctxt, + host, slave_info, + aggregate) + + def remove_fixed_ip_from_instance(self, ctxt, address, instance): + return self.manager.remove_fixed_ip_from_instance(ctxt, address, + instance) + + def remove_volume_connection(self, ctxt, instance, volume_id): + return self.manager.remove_volume_connection(ctxt, instance, volume_id) + + def rescue_instance(self, ctxt, instance, rescue_password, + rescue_image_ref, clean_shutdown): + return self.manager.rescue_instance(ctxt, instance, rescue_password, + rescue_image_ref=rescue_image_ref, + clean_shutdown=clean_shutdown) + + def reset_network(self, ctxt, instance): + return self.manager.reset_network(ctxt, instance) + + def resize_instance(self, ctxt, instance, image, + reservations, migration, instance_type, + clean_shutdown=True): + return self.manager.resize_instance(ctxt, instance, image, + reservations, migration, + instance_type, + clean_shutdown=clean_shutdown) + + def resume_instance(self, ctxt, instance): + return self.manager.resume_instance(ctxt, instance) + + def revert_resize(self, ctxt, instance, migration, reservations=None): + return self.manager.revert_resize(ctxt, instance, migration, + reservations=reservations) + + def rollback_live_migration_at_destination(self, ctxt, instance, + destroy_disks, + migrate_data): + return self.manager.rollback_live_migration_at_destination( + ctxt, instance, destroy_disks=destroy_disks, + migrate_data=migrate_data) + + def set_admin_password(self, ctxt, instance, new_pass): + return self.manager.set_admin_password(ctxt, instance, new_pass) + + def set_host_enabled(self, ctxt, enabled): + return self.manager.set_host_enabled(ctxt, enabled) + + def swap_volume(self, ctxt, instance, old_volume_id, new_volume_id): + return self.manager.swap_volume(ctxt, instance, old_volume_id, + new_volume_id) + + def get_host_uptime(self, ctxt): + return self.manager.get_host_uptime(ctxt) + + def reserve_block_device_name(self, ctxt, instance, device, volume_id, + disk_bus=None, device_type=None): + return self.manager.reserve_block_device_name(ctxt, instance, device, + volume_id, + disk_bus=disk_bus, + device_type=device_type, + return_bdm_object=True) + + def backup_instance(self, ctxt, image_id, instance, backup_type, + rotation): + return self.manager.backup_instance(ctxt, image_id, instance, + backup_type, rotation) + + def snapshot_instance(self, ctxt, image_id, instance): + return self.manager.snapshot_instance(ctxt, image_id, instance) + + def start_instance(self, ctxt, instance): + return self.manager.start_instance(ctxt, instance) + + def stop_instance(self, ctxt, instance, clean_shutdown): + return self.manager.stop_instance(ctxt, instance, clean_shutdown) + + def suspend_instance(self, ctxt, instance): + return self.manager.suspend_instance(ctxt, instance) + + def terminate_instance(self, ctxt, instance, bdms, reservations=None): + return self.manager.terminate_instance(ctxt, instance, bdms, + reservations=reservations) + + def unpause_instance(self, ctxt, instance): + return self.manager.unpause_instance(ctxt, instance) + + def unrescue_instance(self, ctxt, instance): + return self.manager.unrescue_instance(ctxt, instance) + + def soft_delete_instance(self, ctxt, instance, reservations): + return self.manager.soft_delete_instance(ctxt, instance, reservations) + + def restore_instance(self, ctxt, instance): + return self.manager.restore_instance(ctxt, instance) + + def shelve_instance(self, ctxt, instance, image_id=None, + clean_shutdown=True): + return self.manager.shelve_instance(ctxt, instance, image_id=image_id, + clean_shutdown=clean_shutdown) + + def shelve_offload_instance(self, ctxt, instance, clean_shutdown): + return self.manager.shelve_offload_instance(ctxt, instance, + clean_shutdown) + + def unshelve_instance(self, ctxt, instance, image=None, + filter_properties=None, node=None): + return self.manager.unshelve_instance( + ctxt, instance, image=image, + filter_properties=filter_properties, + node=node) + + def volume_snapshot_create(self, ctxt, instance, volume_id, create_info): + return self.manager.volume_snapshot_create(ctxt, instance, volume_id, + create_info) + + def volume_snapshot_delete(self, ctxt, instance, volume_id, snapshot_id, + delete_info): + return self.manager.volume_snapshot_delete(ctxt, instance, volume_id, + snapshot_id, delete_info) + + def external_instance_event(self, ctxt, instances, events): + return self.manager.external_instance_event(ctxt, instances, events) + + def build_and_run_instance(self, ctxt, instance, image, request_spec, + filter_properties, admin_password=None, + injected_files=None, requested_networks=None, + security_groups=None, block_device_mapping=None, + node=None, limits=None): + return self.manager.build_and_run_instance( + ctxt, instance, image, request_spec, filter_properties, + admin_password=admin_password, injected_files=injected_files, + requested_networks=requested_networks, + security_groups=security_groups, + block_device_mapping=block_device_mapping, + node=node, limits=limits) + + def quiesce_instance(self, ctxt, instance): + return self.manager.quiesce_instance(ctxt, instance) + + def unquiesce_instance(self, ctxt, instance, mapping=None): + return self.manager.unquiesce_instance(ctxt, instance, mapping=mapping) diff --git a/nova/compute/rpcapi.py b/nova/compute/rpcapi.py index d70593bc1997..fe116f6d13d6 100644 --- a/nova/compute/rpcapi.py +++ b/nova/compute/rpcapi.py @@ -286,6 +286,12 @@ class ComputeAPI(object): * 3.39 - Add quiesce_instance and unquiesce_instance methods * 3.40 - Make build_and_run_instance() take a new-world topology limits object + + ... Kilo supports messaging version 3.40. So, any changes to + existing methods in 3.x after that point should be done so that they + can handle the version_cap being set to 3.40 + + * 4.0 - Remove 3.x compatibility ''' VERSION_ALIASES = { @@ -296,12 +302,18 @@ class ComputeAPI(object): def __init__(self): super(ComputeAPI, self).__init__() - target = messaging.Target(topic=CONF.compute_topic, version='3.0') + target = messaging.Target(topic=CONF.compute_topic, version='4.0') version_cap = self.VERSION_ALIASES.get(CONF.upgrade_levels.compute, CONF.upgrade_levels.compute) serializer = objects_base.NovaObjectSerializer() self.client = self.get_client(target, version_cap, serializer) + def _compat_ver(self, current, legacy): + if self.client.can_send_version(current): + return current + else: + return legacy + # Cells overrides this def get_client(self, target, version_cap, serializer): return rpc.get_client(target, @@ -318,14 +330,14 @@ class ComputeAPI(object): parameter for the remote method. :param host: This is the host to send the message to. ''' - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=host, version=version) cctxt.cast(ctxt, 'add_aggregate_host', aggregate=aggregate, host=host_param, slave_info=slave_info) def add_fixed_ip_to_instance(self, ctxt, instance, network_id): - version = '3.12' + version = self._compat_ver('4.0', '3.12') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'add_fixed_ip_to_instance', @@ -333,7 +345,7 @@ class ComputeAPI(object): def attach_interface(self, ctxt, instance, network_id, port_id, requested_ip): - version = '3.17' + version = self._compat_ver('4.0', '3.17') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) return cctxt.call(ctxt, 'attach_interface', @@ -341,17 +353,19 @@ class ComputeAPI(object): port_id=port_id, requested_ip=requested_ip) def attach_volume(self, ctxt, instance, volume_id, mountpoint, bdm=None): - # NOTE(ndipanov): Remove volume_id and mountpoint on the next major - # version bump - they are not needed when using bdm objects. - version = '3.16' - kw = {'instance': instance, 'volume_id': volume_id, - 'mountpoint': mountpoint, 'bdm': bdm} + kw = {'instance': instance, 'bdm': bdm} + if self.client.can_send_version('4.0'): + version = '4.0' + else: + version = '3.16' + kw['mountpoint'] = mountpoint + kw['volume_id'] = volume_id cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'attach_volume', **kw) def change_instance_metadata(self, ctxt, instance, diff): - version = '3.7' + version = self._compat_ver('4.0', '3.7') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'change_instance_metadata', @@ -384,7 +398,9 @@ class ComputeAPI(object): def check_can_live_migrate_destination(self, ctxt, instance, destination, block_migration, disk_over_commit): - if self.client.can_send_version('3.32'): + if self.client.can_send_version('4.0'): + version = '4.0' + elif self.client.can_send_version('3.32'): version = '3.32' else: version = '3.0' @@ -396,7 +412,9 @@ class ComputeAPI(object): disk_over_commit=disk_over_commit) def check_can_live_migrate_source(self, ctxt, instance, dest_check_data): - if self.client.can_send_version('3.32'): + if self.client.can_send_version('4.0'): + version = '4.0' + elif self.client.can_send_version('3.32'): version = '3.32' else: version = '3.0' @@ -408,7 +426,9 @@ class ComputeAPI(object): dest_check_data=dest_check_data) def check_instance_shared_storage(self, ctxt, instance, data, host=None): - if self.client.can_send_version('3.29'): + if self.client.can_send_version('4.0'): + version = '4.0' + elif self.client.can_send_version('3.29'): version = '3.29' else: version = '3.0' @@ -421,7 +441,7 @@ class ComputeAPI(object): def confirm_resize(self, ctxt, instance, migration, host, reservations=None, cast=True): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=_compute_host(host, instance), version=version) rpc_method = cctxt.cast if cast else cctxt.call @@ -430,14 +450,16 @@ class ComputeAPI(object): reservations=reservations) def detach_interface(self, ctxt, instance, port_id): - version = '3.17' + version = self._compat_ver('4.0', '3.17') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'detach_interface', instance=instance, port_id=port_id) def detach_volume(self, ctxt, instance, volume_id): - if self.client.can_send_version('3.25'): + if self.client.can_send_version('4.0'): + version = '4.0' + elif self.client.can_send_version('3.25'): version = '3.25' else: version = '3.0' @@ -449,7 +471,7 @@ class ComputeAPI(object): def finish_resize(self, ctxt, instance, migration, image, disk_info, host, reservations=None): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=host, version=version) cctxt.cast(ctxt, 'finish_resize', instance=instance, migration=migration, @@ -457,14 +479,16 @@ class ComputeAPI(object): def finish_revert_resize(self, ctxt, instance, migration, host, reservations=None): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=host, version=version) cctxt.cast(ctxt, 'finish_revert_resize', instance=instance, migration=migration, reservations=reservations) def get_console_output(self, ctxt, instance, tail_length): - if self.client.can_send_version('3.28'): + if self.client.can_send_version('4.0'): + version = '4.0' + elif self.client.can_send_version('3.28'): version = '3.28' else: version = '3.0' @@ -475,18 +499,18 @@ class ComputeAPI(object): instance=instance, tail_length=tail_length) def get_console_pool_info(self, ctxt, console_type, host): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=host, version=version) return cctxt.call(ctxt, 'get_console_pool_info', console_type=console_type) def get_console_topic(self, ctxt, host): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=host, version=version) return cctxt.call(ctxt, 'get_console_topic') def get_diagnostics(self, ctxt, instance): - version = '3.18' + version = self._compat_ver('4.0', '3.18') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) return cctxt.call(ctxt, 'get_diagnostics', instance=instance) @@ -494,41 +518,41 @@ class ComputeAPI(object): def get_instance_diagnostics(self, ctxt, instance): instance_p = jsonutils.to_primitive(instance) kwargs = {'instance': instance_p} - version = '3.31' + version = self._compat_ver('4.0', '3.31') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) return cctxt.call(ctxt, 'get_instance_diagnostics', **kwargs) def get_vnc_console(self, ctxt, instance, console_type): - version = '3.2' + version = self._compat_ver('4.0', '3.2') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) return cctxt.call(ctxt, 'get_vnc_console', instance=instance, console_type=console_type) def get_spice_console(self, ctxt, instance, console_type): - version = '3.1' + version = self._compat_ver('4.0', '3.1') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) return cctxt.call(ctxt, 'get_spice_console', instance=instance, console_type=console_type) def get_rdp_console(self, ctxt, instance, console_type): - version = '3.10' + version = self._compat_ver('4.0', '3.10') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) return cctxt.call(ctxt, 'get_rdp_console', instance=instance, console_type=console_type) def get_serial_console(self, ctxt, instance, console_type): - version = '3.34' + version = self._compat_ver('4.0', '3.34') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) return cctxt.call(ctxt, 'get_serial_console', instance=instance, console_type=console_type) def validate_console_port(self, ctxt, instance, port, console_type): - version = '3.3' + version = self._compat_ver('4.0', '3.3') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) return cctxt.call(ctxt, 'validate_console_port', @@ -544,25 +568,27 @@ class ComputeAPI(object): :param mode: :param host: This is the host to send the message to. ''' - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=host, version=version) return cctxt.call(ctxt, 'host_maintenance_mode', host=host_param, mode=mode) def host_power_action(self, ctxt, action, host): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=host, version=version) return cctxt.call(ctxt, 'host_power_action', action=action) def inject_network_info(self, ctxt, instance): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'inject_network_info', instance=instance) def live_migration(self, ctxt, instance, dest, block_migration, host, migrate_data=None): - if self.client.can_send_version('3.26'): + if self.client.can_send_version('4.0'): + version = '4.0' + elif self.client.can_send_version('3.26'): version = '3.26' else: version = '3.0' @@ -573,21 +599,21 @@ class ComputeAPI(object): migrate_data=migrate_data) def pause_instance(self, ctxt, instance): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'pause_instance', instance=instance) def post_live_migration_at_destination(self, ctxt, instance, block_migration, host): - version = '3.14' + version = self._compat_ver('4.0', '3.14') cctxt = self.client.prepare(server=host, version=version) cctxt.cast(ctxt, 'post_live_migration_at_destination', instance=instance, block_migration=block_migration) def pre_live_migration(self, ctxt, instance, block_migration, disk, host, migrate_data=None): - version = '3.19' + version = self._compat_ver('4.0', '3.19') cctxt = self.client.prepare(server=host, version=version) return cctxt.call(ctxt, 'pre_live_migration', instance=instance, @@ -608,8 +634,11 @@ class ComputeAPI(object): 'filter_properties': filter_properties, 'node': node, 'clean_shutdown': clean_shutdown} - version = '3.38' - if not self.client.can_send_version(version): + if self.client.can_send_version('4.0'): + version = '4.0' + elif self.client.can_send_version('3.38'): + version = '3.38' + else: del msg_args['clean_shutdown'] version = '3.0' cctxt = self.client.prepare(server=host, version=version) @@ -617,7 +646,7 @@ class ComputeAPI(object): def reboot_instance(self, ctxt, instance, block_device_info, reboot_type): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'reboot_instance', @@ -632,7 +661,7 @@ class ComputeAPI(object): # NOTE(danms): kwargs is only here for cells compatibility, don't # actually send it to compute extra = {'preserve_ephemeral': preserve_ephemeral} - version = '3.21' + version = self._compat_ver('4.0', '3.21') cctxt = self.client.prepare(server=_compute_host(host, instance), version=version) cctxt.cast(ctxt, 'rebuild_instance', @@ -644,7 +673,7 @@ class ComputeAPI(object): **extra) def refresh_provider_fw_rules(self, ctxt, host): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=host, version=version) cctxt.cast(ctxt, 'refresh_provider_fw_rules') @@ -658,21 +687,23 @@ class ComputeAPI(object): parameter for the remote method. :param host: This is the host to send the message to. ''' - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=host, version=version) cctxt.cast(ctxt, 'remove_aggregate_host', aggregate=aggregate, host=host_param, slave_info=slave_info) def remove_fixed_ip_from_instance(self, ctxt, instance, address): - version = '3.13' + version = self._compat_ver('4.0', '3.13') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'remove_fixed_ip_from_instance', instance=instance, address=address) def remove_volume_connection(self, ctxt, instance, volume_id, host): - if self.client.can_send_version('3.30'): + if self.client.can_send_version('4.0'): + version = '4.0' + elif self.client.can_send_version('3.30'): version = '3.30' else: version = '3.0' @@ -684,7 +715,11 @@ class ComputeAPI(object): def rescue_instance(self, ctxt, instance, rescue_password, rescue_image_ref=None, clean_shutdown=True): msg_args = {'rescue_password': rescue_password} - if self.client.can_send_version('3.37'): + if self.client.can_send_version('4.0'): + version = '4.0' + msg_args['clean_shutdown'] = clean_shutdown + msg_args['rescue_image_ref'] = rescue_image_ref + elif self.client.can_send_version('3.37'): version = '3.37' msg_args['clean_shutdown'] = clean_shutdown msg_args['rescue_image_ref'] = rescue_image_ref @@ -699,7 +734,7 @@ class ComputeAPI(object): cctxt.cast(ctxt, 'rescue_instance', **msg_args) def reset_network(self, ctxt, instance): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'reset_network', instance=instance) @@ -710,7 +745,10 @@ class ComputeAPI(object): msg_args = {'instance': instance, 'migration': migration, 'image': image, 'reservations': reservations, 'instance_type': instance_type_p} - if self.client.can_send_version('3.37'): + if self.client.can_send_version('4.0'): + version = '4.0' + msg_args['clean_shutdown'] = clean_shutdown + elif self.client.can_send_version('3.37'): version = '3.37' msg_args['clean_shutdown'] = clean_shutdown else: @@ -720,14 +758,14 @@ class ComputeAPI(object): cctxt.cast(ctxt, 'resize_instance', **msg_args) def resume_instance(self, ctxt, instance): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'resume_instance', instance=instance) def revert_resize(self, ctxt, instance, migration, host, reservations=None): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=_compute_host(host, instance), version=version) cctxt.cast(ctxt, 'revert_resize', @@ -737,7 +775,12 @@ class ComputeAPI(object): def rollback_live_migration_at_destination(self, ctxt, instance, host, destroy_disks=True, migrate_data=None): - if self.client.can_send_version('3.32'): + if self.client.can_send_version('4.0'): + version = '4.0' + extra = {'destroy_disks': destroy_disks, + 'migrate_data': migrate_data, + } + elif self.client.can_send_version('3.32'): version = '3.32' extra = {'destroy_disks': destroy_disks, 'migrate_data': migrate_data, @@ -750,42 +793,20 @@ class ComputeAPI(object): cctxt.cast(ctxt, 'rollback_live_migration_at_destination', instance=instance, **extra) - # NOTE(alaski): Remove this method when the scheduler rpc interface is - # bumped to 4.x as the only callers of this method will be removed. - def run_instance(self, ctxt, instance, host, request_spec, - filter_properties, requested_networks, - injected_files, admin_password, - is_first_time, node=None, legacy_bdm_in_spec=True): - if self.client.can_send_version('3.27'): - version = '3.27' - else: - version = '3.0' - instance = jsonutils.to_primitive(instance) - msg_kwargs = {'instance': instance, 'request_spec': request_spec, - 'filter_properties': filter_properties, - 'requested_networks': requested_networks, - 'injected_files': injected_files, - 'admin_password': admin_password, - 'is_first_time': is_first_time, 'node': node, - 'legacy_bdm_in_spec': legacy_bdm_in_spec} - - cctxt = self.client.prepare(server=host, version=version) - cctxt.cast(ctxt, 'run_instance', **msg_kwargs) - def set_admin_password(self, ctxt, instance, new_pass): - version = '3.8' + version = self._compat_ver('4.0', '3.8') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) return cctxt.call(ctxt, 'set_admin_password', instance=instance, new_pass=new_pass) def set_host_enabled(self, ctxt, enabled, host): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=host, version=version) return cctxt.call(ctxt, 'set_host_enabled', enabled=enabled) def swap_volume(self, ctxt, instance, old_volume_id, new_volume_id): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'swap_volume', @@ -793,7 +814,7 @@ class ComputeAPI(object): new_volume_id=new_volume_id) def get_host_uptime(self, ctxt, host): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=host, version=version) return cctxt.call(ctxt, 'get_host_uptime') @@ -802,7 +823,10 @@ class ComputeAPI(object): kw = {'instance': instance, 'device': device, 'volume_id': volume_id, 'disk_bus': disk_bus, 'device_type': device_type, 'return_bdm_object': True} - if self.client.can_send_version('3.35'): + if self.client.can_send_version('4.0'): + version = '4.0' + del kw['return_bdm_object'] + elif self.client.can_send_version('3.35'): version = '3.35' else: del kw['return_bdm_object'] @@ -818,7 +842,7 @@ class ComputeAPI(object): def backup_instance(self, ctxt, instance, image_id, backup_type, rotation): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'backup_instance', @@ -828,7 +852,7 @@ class ComputeAPI(object): rotation=rotation) def snapshot_instance(self, ctxt, instance, image_id): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'snapshot_instance', @@ -836,14 +860,17 @@ class ComputeAPI(object): image_id=image_id) def start_instance(self, ctxt, instance): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'start_instance', instance=instance) def stop_instance(self, ctxt, instance, do_cast=True, clean_shutdown=True): msg_args = {'instance': instance} - if self.client.can_send_version('3.37'): + if self.client.can_send_version('4.0'): + version = '4.0' + msg_args['clean_shutdown'] = clean_shutdown + elif self.client.can_send_version('3.37'): version = '3.37' msg_args['clean_shutdown'] = clean_shutdown else: @@ -854,13 +881,13 @@ class ComputeAPI(object): return rpc_method(ctxt, 'stop_instance', **msg_args) def suspend_instance(self, ctxt, instance): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'suspend_instance', instance=instance) def terminate_instance(self, ctxt, instance, bdms, reservations=None): - version = '3.22' + version = self._compat_ver('4.0', '3.22') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'terminate_instance', @@ -868,26 +895,26 @@ class ComputeAPI(object): reservations=reservations) def unpause_instance(self, ctxt, instance): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'unpause_instance', instance=instance) def unrescue_instance(self, ctxt, instance): - version = '3.11' + version = self._compat_ver('4.0', '3.11') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'unrescue_instance', instance=instance) def soft_delete_instance(self, ctxt, instance, reservations=None): - version = '3.0' + version = self._compat_ver('4.0', '3.0') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'soft_delete_instance', instance=instance, reservations=reservations) def restore_instance(self, ctxt, instance): - version = '3.20' + version = self._compat_ver('4.0', '3.20') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'restore_instance', instance=instance) @@ -895,7 +922,10 @@ class ComputeAPI(object): def shelve_instance(self, ctxt, instance, image_id=None, clean_shutdown=True): msg_args = {'instance': instance, 'image_id': image_id} - if self.client.can_send_version('3.37'): + if self.client.can_send_version('4.0'): + version = '4.0' + msg_args['clean_shutdown'] = clean_shutdown + elif self.client.can_send_version('3.37'): version = '3.37' msg_args['clean_shutdown'] = clean_shutdown else: @@ -907,7 +937,10 @@ class ComputeAPI(object): def shelve_offload_instance(self, ctxt, instance, clean_shutdown=True): msg_args = {'instance': instance} - if self.client.can_send_version('3.37'): + if self.client.can_send_version('4.0'): + version = '4.0' + msg_args['clean_shutdown'] = clean_shutdown + elif self.client.can_send_version('3.37'): version = '3.37' msg_args['clean_shutdown'] = clean_shutdown else: @@ -918,7 +951,7 @@ class ComputeAPI(object): def unshelve_instance(self, ctxt, instance, host, image=None, filter_properties=None, node=None): - version = '3.15' + version = self._compat_ver('4.0', '3.15') msg_kwargs = { 'instance': instance, 'image': image, @@ -930,7 +963,7 @@ class ComputeAPI(object): def volume_snapshot_create(self, ctxt, instance, volume_id, create_info): - version = '3.6' + version = self._compat_ver('4.0', '3.6') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'volume_snapshot_create', instance=instance, @@ -938,7 +971,7 @@ class ComputeAPI(object): def volume_snapshot_delete(self, ctxt, instance, volume_id, snapshot_id, delete_info): - version = '3.6' + version = self._compat_ver('4.0', '3.6') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'volume_snapshot_delete', instance=instance, @@ -948,7 +981,7 @@ class ComputeAPI(object): def external_instance_event(self, ctxt, instances, events): cctxt = self.client.prepare( server=_compute_host(None, instances[0]), - version='3.23') + version=self._compat_ver('4.0', '3.23')) cctxt.cast(ctxt, 'external_instance_event', instances=instances, events=events) @@ -957,7 +990,9 @@ class ComputeAPI(object): requested_networks=None, security_groups=None, block_device_mapping=None, node=None, limits=None): - version = '3.40' + version = '4.0' + if not self.client.can_send_version(version): + version = '3.40' if not self.client.can_send_version(version): version = '3.36' if 'numa_topology' in limits and limits['numa_topology']: @@ -1005,13 +1040,13 @@ class ComputeAPI(object): limits=limits) def quiesce_instance(self, ctxt, instance): - version = '3.39' + version = self._compat_ver('4.0', '3.39') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) return cctxt.call(ctxt, 'quiesce_instance', instance=instance) def unquiesce_instance(self, ctxt, instance, mapping=None): - version = '3.39' + version = self._compat_ver('4.0', '3.39') cctxt = self.client.prepare(server=_compute_host(None, instance), version=version) cctxt.cast(ctxt, 'unquiesce_instance', instance=instance, diff --git a/nova/tests/unit/compute/test_rpcapi.py b/nova/tests/unit/compute/test_rpcapi.py index be9530bc8a01..eca124d7ad0f 100644 --- a/nova/tests/unit/compute/test_rpcapi.py +++ b/nova/tests/unit/compute/test_rpcapi.py @@ -63,7 +63,12 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): self.assertEqual(rpcapi.client.target.topic, CONF.compute_topic) orig_prepare = rpcapi.client.prepare - expected_version = kwargs.pop('version', rpcapi.client.target.version) + # TODO(danms): Remove this special case when we drop 3.x + if CONF.upgrade_levels.compute == 'kilo': + base_version = '3.0' + else: + base_version = rpcapi.client.target.version + expected_version = kwargs.pop('version', base_version) nova_network = kwargs.pop('nova_network', False) expected_kwargs = kwargs.copy() @@ -89,6 +94,11 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): kwargs.pop('legacy_limits', None) expected_kwargs.pop('destination', None) + if 'mountpoint' in expected_kwargs and expected_version == '4.0': + # TODO(danms): Remove me when we drop 3.x + del expected_kwargs['mountpoint'] + del expected_kwargs['volume_id'] + if assert_dict: expected_kwargs['instance'] = jsonutils.to_primitive( expected_kwargs['instance']) @@ -116,7 +126,10 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): rpc_mock, prepare_mock, csv_mock ): prepare_mock.return_value = rpcapi.client - if 'return_bdm_object' in kwargs: + if '_return_value' in kwargs: + rpc_mock.return_value = kwargs.pop('_return_value') + del expected_kwargs['_return_value'] + elif 'return_bdm_object' in kwargs: del kwargs['return_bdm_object'] rpc_mock.return_value = objects_block_dev.BlockDeviceMapping() elif rpc_method == 'call': @@ -138,27 +151,57 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): aggregate={'id': 'fake_id'}, host_param='host', host='host', slave_info={}) + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('add_aggregate_host', 'cast', + aggregate={'id': 'fake_id'}, host_param='host', host='host', + slave_info={}, version='3.0') + def test_add_fixed_ip_to_instance(self): + self._test_compute_api('add_fixed_ip_to_instance', 'cast', + instance=self.fake_instance_obj, network_id='id', + version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('add_fixed_ip_to_instance', 'cast', instance=self.fake_instance_obj, network_id='id', version='3.12') def test_attach_interface(self): + self._test_compute_api('attach_interface', 'call', + instance=self.fake_instance_obj, network_id='id', + port_id='id2', version='4.0', requested_ip='192.168.1.50') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('attach_interface', 'call', instance=self.fake_instance_obj, network_id='id', port_id='id2', version='3.17', requested_ip='192.168.1.50') def test_attach_volume(self): + self._test_compute_api('attach_volume', 'cast', + instance=self.fake_instance_obj, volume_id='id', + mountpoint='mp', bdm=self.fake_volume_bdm, version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('attach_volume', 'cast', instance=self.fake_instance_obj, volume_id='id', mountpoint='mp', bdm=self.fake_volume_bdm, version='3.16') def test_change_instance_metadata(self): + self._test_compute_api('change_instance_metadata', 'cast', + instance=self.fake_instance_obj, diff={}, version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('change_instance_metadata', 'cast', instance=self.fake_instance_obj, diff={}, version='3.7') @mock.patch('nova.compute.rpcapi.ComputeAPI._warn_buggy_live_migrations') def test_check_can_live_migrate_destination(self, mock_warn): + self._test_compute_api('check_can_live_migrate_destination', 'call', + instance=self.fake_instance_obj, + destination='dest', block_migration=True, + disk_over_commit=True, version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('check_can_live_migrate_destination', 'call', instance=self.fake_instance_obj, destination='dest', block_migration=True, @@ -176,6 +219,11 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): @mock.patch('nova.compute.rpcapi.ComputeAPI._warn_buggy_live_migrations') def test_check_can_live_migrate_source(self, mock_warn): + self._test_compute_api('check_can_live_migrate_source', 'call', + instance=self.fake_instance_obj, + dest_check_data={"test": "data"}, version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('check_can_live_migrate_source', 'call', instance=self.fake_instance_obj, dest_check_data={"test": "data"}, version='3.32') @@ -190,6 +238,11 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): mock_warn.assert_called_once_with() def test_check_instance_shared_storage(self): + self._test_compute_api('check_instance_shared_storage', 'call', + instance=self.fake_instance_obj, data='foo', + version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('check_instance_shared_storage', 'call', instance=self.fake_instance_obj, data='foo', version='3.29') @@ -199,17 +252,37 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): instance=self.fake_instance_obj, migration={'id': 'foo'}, host='host', reservations=list('fake_res')) + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('confirm_resize', 'cast', + instance=self.fake_instance_obj, migration={'id': 'foo'}, + host='host', reservations=list('fake_res')) + def test_confirm_resize_call(self): self._test_compute_api('confirm_resize', 'call', instance=self.fake_instance_obj, migration={'id': 'foo'}, host='host', reservations=list('fake_res')) + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('confirm_resize', 'call', + instance=self.fake_instance_obj, migration={'id': 'foo'}, + host='host', reservations=list('fake_res')) + def test_detach_interface(self): + self._test_compute_api('detach_interface', 'cast', + version='4.0', instance=self.fake_instance_obj, + port_id='fake_id') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('detach_interface', 'cast', version='3.17', instance=self.fake_instance_obj, port_id='fake_id') def test_detach_volume(self): + self._test_compute_api('detach_volume', 'cast', + instance=self.fake_instance_obj, volume_id='id', + version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('detach_volume', 'cast', instance=self.fake_instance_obj, volume_id='id', version='3.25') @@ -220,12 +293,28 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): image='image', disk_info='disk_info', host='host', reservations=list('fake_res')) + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('finish_resize', 'cast', + instance=self.fake_instance_obj, migration={'id': 'foo'}, + image='image', disk_info='disk_info', host='host', + reservations=list('fake_res')) + def test_finish_revert_resize(self): self._test_compute_api('finish_revert_resize', 'cast', instance=self.fake_instance_obj, migration={'id': 'fake_id'}, host='host', reservations=list('fake_res')) + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('finish_revert_resize', 'cast', + instance=self.fake_instance_obj, migration={'id': 'fake_id'}, + host='host', reservations=list('fake_res')) + def test_get_console_output(self): + self._test_compute_api('get_console_output', 'call', + instance=self.fake_instance_obj, tail_length='tl', + version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('get_console_output', 'call', instance=self.fake_instance_obj, tail_length='tl', version='3.28') @@ -234,39 +323,80 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): self._test_compute_api('get_console_pool_info', 'call', console_type='type', host='host') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('get_console_pool_info', 'call', + console_type='type', host='host') + def test_get_console_topic(self): self._test_compute_api('get_console_topic', 'call', host='host') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('get_console_topic', 'call', host='host') + def test_get_diagnostics(self): + self._test_compute_api('get_diagnostics', 'call', + instance=self.fake_instance_obj, version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('get_diagnostics', 'call', instance=self.fake_instance_obj, version='3.18') def test_get_instance_diagnostics(self): + self._test_compute_api('get_instance_diagnostics', 'call', + assert_dict=True, instance=self.fake_instance_obj, + version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('get_instance_diagnostics', 'call', assert_dict=True, instance=self.fake_instance_obj, version='3.31') def test_get_vnc_console(self): + self._test_compute_api('get_vnc_console', 'call', + instance=self.fake_instance_obj, console_type='type', + version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('get_vnc_console', 'call', instance=self.fake_instance_obj, console_type='type', version='3.2') def test_get_spice_console(self): + self._test_compute_api('get_spice_console', 'call', + instance=self.fake_instance_obj, console_type='type', + version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('get_spice_console', 'call', instance=self.fake_instance_obj, console_type='type', version='3.1') def test_get_rdp_console(self): + self._test_compute_api('get_rdp_console', 'call', + instance=self.fake_instance_obj, console_type='type', + version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('get_rdp_console', 'call', instance=self.fake_instance_obj, console_type='type', version='3.10') def test_get_serial_console(self): + self._test_compute_api('get_serial_console', 'call', + instance=self.fake_instance_obj, console_type='serial', + version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('get_serial_console', 'call', instance=self.fake_instance_obj, console_type='serial', version='3.34') def test_validate_console_port(self): + self._test_compute_api('validate_console_port', 'call', + instance=self.fake_instance_obj, port="5900", + console_type="novnc", version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('validate_console_port', 'call', instance=self.fake_instance_obj, port="5900", console_type="novnc", version='3.3') @@ -275,21 +405,44 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): self._test_compute_api('host_maintenance_mode', 'call', host_param='param', mode='mode', host='host') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('host_maintenance_mode', 'call', + host_param='param', mode='mode', host='host') + def test_host_power_action(self): self._test_compute_api('host_power_action', 'call', action='action', host='host') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('host_power_action', 'call', action='action', + host='host') + def test_inject_network_info(self): self._test_compute_api('inject_network_info', 'cast', instance=self.fake_instance_obj) + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('inject_network_info', 'cast', + instance=self.fake_instance_obj) + def test_live_migration(self): + self._test_compute_api('live_migration', 'cast', + instance=self.fake_instance_obj, dest='dest', + block_migration='blockity_block', host='tsoh', + migrate_data={}, version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('live_migration', 'cast', instance=self.fake_instance_obj, dest='dest', block_migration='blockity_block', host='tsoh', migrate_data={}, version='3.26') def test_post_live_migration_at_destination(self): + self._test_compute_api('post_live_migration_at_destination', 'cast', + instance=self.fake_instance_obj, + block_migration='block_migration', host='host', version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('post_live_migration_at_destination', 'cast', instance=self.fake_instance_obj, block_migration='block_migration', host='host', version='3.14') @@ -298,27 +451,59 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): self._test_compute_api('pause_instance', 'cast', instance=self.fake_instance_obj) + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('pause_instance', 'cast', + instance=self.fake_instance_obj) + def test_soft_delete_instance(self): self._test_compute_api('soft_delete_instance', 'cast', instance=self.fake_instance_obj, reservations=['uuid1', 'uuid2']) + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('soft_delete_instance', 'cast', + instance=self.fake_instance_obj, + reservations=['uuid1', 'uuid2']) + def test_swap_volume(self): self._test_compute_api('swap_volume', 'cast', instance=self.fake_instance_obj, old_volume_id='oldid', new_volume_id='newid') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('swap_volume', 'cast', + instance=self.fake_instance_obj, old_volume_id='oldid', + new_volume_id='newid') + def test_restore_instance(self): + self._test_compute_api('restore_instance', 'cast', + instance=self.fake_instance_obj, version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('restore_instance', 'cast', instance=self.fake_instance_obj, version='3.20') def test_pre_live_migration(self): + self._test_compute_api('pre_live_migration', 'call', + instance=self.fake_instance_obj, + block_migration='block_migration', disk='disk', host='host', + migrate_data=None, version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('pre_live_migration', 'call', instance=self.fake_instance_obj, block_migration='block_migration', disk='disk', host='host', migrate_data=None, version='3.19') def test_prep_resize(self): + self._test_compute_api('prep_resize', 'cast', + instance=self.fake_instance_obj, instance_type='fake_type', + image='fake_image', host='host', + reservations=list('fake_res'), + request_spec='fake_spec', + filter_properties={'fakeprop': 'fakeval'}, + node='node', clean_shutdown=True, version='4.0') + self.flags(compute='3.0', group='upgrade_levels') self._test_compute_api('prep_resize', 'cast', instance=self.fake_instance_obj, instance_type='fake_type', @@ -335,6 +520,14 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): request_spec='fake_spec', filter_properties={'fakeprop': 'fakeval'}, node='node', clean_shutdown=True, version='3.38') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('prep_resize', 'cast', + instance=self.fake_instance_obj, instance_type='fake_type', + image='fake_image', host='host', + reservations=list('fake_res'), + request_spec='fake_spec', + filter_properties={'fakeprop': 'fakeval'}, + node='node', clean_shutdown=True, version='3.38') def test_reboot_instance(self): self.maxDiff = None @@ -343,7 +536,20 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): block_device_info={}, reboot_type='type') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('reboot_instance', 'cast', + instance=self.fake_instance_obj, + block_device_info={}, + reboot_type='type') + def test_rebuild_instance(self): + self._test_compute_api('rebuild_instance', 'cast', new_pass='None', + injected_files='None', image_ref='None', orig_image_ref='None', + bdms=[], instance=self.fake_instance_obj, host='new_host', + orig_sys_metadata=None, recreate=True, on_shared_storage=True, + preserve_ephemeral=True, version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('rebuild_instance', 'cast', new_pass='None', injected_files='None', image_ref='None', orig_image_ref='None', bdms=[], instance=self.fake_instance_obj, host='new_host', @@ -351,6 +557,13 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): preserve_ephemeral=True, version='3.21') def test_reserve_block_device_name(self): + self._test_compute_api('reserve_block_device_name', 'call', + instance=self.fake_instance_obj, device='device', + volume_id='id', disk_bus='ide', device_type='cdrom', + version='4.0', + _return_value=objects_block_dev.BlockDeviceMapping()) + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('reserve_block_device_name', 'call', instance=self.fake_instance_obj, device='device', volume_id='id', disk_bus='ide', device_type='cdrom', @@ -360,32 +573,65 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): self._test_compute_api('refresh_provider_fw_rules', 'cast', host='host') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('refresh_provider_fw_rules', 'cast', + host='host') + def test_refresh_security_group_rules(self): self._test_compute_api('refresh_security_group_rules', 'cast', rpcapi_class=compute_rpcapi.SecurityGroupAPI, security_group_id='id', host='host') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('refresh_security_group_rules', 'cast', + rpcapi_class=compute_rpcapi.SecurityGroupAPI, + security_group_id='id', host='host') + def test_refresh_security_group_members(self): self._test_compute_api('refresh_security_group_members', 'cast', rpcapi_class=compute_rpcapi.SecurityGroupAPI, security_group_id='id', host='host') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('refresh_security_group_members', 'cast', + rpcapi_class=compute_rpcapi.SecurityGroupAPI, + security_group_id='id', host='host') + def test_remove_aggregate_host(self): self._test_compute_api('remove_aggregate_host', 'cast', aggregate={'id': 'fake_id'}, host_param='host', host='host', slave_info={}) + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('remove_aggregate_host', 'cast', + aggregate={'id': 'fake_id'}, host_param='host', host='host', + slave_info={}) + def test_remove_fixed_ip_from_instance(self): + self._test_compute_api('remove_fixed_ip_from_instance', 'cast', + instance=self.fake_instance_obj, address='addr', + version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('remove_fixed_ip_from_instance', 'cast', instance=self.fake_instance_obj, address='addr', version='3.13') def test_remove_volume_connection(self): + self._test_compute_api('remove_volume_connection', 'call', + instance=self.fake_instance, volume_id='id', host='host', + version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('remove_volume_connection', 'call', instance=self.fake_instance, volume_id='id', host='host', version='3.30') def test_rescue_instance(self): + self._test_compute_api('rescue_instance', 'cast', + instance=self.fake_instance_obj, rescue_password='pw', + rescue_image_ref='fake_image_ref', + clean_shutdown=True, version='4.0') self.flags(compute='3.9', group='upgrade_levels') self._test_compute_api('rescue_instance', 'cast', instance=self.fake_instance_obj, rescue_password='pw', @@ -399,12 +645,26 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): instance=self.fake_instance_obj, rescue_password='pw', rescue_image_ref='fake_image_ref', clean_shutdown=True, version='3.37') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('rescue_instance', 'cast', + instance=self.fake_instance_obj, rescue_password='pw', + rescue_image_ref='fake_image_ref', + clean_shutdown=True, version='3.37') def test_reset_network(self): self._test_compute_api('reset_network', 'cast', instance=self.fake_instance_obj) + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('reset_network', 'cast', + instance=self.fake_instance_obj) + def test_resize_instance(self): + self._test_compute_api('resize_instance', 'cast', + instance=self.fake_instance_obj, migration={'id': 'fake_id'}, + image='image', instance_type={'id': 1}, + reservations=list('fake_res'), + clean_shutdown=True, version='4.0') self.flags(compute='3.0', group='upgrade_levels') self._test_compute_api('resize_instance', 'cast', instance=self.fake_instance_obj, migration={'id': 'fake_id'}, @@ -416,18 +676,38 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): image='image', instance_type={'id': 1}, reservations=list('fake_res'), clean_shutdown=True, version='3.37') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('resize_instance', 'cast', + instance=self.fake_instance_obj, migration={'id': 'fake_id'}, + image='image', instance_type={'id': 1}, + reservations=list('fake_res'), + clean_shutdown=True, version='3.37') def test_resume_instance(self): self._test_compute_api('resume_instance', 'cast', instance=self.fake_instance_obj) + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('resume_instance', 'cast', + instance=self.fake_instance_obj) + def test_revert_resize(self): self._test_compute_api('revert_resize', 'cast', instance=self.fake_instance_obj, migration={'id': 'fake_id'}, host='host', reservations=list('fake_res')) + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('revert_resize', 'cast', + instance=self.fake_instance_obj, migration={'id': 'fake_id'}, + host='host', reservations=list('fake_res')) + @mock.patch('nova.compute.rpcapi.ComputeAPI._warn_buggy_live_migrations') def test_rollback_live_migration_at_destination(self, mock_warn): + self._test_compute_api('rollback_live_migration_at_destination', + 'cast', instance=self.fake_instance_obj, host='host', + destroy_disks=True, migrate_data=None, version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('rollback_live_migration_at_destination', 'cast', instance=self.fake_instance_obj, host='host', destroy_disks=True, migrate_data=None, version='3.32') @@ -442,15 +722,12 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): version='3.0') mock_warn.assert_called_once_with(None) - def test_run_instance(self): - self._test_compute_api('run_instance', 'cast', - instance=self.fake_instance_obj, host='fake_host', - request_spec='fake_spec', filter_properties={}, - requested_networks='networks', injected_files='files', - admin_password='pw', is_first_time=True, node='node', - legacy_bdm_in_spec=False, version='3.27') - def test_set_admin_password(self): + self._test_compute_api('set_admin_password', 'call', + instance=self.fake_instance_obj, new_pass='pw', + version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('set_admin_password', 'call', instance=self.fake_instance_obj, new_pass='pw', version='3.8') @@ -459,23 +736,46 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): self._test_compute_api('set_host_enabled', 'call', enabled='enabled', host='host') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('set_host_enabled', 'call', + enabled='enabled', host='host') + def test_get_host_uptime(self): self._test_compute_api('get_host_uptime', 'call', host='host') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('get_host_uptime', 'call', host='host') + def test_backup_instance(self): self._test_compute_api('backup_instance', 'cast', instance=self.fake_instance_obj, image_id='id', backup_type='type', rotation='rotation') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('backup_instance', 'cast', + instance=self.fake_instance_obj, image_id='id', + backup_type='type', rotation='rotation') + def test_snapshot_instance(self): self._test_compute_api('snapshot_instance', 'cast', instance=self.fake_instance_obj, image_id='id') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('snapshot_instance', 'cast', + instance=self.fake_instance_obj, image_id='id') + def test_start_instance(self): self._test_compute_api('start_instance', 'cast', instance=self.fake_instance_obj) + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('start_instance', 'cast', + instance=self.fake_instance_obj) + def test_stop_instance_cast(self): + self._test_compute_api('stop_instance', 'cast', + instance=self.fake_instance_obj, + clean_shutdown=True, version='4.0') self.flags(compute='3.0', group='upgrade_levels') self._test_compute_api('stop_instance', 'cast', instance=self.fake_instance_obj, version='3.0') @@ -483,8 +783,15 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): self._test_compute_api('stop_instance', 'cast', instance=self.fake_instance_obj, clean_shutdown=True, version='3.37') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('stop_instance', 'cast', + instance=self.fake_instance_obj, + clean_shutdown=True, version='3.37') def test_stop_instance_call(self): + self._test_compute_api('stop_instance', 'call', + instance=self.fake_instance_obj, + clean_shutdown=True, version='4.0') self.flags(compute='3.0', group='upgrade_levels') self._test_compute_api('stop_instance', 'call', instance=self.fake_instance_obj, version='3.0') @@ -492,12 +799,25 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): self._test_compute_api('stop_instance', 'call', instance=self.fake_instance_obj, clean_shutdown=True, version='3.37') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('stop_instance', 'call', + instance=self.fake_instance_obj, + clean_shutdown=True, version='3.37') def test_suspend_instance(self): self._test_compute_api('suspend_instance', 'cast', instance=self.fake_instance_obj) + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('suspend_instance', 'cast', + instance=self.fake_instance_obj) + def test_terminate_instance(self): + self._test_compute_api('terminate_instance', 'cast', + instance=self.fake_instance_obj, bdms=[], + reservations=['uuid1', 'uuid2'], version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('terminate_instance', 'cast', instance=self.fake_instance_obj, bdms=[], reservations=['uuid1', 'uuid2'], version='3.22') @@ -506,11 +826,22 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): self._test_compute_api('unpause_instance', 'cast', instance=self.fake_instance_obj) + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('unpause_instance', 'cast', + instance=self.fake_instance_obj) + def test_unrescue_instance(self): + self._test_compute_api('unrescue_instance', 'cast', + instance=self.fake_instance_obj, version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('unrescue_instance', 'cast', instance=self.fake_instance_obj, version='3.11') def test_shelve_instance(self): + self._test_compute_api('shelve_instance', 'cast', + instance=self.fake_instance_obj, image_id='image_id', + clean_shutdown=True, version='4.0') self.flags(compute='3.0', group='upgrade_levels') self._test_compute_api('shelve_instance', 'cast', instance=self.fake_instance_obj, image_id='image_id', @@ -519,8 +850,15 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): self._test_compute_api('shelve_instance', 'cast', instance=self.fake_instance_obj, image_id='image_id', clean_shutdown=True, version='3.37') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('shelve_instance', 'cast', + instance=self.fake_instance_obj, image_id='image_id', + clean_shutdown=True, version='3.37') def test_shelve_offload_instance(self): + self._test_compute_api('shelve_offload_instance', 'cast', + instance=self.fake_instance_obj, + clean_shutdown=True, version='4.0') self.flags(compute='3.0', group='upgrade_levels') self._test_compute_api('shelve_offload_instance', 'cast', instance=self.fake_instance_obj, @@ -529,30 +867,65 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): self._test_compute_api('shelve_offload_instance', 'cast', instance=self.fake_instance_obj, clean_shutdown=True, version='3.37') + self.flags(compute='kilo', group='upgrade_levels') + self._test_compute_api('shelve_offload_instance', 'cast', + instance=self.fake_instance_obj, + clean_shutdown=True, version='3.37') def test_unshelve_instance(self): + self._test_compute_api('unshelve_instance', 'cast', + instance=self.fake_instance_obj, host='host', image='image', + filter_properties={'fakeprop': 'fakeval'}, node='node', + version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('unshelve_instance', 'cast', instance=self.fake_instance_obj, host='host', image='image', filter_properties={'fakeprop': 'fakeval'}, node='node', version='3.15') def test_volume_snapshot_create(self): + self._test_compute_api('volume_snapshot_create', 'cast', + instance=self.fake_instance_obj, volume_id='fake_id', + create_info={}, version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('volume_snapshot_create', 'cast', instance=self.fake_instance_obj, volume_id='fake_id', create_info={}, version='3.6') def test_volume_snapshot_delete(self): + self._test_compute_api('volume_snapshot_delete', 'cast', + instance=self.fake_instance_obj, volume_id='fake_id', + snapshot_id='fake_id2', delete_info={}, version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('volume_snapshot_delete', 'cast', instance=self.fake_instance_obj, volume_id='fake_id', snapshot_id='fake_id2', delete_info={}, version='3.6') def test_external_instance_event(self): + self._test_compute_api('external_instance_event', 'cast', + instances=[self.fake_instance_obj], + events=['event'], + version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('external_instance_event', 'cast', instances=[self.fake_instance_obj], events=['event'], version='3.23') def test_build_and_run_instance(self): + self._test_compute_api('build_and_run_instance', 'cast', + instance=self.fake_instance_obj, host='host', image='image', + request_spec={'request': 'spec'}, filter_properties=[], + admin_password='passwd', injected_files=None, + requested_networks=['network1'], security_groups=None, + block_device_mapping=None, node='node', limits=[], + version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('build_and_run_instance', 'cast', instance=self.fake_instance_obj, host='host', image='image', request_spec={'request': 'spec'}, filter_properties=[], @@ -591,10 +964,18 @@ class ComputeRpcAPITestCase(test.NoDBTestCase): version='3.23', nova_network=True) def test_quiesce_instance(self): + self._test_compute_api('quiesce_instance', 'call', + instance=self.fake_instance_obj, version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('quiesce_instance', 'call', instance=self.fake_instance_obj, version='3.39') def test_unquiesce_instance(self): + self._test_compute_api('unquiesce_instance', 'cast', + instance=self.fake_instance_obj, mapping=None, version='4.0') + + self.flags(compute='kilo', group='upgrade_levels') self._test_compute_api('unquiesce_instance', 'cast', instance=self.fake_instance_obj, mapping=None, version='3.39')