Beispiel #1
0
def _task_process(ctxt, task_id, task_type, origin, destination, instance,
                  task_info, mp_q, mp_log_q):
    try:
        _setup_task_process(mp_log_q)

        task_runner = task_runners_factory.get_task_runner_class(task_type)()
        event_handler = _ConductorProviderEventHandler(ctxt, task_id)

        LOG.debug(
            "Executing task: %(task_id)s, type: %(task_type)s, "
            "origin: %(origin)s, destination: %(destination)s, "
            "instance: %(instance)s, task_info: %(task_info)s", {
                "task_id": task_id,
                "task_type": task_type,
                "origin": origin,
                "destination": destination,
                "instance": instance,
                "task_info": utils.sanitize_task_info(task_info)
            })

        task_result = task_runner.run(ctxt, instance, origin, destination,
                                      task_info, event_handler)
        # mq_p.put() doesn't raise if new_task_info is not serializable
        utils.is_serializable(task_result)
        mp_q.put(task_result)
    except Exception as ex:
        mp_q.put(str(ex))
        LOG.exception(ex)
    finally:
        # Signal the log event handler that there are no more events
        mp_log_q.put(None)
Beispiel #2
0
    def exec_task(self, ctxt, task_id, task_type, origin, destination,
                  instance, task_info):
        try:
            task_result = self._exec_task_process(ctxt, task_id, task_type,
                                                  origin, destination,
                                                  instance, task_info)

            LOG.info("Output of completed %s task with ID %s: %s", task_type,
                     task_id, utils.sanitize_task_info(task_result))

            self._rpc_conductor_client.task_completed(ctxt, task_id,
                                                      task_result)
        except exception.TaskProcessCanceledException as ex:
            LOG.debug(
                "Task with ID '%s' appears to have been cancelled. "
                "Confirming cancellation to Conductor now. Error was: %s",
                task_id, utils.get_exception_details())
            LOG.exception(ex)
            self._rpc_conductor_client.confirm_task_cancellation(
                ctxt, task_id, str(ex))
        except exception.NoSuitableWorkerServiceError as ex:
            LOG.warn(
                "A conductor-side scheduling error has occurred following the "
                "completion of task '%s'. Ignoring. Error was: %s", task_id,
                utils.get_exception_details())
        except Exception as ex:
            LOG.debug(
                "Task with ID '%s' has error'd out. Reporting error to "
                "Conductor now. Error was: %s", task_id,
                utils.get_exception_details())
            LOG.exception(ex)
            self._rpc_conductor_client.set_task_error(ctxt, task_id, str(ex))
Beispiel #3
0
    def _run(self, ctxt, instance, origin, destination, task_info,
             event_handler):
        event_manager = events.EventManager(event_handler)
        if not task_info.get("volumes_info"):
            LOG.debug("No volumes_info present. Skipping disk deletion.")
            event_manager.progress_update(
                "No previous volumes information present, nothing to delete")
            return {'volumes_info': []}

        provider = providers_factory.get_provider(
            destination["type"], constants.PROVIDER_TYPE_REPLICA_IMPORT,
            event_handler)
        connection_info = base.get_connection_info(ctxt, destination)

        volumes_info = _get_volumes_info(task_info)
        target_environment = task_info['target_environment']

        volumes_info = provider.delete_replica_disks(ctxt, connection_info,
                                                     target_environment,
                                                     volumes_info)
        if volumes_info:
            LOG.warn(
                "'volumes_info' should have been void after disk "
                "deletion task but it is: %s" %
                (utils.sanitize_task_info({'volumes_info': volumes_info})))

        return {'volumes_info': []}
Beispiel #4
0
def _check_ensure_volumes_info_ordering(export_info, volumes_info):
    """ Returns a new list of volumes_info, ensuring that the order of
    the disks in 'volumes_info' is consistent with the order that the
    disks appear in 'export_info[devices][disks]'
    """
    instance = export_info.get('instance_name',
                               export_info.get('name', export_info['id']))
    ordered_volumes_info = []
    for disk in export_info['devices']['disks']:
        disk_id = disk['id']
        matching_volumes = [
            vol for vol in volumes_info if vol['disk_id'] == disk_id
        ]
        if not matching_volumes:
            raise exception.InvalidActionTasksExecutionState(
                "Could not find source disk '%s' (ID '%s') in Replica "
                "volumes info: %s" % (disk, disk_id, volumes_info))
        elif len(matching_volumes) > 1:
            raise exception.InvalidActionTasksExecutionState(
                "Multiple disks with ID '%s' foind in Replica "
                "volumes info: %s" % (disk_id, volumes_info))

        ordered_volumes_info.append(matching_volumes[0])

    vol_info_cpy = utils.sanitize_task_info({
        "volumes_info": volumes_info
    }).get("volumes_info", [])

    ordered_vol_info_cpy = utils.sanitize_task_info({
        "volumes_info":
        ordered_volumes_info
    }).get("volumes_info", [])

    LOG.debug("volumes_info returned by provider for instance "
              "'%s': %s", instance, vol_info_cpy)
    LOG.debug("volumes_info for instance '%s' after "
              "reordering: %s", instance, ordered_vol_info_cpy)

    return ordered_volumes_info
Beispiel #5
0
    def run(self, ctxt, instance, origin, destination, task_info,
            event_handler):
        """ Runs the task with the given params and returns
        a dict with the results.
        NOTE: This should NOT modify the existing task_info in any way.
        """
        missing_info_props = [
            prop for prop in self.get_required_task_info_properties()
            if prop not in task_info
        ]
        if missing_info_props:
            raise exception.CoriolisException(
                "Task type '%s' asked to run on task info with "
                "missing properties: %s" %
                (self.__class__, missing_info_props))

        result = self._run(ctxt, instance, origin, destination, task_info,
                           event_handler)

        if type(result) is not dict:
            raise exception.CoriolisException(
                "Task type '%s' returned result of type %s "
                "instead of a dict: %s" %
                (self.__class__, type(result), result))

        missing_returns = [
            prop for prop in self.get_returned_task_info_properties()
            if prop not in result.keys()
        ]
        if missing_returns:
            raise exception.CoriolisException(
                "Task type '%s' failed to return the following "
                "declared return values in its result: %s. "
                "Result was: %s" % (self.__class__, missing_returns,
                                    utils.sanitize_task_info(result)))

        undeclared_returns = [
            prop for prop in result.keys()
            if prop not in self.get_returned_task_info_properties()
        ]
        if undeclared_returns:
            raise exception.CoriolisException(
                "Task type '%s' returned the following undeclared "
                "keys in its result: %s" %
                (self.__class__, undeclared_returns))

        return result
Beispiel #6
0
    def exec_task(self, ctxt, task_id, task_type, origin, destination,
                  instance, task_info):
        try:
            task_result = self._exec_task_process(ctxt, task_id, task_type,
                                                  origin, destination,
                                                  instance, task_info)

            LOG.info("Output of completed %s task with ID %s: %s", task_type,
                     task_id, utils.sanitize_task_info(task_result))

            self._rpc_conductor_client.task_completed(ctxt, task_id,
                                                      task_result)
        except exception.TaskProcessCanceledException as ex:
            LOG.exception(ex)
            self._rpc_conductor_client.confirm_task_cancellation(
                ctxt, task_id, str(ex))
        except Exception as ex:
            LOG.exception(ex)
            self._rpc_conductor_client.set_task_error(ctxt, task_id, str(ex))
Beispiel #7
0
    def _run(self, ctxt, instance, origin, destination, task_info,
             event_handler):
        if not task_info.get("volumes_info"):
            LOG.debug("No volumes_info present. Skipping disk deletion.")
            return {'volumes_info': []}

        provider = providers_factory.get_provider(
            destination["type"], constants.PROVIDER_TYPE_REPLICA_IMPORT,
            event_handler)
        connection_info = base.get_connection_info(ctxt, destination)

        volumes_info = _get_volumes_info(task_info)

        # TODO (aznashwan): add target_env options to `delete_replica_disks`:
        volumes_info = provider.delete_replica_disks(ctxt, connection_info,
                                                     volumes_info)
        if volumes_info:
            LOG.warn(
                "'volumes_info' should have been void after disk "
                "deletion task but it is: %s" %
                (utils.sanitize_task_info({'volumes_info': volumes_info})))

        return {'volumes_info': []}