diff --git a/coriolis/api-refs/source/endpoint.inc b/coriolis/api-refs/source/endpoint.inc index 7db727b65..943fa8c2c 100644 --- a/coriolis/api-refs/source/endpoint.inc +++ b/coriolis/api-refs/source/endpoint.inc @@ -251,6 +251,7 @@ Request .. rest_parameters:: parameters.yaml - endpoint_id : endpoint_id_path + - refresh : instance_refresh Response -------- diff --git a/coriolis/api-refs/source/parameters.yaml b/coriolis/api-refs/source/parameters.yaml index 869d2dc0c..9fef155a1 100644 --- a/coriolis/api-refs/source/parameters.yaml +++ b/coriolis/api-refs/source/parameters.yaml @@ -87,6 +87,15 @@ instance_limit: in: query required: false type: integer +instance_refresh: + description: | + When set to true, forces a refresh of any cached instance data from the + source platform. This is useful when the instance list may have changed + and you want to ensure fresh data is retrieved. + in: query + required: false + type: boolean + default: false show_deleted: description: | Whether to include deleted resources in the response. diff --git a/coriolis/api/v1/endpoint_instances.py b/coriolis/api/v1/endpoint_instances.py index c70622e72..cc327dd32 100644 --- a/coriolis/api/v1/endpoint_instances.py +++ b/coriolis/api/v1/endpoint_instances.py @@ -24,6 +24,7 @@ def index(self, req, endpoint_id): endpoint_policies.ENDPOINTS_POLICY_PREFIX)) marker, limit = common.get_paging_params(req) instance_name_pattern = req.GET.get("name") + refresh = req.GET.get("refresh", "false").lower() == "true" env = req.GET.get("env") if env is not None: @@ -34,7 +35,7 @@ def index(self, req, endpoint_id): return endpoint_resources_view.instances_collection( self._instance_api.get_endpoint_instances( context, endpoint_id, env, marker, limit, - instance_name_pattern)) + instance_name_pattern, refresh=refresh)) def show(self, req, endpoint_id, id): context = req.environ['coriolis.context'] diff --git a/coriolis/conductor/rpc/client.py b/coriolis/conductor/rpc/client.py index da71cd27b..dabf2bbec 100644 --- a/coriolis/conductor/rpc/client.py +++ b/coriolis/conductor/rpc/client.py @@ -58,14 +58,15 @@ def delete_endpoint(self, ctxt, endpoint_id): def get_endpoint_instances(self, ctxt, endpoint_id, source_environment, marker=None, limit=None, - instance_name_pattern=None): + instance_name_pattern=None, refresh=False): return self._call( ctxt, 'get_endpoint_instances', endpoint_id=endpoint_id, source_environment=source_environment, marker=marker, limit=limit, - instance_name_pattern=instance_name_pattern) + instance_name_pattern=instance_name_pattern, + refresh=refresh) def get_endpoint_instance( self, ctxt, endpoint_id, source_environment, instance_name): diff --git a/coriolis/conductor/rpc/server.py b/coriolis/conductor/rpc/server.py index 221390c7f..0158f7a0a 100644 --- a/coriolis/conductor/rpc/server.py +++ b/coriolis/conductor/rpc/server.py @@ -493,7 +493,8 @@ def delete_endpoint(self, ctxt, endpoint_id): db_api.delete_endpoint(ctxt, endpoint_id) def get_endpoint_instances(self, ctxt, endpoint_id, source_environment, - marker, limit, instance_name_pattern): + marker, limit, instance_name_pattern, + refresh=False): endpoint = self.get_endpoint(ctxt, endpoint_id) worker_rpc = self._get_worker_service_rpc_for_specs( @@ -503,7 +504,8 @@ def get_endpoint_instances(self, ctxt, endpoint_id, source_environment, endpoint.type: [constants.PROVIDER_TYPE_ENDPOINT_INSTANCES]}) return worker_rpc.get_endpoint_instances( ctxt, endpoint.type, endpoint.connection_info, - source_environment, marker, limit, instance_name_pattern) + source_environment, marker, limit, instance_name_pattern, + refresh=refresh) def get_endpoint_instance( self, ctxt, endpoint_id, source_environment, instance_name): diff --git a/coriolis/endpoint_resources/api.py b/coriolis/endpoint_resources/api.py index 3f32ab150..ee2364b83 100644 --- a/coriolis/endpoint_resources/api.py +++ b/coriolis/endpoint_resources/api.py @@ -10,10 +10,10 @@ def __init__(self): def get_endpoint_instances(self, ctxt, endpoint_id, source_environment, marker=None, limit=None, - instance_name_pattern=None): + instance_name_pattern=None, refresh=False): return self._rpc_client.get_endpoint_instances( ctxt, endpoint_id, source_environment, marker, - limit, instance_name_pattern) + limit, instance_name_pattern, refresh=refresh) def get_endpoint_instance( self, ctxt, endpoint_id, source_environment, instance_name): diff --git a/coriolis/providers/base.py b/coriolis/providers/base.py index d9190a3dc..8f39d2211 100644 --- a/coriolis/providers/base.py +++ b/coriolis/providers/base.py @@ -36,8 +36,11 @@ class BaseEndpointInstancesProvider(BaseEndpointProvider): @abc.abstractmethod def get_instances(self, ctxt, connection_info, source_environment, limit=None, last_seen_id=None, - instance_name_pattern=None): - """Returns a list of instances.""" + instance_name_pattern=None, refresh=False): + """Returns a list of instances. + + :param refresh: If True, forces a refresh of any cached instance data. + """ raise NotImplementedError() @abc.abstractmethod diff --git a/coriolis/tests/api/v1/test_endpoint_instances.py b/coriolis/tests/api/v1/test_endpoint_instances.py index 0fe373278..181384e64 100644 --- a/coriolis/tests/api/v1/test_endpoint_instances.py +++ b/coriolis/tests/api/v1/test_endpoint_instances.py @@ -52,7 +52,7 @@ def test_index( mock_get_endpoint_instances.assert_called_once_with( mock_context, endpoint_id, mock_decode_base64_param.return_value, - marker, limit, instance_name_pattern) + marker, limit, instance_name_pattern, refresh=False) mock_instances_collection.assert_called_once_with( mock_get_endpoint_instances.return_value) self.assertEqual( @@ -84,7 +84,7 @@ def test_index_no_env_and_options( mock_decode_base64_param.assert_not_called() mock_get_endpoint_instances.assert_called_once_with( mock_context, endpoint_id, - {}, None, None, None) + {}, None, None, None, refresh=False) mock_instances_collection.assert_called_once_with( mock_get_endpoint_instances.return_value) self.assertEqual( diff --git a/coriolis/tests/conductor/rpc/test_client.py b/coriolis/tests/conductor/rpc/test_client.py index 6bcfd0b15..2fc6084b5 100644 --- a/coriolis/tests/conductor/rpc/test_client.py +++ b/coriolis/tests/conductor/rpc/test_client.py @@ -76,7 +76,8 @@ def test_get_endpoint_instances(self): "source_environment": "mock_source_environment", "marker": None, "limit": None, - "instance_name_pattern": None + "instance_name_pattern": None, + "refresh": False } self._test(self.client.get_endpoint_instances, args) diff --git a/coriolis/tests/conductor/rpc/test_server.py b/coriolis/tests/conductor/rpc/test_server.py index 20ab42dde..2de7bda79 100644 --- a/coriolis/tests/conductor/rpc/test_server.py +++ b/coriolis/tests/conductor/rpc/test_server.py @@ -303,6 +303,7 @@ def test_get_endpoint_instances( mock.sentinel.marker, mock.sentinel.limit, mock.sentinel.instance_name_pattern, + mock.sentinel.refresh, ) mock_get_endpoint.assert_called_once_with( diff --git a/coriolis/tests/endpoint_resources/test_api.py b/coriolis/tests/endpoint_resources/test_api.py index 2e7de10e2..9504fa3f8 100644 --- a/coriolis/tests/endpoint_resources/test_api.py +++ b/coriolis/tests/endpoint_resources/test_api.py @@ -26,7 +26,8 @@ def test_get_endpoint_instances(self): source_environment=mock.sentinel.source_environment, marker=mock.sentinel.marker, limit=mock.sentinel.limit, - instance_name_pattern=mock.sentinel.instance_name_pattern + instance_name_pattern=mock.sentinel.instance_name_pattern, + refresh=mock.sentinel.refresh ) (self.endpoint_resources_api._rpc_client. get_endpoint_instances.assert_called_once_with)( @@ -34,7 +35,8 @@ def test_get_endpoint_instances(self): mock.sentinel.source_environment, mock.sentinel.marker, mock.sentinel.limit, - mock.sentinel.instance_name_pattern + mock.sentinel.instance_name_pattern, + refresh=mock.sentinel.refresh ) self.assertEqual( (self.endpoint_resources_api._rpc_client. diff --git a/coriolis/tests/worker/rpc/test_client.py b/coriolis/tests/worker/rpc/test_client.py index d0e7bbca0..3b8e53b78 100644 --- a/coriolis/tests/worker/rpc/test_client.py +++ b/coriolis/tests/worker/rpc/test_client.py @@ -107,6 +107,7 @@ def test_get_endpoint_instances(self): 'marker': None, 'limit': None, 'instance_name_pattern': None, + 'refresh': False } self._test(self.client.get_endpoint_instances, args) diff --git a/coriolis/tests/worker/rpc/test_server.py b/coriolis/tests/worker/rpc/test_server.py index b38180cb1..20b32f4bf 100644 --- a/coriolis/tests/worker/rpc/test_server.py +++ b/coriolis/tests/worker/rpc/test_server.py @@ -554,6 +554,7 @@ def test_get_endpoint_instances( mock.sentinel.marker, mock.sentinel.limit, mock.sentinel.instance_name_pattern, + mock.sentinel.refresh, ) mock_get_provider.assert_called_once_with( @@ -571,6 +572,7 @@ def test_get_endpoint_instances( last_seen_id=mock.sentinel.marker, limit=mock.sentinel.limit, instance_name_pattern=mock.sentinel.instance_name_pattern, + refresh=mock.sentinel.refresh, ) # values are validated for each instance returned by the provider diff --git a/coriolis/worker/rpc/client.py b/coriolis/worker/rpc/client.py index 48d4fab47..cec7aa0c8 100644 --- a/coriolis/worker/rpc/client.py +++ b/coriolis/worker/rpc/client.py @@ -72,7 +72,7 @@ def cancel_task(self, ctxt, task_id, process_id, force): def get_endpoint_instances(self, ctxt, platform_name, connection_info, source_environment, marker=None, limit=None, - instance_name_pattern=None): + instance_name_pattern=None, refresh=False): return self._call( ctxt, 'get_endpoint_instances', platform_name=platform_name, @@ -80,7 +80,8 @@ def get_endpoint_instances(self, ctxt, platform_name, connection_info, source_environment=source_environment, marker=marker, limit=limit, - instance_name_pattern=instance_name_pattern) + instance_name_pattern=instance_name_pattern, + refresh=refresh) def get_endpoint_instance(self, ctxt, platform_name, connection_info, source_environment, instance_name): diff --git a/coriolis/worker/rpc/server.py b/coriolis/worker/rpc/server.py index 36fd514c5..19d9dbf35 100644 --- a/coriolis/worker/rpc/server.py +++ b/coriolis/worker/rpc/server.py @@ -334,7 +334,7 @@ def exec_task(self, ctxt, task_id, task_type, origin, destination, def get_endpoint_instances(self, ctxt, platform_name, connection_info, source_environment, marker, limit, - instance_name_pattern): + instance_name_pattern, refresh=False): export_provider = providers_factory.get_provider( platform_name, constants.PROVIDER_TYPE_ENDPOINT_INSTANCES, None) @@ -344,7 +344,7 @@ def get_endpoint_instances(self, ctxt, platform_name, connection_info, instances_info = export_provider.get_instances( ctxt, secret_connection_info, source_environment, last_seen_id=marker, limit=limit, - instance_name_pattern=instance_name_pattern) + instance_name_pattern=instance_name_pattern, refresh=refresh) for instance_info in instances_info: schemas.validate_value( instance_info, schemas.CORIOLIS_VM_INSTANCE_INFO_SCHEMA)