فهرست منبع

Added target environment validation upon migration/replica creation.

Nashwan Azhari 8 سال پیش
والد
کامیت
89c13348f9

+ 12 - 0
coriolis/api/v1/migrations.py

@@ -6,6 +6,7 @@ from webob import exc
 
 from coriolis.api.v1.views import migration_view
 from coriolis.api import wsgi as api_wsgi
+from coriolis.endpoints import api as endpoints_api
 from coriolis import exception
 from coriolis.migrations import api
 
@@ -15,6 +16,7 @@ LOG = logging.getLogger(__name__)
 class MigrationController(api_wsgi.Controller):
     def __init__(self):
         self._migration_api = api.API()
+        self._endpoints_api = endpoints_api.API()
         super(MigrationController, self).__init__()
 
     def show(self, req, id):
@@ -66,6 +68,8 @@ class MigrationController(api_wsgi.Controller):
             force = migration_body.get("force", False)
             skip_os_morphing = migration_body.get("skip_os_morphing", False)
 
+            # NOTE: destination environment for replica should have been
+            # validated upon its creation.
             migration = self._migration_api.deploy_replica_instances(
                 context, replica_id, clone_disks, force, skip_os_morphing)
         else:
@@ -76,6 +80,14 @@ class MigrationController(api_wsgi.Controller):
              notes,
              skip_os_morphing) = self._validate_migration_input(
                 migration_body)
+            is_valid, message = (
+                self._endpoints_api.validate_target_environment(
+                    context, destination_endpoint_id, destination_environment))
+            if not is_valid:
+                raise exc.HTTPBadRequest(
+                    explanation="Invalid destination "
+                                "environment: %s" % message)
+
             migration = self._migration_api.migrate_instances(
                 context, origin_endpoint_id, destination_endpoint_id,
                 destination_environment, instances, notes, skip_os_morphing)

+ 11 - 0
coriolis/api/v1/replicas.py

@@ -6,6 +6,7 @@ from webob import exc
 
 from coriolis.api.v1.views import replica_view
 from coriolis.api import wsgi as api_wsgi
+from coriolis.endpoints import api as endpoints_api
 from coriolis import exception
 from coriolis.replicas import api
 
@@ -15,6 +16,7 @@ LOG = logging.getLogger(__name__)
 class ReplicaController(api_wsgi.Controller):
     def __init__(self):
         self._replica_api = api.API()
+        self._endpoints_api = endpoints_api.API()
         super(ReplicaController, self).__init__()
 
     def show(self, req, id):
@@ -62,6 +64,15 @@ class ReplicaController(api_wsgi.Controller):
          destination_environment, instances,
          notes) = self._validate_create_body(body)
 
+        is_valid, message = (
+            self._endpoints_api.validate_target_environment(
+                req.environ["coriolis.context"], destination_endpoint_id,
+                destination_environment))
+        if not is_valid:
+            raise exc.HTTPBadRequest(
+                explanation="Invalid destination "
+                            "environment: %s" % message)
+
         return replica_view.single(req, self._replica_api.create(
             req.environ['coriolis.context'], origin_endpoint_id,
             destination_endpoint_id, destination_environment, instances,

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

@@ -82,6 +82,12 @@ class ConductorClient(object):
             ctxt, 'validate_endpoint_connection',
             endpoint_id=endpoint_id)
 
+    def validate_endpoint_target_environment(
+            self, ctxt, endpoint_id, target_env):
+        return self._client.call(
+            ctxt, 'validate_endpoint_target_environment',
+            endpoint_id=endpoint_id, target_env=target_env)
+
     def get_available_providers(self, ctxt):
         return self._client.call(
             ctxt, 'get_available_providers')

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

@@ -156,6 +156,12 @@ class ConductorServerEndpoint(object):
         return self._rpc_worker_client.validate_endpoint_connection(
             ctxt, endpoint.type, endpoint.connection_info)
 
+    def validate_endpoint_target_environment(
+            self, ctxt, endpoint_id, target_env):
+        endpoint = self.get_endpoint(ctxt, endpoint_id)
+        return self._rpc_worker_client.validate_endpoint_target_environment(
+            ctxt, endpoint.type, target_env)
+
     def get_available_providers(self, ctxt):
         return self._rpc_worker_client.get_available_providers(ctxt)
 

+ 4 - 0
coriolis/endpoints/api.py

@@ -32,3 +32,7 @@ class API(object):
     def validate_connection(self, ctxt, endpoint_id):
         return self._rpc_client.validate_endpoint_connection(
             ctxt, endpoint_id)
+
+    def validate_target_environment(self, ctxt, endpoint_id, target_env):
+        return self._rpc_client.validate_endpoint_target_environment(
+            ctxt, endpoint_id, target_env)

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

@@ -84,6 +84,13 @@ class WorkerClient(object):
             platform_name=platform_name,
             connection_info=connection_info)
 
+    def validate_endpoint_target_environment(
+            self, ctxt, platform_name, target_env):
+        return self._client.call(
+            ctxt, 'validate_endpoint_target_environment',
+            platform_name=platform_name,
+            target_env=target_env)
+
     def get_available_providers(self, ctxt):
         return self._client.call(
             ctxt, 'get_available_providers')

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

@@ -280,6 +280,22 @@ class WorkerServerEndpoint(object):
     def get_available_providers(self, ctxt):
         return providers_factory.get_available_providers()
 
+    def validate_endpoint_target_environment(
+            self, ctxt, platform_name, target_env):
+        provider = providers_factory.get_provider(
+            platform_name, constants.PROVIDER_TYPE_OS_MORPHING, None)
+        target_env_schema = provider.get_target_environment_schema()
+
+        is_valid = True
+        message = None
+        try:
+            schemas.validate_value(target_env, target_env_schema)
+        except exception.SchemaValidationException as ex:
+            is_valid = False
+            message = str(ex)
+
+        return (is_valid, message)
+
     def validate_endpoint_connection(self, ctxt, platform_name,
                                      connection_info):
         provider = providers_factory.get_provider(