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

Save 'transfer_result' for migrations/replicas in the DB.

Nashwan Azhari 7 лет назад
Родитель
Сommit
e35a77bb54

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

@@ -14,6 +14,7 @@ from coriolis.db.sqlalchemy import models
 from coriolis import exception
 from coriolis import exception
 from coriolis import keystone
 from coriolis import keystone
 from coriolis.replica_cron.rpc import client as rpc_cron_client
 from coriolis.replica_cron.rpc import client as rpc_cron_client
+from coriolis import schemas
 from coriolis import utils
 from coriolis import utils
 from coriolis.worker.rpc import client as rpc_worker_client
 from coriolis.worker.rpc import client as rpc_worker_client
 
 
@@ -784,6 +785,33 @@ class ConductorServerEndpoint(object):
                 # new volumes need to be deployed in place of the migrated
                 # new volumes need to be deployed in place of the migrated
                 # ones.
                 # ones.
                 updated_task_info = {"volumes_info": None}
                 updated_task_info = {"volumes_info": None}
+        elif task_type in (
+                constants.TASK_TYPE_FINALIZE_IMPORT_INSTANCE,
+                constants.TASK_TYPE_FINALIZE_REPLICA_INSTANCE_DEPLOYMENT):
+            # set 'transfer_result' in the 'base_transfer_action'
+            # table if the task returned a result.
+            if "transfer_result" in task_info:
+                transfer_result = task_info.get("transfer_result")
+                try:
+                    schemas.validate_value(
+                        transfer_result,
+                        schemas.CORIOLIS_VM_EXPORT_INFO_SCHEMA)
+                    LOG.debug(
+                        "Setting result for transfer action '%s': %s",
+                        execution.action_id, transfer_result)
+                    db_api.set_transfer_action_result(
+                        ctxt, execution.action_id, task.instance,
+                        transfer_result)
+                except exception.SchemaValidationException as ex:
+                    LOG.warn(
+                        "Could not validate transfer result '%s' against the "
+                        "VM export info schema. NOT saving value in Database. "
+                        "Exception details: %s",
+                        transfer_result, utils.get_exception_details())
+            else:
+                LOG.debug(
+                    "No 'transfer_result' was returned for task type '%s' "
+                    "for transfer action '%s'", task_type, execution.action_id)
 
 
         if updated_task_info:
         if updated_task_info:
             self._update_replica_volumes_info(
             self._update_replica_volumes_info(

+ 16 - 0
coriolis/db/api.py

@@ -454,6 +454,22 @@ def set_transfer_action_info(context, action_id, instance, instance_info):
     return action_info[instance]
     return action_info[instance]
 
 
 
 
+@enginefacade.writer
+def set_transfer_action_result(context, action_id, instance, result):
+    """ Adds the result for the given 'instance' in the 'transfer_result'
+    JSON in the 'base_transfer_action' table.
+    """
+    action = get_action(context, action_id)
+
+    transfer_result = {}
+    if action.transfer_result:
+        transfer_result = action.transfer_result.copy()
+    transfer_result[instance] = result
+    action.transfer_result = transfer_result
+
+    return transfer_result[instance]
+
+
 @enginefacade.reader
 @enginefacade.reader
 def get_tasks_execution(context, execution_id):
 def get_tasks_execution(context, execution_id):
     q = _soft_delete_aware_query(context, models.TasksExecution)
     q = _soft_delete_aware_query(context, models.TasksExecution)

+ 17 - 0
coriolis/db/sqlalchemy/migrate_repo/versions/005_adds_transfer_result.py

@@ -0,0 +1,17 @@
+# Copyright 2018 Cloudbase Solutions Srl
+# All Rights Reserved.
+
+import sqlalchemy
+
+
+def upgrade(migrate_engine):
+    meta = sqlalchemy.MetaData()
+    meta.bind = migrate_engine
+
+    # add 'transfer_result' column to 'base_transfer_action':
+    base_transfer_action = sqlalchemy.Table(
+        'base_transfer_action', meta, autoload=True)
+
+    transfer_result = sqlalchemy.Column(
+        "transfer_result", sqlalchemy.Text, nullable=True)
+    base_transfer_action.create_column(transfer_result)

+ 1 - 0
coriolis/db/sqlalchemy/models.py

@@ -111,6 +111,7 @@ class BaseTransferAction(BASE, models.TimestampMixin, models.ModelBase,
     destination_endpoint_id = sqlalchemy.Column(
     destination_endpoint_id = sqlalchemy.Column(
         sqlalchemy.String(36),
         sqlalchemy.String(36),
         sqlalchemy.ForeignKey('endpoint.id'), nullable=False)
         sqlalchemy.ForeignKey('endpoint.id'), nullable=False)
+    transfer_result = sqlalchemy.Column(types.Json, nullable=True)
 
 
     __mapper_args__ = {
     __mapper_args__ = {
         'polymorphic_identity': 'base_transfer_action',
         'polymorphic_identity': 'base_transfer_action',

+ 10 - 2
coriolis/providers/base.py

@@ -183,7 +183,11 @@ class BaseImportProvider(BaseImportInstanceProvider):
     @abc.abstractmethod
     @abc.abstractmethod
     def finalize_import_instance(self, ctxt, connection_info,
     def finalize_import_instance(self, ctxt, connection_info,
                                  instance_deployment_info):
                                  instance_deployment_info):
-        pass
+        """ Should return a dict with the info of the migrated VM on the
+        destination platform in the same format as offered by
+        'BaseExportProvider.export_instance()'.
+        """
+        return {}
 
 
     @abc.abstractmethod
     @abc.abstractmethod
     def cleanup_failed_import_instance(self, ctxt, connection_info,
     def cleanup_failed_import_instance(self, ctxt, connection_info,
@@ -202,7 +206,11 @@ class BaseReplicaImportProvider(BaseImportInstanceProvider):
     @abc.abstractmethod
     @abc.abstractmethod
     def finalize_replica_instance_deployment(self, ctxt, connection_info,
     def finalize_replica_instance_deployment(self, ctxt, connection_info,
                                              instance_deployment_info):
                                              instance_deployment_info):
-        pass
+        """ Should return a dict with the info of the migrated VM on the
+        destination platform in the same format as offered by
+        'BaseExportProvider.export_instance()'.
+        """
+        return {}
 
 
     @abc.abstractmethod
     @abc.abstractmethod
     def cleanup_failed_replica_instance_deployment(self, ctxt, connection_info,
     def cleanup_failed_replica_instance_deployment(self, ctxt, connection_info,

+ 7 - 1
coriolis/tasks/migration_tasks.py

@@ -138,8 +138,14 @@ class FinalizeImportInstanceTask(base.TaskRunner):
         connection_info = base.get_connection_info(ctxt, destination)
         connection_info = base.get_connection_info(ctxt, destination)
         instance_deployment_info = task_info["instance_deployment_info"]
         instance_deployment_info = task_info["instance_deployment_info"]
 
 
-        provider.finalize_import_instance(
+        result = provider.finalize_import_instance(
             ctxt, connection_info, instance_deployment_info)
             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)
 
 
         return task_info
         return task_info
 
 

+ 7 - 1
coriolis/tasks/replica_tasks.py

@@ -247,8 +247,14 @@ class FinalizeReplicaInstanceDeploymentTask(base.TaskRunner):
         connection_info = base.get_connection_info(ctxt, destination)
         connection_info = base.get_connection_info(ctxt, destination)
         instance_deployment_info = task_info["instance_deployment_info"]
         instance_deployment_info = task_info["instance_deployment_info"]
 
 
-        provider.finalize_replica_instance_deployment(
+        result = provider.finalize_replica_instance_deployment(
             ctxt, connection_info, instance_deployment_info)
             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 Replica Instance "
+                "deployment task '%s'.", task_info)
 
 
         return task_info
         return task_info