Beispiel #1
0
def mv_files(source, target, workflow):
    """Move files within workspace."""
    absolute_workspace_path = os.path.join(app.config['SHARED_VOLUME_PATH'],
                                           workflow.workspace_path)
    absolute_source_path = os.path.join(app.config['SHARED_VOLUME_PATH'],
                                        absolute_workspace_path, source)
    absolute_target_path = os.path.join(app.config['SHARED_VOLUME_PATH'],
                                        absolute_workspace_path, target)

    if not os.path.exists(absolute_source_path):
        message = 'Path {} does not exist'.format(source)
        raise REANAWorkflowControllerError(message)
    if not absolute_source_path.startswith(absolute_workspace_path):
        message = 'Source path is outside user workspace'
        raise REANAWorkflowControllerError(message)
    if not absolute_source_path.startswith(absolute_workspace_path):
        message = 'Target path is outside workspace'
        raise REANAWorkflowControllerError(message)
    try:
        reana_fs = fs.open_fs(absolute_workspace_path)
        source_info = reana_fs.getinfo(source)
        if source_info.is_dir:
            reana_fs.movedir(src_path=source, dst_path=target, create=True)
        else:
            reana_fs.move(src_path=source, dst_path=target)
        reana_fs.close()
    except Exception as e:
        reana_fs.close()
        message = 'Something went wrong:\n {}'.format(e)
        raise REANAWorkflowControllerError(message)
Beispiel #2
0
def start_workflow(workflow, parameters):
    """Start a workflow."""

    def _start_workflow_db(workflow, parameters):
        workflow.run_started_at = datetime.now()
        workflow.status = WorkflowStatus.running
        if parameters:
            workflow.input_parameters = parameters.get("input_parameters")
            workflow.operational_options = parameters.get("operational_options")
        current_db_sessions.add(workflow)
        current_db_sessions.commit()

    current_db_sessions = Session.object_session(workflow)
    kwrm = KubernetesWorkflowRunManager(workflow)

    failure_message = (
        "Workflow {id_} could not be started because it {verb} " "already {status}."
    ).format(
        id_=workflow.id_,
        verb=get_workflow_status_change_verb(workflow.status.name),
        status=str(workflow.status.name),
    )
    if "restart" in parameters.keys():
        if parameters["restart"]:
            if workflow.status not in [
                WorkflowStatus.failed,
                WorkflowStatus.finished,
                WorkflowStatus.queued,
            ]:
                raise REANAWorkflowControllerError(failure_message)
    elif workflow.status not in [WorkflowStatus.created, WorkflowStatus.queued]:
        if workflow.status == WorkflowStatus.deleted:
            raise REANAWorkflowStatusError(failure_message)
        raise REANAWorkflowControllerError(failure_message)

    try:
        kwrm.start_batch_workflow_run(
            overwrite_input_params=parameters.get("input_parameters"),
            overwrite_operational_options=parameters.get("operational_options"),
        )
        _start_workflow_db(workflow, parameters)
    except SQLAlchemyError as e:
        message = "Database connection failed, please retry."
        logging.error(
            f"Error while creating {workflow.id_}: {message}\n{e}", exc_info=True
        )
        # Rollback Kubernetes job creation
        kwrm.stop_batch_workflow_run()
        logging.error(
            f"Stopping Kubernetes jobs associated with workflow " f"{workflow.id_} ..."
        )
        raise REANAExternalCallError(message)
    except ApiException as e:
        message = "Kubernetes connection failed, please retry."
        logging.error(
            f"Error while creating {workflow.id_}: {message}\n{e}", exc_info=True
        )
        raise REANAExternalCallError(message)
def _delete_workflow_engine_pod(workflow):
    """Delete workflow engine pod."""
    try:
        jobs = current_k8s_corev1_api_client.list_namespaced_pod(
            namespace=REANA_RUNTIME_KUBERNETES_NAMESPACE,
        )
        for job in jobs.items:
            if str(workflow.id_) in job.metadata.name:
                workflow_enginge_logs = current_k8s_corev1_api_client.read_namespaced_pod_log(
                    namespace=job.metadata.namespace,
                    name=job.metadata.name,
                    container="workflow-engine",
                )
                workflow.logs = (workflow.logs or "") + workflow_enginge_logs + "\n"
                current_k8s_batchv1_api_client.delete_namespaced_job(
                    namespace=job.metadata.namespace,
                    propagation_policy="Background",
                    name=job.metadata.labels["job-name"],
                )
                break
    except ApiException as e:
        raise REANAWorkflowControllerError(
            "Workflow engine pod cound not be deleted {}.".format(e)
        )
    except Exception as e:
        logging.error(traceback.format_exc())
        logging.error("Unexpected error: {}".format(e))
def _delete_workflow_engine_pod(workflow):
    """Delete workflow engine pod."""
    try:
        jobs = current_k8s_corev1_api_client.list_namespaced_pod(
            namespace='default',
        )
        for job in jobs.items:
            if str(workflow.id_) in job.metadata.name:
                workflow_enginge_logs = \
                    current_k8s_corev1_api_client.read_namespaced_pod_log(
                        namespace=job.metadata.namespace,
                        name=job.metadata.name,
                        container='workflow-engine')
                workflow.logs =  \
                    (workflow.logs or '') + workflow_enginge_logs + '\n'
                current_k8s_batchv1_api_client.delete_namespaced_job(
                    namespace='default',
                    propagation_policy="Background",
                    name=job.metadata.labels['job-name'])
                break
    except ApiException as e:
        raise REANAWorkflowControllerError(
            "Workflow engine pod cound not be deleted {}.".format(e))
    except Exception as e:
        logging.error(traceback.format_exc())
        logging.error("Unexpected error: {}".format(e))
Beispiel #5
0
def stop_workflow(workflow):
    """Stop a given workflow."""
    if workflow.status == RunStatus.running:
        kwrm = KubernetesWorkflowRunManager(workflow)
        kwrm.stop_batch_workflow_run()
        workflow.status = RunStatus.stopped
        Session.add(workflow)
        Session.commit()
    else:
        message = ("Workflow {id_} is not running.").format(id_=workflow.id_)
        raise REANAWorkflowControllerError(message)
def _delete_workflow_job(workflow: Workflow) -> None:
    job_name = build_unique_component_name("run-batch", workflow.id_)
    try:
        current_k8s_batchv1_api_client.delete_namespaced_job(
            name=job_name,
            namespace=REANA_RUNTIME_KUBERNETES_NAMESPACE,
            propagation_policy="Background",
        )
    except ApiException as e:
        raise REANAWorkflowControllerError(
            f"Workflow engine pod could not be deleted. Error: {e}")
Beispiel #7
0
 def start_batch_workflow_run(self):
     """Start a batch workflow run."""
     workflow_run_name = self._workflow_run_name_generator('batch')
     job = self._create_job_spec(workflow_run_name)
     try:
         current_k8s_batchv1_api_client.create_namespaced_job(
             namespace=KubernetesWorkflowRunManager.default_namespace,
             body=job)
     except ApiException as e:
         msg = 'Workflow engine/job controller pod ' \
               'creation failed {}'.format(e)
         logging.error(msg, exc_info=True)
         raise REANAWorkflowControllerError(e)
Beispiel #8
0
def stop_workflow(workflow):
    """Stop a given workflow."""
    if workflow.status == WorkflowStatus.running:
        kwrm = KubernetesWorkflowRunManager(workflow)
        workflow.run_stopped_at = datetime.now()
        kwrm.stop_batch_workflow_run()
        workflow.status = WorkflowStatus.stopped
        current_db_sessions = Session.object_session(workflow)
        current_db_sessions.add(workflow)
        current_db_sessions.commit()
    else:
        message = ("Workflow {id_} is not running.").format(id_=workflow.id_)
        raise REANAWorkflowControllerError(message)
def _delete_workflow_engine_pod(workflow_uuid):
    """Delete workflow engine pod."""
    try:
        jobs = current_k8s_batchv1_api_client.list_namespaced_job(
            namespace='default', )
        for job in jobs.items:
            if workflow_uuid in job.metadata.name:
                current_k8s_batchv1_api_client.delete_namespaced_job(
                    namespace='default',
                    propagation_policy="Background",
                    name=job.metadata.name)
                break
    except ApiException as e:
        raise REANAWorkflowControllerError(
            "Workflow engine pod cound not be deleted {}.".format(e))
def _get_workflow_engine_pod_logs(workflow: Workflow) -> str:
    try:
        pods = current_k8s_corev1_api_client.list_namespaced_pod(
            namespace=REANA_RUNTIME_KUBERNETES_NAMESPACE,
            label_selector=f"reana-run-batch-workflow-uuid={str(workflow.id_)}",
        )
        for pod in pods.items:
            if str(workflow.id_) in pod.metadata.name:
                return current_k8s_corev1_api_client.read_namespaced_pod_log(
                    namespace=pod.metadata.namespace,
                    name=pod.metadata.name,
                    container="workflow-engine",
                )
    except ApiException as e:
        raise REANAWorkflowControllerError(
            f"Workflow engine pod logs could not be fetched. Error: {e}")