Просмотр исходного кода

Add 'storage_mappings' field to Migration/Replica API.

The 'storage_mappings' field will be passed to the provider plugins in
order to determine what storage backends to use for each of the
migrated/replicated VM disks.

The current implementation simply appends the 'storage_mappings' to the
'destination_environment' options, though an overhaul of the provider
interfaces to support (and allow for ease of addition of new options)
should be performed in the long run.
Nashwan Azhari 7 лет назад
Родитель
Сommit
cb200c616e
3 измененных файлов с 66 добавлено и 40 удалено
  1. 16 19
      coriolis/api/v1/migrations.py
  2. 19 21
      coriolis/api/v1/replicas.py
  3. 31 0
      coriolis/api/v1/utils.py

+ 16 - 19
coriolis/api/v1/migrations.py

@@ -5,7 +5,7 @@ from oslo_log import log as logging
 from webob import exc
 
 from coriolis import exception
-from coriolis import schemas
+from coriolis.api.v1 import utils as api_utils
 from coriolis.api.v1.views import migration_view
 from coriolis.api import wsgi as api_wsgi
 from coriolis.endpoints import api as endpoints_api
@@ -53,29 +53,25 @@ class MigrationController(api_wsgi.Controller):
             instances = migration["instances"]
             notes = migration.get("notes")
             skip_os_morphing = migration.get("skip_os_morphing", False)
+
             network_map = migration.get("network_map", {})
-            try:
-                schemas.validate_value(
-                    network_map, schemas.CORIOLIS_NETWORK_MAP_SCHEMA)
-            except exception.SchemaValidationException:
-                raise exc.HTTPBadRequest(
-                    explanation="Invalid network_map "
-                                "%s" % network_map)
+            api_utils.validate_network_map(network_map)
+
+            storage_mappings = migration.get("storage_mappings", {})
+            api_utils.validate_storage_mappings(storage_mappings)
 
-            # NOTE: until the provider plugin interface is updated to have a
-            # separate 'network_map' field, we add it into the destination
-            # environment.
+            # TODO(aznashwan): until the provider plugin interface is updated
+            # to have separate 'network_map' and 'storage_mappings' fields,
+            # we add them as part of the destination environment:
             destination_environment['network_map'] = network_map
+            destination_environment['storage_mappings'] = storage_mappings
 
             return (origin_endpoint_id, destination_endpoint_id,
                     destination_environment, instances, notes,
-                    skip_os_morphing, network_map)
+                    skip_os_morphing, network_map, storage_mappings)
         except Exception as ex:
             LOG.exception(ex)
-            if hasattr(ex, "message"):
-                msg = ex.message
-            else:
-                msg = str(ex)
+            msg = getattr(ex, "message", str(ex))
             raise exception.InvalidInput(msg)
 
     def create(self, req, body):
@@ -100,7 +96,8 @@ class MigrationController(api_wsgi.Controller):
              destination_environment,
              instances,
              notes,
-             skip_os_morphing, network_map) = self._validate_migration_input(
+             skip_os_morphing, network_map,
+             storage_mappings) = self._validate_migration_input(
                 migration_body)
             is_valid, message = (
                 self._endpoints_api.validate_target_environment(
@@ -112,8 +109,8 @@ class MigrationController(api_wsgi.Controller):
 
             migration = self._migration_api.migrate_instances(
                 context, origin_endpoint_id, destination_endpoint_id,
-                destination_environment, instances, network_map, notes,
-                skip_os_morphing)
+                destination_environment, instances, network_map,
+                storage_mappings, notes, skip_os_morphing)
 
         return migration_view.single(req, migration)
 

+ 19 - 21
coriolis/api/v1/replicas.py

@@ -5,7 +5,7 @@ from oslo_log import log as logging
 from webob import exc
 
 from coriolis import exception
-from coriolis import schemas
+from coriolis.api.v1 import utils as api_utils
 from coriolis.api.v1.views import replica_view
 from coriolis.api import wsgi as api_wsgi
 from coriolis.endpoints import api as endpoints_api
@@ -54,28 +54,25 @@ class ReplicaController(api_wsgi.Controller):
             destination_environment = replica.get("destination_environment")
             instances = replica["instances"]
             notes = replica.get("notes")
-            network_map = replica.get("network_map")
-            try:
-                schemas.validate_value(
-                    network_map, schemas.CORIOLIS_NETWORK_MAP_SCHEMA)
-            except exception.SchemaValidationException:
-                raise exc.HTTPBadRequest(
-                    explanation="Invalid network_map "
-                                "%s" % network_map)
-
-            # NOTE: until the provider plugin interface is updated to have a
-            # separate 'network_map' field, we add it into the destination
-            # environment.
-            destination_environment["network_map"] = network_map
+
+            network_map = replica.get("network_map", {})
+            api_utils.validate_network_map(network_map)
+
+            storage_mappings = replica.get("storage_mappings", {})
+            api_utils.validate_storage_mappings(storage_mappings)
+
+            # TODO(aznashwan): until the provider plugin interface is updated
+            # to have separate 'network_map' and 'storage_mappings' fields,
+            # we add them as part of the destination environment:
+            destination_environment['network_map'] = network_map
+            destination_environment['storage_mappings'] = storage_mappings
 
             return (origin_endpoint_id, destination_endpoint_id,
-                    destination_environment, instances, network_map, notes)
+                    destination_environment, instances, network_map,
+                    storage_mappings, notes)
         except Exception as ex:
             LOG.exception(ex)
-            if hasattr(ex, "message"):
-                msg = ex.message
-            else:
-                msg = str(ex)
+            msg = getattr(ex, "message", str(ex))
             raise exception.InvalidInput(msg)
 
     def create(self, req, body):
@@ -84,7 +81,7 @@ class ReplicaController(api_wsgi.Controller):
 
         (origin_endpoint_id, destination_endpoint_id,
          destination_environment, instances, network_map,
-         notes) = self._validate_create_body(body)
+         storage_mappings, notes) = self._validate_create_body(body)
 
         is_valid, message = (
             self._endpoints_api.validate_target_environment(
@@ -97,7 +94,8 @@ class ReplicaController(api_wsgi.Controller):
 
         return replica_view.single(req, self._replica_api.create(
             context, origin_endpoint_id, destination_endpoint_id,
-            destination_environment, instances, network_map, notes))
+            destination_environment, instances, network_map,
+            storage_mappings, notes))
 
     def delete(self, req, id):
         context = req.environ["coriolis.context"]

+ 31 - 0
coriolis/api/v1/utils.py

@@ -0,0 +1,31 @@
+# Copyright 2018 Cloudbase Solutions Srl
+# All Rights Reserved.
+
+from oslo_log import log as logging
+from webob import exc
+
+from coriolis import exception
+from coriolis import schemas
+
+
+LOG = logging.getLogger(__name__)
+
+
+def validate_network_map(network_map):
+    """ Validates the JSON schema for the network_map. """
+    try:
+        schemas.validate_value(
+            network_map, schemas.CORIOLIS_NETWORK_MAP_SCHEMA)
+    except exception.SchemaValidationException as ex:
+        raise exc.HTTPBadRequest(
+            explanation="Invalid network_map: %s" % str(ex))
+
+
+def validate_storage_mappings(storage_mappings):
+    """ Validates the JSON schema for the storage_mappings. """
+    try:
+        schemas.validate_value(
+            storage_mappings, schemas.CORIOLIS_STORAGE_MAPPINGS_SCHEMA)
+    except exception.SchemaValidationException as ex:
+        raise exc.HTTPBadRequest(
+            explanation="Invalid storage_mappings: %s" % str(ex))