Sfoglia il codice sorgente

Adds endpoint connection validation API

Alessandro Pilotti 9 anni fa
parent
commit
f8c5ecdd75

+ 32 - 0
coriolis/api/v1/endpoint_actions.py

@@ -0,0 +1,32 @@
+# Copyright 2016 Cloudbase Solutions Srl
+# All Rights Reserved.
+
+from webob import exc
+
+from coriolis.api import wsgi as api_wsgi
+from coriolis import exception
+from coriolis.endpoints import api
+
+
+class EndpointActionsController(api_wsgi.Controller):
+    def __init__(self):
+        self._endpoint_api = api.API()
+        super(EndpointActionsController, self).__init__()
+
+    @api_wsgi.action('validate-connection')
+    def _cancel(self, req, id, body):
+        try:
+            is_valid, message = self._endpoint_api.validate_connection(
+                req.environ['coriolis.context'], id)
+            return {
+                "validate-connection":
+                    {"valid": is_valid, "message": message}
+            }
+        except exception.NotFound as ex:
+            raise exc.HTTPNotFound(explanation=ex.msg)
+        except exception.InvalidParameterValue as ex:
+            raise exc.HTTPNotFound(explanation=ex.msg)
+
+
+def create_resource():
+    return api_wsgi.Resource(EndpointActionsController())

+ 10 - 0
coriolis/api/v1/router.py

@@ -4,6 +4,7 @@
 from oslo_log import log as logging
 from oslo_log import log as logging
 
 
 from coriolis import api
 from coriolis import api
+from coriolis.api.v1 import endpoint_actions
 from coriolis.api.v1 import endpoints
 from coriolis.api.v1 import endpoints
 from coriolis.api.v1 import endpoint_instances
 from coriolis.api.v1 import endpoint_instances
 from coriolis.api.v1 import migrations
 from coriolis.api.v1 import migrations
@@ -36,6 +37,15 @@ class APIRouter(api.APIRouter):
                         collection={'detail': 'GET'},
                         collection={'detail': 'GET'},
                         member={'action': 'POST'})
                         member={'action': 'POST'})
 
 
+        endpoint_actions_resource = endpoint_actions.create_resource()
+        self.resources['endpoint_actions'] = endpoint_actions_resource
+        endpoint_path = '/{project_id}/endpoints/{id}'
+        mapper.connect('endpoint_actions',
+                       endpoint_path + '/actions',
+                       controller=self.resources['endpoint_actions'],
+                       action='action',
+                       conditions={'method': 'POST'})
+
         self.resources['endpoint_instances'] = \
         self.resources['endpoint_instances'] = \
             endpoint_instances.create_resource()
             endpoint_instances.create_resource()
         mapper.resource('instance', 'endpoints/{endpoint_id}/instances',
         mapper.resource('instance', 'endpoints/{endpoint_id}/instances',

+ 5 - 0
coriolis/conductor/rpc/client.py

@@ -40,6 +40,11 @@ class ConductorClient(object):
             limit=limit,
             limit=limit,
             instance_name_pattern=instance_name_pattern)
             instance_name_pattern=instance_name_pattern)
 
 
+    def validate_endpoint_connection(self, ctxt, endpoint_id):
+        return self._client.call(
+            ctxt, 'validate_endpoint_connection',
+            endpoint_id=endpoint_id)
+
     def execute_replica_tasks(self, ctxt, replica_id,
     def execute_replica_tasks(self, ctxt, replica_id,
                               shutdown_instances=False):
                               shutdown_instances=False):
         return self._client.call(
         return self._client.call(

+ 5 - 0
coriolis/conductor/rpc/server.py

@@ -108,6 +108,11 @@ class ConductorServerEndpoint(object):
             ctxt, endpoint.type, endpoint.connection_info, marker, limit,
             ctxt, endpoint.type, endpoint.connection_info, marker, limit,
             instance_name_pattern)
             instance_name_pattern)
 
 
+    def validate_endpoint_connection(self, ctxt, endpoint_id):
+        endpoint = self.get_endpoint(ctxt, endpoint_id)
+        return self._rpc_worker_client.validate_endpoint_connection(
+            ctxt, endpoint.type, endpoint.connection_info)
+
     @staticmethod
     @staticmethod
     def _create_task(instance, task_type, execution, depends_on=None,
     def _create_task(instance, task_type, execution, depends_on=None,
                      on_error=False):
                      on_error=False):

+ 4 - 0
coriolis/endpoints/api.py

@@ -21,3 +21,7 @@ class API(object):
 
 
     def get_endpoint(self, ctxt, endpoint_id):
     def get_endpoint(self, ctxt, endpoint_id):
         return self._rpc_client.get_endpoint(ctxt, endpoint_id)
         return self._rpc_client.get_endpoint(ctxt, endpoint_id)
+
+    def validate_connection(self, ctxt, endpoint_id):
+        return self._rpc_client.validate_endpoint_connection(
+            ctxt, endpoint_id)

+ 7 - 0
coriolis/worker/rpc/client.py

@@ -40,3 +40,10 @@ class WorkerClient(object):
             marker=marker,
             marker=marker,
             limit=limit,
             limit=limit,
             instance_name_pattern=instance_name_pattern)
             instance_name_pattern=instance_name_pattern)
+
+    def validate_endpoint_connection(self, ctxt, endpoint_type,
+                                     connection_info):
+        return self._client.call(
+            ctxt, 'validate_endpoint_connection',
+            endpoint_type=endpoint_type,
+            connection_info=connection_info)

+ 19 - 0
coriolis/worker/rpc/server.py

@@ -184,6 +184,25 @@ class WorkerServerEndpoint(object):
 
 
         return instances_info
         return instances_info
 
 
+    def validate_endpoint_connection(self, ctxt, endpoint_type,
+                                     connection_info):
+        provider = providers_factory.get_provider(
+            endpoint_type, constants.PROVIDER_TYPE_ENDPOINT, None)
+
+        secret_connection_info = utils.get_secret_connection_info(
+            ctxt, connection_info)
+
+        is_valid = True
+        message = None
+        try:
+            provider.validate_connection_info(
+                secret_connection_info)
+        except Exception as ex:
+            is_valid = False
+            message = str(ex)
+
+        return (is_valid, message)
+
 
 
 def _get_task_export_path(task_id, create=False):
 def _get_task_export_path(task_id, create=False):
     export_path = os.path.join(CONF.worker.export_base_path, task_id)
     export_path = os.path.join(CONF.worker.export_base_path, task_id)