def do_operation_launch(operation_id):
    """
    Event attached to the local queue for executing an operation, when we will have resources available.
    """
    log = get_logger('tvb.core.operation_async_launcher')
    burst_service = BurstService()

    try:
        log.debug("Loading operation with id=%s" % operation_id)
        curent_operation = dao.get_operation_by_id(operation_id)
        stored_adapter = curent_operation.algorithm
        log.debug("Importing Algorithm: " + str(stored_adapter.classname) +
                  " for Operation:" + str(curent_operation.id))
        adapter_instance = ABCAdapter.build_adapter(stored_adapter)
        # Un-comment bellow for profiling an operation:
        # import cherrypy.lib.profiler as profiler
        # p = profiler.Profiler("/Users/lia.domide/TVB/profiler/")
        # p.run(OperationService().initiate_prelaunch, curent_operation, adapter_instance, {}, **PARAMS)

        OperationService().initiate_prelaunch(curent_operation,
                                              adapter_instance)
        if curent_operation.fk_operation_group:
            parent_burst = dao.get_generic_entity(
                BurstConfiguration, curent_operation.fk_operation_group,
                'fk_operation_group')[0]
            operations_in_group = dao.get_operations_in_group(
                curent_operation.fk_operation_group)
            if parent_burst.fk_metric_operation_group:
                operations_in_group.extend(
                    dao.get_operations_in_group(
                        parent_burst.fk_metric_operation_group))
            burst_finished = True
            for operation in operations_in_group:
                if not has_finished(operation.status):
                    burst_finished = False
                    break

            if burst_finished and parent_burst is not None and parent_burst.status != BurstConfiguration.BURST_ERROR:
                burst_service.mark_burst_finished(parent_burst)
        else:
            parent_burst = burst_service.get_burst_for_operation_id(
                operation_id)
            if parent_burst is not None:
                burst_service.mark_burst_finished(parent_burst)

        log.debug("Successfully finished operation " + str(operation_id))

    except Exception as excep:
        log.error("Could not execute operation " + str(operation_id))
        log.exception(excep)
        parent_burst = burst_service.get_burst_for_operation_id(operation_id)
        if parent_burst is not None:
            burst_service.mark_burst_finished(parent_burst,
                                              error_message=str(excep))
예제 #2
0
class SimulatorService(object):
    def __init__(self):
        self.logger = get_logger(self.__class__.__module__)
        self.burst_service = BurstService()
        self.operation_service = OperationService()
        self.files_helper = FilesHelper()

    def _reset_model(self, session_stored_simulator):
        session_stored_simulator.model = type(session_stored_simulator.model)()
        vi_indexes = MonitorForm.determine_indexes_for_chosen_vars_of_interest(
            session_stored_simulator)
        vi_indexes = numpy.array(list(vi_indexes.values()))
        for monitor in session_stored_simulator.monitors:
            monitor.variables_of_interest = vi_indexes

    def reset_at_connectivity_change(self, is_simulator_copy, form,
                                     session_stored_simulator):
        """
        In case the user copies a simulation and changes the Connectivity, we want to reset the Model and Noise
        parameters because they might not fit to the new Connectivity's nr of regions.
        """
        if is_simulator_copy and form.connectivity.value != session_stored_simulator.connectivity:
            self._reset_model(session_stored_simulator)
            if issubclass(type(session_stored_simulator.integrator),
                          IntegratorStochastic):
                session_stored_simulator.integrator.noise = type(
                    session_stored_simulator.integrator.noise)()

    def reset_at_surface_change(self, is_simulator_copy, form,
                                session_stored_simulator):
        """
        In case the user copies a surface-simulation and changes the Surface, we want to reset the Model
        parameters because they might not fit to the new Surface's nr of vertices.
        """
        if is_simulator_copy and (
                session_stored_simulator.surface is None and form.surface.value
                or session_stored_simulator.surface and form.surface.value !=
                session_stored_simulator.surface.surface_gid):
            self._reset_model(session_stored_simulator)

    @staticmethod
    def _set_simulator_range_parameter(simulator, range_parameter_name,
                                       range_parameter_value):
        range_param_name_list = range_parameter_name.split('.')
        current_attr = simulator
        for param_name in range_param_name_list[:len(range_param_name_list) -
                                                1]:
            current_attr = getattr(current_attr, param_name)
        setattr(current_attr, range_param_name_list[-1], range_parameter_value)

    def async_launch_and_prepare_simulation(self, burst_config, user, project,
                                            simulator_algo,
                                            session_stored_simulator):
        try:
            operation = self.operation_service.prepare_operation(
                user.id, project.id, simulator_algo,
                session_stored_simulator.gid)
            ga = self.operation_service._prepare_metadata(
                simulator_algo.algorithm_category, {}, None, burst_config.gid)
            session_stored_simulator.generic_attributes = ga
            storage_path = self.files_helper.get_project_folder(
                project, str(operation.id))
            h5.store_view_model(session_stored_simulator, storage_path)
            burst_config = self.burst_service.update_simulation_fields(
                burst_config.id, operation.id, session_stored_simulator.gid)
            self.burst_service.store_burst_configuration(
                burst_config, storage_path)

            wf_errs = 0
            try:
                OperationService().launch_operation(operation.id, True)
                return operation
            except Exception as excep:
                self.logger.error(excep)
                wf_errs += 1
                if burst_config:
                    self.burst_service.mark_burst_finished(
                        burst_config, error_message=str(excep))

            self.logger.debug(
                "Finished launching workflow. The operation was launched successfully, "
                + str(wf_errs) + " had error on pre-launch steps")

        except Exception as excep:
            self.logger.error(excep)
            if burst_config:
                self.burst_service.mark_burst_finished(
                    burst_config, error_message=str(excep))

    def prepare_simulation_on_server(self, user_id, project, algorithm,
                                     zip_folder_path, simulator_file):
        simulator_vm = h5.load_view_model_from_file(simulator_file)
        operation = self.operation_service.prepare_operation(
            user_id, project.id, algorithm, simulator_vm.gid)
        storage_operation_path = self.files_helper.get_project_folder(
            project, str(operation.id))
        self.async_launch_simulation_on_server(operation, zip_folder_path,
                                               storage_operation_path)

        return operation

    def async_launch_simulation_on_server(self, operation, zip_folder_path,
                                          storage_operation_path):
        try:
            for file in os.listdir(zip_folder_path):
                shutil.move(os.path.join(zip_folder_path, file),
                            storage_operation_path)
            try:
                OperationService().launch_operation(operation.id, True)
                shutil.rmtree(zip_folder_path)
                return operation
            except Exception as excep:
                self.logger.error(excep)
        except Exception as excep:
            self.logger.error(excep)

    @staticmethod
    def _set_range_param_in_dict(param_value):
        if type(param_value) is numpy.ndarray:
            return param_value[0]
        elif isinstance(param_value, uuid.UUID):
            return param_value.hex
        else:
            return param_value

    def async_launch_and_prepare_pse(self, burst_config, user, project,
                                     simulator_algo, range_param1,
                                     range_param2, session_stored_simulator):
        try:
            algo_category = simulator_algo.algorithm_category
            operation_group = burst_config.operation_group
            metric_operation_group = burst_config.metric_operation_group
            operations = []
            range_param2_values = [None]
            if range_param2:
                range_param2_values = range_param2.get_range_values()
            first_simulator = None

            ga = self.operation_service._prepare_metadata(
                simulator_algo.algorithm_category, {}, operation_group,
                burst_config.gid)
            session_stored_simulator.generic_attributes = ga

            for param1_value in range_param1.get_range_values():
                for param2_value in range_param2_values:
                    # Copy, but generate a new GUID for every Simulator in PSE
                    simulator = copy.deepcopy(session_stored_simulator)
                    simulator.gid = uuid.uuid4()
                    self._set_simulator_range_parameter(
                        simulator, range_param1.name, param1_value)

                    ranges = {
                        range_param1.name:
                        self._set_range_param_in_dict(param1_value)
                    }

                    if param2_value is not None:
                        self._set_simulator_range_parameter(
                            simulator, range_param2.name, param2_value)
                        ranges[
                            range_param2.name] = self._set_range_param_in_dict(
                                param2_value)

                    ranges = json.dumps(ranges)

                    operation = self.operation_service.prepare_operation(
                        user.id, project.id, simulator_algo, simulator.gid,
                        operation_group, ranges)

                    storage_path = self.files_helper.get_project_folder(
                        project, str(operation.id))
                    h5.store_view_model(simulator, storage_path)
                    operations.append(operation)
                    if first_simulator is None:
                        first_simulator = simulator

            first_operation = operations[0]
            storage_path = self.files_helper.get_project_folder(
                project, str(first_operation.id))
            burst_config = self.burst_service.update_simulation_fields(
                burst_config.id, first_operation.id, first_simulator.gid)
            self.burst_service.store_burst_configuration(
                burst_config, storage_path)
            datatype_group = DataTypeGroup(
                operation_group,
                operation_id=first_operation.id,
                fk_parent_burst=burst_config.gid,
                state=algo_category.defaultdatastate)
            dao.store_entity(datatype_group)

            metrics_datatype_group = DataTypeGroup(
                metric_operation_group, fk_parent_burst=burst_config.gid)
            dao.store_entity(metrics_datatype_group)

            wf_errs = 0
            for operation in operations:
                try:
                    OperationService().launch_operation(operation.id, True)
                except Exception as excep:
                    self.logger.error(excep)
                    wf_errs += 1
                    self.burst_service.mark_burst_finished(
                        burst_config, error_message=str(excep))

            self.logger.debug("Finished launching workflows. " +
                              str(len(operations) - wf_errs) +
                              " were launched successfully, " + str(wf_errs) +
                              " had error on pre-launch steps")
            return first_operation

        except Exception as excep:
            self.logger.error(excep)
            self.burst_service.mark_burst_finished(burst_config,
                                                   error_message=str(excep))

    def load_from_zip(self, zip_file, project):
        import_service = ImportService()
        simulator_folder = import_service.import_simulator_configuration_zip(
            zip_file)

        simulator_h5_filename = DirLoader(
            simulator_folder,
            None).find_file_for_has_traits_type(SimulatorAdapterModel)
        simulator_h5_filepath = os.path.join(simulator_folder,
                                             simulator_h5_filename)
        simulator = h5.load_view_model_from_file(simulator_h5_filepath)

        burst_config = self.burst_service.load_burst_configuration_from_folder(
            simulator_folder, project)
        return simulator, burst_config
예제 #3
0
class SimulatorService(object):
    def __init__(self):
        self.logger = get_logger(self.__class__.__module__)
        self.burst_service = BurstService()
        self.operation_service = OperationService()
        self.algorithm_service = AlgorithmService()
        self.storage_interface = StorageInterface()

    @staticmethod
    def _reset_model(session_stored_simulator):
        session_stored_simulator.model = type(session_stored_simulator.model)()
        vi_indexes = session_stored_simulator.determine_indexes_for_chosen_vars_of_interest(
        )
        vi_indexes = numpy.array(list(vi_indexes.values()))
        for monitor in session_stored_simulator.monitors:
            monitor.variables_of_interest = vi_indexes

    def reset_at_connectivity_change(self, is_simulator_copy, form,
                                     session_stored_simulator):
        """
        In case the user copies a simulation and changes the Connectivity, we want to reset the Model and Noise
        parameters because they might not fit to the new Connectivity's nr of regions.
        """
        if is_simulator_copy and form.connectivity.value != session_stored_simulator.connectivity:
            self._reset_model(session_stored_simulator)
            if issubclass(type(session_stored_simulator.integrator),
                          IntegratorStochastic):
                session_stored_simulator.integrator.noise = type(
                    session_stored_simulator.integrator.noise)()

    def reset_at_surface_change(self, is_simulator_copy, form,
                                session_stored_simulator):
        """
        In case the user copies a surface-simulation and changes the Surface, we want to reset the Model
        parameters because they might not fit to the new Surface's nr of vertices.
        """
        if is_simulator_copy and (
                session_stored_simulator.surface is None and form.surface.value
                or session_stored_simulator.surface and form.surface.value !=
                session_stored_simulator.surface.surface_gid):
            self._reset_model(session_stored_simulator)

    @staticmethod
    def _set_simulator_range_parameter(simulator, range_parameter_name,
                                       range_parameter_value):
        range_param_name_list = range_parameter_name.split('.')
        current_attr = simulator
        for param_name in range_param_name_list[:len(range_param_name_list) -
                                                1]:
            current_attr = getattr(current_attr, param_name)
        setattr(current_attr, range_param_name_list[-1], range_parameter_value)

    def async_launch_and_prepare_simulation(self, burst_config, user, project,
                                            simulator_algo, simulator):
        try:
            operation = self.operation_service.prepare_operation(
                user.id,
                project,
                simulator_algo,
                view_model=simulator,
                burst_gid=burst_config.gid,
                op_group_id=burst_config.fk_operation_group)
            burst_config = self.burst_service.update_simulation_fields(
                burst_config, operation.id, simulator.gid)
            storage_path = self.storage_interface.get_project_folder(
                project.name, str(operation.id))
            self.burst_service.store_burst_configuration(
                burst_config, storage_path)

            wf_errs = 0
            try:
                OperationService().launch_operation(operation.id, True)
                return operation
            except Exception as excep:
                self.logger.error(excep)
                wf_errs += 1
                if burst_config:
                    self.burst_service.mark_burst_finished(
                        burst_config, error_message=str(excep))

            self.logger.debug(
                "Finished launching workflow. The operation was launched successfully, "
                + str(wf_errs) + " had error on pre-launch steps")

        except Exception as excep:
            self.logger.error(excep)
            if burst_config:
                self.burst_service.mark_burst_finished(
                    burst_config, error_message=str(excep))

    def prepare_simulation_on_server(self, user_id, project, algorithm,
                                     zip_folder_path, simulator_file):
        simulator_vm = h5.load_view_model_from_file(simulator_file)
        operation = self.operation_service.prepare_operation(
            user_id, project, algorithm, view_model=simulator_vm)
        self.async_launch_simulation_on_server(operation, zip_folder_path)

        return operation

    def async_launch_simulation_on_server(self, operation, zip_folder_path):
        try:
            OperationService().launch_operation(operation.id, True)
            return operation
        except Exception as excep:
            self.logger.error(excep)
        finally:
            shutil.rmtree(zip_folder_path)

    @staticmethod
    def _set_range_param_in_dict(param_value):
        if type(param_value) is numpy.ndarray:
            return param_value[0]
        elif isinstance(param_value, uuid.UUID):
            return param_value.hex
        else:
            return param_value

    def async_launch_and_prepare_pse(self, burst_config, user, project,
                                     simulator_algo, range_param1,
                                     range_param2, session_stored_simulator):
        try:
            algo_category = simulator_algo.algorithm_category
            operation_group = burst_config.operation_group
            metric_operation_group = burst_config.metric_operation_group
            range_param2_values = [None]
            if range_param2:
                range_param2_values = range_param2.get_range_values()
            GROUP_BURST_PENDING[burst_config.id] = True
            operations, pse_canceled = self._prepare_operations(
                algo_category, burst_config, metric_operation_group,
                operation_group, project, range_param1, range_param2,
                range_param2_values, session_stored_simulator, simulator_algo,
                user)

            GROUP_BURST_PENDING[burst_config.id] = False
            if pse_canceled:
                return

            wf_errs = self._launch_operations(operations, burst_config)
            self.logger.debug("Finished launching workflows. " +
                              str(len(operations) - wf_errs) +
                              " were launched successfully, " + str(wf_errs) +
                              " had error on pre-launch steps")
            return operations[0] if len(operations) > 0 else None

        except Exception as excep:
            self.logger.error(excep)
            self.burst_service.mark_burst_finished(burst_config,
                                                   error_message=str(excep))

    def _launch_operations(self, operations, burst_config):
        wf_errs = 0
        for operation in operations:
            try:
                burst_config = dao.get_burst_by_id(burst_config.id)
                if burst_config is None or burst_config.status in [
                        BurstConfiguration.BURST_CANCELED,
                        BurstConfiguration.BURST_ERROR
                ]:
                    self.logger.debug(
                        "Preparing operations cannot continue. Burst config {}"
                        .format(burst_config))
                    return
                OperationService().launch_operation(operation.id, True)
            except Exception as excep:
                self.logger.error(excep)
                wf_errs += 1
                self.burst_service.mark_burst_finished(
                    burst_config, error_message=str(excep))
        return wf_errs

    def _prepare_operations(self, algo_category, burst_config,
                            metric_operation_group, operation_group, project,
                            range_param1, range_param2, range_param2_values,
                            session_stored_simulator, simulator_algo, user):
        first_simulator = None
        pse_canceled = False
        operations = []
        for param1_value in range_param1.get_range_values():
            for param2_value in range_param2_values:
                burst_config = dao.get_burst_by_id(burst_config.id)
                if burst_config is None:
                    self.logger.debug("Burst config was deleted")
                    pse_canceled = True
                    break

                if burst_config.status in [
                        BurstConfiguration.BURST_CANCELED,
                        BurstConfiguration.BURST_ERROR
                ]:
                    self.logger.debug(
                        "Current burst status is {}. Preparing operations cannot continue."
                        .format(burst_config.status))
                    pse_canceled = True
                    break
                # Copy, but generate a new GUID for every Simulator in PSE
                simulator = copy.deepcopy(session_stored_simulator)
                simulator.gid = uuid.uuid4()
                self._set_simulator_range_parameter(simulator,
                                                    range_param1.name,
                                                    param1_value)

                ranges = {
                    range_param1.name:
                    self._set_range_param_in_dict(param1_value)
                }

                if param2_value is not None:
                    self._set_simulator_range_parameter(
                        simulator, range_param2.name, param2_value)
                    ranges[range_param2.name] = self._set_range_param_in_dict(
                        param2_value)

                ranges = json.dumps(ranges)

                operation = self.operation_service.prepare_operation(
                    user.id,
                    project,
                    simulator_algo,
                    view_model=simulator,
                    ranges=ranges,
                    burst_gid=burst_config.gid,
                    op_group_id=burst_config.fk_operation_group)
                simulator.range_values = ranges
                operations.append(operation)
                if first_simulator is None:
                    first_simulator = simulator
                    storage_path = self.storage_interface.get_project_folder(
                        project.name, str(operation.id))
                    burst_config = self.burst_service.update_simulation_fields(
                        burst_config, operation.id, first_simulator.gid)
                    self.burst_service.store_burst_configuration(
                        burst_config, storage_path)
                    datatype_group = DataTypeGroup(
                        operation_group,
                        operation_id=operation.id,
                        fk_parent_burst=burst_config.gid,
                        state=algo_category.defaultdatastate)
                    dao.store_entity(datatype_group)

                    metrics_datatype_group = DataTypeGroup(
                        metric_operation_group,
                        fk_parent_burst=burst_config.gid,
                        state=algo_category.defaultdatastate)
                    dao.store_entity(metrics_datatype_group)
        return operations, pse_canceled

    @staticmethod
    def compute_conn_branch_conditions(is_branch, simulator):
        if not is_branch:
            return None

        conn = load.load_entity_by_gid(simulator.connectivity)
        if conn.number_of_regions:
            return FilterChain(
                fields=[FilterChain.datatype + '.number_of_regions'],
                operations=["=="],
                values=[conn.number_of_regions])

    @staticmethod
    def validate_first_fragment(form, project_id, conn_idx):
        conn_count = dao.count_datatypes(project_id, conn_idx)
        if conn_count == 0:
            form.connectivity.errors.append(
                "No connectivity in the project! Simulation cannot be started without "
                "a connectivity!")

    def get_simulation_state_index(self, burst_config,
                                   simulation_history_class):
        parent_burst = burst_config.parent_burst_object
        simulation_state_index = dao.get_generic_entity(
            simulation_history_class, parent_burst.gid, "fk_parent_burst")

        if simulation_state_index is None or len(simulation_state_index) < 1:
            exc = BurstServiceException(
                "Simulation State not found for %s, thus we are unable to branch from "
                "it!" % burst_config.name)
            self.logger.error(exc)
            raise exc

        return simulation_state_index
예제 #4
0
class SimulatorController(BurstBaseController):
    KEY_IS_LOAD_AFTER_REDIRECT = "is_load_after_redirect"
    COPY_NAME_FORMAT = "copy_of_{}"
    BRANCH_NAME_FORMAT = "{}_branch{}"
    KEY_KEEP_SAME_SIM_WIZARD = "keep_same_wizard"

    def __init__(self):
        BurstBaseController.__init__(self)
        self.range_parameters = SimulatorRangeParameters()
        self.burst_service = BurstService()
        self.simulator_service = SimulatorService()
        self.cached_simulator_algorithm = self.algorithm_service.get_algorithm_by_module_and_class(
            IntrospectionRegistry.SIMULATOR_MODULE,
            IntrospectionRegistry.SIMULATOR_CLASS)
        self.context = SimulatorContext()
        self.monitors_handler = MonitorsWizardHandler()

    @expose_json
    def cancel_or_remove_burst(self, burst_id):
        """
        Cancel or Remove the burst entity given by burst_id (and all linked entities: op, DTs)
        :returns True: if the op was successfully.
        """
        burst_config = BurstService.load_burst_configuration(int(burst_id))
        op_id, is_group = burst_config.operation_info_for_burst_removal

        return self.cancel_or_remove_operation(op_id, is_group,
                                               burst_config.is_finished)

    def cancel_or_remove_operation(self,
                                   operation_id,
                                   is_group,
                                   remove_after_stop=False):
        """
        Stop the operation given by operation_id. If is_group is true stop all the
        operations from that group.
        """
        # Load before we remove, to have its data in memory here
        burst_config = BurstService.get_burst_for_operation_id(
            operation_id, is_group)
        if burst_config is not None:
            self.burst_service.mark_burst_finished(
                burst_config,
                BurstConfiguration.BURST_CANCELED,
                store_h5_file=False)
            while GROUP_BURST_PENDING.get(burst_config.id, False):
                pass
            GROUP_BURST_PENDING.pop(burst_config.id, False)
        result = OperationService.stop_operation(operation_id, is_group,
                                                 remove_after_stop)

        if remove_after_stop:
            current_burst = self.context.burst_config
            if (current_burst is not None and burst_config is not None
                    and current_burst.id == burst_config.id and
                ((current_burst.fk_simulation == operation_id and not is_group)
                 or (current_burst.fk_operation_group == operation_id
                     and is_group))):
                self.reset_simulator_configuration()
            if burst_config is not None:
                burst_config = BurstService.load_burst_configuration(
                    burst_config.id)
                if burst_config:
                    BurstService.remove_burst_configuration(burst_config.id)
        return result

    @expose_page
    @settings
    @context_selected
    def index(self):
        """Get on burst main page"""
        template_specification = dict(
            mainContent="burst/main_burst",
            title="Simulation Cockpit",
            includedResources='project/included_resources')

        if not self.context.last_loaded_fragment_url:
            self.context.add_last_loaded_form_url_to_session(
                SimulatorWizzardURLs.SET_CONNECTIVITY_URL)

        self.context.set_burst_config()

        _, is_simulation_copy, is_simulation_load, is_branch = self.context.get_common_params(
        )
        if self.context.burst_config.start_time is not None:
            is_simulation_load = True
            self.context.add_simulator_load_to_session(True)

        template_specification['burstConfig'] = self.context.burst_config
        template_specification[
            'burst_list'] = self.burst_service.get_available_bursts(
                self.context.project.id)

        form = self.prepare_first_fragment()
        rendering_rules = SimulatorFragmentRenderingRules(
            form,
            SimulatorWizzardURLs.SET_CONNECTIVITY_URL,
            None,
            is_simulation_copy,
            is_simulation_load,
            last_form_url=self.context.last_loaded_fragment_url,
            last_request_type=cherrypy.request.method,
            is_first_fragment=True,
            is_branch=is_branch)
        template_specification.update(**rendering_rules.to_dict())

        cherrypy.response.headers[
            'Cache-Control'] = 'no-cache, no-store, must-revalidate'
        cherrypy.response.headers['Pragma'] = 'no-cache'
        cherrypy.response.headers['Expires'] = '0'

        return self.fill_default_attributes(template_specification)

    def prepare_first_fragment(self):
        self.context.set_simulator()
        simulator, _, _, is_branch = self.context.get_common_params()
        branch_conditions = self.simulator_service.compute_conn_branch_conditions(
            is_branch, simulator)
        form = self.algorithm_service.prepare_adapter_form(
            form_instance=SimulatorAdapterForm(),
            project_id=self.context.project.id,
            extra_conditions=branch_conditions)

        self.simulator_service.validate_first_fragment(form,
                                                       self.context.project.id,
                                                       ConnectivityIndex)
        form.fill_from_trait(self.context.simulator)
        return form

    @expose_json
    def set_fragment_url(self, **data):
        try:
            self.context.add_last_loaded_form_url_to_session(data['url'])
        except KeyError:
            self.logger.error(
                "Cannot set last loaded url to session because the required data was not found."
            )

    @expose_fragment('simulator_fragment')
    def set_connectivity(self, **data):
        session_stored_simulator, is_simulation_copy, is_simulation_load, _ = self.context.get_common_params(
        )

        if cherrypy.request.method == POST_REQUEST:
            self.context.add_last_loaded_form_url_to_session(
                SimulatorWizzardURLs.SET_COUPLING_PARAMS_URL)
            form = SimulatorAdapterForm()
            form.fill_from_post(data)
            self.simulator_service.reset_at_connectivity_change(
                is_simulation_copy, form, session_stored_simulator)
            form.fill_trait(session_stored_simulator)

        next_form = self.algorithm_service.prepare_adapter_form(
            form_instance=get_form_for_coupling(
                type(session_stored_simulator.coupling))())
        self.range_parameters.coupling_parameters = next_form.get_range_parameters(
        )
        next_form.fill_from_trait(session_stored_simulator.coupling)

        rendering_rules = SimulatorFragmentRenderingRules(
            next_form, SimulatorWizzardURLs.SET_COUPLING_PARAMS_URL,
            SimulatorWizzardURLs.SET_CONNECTIVITY_URL, is_simulation_copy,
            is_simulation_load, self.context.last_loaded_fragment_url,
            cherrypy.request.method)
        return rendering_rules.to_dict()

    @expose_fragment('simulator_fragment')
    def set_coupling_params(self, **data):
        session_stored_simulator, is_simulation_copy, is_simulation_load, is_branch = self.context.get_common_params(
        )

        if cherrypy.request.method == POST_REQUEST:
            self.context.add_last_loaded_form_url_to_session(
                SimulatorWizzardURLs.SET_SURFACE_URL)
            form = get_form_for_coupling(
                type(session_stored_simulator.coupling))()
            form.fill_from_post(data)
            form.fill_trait(session_stored_simulator.coupling)

        surface_fragment = self.algorithm_service.prepare_adapter_form(
            form_instance=SimulatorSurfaceFragment(),
            project_id=self.context.project.id)
        surface_fragment.fill_from_trait(session_stored_simulator.surface)

        rendering_rules = SimulatorFragmentRenderingRules(
            surface_fragment,
            SimulatorWizzardURLs.SET_SURFACE_URL,
            SimulatorWizzardURLs.SET_COUPLING_PARAMS_URL,
            is_simulation_copy,
            is_simulation_load,
            self.context.last_loaded_fragment_url,
            cherrypy.request.method,
            is_branch=is_branch)
        return rendering_rules.to_dict()

    @expose_fragment('simulator_fragment')
    def set_surface(self, **data):
        session_stored_simulator, is_simulation_copy, is_simulation_load, is_branch = self.context.get_common_params(
        )
        rendering_rules = SimulatorFragmentRenderingRules(
            previous_form_action_url=SimulatorWizzardURLs.SET_SURFACE_URL,
            is_simulation_copy=is_simulation_copy,
            is_simulation_readonly_load=is_simulation_load,
            last_form_url=self.context.last_loaded_fragment_url,
            last_request_type=cherrypy.request.method,
            is_branch=is_branch)

        if cherrypy.request.method == POST_REQUEST:
            form = SimulatorSurfaceFragment()
            form.fill_from_post(data)
            self.simulator_service.reset_at_surface_change(
                is_simulation_copy, form, session_stored_simulator)
            form.fill_trait(session_stored_simulator)

            if session_stored_simulator.surface:
                self.context.add_last_loaded_form_url_to_session(
                    SimulatorWizzardURLs.SET_CORTEX_URL)
            else:
                self.context.add_last_loaded_form_url_to_session(
                    SimulatorWizzardURLs.SET_STIMULUS_URL)

        return SimulatorSurfaceFragment.prepare_next_fragment_after_surface(
            session_stored_simulator, rendering_rules, self.context.project.id,
            SimulatorWizzardURLs.SET_CORTEX_URL,
            SimulatorWizzardURLs.SET_STIMULUS_URL)

    @expose_fragment('simulator_fragment')
    def set_cortex(self, **data):
        session_stored_simulator, is_simulation_copy, is_simulation_load, _ = self.context.get_common_params(
        )

        if cherrypy.request.method == POST_REQUEST:
            self.context.add_last_loaded_form_url_to_session(
                SimulatorWizzardURLs.SET_STIMULUS_URL)
            rm_fragment = SimulatorRMFragment()
            rm_fragment.fill_from_post(data)
            rm_fragment.fill_trait(session_stored_simulator.surface)

        rendering_rules = SimulatorFragmentRenderingRules(
            None, None, SimulatorWizzardURLs.SET_CORTEX_URL,
            is_simulation_copy, is_simulation_load,
            self.context.last_loaded_fragment_url, cherrypy.request.method)

        return SimulatorStimulusFragment.prepare_stimulus_fragment(
            session_stored_simulator, rendering_rules, True,
            SimulatorWizzardURLs.SET_STIMULUS_URL, self.context.project.id)

    @expose_fragment('simulator_fragment')
    def set_stimulus(self, **data):
        session_stored_simulator, is_simulation_copy, is_simulation_load, is_branch = self.context.get_common_params(
        )

        if cherrypy.request.method == POST_REQUEST:
            self.context.add_last_loaded_form_url_to_session(
                SimulatorWizzardURLs.SET_MODEL_URL)
            stimuli_fragment = SimulatorStimulusFragment(
                session_stored_simulator.is_surface_simulation)
            stimuli_fragment.fill_from_post(data)
            stimuli_fragment.fill_trait(session_stored_simulator)

        model_fragment = self.algorithm_service.prepare_adapter_form(
            form_instance=SimulatorModelFragment())
        model_fragment.fill_from_trait(session_stored_simulator)

        rendering_rules = SimulatorFragmentRenderingRules(
            model_fragment,
            SimulatorWizzardURLs.SET_MODEL_URL,
            SimulatorWizzardURLs.SET_STIMULUS_URL,
            is_simulation_copy,
            is_simulation_load,
            self.context.last_loaded_fragment_url,
            cherrypy.request.method,
            is_model_fragment=True,
            is_surface_simulation=session_stored_simulator.
            is_surface_simulation,
            is_branch=is_branch)
        return rendering_rules.to_dict()

    @expose_fragment('simulator_fragment')
    def set_model(self, **data):
        session_stored_simulator, is_simulation_copy, is_simulation_load, is_branch = self.context.get_common_params(
        )

        if cherrypy.request.method == POST_REQUEST:
            set_next_wizard = True
            if SimulatorController.KEY_KEEP_SAME_SIM_WIZARD in data:
                set_next_wizard = False
            if set_next_wizard:
                self.context.add_last_loaded_form_url_to_session(
                    SimulatorWizzardURLs.SET_MODEL_PARAMS_URL)
            form = SimulatorModelFragment()
            form.fill_from_post(data)
            form.fill_trait(session_stored_simulator)

        form = self.algorithm_service.prepare_adapter_form(
            form_instance=get_form_for_model(
                type(session_stored_simulator.model))(is_branch))
        self.range_parameters.model_parameters = form.get_range_parameters()
        form.fill_from_trait(session_stored_simulator.model)

        rendering_rules = SimulatorFragmentRenderingRules(
            form, SimulatorWizzardURLs.SET_MODEL_PARAMS_URL,
            SimulatorWizzardURLs.SET_MODEL_URL, is_simulation_copy,
            is_simulation_load, self.context.last_loaded_fragment_url,
            cherrypy.request.method)
        return rendering_rules.to_dict()

    @expose_fragment('simulator_fragment')
    def set_model_params(self, **data):
        session_stored_simulator, is_simulation_copy, is_simulation_load, is_branch = self.context.get_common_params(
        )

        if cherrypy.request.method == POST_REQUEST:
            self.context.add_last_loaded_form_url_to_session(
                SimulatorWizzardURLs.SET_INTEGRATOR_URL)
            form = get_form_for_model(type(
                session_stored_simulator.model))(is_branch)

            if is_branch:
                data['variables_of_interest'] = list(
                    session_stored_simulator.model.variables_of_interest)

            form.fill_from_post(data)
            form.fill_trait(session_stored_simulator.model)

        integrator_fragment = self.algorithm_service.prepare_adapter_form(
            form_instance=SimulatorIntegratorFragment())
        integrator_fragment.integrator.display_subform = False
        integrator_fragment.fill_from_trait(session_stored_simulator)

        rendering_rules = SimulatorFragmentRenderingRules(
            integrator_fragment,
            SimulatorWizzardURLs.SET_INTEGRATOR_URL,
            SimulatorWizzardURLs.SET_MODEL_PARAMS_URL,
            is_simulation_copy,
            is_simulation_load,
            self.context.last_loaded_fragment_url,
            cherrypy.request.method,
            is_branch=is_branch)
        return rendering_rules.to_dict()

    @expose_fragment('simulator_fragment')
    def set_integrator(self, **data):
        session_stored_simulator, is_simulation_copy, is_simulation_load, is_branch = self.context.get_common_params(
        )

        if cherrypy.request.method == POST_REQUEST:
            self.context.add_last_loaded_form_url_to_session(
                SimulatorWizzardURLs.SET_INTEGRATOR_PARAMS_URL)
            fragment = SimulatorIntegratorFragment()
            fragment.fill_from_post(data)
            fragment.fill_trait(session_stored_simulator)

        form = self.algorithm_service.prepare_adapter_form(
            form_instance=get_form_for_integrator(
                type(session_stored_simulator.integrator))(is_branch))

        if hasattr(form, 'noise'):
            form.noise.display_subform = False

        form.fill_from_trait(session_stored_simulator.integrator)

        rendering_rules = SimulatorFragmentRenderingRules(
            form, SimulatorWizzardURLs.SET_INTEGRATOR_PARAMS_URL,
            SimulatorWizzardURLs.SET_INTEGRATOR_URL, is_simulation_copy,
            is_simulation_load, self.context.last_loaded_fragment_url,
            cherrypy.request.method)
        return rendering_rules.to_dict()

    @expose_fragment('simulator_fragment')
    def set_integrator_params(self, **data):
        session_stored_simulator, is_simulation_copy, is_simulation_load, is_branch = self.context.get_common_params(
        )

        if cherrypy.request.method == POST_REQUEST:
            form = get_form_for_integrator(
                type(session_stored_simulator.integrator))(is_branch)

            if is_branch:
                data['dt'] = str(session_stored_simulator.integrator.dt)

            form.fill_from_post(data)
            form.fill_trait(session_stored_simulator.integrator)

            if isinstance(session_stored_simulator.integrator,
                          IntegratorStochasticViewModel):
                self.context.add_last_loaded_form_url_to_session(
                    SimulatorWizzardURLs.SET_NOISE_PARAMS_URL)
            else:
                self.context.add_last_loaded_form_url_to_session(
                    SimulatorWizzardURLs.SET_MONITORS_URL)

        rendering_rules = SimulatorFragmentRenderingRules(
            None,
            None,
            SimulatorWizzardURLs.SET_INTEGRATOR_PARAMS_URL,
            is_simulation_copy,
            is_simulation_load,
            self.context.last_loaded_fragment_url,
            cherrypy.request.method,
            is_noise_fragment=False)

        if not isinstance(session_stored_simulator.integrator,
                          IntegratorStochasticViewModel):
            return self.monitors_handler.prepare_monitor_fragment(
                session_stored_simulator, rendering_rules,
                SimulatorWizzardURLs.SET_MONITORS_URL)

        integrator_noise_fragment = get_form_for_noise(
            type(session_stored_simulator.integrator.noise))()
        if hasattr(integrator_noise_fragment, 'equation'):
            integrator_noise_fragment.equation.display_subform = False

        self.range_parameters.integrator_noise_parameters = integrator_noise_fragment.get_range_parameters(
        )
        integrator_noise_fragment.fill_from_trait(
            session_stored_simulator.integrator.noise)

        rendering_rules.form = integrator_noise_fragment
        rendering_rules.form_action_url = SimulatorWizzardURLs.SET_NOISE_PARAMS_URL
        rendering_rules.is_noise_fragment = True
        return rendering_rules.to_dict()

    @expose_fragment('simulator_fragment')
    def set_noise_params(self, **data):
        session_stored_simulator, is_simulation_copy, is_simulation_load, is_branch = self.context.get_common_params(
        )

        if cherrypy.request.method == POST_REQUEST:
            form = get_form_for_noise(
                type(session_stored_simulator.integrator.noise))()
            form.fill_from_post(data)
            form.fill_trait(session_stored_simulator.integrator.noise)
            if isinstance(session_stored_simulator.integrator.noise,
                          AdditiveNoiseViewModel):
                self.context.add_last_loaded_form_url_to_session(
                    SimulatorWizzardURLs.SET_MONITORS_URL)
            else:
                self.context.add_last_loaded_form_url_to_session(
                    SimulatorWizzardURLs.SET_NOISE_EQUATION_PARAMS_URL)

        rendering_rules = SimulatorFragmentRenderingRules(
            None, None, SimulatorWizzardURLs.SET_NOISE_PARAMS_URL,
            is_simulation_copy, is_simulation_load,
            self.context.last_loaded_fragment_url, cherrypy.request.method)

        return self.monitors_handler.prepare_next_fragment_after_noise(
            session_stored_simulator, is_branch, rendering_rules,
            SimulatorWizzardURLs.SET_MONITORS_URL,
            SimulatorWizzardURLs.SET_NOISE_EQUATION_PARAMS_URL)

    @expose_fragment('simulator_fragment')
    def set_noise_equation_params(self, **data):
        session_stored_simulator, is_simulation_copy, is_simulation_load, _ = self.context.get_common_params(
        )

        if cherrypy.request.method == POST_REQUEST:
            self.context.add_last_loaded_form_url_to_session(
                SimulatorWizzardURLs.SET_MONITORS_URL)
            form = get_form_for_equation(
                type(session_stored_simulator.integrator.noise.b))()
            form.fill_from_post(data)
            form.fill_trait(session_stored_simulator.integrator.noise.b)

        rendering_rules = SimulatorFragmentRenderingRules(
            None, None, SimulatorWizzardURLs.SET_NOISE_EQUATION_PARAMS_URL,
            is_simulation_copy, is_simulation_load,
            self.context.last_loaded_fragment_url, cherrypy.request.method)

        return self.monitors_handler.prepare_monitor_fragment(
            session_stored_simulator, rendering_rules,
            SimulatorWizzardURLs.SET_MONITORS_URL)

    @staticmethod
    def build_monitor_url(fragment_url, monitor):
        url_regex = '{}/{}'
        url = url_regex.format(fragment_url, monitor)
        return url

    def get_first_monitor_fragment_url(self, simulator, monitors_url):
        first_monitor = simulator.first_monitor
        if first_monitor is not None:
            monitor_vm_name = type(first_monitor).__name__
            return self.build_monitor_url(monitors_url, monitor_vm_name)
        return SimulatorWizzardURLs.SETUP_PSE_URL

    @expose_fragment('simulator_fragment')
    def set_monitors(self, **data):
        session_stored_simulator, is_simulation_copy, is_simulation_load, is_branch = self.context.get_common_params(
        )
        if cherrypy.request.method == POST_REQUEST:
            fragment = SimulatorMonitorFragment(
                is_surface_simulation=session_stored_simulator.
                is_surface_simulation)
            fragment.fill_from_post(data)
            self.monitors_handler.set_monitors_list_on_simulator(
                session_stored_simulator, fragment.monitors.value)

        last_loaded_fragment_url = self.get_first_monitor_fragment_url(
            session_stored_simulator,
            SimulatorWizzardURLs.SET_MONITOR_PARAMS_URL)

        if cherrypy.request.method == POST_REQUEST:
            self.context.add_last_loaded_form_url_to_session(
                last_loaded_fragment_url)

        rendering_rules = SimulatorFragmentRenderingRules(
            is_simulation_copy=is_simulation_copy,
            is_simulation_readonly_load=is_simulation_load,
            last_request_type=cherrypy.request.method,
            form_action_url=last_loaded_fragment_url,
            previous_form_action_url=SimulatorWizzardURLs.SET_MONITORS_URL)
        return self.monitors_handler.get_fragment_after_monitors(
            session_stored_simulator, self.context.burst_config,
            self.context.project.id, is_branch, rendering_rules,
            SimulatorWizzardURLs.SETUP_PSE_URL)

    def get_url_after_monitors(self, current_monitor, monitor_name,
                               next_monitor):
        if isinstance(current_monitor, BoldViewModel):
            return self.build_monitor_url(
                SimulatorWizzardURLs.SET_MONITOR_EQUATION_URL, monitor_name)
        if next_monitor is not None:
            return self.build_monitor_url(
                SimulatorWizzardURLs.SET_MONITOR_PARAMS_URL,
                type(next_monitor).__name__)
        return SimulatorWizzardURLs.SETUP_PSE_URL

    @staticmethod
    def get_url_for_final_fragment(burst_config):
        if burst_config.is_pse_burst():
            return SimulatorWizzardURLs.LAUNCH_PSE_URL
        return SimulatorWizzardURLs.SETUP_PSE_URL

    def get_urls_for_next_monitor_fragment(self, next_monitor,
                                           current_monitor):
        form_action_url = self.build_monitor_url(
            SimulatorWizzardURLs.SET_MONITOR_PARAMS_URL,
            type(next_monitor).__name__)
        if_bold_url = self.build_monitor_url(
            SimulatorWizzardURLs.SET_MONITOR_EQUATION_URL,
            type(current_monitor).__name__)
        return form_action_url, if_bold_url

    @expose_fragment('simulator_fragment')
    def set_monitor_params(self, current_monitor_name, **data):
        session_stored_simulator, is_simulation_copy, is_simulator_load, is_branch = self.context.get_common_params(
        )

        current_monitor, next_monitor = self.monitors_handler.get_current_and_next_monitor_form(
            current_monitor_name, session_stored_simulator)

        if cherrypy.request.method == POST_REQUEST:
            form = get_form_for_monitor(type(current_monitor))(
                session_stored_simulator, is_branch)

            if is_branch:
                data['period'] = str(current_monitor.period)
                data['variables_of_interest'] = [
                    session_stored_simulator.model.variables_of_interest[i]
                    for i in current_monitor.variables_of_interest
                ]

            form.fill_from_post(data)
            form.fill_trait(current_monitor)

            last_loaded_form_url = self.get_url_after_monitors(
                current_monitor, current_monitor_name, next_monitor)
            self.context.add_last_loaded_form_url_to_session(
                last_loaded_form_url)

        previous_form_action_url = self.build_monitor_url(
            SimulatorWizzardURLs.SET_MONITOR_PARAMS_URL, current_monitor_name)
        rendering_rules = SimulatorFragmentRenderingRules(
            is_simulation_copy=is_simulation_copy,
            is_simulation_readonly_load=is_simulator_load,
            last_request_type=cherrypy.request.method,
            last_form_url=self.context.last_loaded_fragment_url,
            previous_form_action_url=previous_form_action_url)

        form_action_url, if_bold_url = self.get_urls_for_next_monitor_fragment(
            next_monitor, current_monitor)
        self.monitors_handler.update_monitor(current_monitor)
        return self.monitors_handler.handle_next_fragment_for_monitors(
            self.context, rendering_rules, current_monitor, next_monitor,
            False, form_action_url, if_bold_url)

    def get_url_after_monitor_equation(self, next_monitor):
        if next_monitor is None:
            return SimulatorWizzardURLs.SETUP_PSE_URL

        last_loaded_fragment_url = self.build_monitor_url(
            SimulatorWizzardURLs.SET_MONITOR_PARAMS_URL,
            type(next_monitor).__name__)
        return last_loaded_fragment_url

    @expose_fragment('simulator_fragment')
    def set_monitor_equation(self, current_monitor_name, **data):
        session_stored_simulator, is_simulation_copy, is_simulator_load, is_branch = self.context.get_common_params(
        )
        current_monitor, next_monitor = self.monitors_handler.get_current_and_next_monitor_form(
            current_monitor_name, session_stored_simulator)

        if cherrypy.request.method == POST_REQUEST:
            form = get_form_for_equation(type(current_monitor.hrf_kernel))()
            form.fill_from_post(data)
            form.fill_trait(current_monitor.hrf_kernel)

            last_loaded_fragment_url = self.get_url_after_monitor_equation(
                next_monitor)
            self.context.add_last_loaded_form_url_to_session(
                last_loaded_fragment_url)

        previous_form_action_url = self.build_monitor_url(
            SimulatorWizzardURLs.SET_MONITOR_EQUATION_URL,
            current_monitor_name)
        rendering_rules = SimulatorFragmentRenderingRules(
            None, None, previous_form_action_url, is_simulation_copy,
            is_simulator_load, self.context.last_loaded_fragment_url,
            cherrypy.request)

        form_action_url, if_bold_url = self.get_urls_for_next_monitor_fragment(
            next_monitor, current_monitor)
        return self.monitors_handler.handle_next_fragment_for_monitors(
            self.context, rendering_rules, current_monitor, next_monitor, True,
            form_action_url, if_bold_url)

    @expose_fragment('simulator_fragment')
    def setup_pse(self, **data):
        session_stored_simulator, is_simulation_copy, is_simulator_load, _ = self.context.get_common_params(
        )
        burst_config = self.context.burst_config
        all_range_parameters = self.range_parameters.get_all_range_parameters()
        next_form = self.algorithm_service.prepare_adapter_form(
            form_instance=SimulatorPSEConfigurationFragment(
                self.range_parameters.get_all_range_parameters()))

        if cherrypy.request.method == POST_REQUEST:
            session_stored_simulator.simulation_length = float(
                data['simulation_length'])
            burst_config.name = data['input_simulation_name_id']
            self.context.add_last_loaded_form_url_to_session(
                SimulatorWizzardURLs.SET_PSE_PARAMS_URL)

        param1, param2 = self.burst_service.handle_range_params_at_loading(
            burst_config, all_range_parameters)
        if param1:
            param_dict = {'pse_param1': param1.name}
            if param2 is not None:
                param_dict['pse_param2'] = param2.name
            next_form.fill_from_post(param_dict)

        rendering_rules = SimulatorFragmentRenderingRules(
            next_form, SimulatorWizzardURLs.SET_PSE_PARAMS_URL,
            SimulatorWizzardURLs.SETUP_PSE_URL, is_simulation_copy,
            is_simulator_load, self.context.last_loaded_fragment_url,
            cherrypy.request.method)
        return rendering_rules.to_dict()

    @expose_fragment('simulator_fragment')
    def set_pse_params(self, **data):
        session_stored_simulator, is_simulation_copy, is_simulation_load, _ = self.context.get_common_params(
        )
        burst_config = self.context.burst_config
        form = SimulatorPSEConfigurationFragment(
            self.range_parameters.get_all_range_parameters())

        if cherrypy.request.method == POST_REQUEST:
            self.context.add_last_loaded_form_url_to_session(
                SimulatorWizzardURLs.LAUNCH_PSE_URL)
            form.fill_from_post(data)

            param1 = form.pse_param1.value
            burst_config.range1 = param1.to_json()
            param2 = None
            if form.pse_param2.value:
                param2 = form.pse_param2.value
                burst_config.range2 = param2.to_json()
        else:
            all_range_parameters = self.range_parameters.get_all_range_parameters(
            )
            param1, param2 = self.burst_service.handle_range_params_at_loading(
                burst_config, all_range_parameters)
        next_form = self.algorithm_service.prepare_adapter_form(
            form_instance=SimulatorPSERangeFragment(param1, param2))

        rendering_rules = SimulatorFragmentRenderingRules(
            next_form,
            SimulatorWizzardURLs.LAUNCH_PSE_URL,
            SimulatorWizzardURLs.SET_PSE_PARAMS_URL,
            is_simulation_copy,
            is_simulation_load,
            last_form_url=self.context.last_loaded_fragment_url,
            is_launch_pse_fragment=True)
        return rendering_rules.to_dict()

    @expose_json
    def launch_pse(self, **data):
        session_stored_simulator = self.context.simulator
        all_range_parameters = self.range_parameters.get_all_range_parameters()
        range_param1, range_param2 = SimulatorPSERangeFragment.fill_from_post(
            all_range_parameters, **data)

        burst_config = self.context.burst_config
        burst_config.start_time = datetime.now()
        burst_config.range1 = range_param1.to_json()
        if range_param2:
            burst_config.range2 = range_param2.to_json()
        burst_config = self.burst_service.prepare_burst_for_pse(burst_config)
        session_stored_simulator.operation_group_gid = uuid.UUID(
            burst_config.operation_group.gid)
        session_stored_simulator.ranges = json.dumps(burst_config.ranges)

        try:
            thread = threading.Thread(
                target=self.simulator_service.async_launch_and_prepare_pse,
                kwargs={
                    'burst_config': burst_config,
                    'user': self.context.logged_user,
                    'project': self.context.project,
                    'simulator_algo': self.cached_simulator_algorithm,
                    'range_param1': range_param1,
                    'range_param2': range_param2,
                    'session_stored_simulator': session_stored_simulator
                })
            thread.start()
            return {'id': burst_config.id}
        except BurstServiceException as e:
            self.logger.exception("Could not launch burst!")
            return {'error': e.message}

    @expose_json
    def launch_simulation(self, launch_mode, **data):
        current_form = SimulatorFinalFragment()
        burst_config = self.context.burst_config
        burst_config.range1 = None
        burst_config.range2 = None

        try:
            current_form.fill_from_post(data)
        except Exception as exc:
            self.logger.exception(exc)
            return {'error': str(exc)}

        burst_name = current_form.simulation_name.value
        session_stored_simulator = self.context.simulator
        session_stored_simulator.simulation_length = current_form.simulation_length.value

        if burst_name != 'none_undefined':
            burst_config.name = burst_name

        if launch_mode == self.burst_service.LAUNCH_BRANCH:
            simulation_state_index = self.simulator_service.get_simulation_state_index(
                burst_config, SimulationHistoryIndex)
            session_stored_simulator.history_gid = simulation_state_index[
                0].gid

        burst_config.start_time = datetime.now()
        session_burst_config = self.burst_service.store_burst(burst_config)

        try:
            thread = threading.Thread(target=self.simulator_service.
                                      async_launch_and_prepare_simulation,
                                      kwargs={
                                          'burst_config': session_burst_config,
                                          'user': self.context.logged_user,
                                          'project': self.context.project,
                                          'simulator_algo':
                                          self.cached_simulator_algorithm,
                                          'simulator': session_stored_simulator
                                      })
            thread.start()
            return {'id': session_burst_config.id}
        except BurstServiceException as e:
            self.logger.exception('Could not launch burst!')
            return {'error': e.message}

    @expose_fragment('burst/burst_history')
    def load_burst_history(self, initBurst=None):
        """
        Load the available burst that are stored in the database at this time.
        This is one alternative to 'chrome-back problem'.
        """
        bursts = self.burst_service.get_available_bursts(
            self.context.project.id)
        self.burst_service.populate_burst_disk_usage(bursts)
        fromInit = False
        if initBurst is not None:
            fromInit = True
        return {
            'burst_list': bursts,
            'fromInit': fromInit,
            'selectedBurst': self.context.burst_config.id,
            'first_fragment_url':
            SimulatorFragmentRenderingRules.FIRST_FORM_URL
        }

    @cherrypy.expose
    def get_last_fragment_url(self, burst_config_id):
        burst_config = self.burst_service.load_burst_configuration(
            burst_config_id)
        return self.get_url_for_final_fragment(burst_config)

    @expose_fragment('simulator_fragment')
    def load_burst_read_only(self, burst_config_id):
        try:
            burst_config = self.burst_service.load_burst_configuration(
                burst_config_id)
            storage_path = StorageInterface().get_project_folder(
                self.context.project.name, str(burst_config.fk_simulation))
            simulator = h5.load_view_model(burst_config.simulator_gid,
                                           storage_path)
            last_loaded_form_url = self.get_url_for_final_fragment(
                burst_config)
            self.context.init_session_at_burst_loading(burst_config, simulator,
                                                       last_loaded_form_url)

            form = self.prepare_first_fragment()
            self.monitors_handler.build_list_of_monitors_from_view_models(
                self.context.simulator)
            rendering_rules = SimulatorFragmentRenderingRules(
                form,
                SimulatorWizzardURLs.SET_CONNECTIVITY_URL,
                is_simulation_readonly_load=True,
                is_first_fragment=True)
            return rendering_rules.to_dict()
        except Exception:
            # Most probably Burst was removed. Delete it from session, so that client
            # has a good chance to get a good response on refresh
            self.logger.exception("Error loading burst")
            self.context.remove_burst_config_from_session()
            raise

    def _prepare_first_fragment_for_burst_copy(self, burst_config_id,
                                               burst_name_format):
        simulator, burst_config_copy = self.burst_service.prepare_data_for_burst_copy(
            burst_config_id, burst_name_format, self.context.project)
        self.monitors_handler.build_list_of_monitors_from_view_models(
            simulator)

        last_loaded_form_url = self.get_url_for_final_fragment(
            burst_config_copy)
        self.context.init_session_at_copy_preparation(burst_config_copy,
                                                      simulator,
                                                      last_loaded_form_url)
        return self.prepare_first_fragment()

    @expose_fragment('simulator_fragment')
    def copy_simulator_configuration(self, burst_config_id):
        self.context.add_branch_and_copy_to_session(False, True)
        form = self._prepare_first_fragment_for_burst_copy(
            burst_config_id, self.COPY_NAME_FORMAT)
        rendering_rules = SimulatorFragmentRenderingRules(
            form,
            SimulatorWizzardURLs.SET_CONNECTIVITY_URL,
            is_simulation_copy=True,
            is_simulation_readonly_load=True,
            is_first_fragment=True)
        return rendering_rules.to_dict()

    @expose_fragment('simulator_fragment')
    def branch_simulator_configuration(self, burst_config_id):
        self.context.add_branch_and_copy_to_session(True, False)
        form = self._prepare_first_fragment_for_burst_copy(
            burst_config_id, self.BRANCH_NAME_FORMAT)
        rendering_rules = SimulatorFragmentRenderingRules(
            form,
            SimulatorWizzardURLs.SET_CONNECTIVITY_URL,
            is_simulation_copy=True,
            is_simulation_readonly_load=True,
            is_first_fragment=True)

        return rendering_rules.to_dict()

    @expose_fragment('simulator_fragment')
    def reset_simulator_configuration(self):
        burst_config = BurstConfiguration(self.context.project.id)
        self.context.init_session_at_sim_reset(
            burst_config, SimulatorWizzardURLs.SET_CONNECTIVITY_URL)
        self.monitors_handler.clear_next_monitors_dict()

        form = self.prepare_first_fragment()
        rendering_rules = SimulatorFragmentRenderingRules(
            form,
            SimulatorWizzardURLs.SET_CONNECTIVITY_URL,
            is_first_fragment=True)
        return rendering_rules.to_dict()

    @expose_json
    def rename_burst(self, burst_id, burst_name):
        """
        Rename the burst given by burst_id, setting it's new name to
        burst_name.
        """
        validation_result = SimulatorFinalFragment.is_burst_name_ok(burst_name)
        if validation_result is True:
            self.burst_service.rename_burst(burst_id, burst_name)
            return {'success': "Simulation successfully renamed!"}
        else:
            self.logger.exception(validation_result)
            return {'error': validation_result}

    @expose_json
    def get_history_status(self, **data):
        """
        For each burst id received, get the status and return it.
        """
        return self.burst_service.update_history_status(
            json.loads(data['burst_ids']))

    @cherrypy.expose
    @handle_error(redirect=False)
    @check_user
    def export(self, burst_id):
        export_manager = ExportManager()
        export_zip = export_manager.export_simulator_configuration(burst_id)

        result_name = "tvb_simulation_" + str(burst_id) + ".zip"
        return serve_file(export_zip, "application/x-download", "attachment",
                          result_name)

    @expose_fragment("overlay")
    def get_upload_overlay(self):
        template_specification = self.fill_overlay_attributes(
            None, "Upload", "Simulation ZIP", "burst/upload_burst_overlay",
            "dialog-upload")
        template_specification[
            'first_fragment_url'] = SimulatorWizzardURLs.SET_CONNECTIVITY_URL
        return self.fill_default_attributes(template_specification)

    @cherrypy.expose
    @handle_error(redirect=True)
    @check_user
    @settings
    def load_simulator_configuration_from_zip(self, **data):
        """Upload Simulator from previously exported ZIP file"""
        self.logger.debug("Uploading ..." + str(data))
        last_loaded_form_url = SimulatorWizzardURLs.SETUP_PSE_URL

        try:
            upload_param = "uploadedfile"
            if upload_param in data and data[upload_param]:
                simulator, burst_config, sim_folder = self.burst_service.load_simulation_from_zip(
                    data[upload_param], self.context.project)

                dts_folder = os.path.join(
                    sim_folder, StorageInterface.EXPORTED_SIMULATION_DTS_DIR)
                ImportService().import_project_operations(
                    self.context.project, dts_folder, False, None)

                self.monitors_handler.build_list_of_monitors_from_view_models(
                    simulator)
                if burst_config.is_pse_burst():
                    last_loaded_form_url = SimulatorWizzardURLs.LAUNCH_PSE_URL
                self.context.init_session_at_sim_config_from_zip(
                    burst_config, simulator, last_loaded_form_url)
        except IOError as ioexcep:
            self.logger.exception(ioexcep)
            self.context.set_warning_message(
                "This ZIP does not contain a complete simulator configuration")
        except ServicesBaseException as excep:
            self.logger.warning(excep.message)
            self.context.set_warning_message(excep.message)

        raise cherrypy.HTTPRedirect('/burst/')
예제 #5
0
class SimulatorService(object):
    def __init__(self):
        self.logger = get_logger(self.__class__.__module__)
        self.burst_service = BurstService()
        self.operation_service = OperationService()
        self.files_helper = FilesHelper()

    @transactional
    def _prepare_operation(self,
                           project_id,
                           user_id,
                           simulator_id,
                           simulator_gid,
                           algo_category,
                           op_group,
                           metadata,
                           ranges=None):
        operation_parameters = json.dumps({'gid': simulator_gid.hex})
        metadata, user_group = self.operation_service._prepare_metadata(
            metadata, algo_category, op_group, {})
        meta_str = json.dumps(metadata)

        op_group_id = None
        if op_group:
            op_group_id = op_group.id

        operation = Operation(user_id,
                              project_id,
                              simulator_id,
                              operation_parameters,
                              op_group_id=op_group_id,
                              meta=meta_str,
                              range_values=ranges)

        self.logger.info("Saving Operation(userId=" + str(user_id) +
                         ", projectId=" + str(project_id) + "," +
                         str(metadata) + ", algorithmId=" + str(simulator_id) +
                         ", ops_group= " + str(op_group_id) + ", params=" +
                         str(operation_parameters) + ")")

        operation = dao.store_entity(operation)
        # TODO: prepare portlets/handle operation groups/no workflows
        return operation

    @staticmethod
    def _set_simulator_range_parameter(simulator, range_parameter_name,
                                       range_parameter_value):
        range_param_name_list = range_parameter_name.split('.')
        current_attr = simulator
        for param_name in range_param_name_list[:len(range_param_name_list) -
                                                1]:
            current_attr = getattr(current_attr, param_name)
        setattr(current_attr, range_param_name_list[-1], range_parameter_value)

    def async_launch_and_prepare_simulation(self, burst_config, user, project,
                                            simulator_algo,
                                            session_stored_simulator,
                                            simulation_state_gid):
        try:
            metadata = {}
            metadata.update({DataTypeMetaData.KEY_BURST: burst_config.id})
            simulator_id = simulator_algo.id
            algo_category = simulator_algo.algorithm_category
            operation = self._prepare_operation(project.id, user.id,
                                                simulator_id,
                                                session_stored_simulator.gid,
                                                algo_category, None, metadata)
            storage_path = self.files_helper.get_project_folder(
                project, str(operation.id))
            SimulatorSerializer().serialize_simulator(session_stored_simulator,
                                                      simulation_state_gid,
                                                      storage_path)
            burst_config = self.burst_service.update_simulation_fields(
                burst_config.id, operation.id, session_stored_simulator.gid)
            self.burst_service.store_burst_configuration(
                burst_config, storage_path)

            wf_errs = 0
            try:
                OperationService().launch_operation(operation.id, True)
                return operation
            except Exception as excep:
                self.logger.error(excep)
                wf_errs += 1
                if burst_config:
                    self.burst_service.mark_burst_finished(
                        burst_config, error_message=str(excep))

            self.logger.debug(
                "Finished launching workflow. The operation was launched successfully, "
                + str(wf_errs) + " had error on pre-launch steps")

        except Exception as excep:
            self.logger.error(excep)
            if burst_config:
                self.burst_service.mark_burst_finished(
                    burst_config, error_message=str(excep))

    def prepare_simulation_on_server(self, user_id, project, algorithm,
                                     zip_folder_path, simulator_file):
        with SimulatorH5(simulator_file) as simulator_h5:
            simulator_gid = simulator_h5.gid.load()

        metadata = {}
        simulator_id = algorithm.id
        algo_category = algorithm.algorithm_category
        operation = self._prepare_operation(project.id, user_id, simulator_id,
                                            simulator_gid, algo_category, None,
                                            metadata)
        storage_operation_path = self.files_helper.get_project_folder(
            project, str(operation.id))
        self.async_launch_simulation_on_server(operation, zip_folder_path,
                                               storage_operation_path)

        return operation

    def async_launch_simulation_on_server(self, operation, zip_folder_path,
                                          storage_operation_path):
        try:
            for file in os.listdir(zip_folder_path):
                shutil.move(os.path.join(zip_folder_path, file),
                            storage_operation_path)
            try:
                OperationService().launch_operation(operation.id, True)
                shutil.rmtree(zip_folder_path)
                return operation
            except Exception as excep:
                self.logger.error(excep)
        except Exception as excep:
            self.logger.error(excep)

    @staticmethod
    def _set_range_param_in_dict(param_value):
        if type(param_value) is numpy.ndarray:
            return param_value[0]
        elif isinstance(param_value, uuid.UUID):
            return param_value.hex
        else:
            return param_value

    def async_launch_and_prepare_pse(self, burst_config, user, project,
                                     simulator_algo, range_param1,
                                     range_param2, session_stored_simulator):
        try:
            simulator_id = simulator_algo.id
            algo_category = simulator_algo.algorithm_category
            operation_group = burst_config.operation_group
            metric_operation_group = burst_config.metric_operation_group
            operations = []
            range_param2_values = [None]
            if range_param2:
                range_param2_values = range_param2.get_range_values()
            first_simulator = None

            for param1_value in range_param1.get_range_values():
                for param2_value in range_param2_values:
                    # Copy, but generate a new GUID for every Simulator in PSE
                    simulator = copy.deepcopy(session_stored_simulator)
                    simulator.gid = uuid.uuid4()
                    self._set_simulator_range_parameter(
                        simulator, range_param1.name, param1_value)

                    ranges = {
                        range_param1.name:
                        self._set_range_param_in_dict(param1_value)
                    }

                    if param2_value is not None:
                        self._set_simulator_range_parameter(
                            simulator, range_param2.name, param2_value)
                        ranges[
                            range_param2.name] = self._set_range_param_in_dict(
                                param2_value)

                    ranges = json.dumps(ranges)

                    operation = self._prepare_operation(
                        project.id, user.id, simulator_id, simulator.gid,
                        algo_category, operation_group,
                        {DataTypeMetaData.KEY_BURST: burst_config.id}, ranges)

                    storage_path = self.files_helper.get_project_folder(
                        project, str(operation.id))
                    SimulatorSerializer().serialize_simulator(
                        simulator, None, storage_path)
                    operations.append(operation)
                    if first_simulator is None:
                        first_simulator = simulator

            first_operation = operations[0]
            storage_path = self.files_helper.get_project_folder(
                project, str(first_operation.id))
            burst_config = self.burst_service.update_simulation_fields(
                burst_config.id, first_operation.id, first_simulator.gid)
            self.burst_service.store_burst_configuration(
                burst_config, storage_path)
            datatype_group = DataTypeGroup(
                operation_group,
                operation_id=first_operation.id,
                fk_parent_burst=burst_config.id,
                state=json.loads(
                    first_operation.meta_data)[DataTypeMetaData.KEY_STATE])
            dao.store_entity(datatype_group)

            metrics_datatype_group = DataTypeGroup(
                metric_operation_group, fk_parent_burst=burst_config.id)
            dao.store_entity(metrics_datatype_group)

            wf_errs = 0
            for operation in operations:
                try:
                    OperationService().launch_operation(operation.id, True)
                except Exception as excep:
                    self.logger.error(excep)
                    wf_errs += 1
                    self.burst_service.mark_burst_finished(
                        burst_config, error_message=str(excep))

            self.logger.debug("Finished launching workflows. " +
                              str(len(operations) - wf_errs) +
                              " were launched successfully, " + str(wf_errs) +
                              " had error on pre-launch steps")

        except Exception as excep:
            self.logger.error(excep)
            self.burst_service.mark_burst_finished(burst_config,
                                                   error_message=str(excep))

    def load_from_zip(self, zip_file, project):
        import_service = ImportService()
        simulator_folder = import_service.import_simulator_configuration_zip(
            zip_file)

        simulator_h5_filename = DirLoader(
            simulator_folder, None).find_file_for_has_traits_type(Simulator)
        with SimulatorH5(os.path.join(simulator_folder,
                                      simulator_h5_filename)) as sim_h5:
            simulator_gid = sim_h5.gid.load()
        simulator = SimulatorSerializer.deserialize_simulator(
            simulator_gid, simulator_folder)

        burst_config = self.burst_service.load_burst_configuration_from_folder(
            simulator_folder, project)
        return simulator, burst_config
예제 #6
0
    def run(self):
        """
        Get the required data from the operation queue and launch the operation.
        """
        # Try to get a spot to launch own operation.
        LOCKS_QUEUE.get(True)
        operation_id = self.operation_id
        run_params = [
            TvbProfile.current.PYTHON_INTERPRETER_PATH, '-m',
            'tvb.core.operation_async_launcher',
            str(operation_id), TvbProfile.CURRENT_PROFILE_NAME
        ]

        # In the exceptional case where the user pressed stop while the Thread startup is done,
        # We should no longer launch the operation.
        if self.stopped() is False:

            env = os.environ.copy()
            env['PYTHONPATH'] = os.pathsep.join(sys.path)
            # anything that was already in $PYTHONPATH should have been reproduced in sys.path

            launched_process = Popen(run_params,
                                     stdout=PIPE,
                                     stderr=PIPE,
                                     env=env)

            LOGGER.debug(
                "Storing pid=%s for operation id=%s launched on local machine."
                % (operation_id, launched_process.pid))
            op_ident = OperationProcessIdentifier(operation_id,
                                                  pid=launched_process.pid)
            dao.store_entity(op_ident)

            if self.stopped():
                # In the exceptional case where the user pressed stop while the Thread startup is done.
                # and stop_operation is concurrently asking about OperationProcessIdentity.
                self.stop_pid(launched_process.pid)

            subprocess_result = launched_process.communicate()
            LOGGER.info("Finished with launch of operation %s" % operation_id)
            returned = launched_process.wait()

            if returned != 0 and not self.stopped():
                # Process did not end as expected. (e.g. Segmentation fault)
                burst_service = BurstService()
                operation = dao.get_operation_by_id(self.operation_id)
                LOGGER.error(
                    "Operation suffered fatal failure! Exit code: %s Exit message: %s"
                    % (returned, subprocess_result))

                burst_service.persist_operation_state(
                    operation, STATUS_ERROR,
                    "Operation failed unexpectedly! Please check the log files."
                )

                burst_entity = dao.get_burst_for_operation_id(
                    self.operation_id)
                if burst_entity:
                    message = "Error in operation process! Possibly segmentation fault."
                    burst_service.mark_burst_finished(burst_entity,
                                                      error_message=message)

            del launched_process

        # Give back empty spot now that you finished your operation
        CURRENT_ACTIVE_THREADS.remove(self)
        LOCKS_QUEUE.put(1)