Forráskód Böngészése

Merge pull request #79 from Dany9966/migr_redefine

Replica-backed-migrations redefinitions.
Nashwan Azhari 6 éve
szülő
commit
978ca7a866

+ 36 - 41
coriolis/conductor/rpc/server.py

@@ -732,34 +732,34 @@ class ConductorServerEndpoint(object):
                 instance, constants.TASK_TYPE_GET_INSTANCE_INFO,
                 execution)
 
-            validate_replica_source_inputs_task = self._create_task(
+            validate_migration_source_inputs_task = self._create_task(
                 instance,
-                constants.TASK_TYPE_VALIDATE_REPLICA_SOURCE_INPUTS,
+                constants.TASK_TYPE_VALIDATE_MIGRATION_SOURCE_INPUTS,
                 execution)
 
-            validate_replica_destination_inputs_task = self._create_task(
+            validate_migration_destination_inputs_task = self._create_task(
                 instance,
-                constants.TASK_TYPE_VALIDATE_REPLICA_DESTINATION_INPUTS,
+                constants.TASK_TYPE_VALIDATE_MIGRATION_DESTINATION_INPUTS,
                 execution,
                 depends_on=[get_instance_info_task.id])
 
             depends_on = [
-                validate_replica_source_inputs_task.id,
-                validate_replica_destination_inputs_task.id]
+                validate_migration_source_inputs_task.id,
+                validate_migration_destination_inputs_task.id]
 
-            deploy_replica_disks_task = self._create_task(
-                instance, constants.TASK_TYPE_DEPLOY_REPLICA_DISKS,
+            create_instance_disks_task = self._create_task(
+                instance, constants.TASK_TYPE_CREATE_INSTANCE_DISKS,
                 execution, depends_on=depends_on)
 
-            deploy_replica_source_resources_task = self._create_task(
+            deploy_migration_source_resources_task = self._create_task(
                 instance,
-                constants.TASK_TYPE_DEPLOY_REPLICA_SOURCE_RESOURCES,
-                execution, depends_on=[deploy_replica_disks_task.id])
+                constants.TASK_TYPE_DEPLOY_MIGRATION_SOURCE_RESOURCES,
+                execution, depends_on=[create_instance_disks_task.id])
 
-            deploy_replica_target_resources_task = self._create_task(
+            deploy_migration_target_resources_task = self._create_task(
                 instance,
-                constants.TASK_TYPE_DEPLOY_REPLICA_TARGET_RESOURCES,
-                execution, depends_on=[deploy_replica_disks_task.id])
+                constants.TASK_TYPE_DEPLOY_MIGRATION_TARGET_RESOURCES,
+                execution, depends_on=[create_instance_disks_task.id])
 
             # NOTE(aznashwan): re-executing the REPLICATE_DISKS task only works
             # if all the source disk snapshotting and worker setup steps are
@@ -768,48 +768,48 @@ class ConductorServerEndpoint(object):
             # Alternatively, if the DEPLOY_REPLICA_SOURCE/DEST_RESOURCES tasks
             # will no longer have a state conflict, iterating through and
             # re-executing DEPLOY_REPLICA_SOURCE_RESOURCES will be required:
-            last_replica_task = None
-            replica_resources_tasks = [
-                deploy_replica_source_resources_task.id,
-                deploy_replica_target_resources_task.id]
+            last_migration_task = None
+            migration_resources_tasks = [
+                deploy_migration_source_resources_task.id,
+                deploy_migration_target_resources_task.id]
             for i in range(migration.replication_count):
                 # insert SHUTDOWN_INSTANCES task before the last sync:
                 if i == (migration.replication_count - 1) and (
                         migration.shutdown_instances):
-                    shutdown_deps = replica_resources_tasks
-                    if last_replica_task:
-                        shutdown_deps = [last_replica_task.id]
-                    last_replica_task = self._create_task(
+                    shutdown_deps = migration_resources_tasks
+                    if last_migration_task:
+                        shutdown_deps = [last_migration_task.id]
+                    last_migration_task = self._create_task(
                         instance, constants.TASK_TYPE_SHUTDOWN_INSTANCE,
                         execution, depends_on=shutdown_deps)
 
-                replication_deps = replica_resources_tasks
-                if last_replica_task:
-                    replication_deps = [last_replica_task.id]
+                replication_deps = migration_resources_tasks
+                if last_migration_task:
+                    replication_deps = [last_migration_task.id]
 
-                last_replica_task = self._create_task(
+                last_migration_task = self._create_task(
                     instance, constants.TASK_TYPE_REPLICATE_DISKS,
                     execution, depends_on=replication_deps)
 
             delete_source_resources_task = self._create_task(
                 instance,
-                constants.TASK_TYPE_DELETE_REPLICA_SOURCE_RESOURCES,
-                execution, depends_on=[last_replica_task.id],
+                constants.TASK_TYPE_DELETE_MIGRATION_SOURCE_RESOURCES,
+                execution, depends_on=[last_migration_task.id],
                 on_error=True)
 
             delete_destination_resources_task = self._create_task(
                 instance,
-                constants.TASK_TYPE_DELETE_REPLICA_TARGET_RESOURCES,
-                execution, depends_on=[last_replica_task.id],
+                constants.TASK_TYPE_DELETE_MIGRATION_TARGET_RESOURCES,
+                execution, depends_on=[last_migration_task.id],
                 on_error=True)
 
-            deploy_replica_task = self._create_task(
-                instance, constants.TASK_TYPE_DEPLOY_REPLICA_INSTANCE,
+            deploy_instance_task = self._create_task(
+                instance, constants.TASK_TYPE_DEPLOY_INSTANCE_RESOURCES,
                 execution, depends_on=[
                     delete_source_resources_task.id,
                     delete_destination_resources_task.id])
 
-            last_task = deploy_replica_task
+            last_task = deploy_instance_task
             if not skip_os_morphing:
                 task_deploy_os_morphing_resources = self._create_task(
                     instance, constants.TASK_TYPE_DEPLOY_OS_MORPHING_RESOURCES,
@@ -836,16 +836,16 @@ class ConductorServerEndpoint(object):
 
             self._create_task(
                 instance,
-                constants.TASK_TYPE_FINALIZE_REPLICA_INSTANCE_DEPLOYMENT,
+                constants.TASK_TYPE_FINALIZE_INSTANCE_DEPLOYMENT,
                 execution, depends_on=[last_task.id])
 
             self._create_task(
                 instance,
-                constants.TASK_TYPE_CLEANUP_FAILED_REPLICA_INSTANCE_DEPLOYMENT,
+                constants.TASK_TYPE_CLEANUP_FAILED_INSTANCE_DEPLOYMENT,
                 execution, on_error=True)
 
             self._create_task(
-                instance, constants.TASK_TYPE_DELETE_REPLICA_DISKS,
+                instance, constants.TASK_TYPE_CLEANUP_INSTANCE_STORAGE,
                 execution, on_error=True)
 
         db_api.add_migration(ctxt, migration)
@@ -966,12 +966,7 @@ class ConductorServerEndpoint(object):
                                 start_task = False
                                 break
                     if start_task:
-                        # instance imports need to be executed on the same host
                         server = None
-                        if (task.task_type ==
-                                constants.TASK_TYPE_IMPORT_INSTANCE):
-                            server = parent_task.host
-
                         self._rpc_worker_client.begin_task(
                             ctxt, server=server,
                             task_id=task.id,

+ 15 - 9
coriolis/constants.py

@@ -13,15 +13,21 @@ TASK_STATUS_CANCELED = "CANCELED"
 TASK_STATUS_CANCELED_FOR_DEBUGGING = "CANCELED_FOR_DEBUGGING"
 TASK_STATUS_ON_ERROR_ONLY = "EXECUTE_ON_ERROR_ONLY"
 
-TASK_TYPE_EXPORT_INSTANCE = "EXPORT_INSTANCE"
-TASK_TYPE_IMPORT_INSTANCE = "IMPORT_INSTANCE"
-TASK_TYPE_FINALIZE_IMPORT_INSTANCE = "FINALIZE_IMPORT_INSTANCE"
-TASK_TYPE_CLEANUP_FAILED_IMPORT_INSTANCE = "CLEANUP_FAILED_IMPORT_INSTANCE"
-
-TASK_TYPE_DEPLOY_DISK_COPY_RESOURCES = "DEPLOY_DISK_COPY_RESOURCES"
-TASK_TYPE_COPY_DISK_DATA = "COPY_DISK_DATA"
-TASK_TYPE_DELETE_DISK_COPY_RESOURCES = "DELETE_DISK_COPY_RESOURCES"
-
+TASK_TYPE_DEPLOY_MIGRATION_SOURCE_RESOURCES = (
+    "DEPLOY_MIGRATION_SOURCE_RESOURCES")
+TASK_TYPE_DEPLOY_MIGRATION_TARGET_RESOURCES = (
+    "DEPLOY_MIGRATION_TARGET_RESOURCES")
+TASK_TYPE_DELETE_MIGRATION_SOURCE_RESOURCES = (
+    "DELETE_MIGRATION_SOURCE_RESOURCES")
+TASK_TYPE_DELETE_MIGRATION_TARGET_RESOURCES = (
+    "DELETE_MIGRATION_TARGET_RESOURCES")
+TASK_TYPE_DEPLOY_INSTANCE_RESOURCES = "DEPLOY_INSTANCE_RESOURCES"
+TASK_TYPE_FINALIZE_INSTANCE_DEPLOYMENT = "FINALIZE_INSTANCE_DEPLOYMENT"
+TASK_TYPE_CLEANUP_FAILED_INSTANCE_DEPLOYMENT = (
+    "CLEANUP_FAILED_INSTANCE_DEPLOYMENT")
+TASK_TYPE_CLEANUP_INSTANCE_STORAGE = "CLEANUP_INSTANCE_STORAGE"
+
+TASK_TYPE_CREATE_INSTANCE_DISKS = "CREATE_INSTANCE_DISKS"
 
 TASK_TYPE_DEPLOY_OS_MORPHING_RESOURCES = "DEPLOY_OS_MORPHING_RESOURCES"
 TASK_TYPE_OS_MORPHING = "OS_MORPHING"

+ 2 - 1
coriolis/providers/base.py

@@ -265,7 +265,8 @@ class BaseReplicaImportValidationProvider(
 
     @abc.abstractmethod
     def validate_replica_import_input(
-            self, ctxt, connection_info, target_environment, export_info):
+            self, ctxt, connection_info, target_environment, export_info,
+            check_os_morphing_resources=False, check_final_vm_params=False):
         """ Validates the provided Replica parameters """
         pass
 

+ 1 - 3
coriolis/schemas/vm_export_info_schema.json

@@ -109,9 +109,7 @@
               }
             },
             "required": [
-              "format",
-              "size_bytes",
-              "path"
+              "size_bytes"
             ]
           }
         },

+ 18 - 14
coriolis/tasks/factory.py

@@ -8,20 +8,24 @@ from coriolis.tasks import osmorphing_tasks
 from coriolis.tasks import replica_tasks
 
 _TASKS_MAP = {
-    constants.TASK_TYPE_EXPORT_INSTANCE:
-        migration_tasks.ExportInstanceTask,
-    constants.TASK_TYPE_IMPORT_INSTANCE:
-        migration_tasks.ImportInstanceTask,
-    constants.TASK_TYPE_FINALIZE_IMPORT_INSTANCE:
-        migration_tasks.FinalizeImportInstanceTask,
-    constants.TASK_TYPE_DEPLOY_DISK_COPY_RESOURCES:
-        migration_tasks.DeployDiskCopyResources,
-    constants.TASK_TYPE_COPY_DISK_DATA:
-        migration_tasks.CopyDiskData,
-    constants.TASK_TYPE_DELETE_DISK_COPY_RESOURCES:
-        migration_tasks.DeleteDiskCopyResources,
-    constants.TASK_TYPE_CLEANUP_FAILED_IMPORT_INSTANCE:
-        migration_tasks.CleanupFailedImportInstanceTask,
+    constants.TASK_TYPE_DEPLOY_MIGRATION_SOURCE_RESOURCES:
+        migration_tasks.DeployMigrationSourceResourcesTask,
+    constants.TASK_TYPE_DEPLOY_MIGRATION_TARGET_RESOURCES:
+        migration_tasks.DeployMigrationTargetResourcesTask,
+    constants.TASK_TYPE_DELETE_MIGRATION_SOURCE_RESOURCES:
+        migration_tasks.DeleteMigrationSourceResourcesTask,
+    constants.TASK_TYPE_DELETE_MIGRATION_TARGET_RESOURCES:
+        migration_tasks.DeleteMigrationTargetResourcesTask,
+    constants.TASK_TYPE_DEPLOY_INSTANCE_RESOURCES:
+        migration_tasks.DeployInstanceResourcesTask,
+    constants.TASK_TYPE_FINALIZE_INSTANCE_DEPLOYMENT:
+        migration_tasks.FinalizeInstanceDeploymentTask,
+    constants.TASK_TYPE_CREATE_INSTANCE_DISKS:
+        migration_tasks.CreateInstanceDisksTask,
+    constants.TASK_TYPE_CLEANUP_FAILED_INSTANCE_DEPLOYMENT:
+        migration_tasks.CleanupFailedInstanceDeploymentTask,
+    constants.TASK_TYPE_CLEANUP_INSTANCE_STORAGE:
+        migration_tasks.CleanupInstanceStorageTask,
     constants.TASK_TYPE_GET_OPTIMAL_FLAVOR:
         migration_tasks.GetOptimalFlavorTask,
     constants.TASK_TYPE_VALIDATE_MIGRATION_SOURCE_INPUTS:

+ 46 - 238
coriolis/tasks/migration_tasks.py

@@ -5,284 +5,92 @@ from oslo_log import log as logging
 
 from coriolis import constants
 from coriolis import events
-from coriolis import exception
-from coriolis.migrations import manager
 from coriolis.providers import factory as providers_factory
-from coriolis import schemas
 from coriolis.tasks import base
+from coriolis.tasks import replica_tasks
 
 LOG = logging.getLogger(__name__)
 
 
-class ExportInstanceTask(base.TaskRunner):
+class GetOptimalFlavorTask(base.TaskRunner):
     def run(self, ctxt, instance, origin, destination, task_info,
             event_handler):
         provider = providers_factory.get_provider(
-            origin["type"], constants.PROVIDER_TYPE_EXPORT, event_handler)
-        connection_info = base.get_connection_info(ctxt, origin)
-        export_path = task_info["export_path"]
-
-        source_environment = origin.get('source_environment') or {}
-        export_info = provider.export_instance(
-            ctxt, connection_info, source_environment, instance, export_path)
-
-        # Validate the output
-        schemas.validate_value(
-            export_info, schemas.CORIOLIS_VM_EXPORT_INFO_SCHEMA)
-        task_info["export_info"] = export_info
-        task_info["retain_export_path"] = True
-
-        return task_info
-
+            destination["type"], constants.PROVIDER_TYPE_INSTANCE_FLAVOR,
+            event_handler)
 
-class ImportInstanceTask(base.TaskRunner):
-    def run(self, ctxt, instance, origin, destination, task_info,
-            event_handler):
+        connection_info = base.get_connection_info(ctxt, destination)
         target_environment = destination.get("target_environment") or {}
         export_info = task_info["export_info"]
 
-        provider = providers_factory.get_provider(
-            destination["type"], constants.PROVIDER_TYPE_IMPORT, event_handler)
-        connection_info = base.get_connection_info(ctxt, destination)
-
-        import_info = provider.import_instance(
-            ctxt, connection_info, target_environment, instance, export_info)
+        flavor = provider.get_optimal_flavor(
+            ctxt, connection_info, target_environment, export_info)
 
         if task_info.get("instance_deployment_info") is None:
             task_info["instance_deployment_info"] = {}
-        task_info["instance_deployment_info"].update(import_info[
-            "instance_deployment_info"])
-
-        task_info["origin_provider_type"] = constants.PROVIDER_TYPE_EXPORT
-        task_info["destination_provider_type"] = constants.PROVIDER_TYPE_IMPORT
-        # We need to retain export info until after disk sync
-        # TODO(gsamfira): remove this when we implement multi-worker, and by
-        # extension some external storage for needed resources (like swift)
-        task_info["retain_export_path"] = True
-
-        return task_info
+        task_info["instance_deployment_info"]["selected_flavor"] = flavor
 
+        events.EventManager(event_handler).progress_update(
+            "Selected flavor: %s" % flavor)
 
-class DeployDiskCopyResources(base.TaskRunner):
-    def run(self, ctxt, instance, origin, destination, task_info,
-            event_handler):
-        provider = providers_factory.get_provider(
-            destination["type"], constants.PROVIDER_TYPE_IMPORT, event_handler)
-        connection_info = base.get_connection_info(ctxt, destination)
-        target_environment = destination.get("target_environment") or {}
-        instance_deployment_info = task_info["instance_deployment_info"]
-
-        resources_info = provider.deploy_disk_copy_resources(
-            ctxt, connection_info, target_environment,
-            instance_deployment_info)
-
-        instance_deployment_info = resources_info["instance_deployment_info"]
-        schemas.validate_value(
-            instance_deployment_info,
-            schemas.CORIOLIS_DISK_SYNC_RESOURCES_INFO_SCHEMA,
-            # NOTE: we avoid raising so that the cleanup task
-            # can [try] to deal with the temporary resources.
-            raise_on_error=False)
-
-        disk_sync_conn_info = resources_info[
-            "instance_deployment_info"]["disk_sync_connection_info"]
-        disk_sync_conn_info = base.marshal_migr_conn_info(
-            disk_sync_conn_info)
-        schemas.validate_value(
-            disk_sync_conn_info,
-            schemas.CORIOLIS_DISK_SYNC_RESOURCES_CONN_INFO_SCHEMA)
-        instance_deployment_info[
-            'disk_sync_connection_info'] = disk_sync_conn_info
-
-        task_info["instance_deployment_info"] = instance_deployment_info
-
-        # We need to retain export info until after disk sync
-        # TODO(gsamfira): remove this when we implement multi-worker, and by
-        # extension some external storage for needed resources (like swift)
         task_info["retain_export_path"] = True
 
         return task_info
 
 
-class CopyDiskData(base.TaskRunner):
-    def run(self, ctxt, instance, origin, destination, task_info,
-            event_handler):
-        instance_deployment_info = task_info["instance_deployment_info"]
-        schemas.validate_value(
-            instance_deployment_info['disk_sync_connection_info'],
-            schemas.CORIOLIS_DISK_SYNC_RESOURCES_CONN_INFO_SCHEMA)
-
-        volumes_info = instance_deployment_info["volumes_info"]
-        schemas.validate_value(
-            {"volumes_info": volumes_info},
-            schemas.CORIOLIS_DISK_SYNC_RESOURCES_INFO_SCHEMA)
-        LOG.info("Volumes info is: %r" % volumes_info)
-
-        image_paths = [i.get("disk_image_uri") for i in volumes_info]
-        if None in image_paths:
-            raise exception.InvalidActionTasksExecutionState(
-                "disk_image_uri must be part of volumes_info for"
-                " standard migrations")
-
-        target_conn_info = base.unmarshal_migr_conn_info(
-            instance_deployment_info["disk_sync_connection_info"])
-        manager.copy_disk_data(
-            target_conn_info, volumes_info, event_handler)
+class DeployMigrationSourceResourcesTask(
+        replica_tasks.DeployReplicaSourceResourcesTask):
+    pass
 
-        return task_info
 
+class DeployMigrationTargetResourcesTask(
+        replica_tasks.DeployReplicaTargetResourcesTask):
+    pass
 
-class DeleteDiskCopyResources(base.TaskRunner):
-    def run(self, ctxt, instance, origin, destination, task_info,
-            event_handler):
-        provider = providers_factory.get_provider(
-            destination["type"], constants.PROVIDER_TYPE_IMPORT, event_handler)
-        connection_info = base.get_connection_info(ctxt, destination)
-        instance_deployment_info = task_info.get(
-            "instance_deployment_info", {})
-        provider.delete_disk_copy_resources(
-            ctxt, connection_info, instance_deployment_info)
 
-        if instance_deployment_info.get("disk_sync_connection_info"):
-            del instance_deployment_info["disk_sync_connection_info"]
-        if instance_deployment_info.get("disk_sync_tgt_resources"):
-            del instance_deployment_info["disk_sync_tgt_resources"]
+class CreateInstanceDisksTask(
+        replica_tasks.DeployReplicaDisksTask):
+    pass
 
-        return task_info
 
+class CleanupInstanceStorageTask(replica_tasks.DeleteReplicaDisksTask):
+    pass
 
-class FinalizeImportInstanceTask(base.TaskRunner):
-    def run(self, ctxt, instance, origin, destination, task_info,
-            event_handler):
-        provider = providers_factory.get_provider(
-            destination["type"], constants.PROVIDER_TYPE_IMPORT, event_handler)
-        connection_info = base.get_connection_info(ctxt, destination)
-        instance_deployment_info = task_info["instance_deployment_info"]
 
-        result = provider.finalize_import_instance(
-            ctxt, connection_info, instance_deployment_info)
-        if result is not None:
-            task_info["transfer_result"] = result
-        else:
-            LOG.warn(
-                "'None' was returned as result for Finalize Import Instance "
-                "task '%s'.", task_info)
+class FinalizeInstanceDeploymentTask(
+        replica_tasks.FinalizeReplicaInstanceDeploymentTask):
+    pass
 
-        return task_info
 
+class CleanupFailedInstanceDeploymentTask(
+        replica_tasks.CleanupFailedReplicaInstanceDeploymentTask):
+    pass
 
-class CleanupFailedImportInstanceTask(base.TaskRunner):
-    def run(self, ctxt, instance, origin, destination, task_info,
-            event_handler):
-        provider = providers_factory.get_provider(
-            destination["type"], constants.PROVIDER_TYPE_IMPORT, event_handler)
-        connection_info = base.get_connection_info(ctxt, destination)
-        instance_deployment_info = task_info.get(
-            "instance_deployment_info", {})
 
-        provider.cleanup_failed_import_instance(
-            ctxt, connection_info, instance_deployment_info)
+class ValidateMigrationSourceInputsTask(
+        replica_tasks.ValidateReplicaExecutionSourceInputsTask):
+    pass
 
-        return task_info
 
+class ValidateMigrationDestinationInputsTask(
+        replica_tasks.ValidateReplicaExecutionDestinationInputsTask):
+    def _validate_provider_replica_import_input(
+            self, provider, ctxt, conn_info, target_environment, export_info):
+        provider.validate_replica_import_input(
+            ctxt, conn_info, target_environment, export_info,
+            check_os_morphing_resources=True,
+            check_final_vm_params=True)
 
-class GetOptimalFlavorTask(base.TaskRunner):
-    def run(self, ctxt, instance, origin, destination, task_info,
-            event_handler):
-        provider = providers_factory.get_provider(
-            destination["type"], constants.PROVIDER_TYPE_INSTANCE_FLAVOR,
-            event_handler)
 
-        connection_info = base.get_connection_info(ctxt, destination)
-        target_environment = destination.get("target_environment") or {}
-        export_info = task_info["export_info"]
+class DeleteMigrationSourceResourcesTask(
+        replica_tasks.DeleteReplicaSourceResourcesTask):
+    pass
 
-        flavor = provider.get_optimal_flavor(
-            ctxt, connection_info, target_environment, export_info)
-
-        if task_info.get("instance_deployment_info") is None:
-            task_info["instance_deployment_info"] = {}
-        task_info["instance_deployment_info"]["selected_flavor"] = flavor
-
-        events.EventManager(event_handler).progress_update(
-            "Selected flavor: %s" % flavor)
-
-        task_info["retain_export_path"] = True
-
-        return task_info
 
-
-class ValidateMigrationSourceInputsTask(base.TaskRunner):
-    def run(self, ctxt, instance, origin, destination, task_info,
-            event_handler):
-        event_manager = events.EventManager(event_handler)
-        origin_connection_info = base.get_connection_info(ctxt, origin)
-        origin_type = origin["type"]
-
-        source_provider = providers_factory.get_provider(
-            origin_type, constants.PROVIDER_TYPE_VALIDATE_MIGRATION_EXPORT,
-            event_handler, raise_if_not_found=False)
-        source_environment = origin.get("source_environment", {})
-        export_info = None
-        if source_provider:
-            export_info = source_provider.validate_migration_export_input(
-                ctxt, origin_connection_info, instance, source_environment)
-        else:
-            event_manager.progress_update(
-                "Migration Export Provider for platform '%s' does not "
-                "support Migration input validation" % origin_type)
-
-        if export_info is None:
-            source_endpoint_provider = providers_factory.get_provider(
-                origin_type, constants.PROVIDER_TYPE_ENDPOINT_INSTANCES,
-                event_handler, raise_if_not_found=False)
-            if not source_endpoint_provider:
-                event_manager.progress_update(
-                    "Migration Export Provider for platform '%s' does not "
-                    "support querying instance export info" % origin_type)
-                return task_info
-            export_info = source_endpoint_provider.get_instance(
-                ctxt, origin_connection_info, source_environment, instance)
-
-        # validate Export info:
-        schemas.validate_value(
-            export_info, schemas.CORIOLIS_VM_EXPORT_INFO_SCHEMA)
-        # NOTE: this export info will get overridden with updated values
-        # and disk paths after the ExportInstanceTask.
-        task_info["export_info"] = export_info
-
-        return task_info
+class DeleteMigrationTargetResourcesTask(
+        replica_tasks.DeleteReplicaTargetResourcesTask):
+    pass
 
 
-class ValidateMigrationDestinationInputsTask(base.TaskRunner):
-    def run(self, ctxt, instance, origin, destination, task_info,
-            event_handler):
-        event_manager = events.EventManager(event_handler)
-        destination_type = destination["type"]
-        if task_info.get("export_info") is None:
-            event_manager.progress_update(
-                "Instance export info is not set. Cannot perform Migration "
-                "Import validation for destination platform "
-                "'%s'" % destination_type)
-            return task_info
-
-        destination_connection_info = base.get_connection_info(
-            ctxt, destination)
-        destination_provider = providers_factory.get_provider(
-            destination_type,
-            constants.PROVIDER_TYPE_VALIDATE_MIGRATION_IMPORT, event_handler,
-            raise_if_not_found=False)
-        if not destination_provider:
-            event_manager.progress_update(
-                "Migration Import Provider for platform '%s' does not "
-                "support Migration input validation" % destination_type)
-            return task_info
-
-        # NOTE: the target environment JSON schema should have been validated
-        # upon accepting the Migration API creation request.
-        target_environment = destination.get("target_environment", {})
-        destination_provider.validate_migration_import_input(
-            ctxt, destination_connection_info, target_environment,
-            task_info["export_info"])
-
-        return task_info
+class DeployInstanceResourcesTask(replica_tasks.DeployReplicaInstanceTask):
+    pass

+ 10 - 3
coriolis/tasks/replica_tasks.py

@@ -470,6 +470,13 @@ class ValidateReplicaExecutionSourceInputsTask(base.TaskRunner):
 
 
 class ValidateReplicaExecutionDestinationInputsTask(base.TaskRunner):
+    def _validate_provider_replica_import_input(
+            self, provider, ctxt, conn_info, target_environment, export_info):
+        provider.validate_replica_import_input(
+            ctxt, conn_info, target_environment, export_info,
+            check_os_morphing_resources=False,
+            check_final_vm_params=False)
+
     def run(self, ctxt, instance, origin, destination, task_info,
             event_handler):
         event_manager = events.EventManager(event_handler)
@@ -497,9 +504,9 @@ class ValidateReplicaExecutionDestinationInputsTask(base.TaskRunner):
         # NOTE: the target environment JSON schema should have been validated
         # upon accepting the Replica API creation request.
         target_environment = destination.get("target_environment", {})
-        destination_provider.validate_replica_import_input(
-            ctxt, destination_connection_info, target_environment,
-            export_info)
+        self._validate_provider_replica_import_input(
+            destination_provider, ctxt, destination_connection_info,
+            target_environment, export_info)
 
         return task_info