def get(self, sim_id, command):
        """
        Queries the simulation recorder for a value/status. See parameter description for
        supported query commands.

        :param sim_id: The simulation ID to command.
        :param command: The command to query, supported: [is-recording]

        :status 500: {0}
        :status 404: {1}
        :status 200: Success. The query was issued and value returned.
        """

        # validate simulation id, allow any users/viewers to query recorder
        sim = _get_simulation_or_abort(sim_id)

        # validate the command type
        if command not in ['is-recording']:
            raise NRPServicesClientErrorException('Invalid recorder query: %s' % command,
                                                  error_code=404)

        # command the recorder, return boolean state as a string
        try:
            state = str(sim.cle.command_simulation_recorder(SimulationRecorderRequest.STATE).value)
            return state, 200

        # internal CLE ROS error if service call fails, notify frontend
        except ROSCLEClientException as e:
            raise NRPServicesGeneralException(str(e), 'CLE error', 500)
    def setUp(self):

        self.patch_state = patch('hbp_nrp_backend.simulation_control.__Simulation.Simulation.state')
        self.mock_state = self.patch_state.start()

        self.patch_sm = patch('hbp_nrp_backend.simulation_control.__Simulation.StateMachineManager')
        self.mock_sm_manager = self.patch_sm.start()

        sm = StateMachineManager()
        self.mock_sm_manager_instance = MagicMock(name='SM_manager', wraps=sm)
        self.mock_sm_manager.return_value = self.mock_sm_manager_instance

        self.sm_instance_name = "Control1"
        self.sm_instance = sm.create_state_machine(self.sm_instance_name, 0)
        self.mock_sm_instance = MagicMock(name='SM_instance', sm_id=self.sm_instance_name, wraps=self.sm_instance)
        self.mock_sm_manager_instance.create_state_machine.return_value = self.mock_sm_instance
        self.mock_sm_manager_instance.get_state_machine =\
            Mock(side_effect=lambda name: self.mock_sm_instance if name == self.sm_instance_name else None)

        load_data = {
            "experimentConfiguration": "experiments/experiment_data/test_1.exc",
            "gzserverHost": "local"
        }
        self.client.post('/simulation', data=json.dumps(load_data))

        simulation = _get_simulation_or_abort(0)
        simulation.state = "paused"
Beispiel #3
0
    def put(self, sim_id, transfer_function_name):
        """
        Applies user changes to transfer function code

        :param sim_id: The simulation ID
        :param transfer_function_name: The name of the transfer function to be modified

        :< string data: The source code of the transfer function

        :status 404: {0}
        :status 403: {1}
        :status 401: {2}
        :status 400: {3}
        :status 200: Success. The transfer function was successfully patched
        """
        simulation = _get_simulation_or_abort(sim_id)
        if not UserAuthentication.can_modify(simulation):
            raise NRPServicesWrongUserException()

        transfer_function_source = request.data
        error_message = simulation.cle.edit_simulation_transfer_function(
            transfer_function_name, transfer_function_source)

        if error_message:
            ex_msg = ("Transfer Function patch failed: {error_msg}\n"
                      "Updated source:\n"
                      "{tf_src}").format(error_msg=error_message,
                                         tf_src=str(transfer_function_source))
            raise NRPServicesDuplicateNameException(ex_msg) if "duplicate" in error_message \
                else NRPServicesTransferFunctionException(ex_msg)

        return 200
    def setUp(self):

        self.path_can_view = patch('hbp_nrp_backend.__UserAuthentication.UserAuthentication.can_view')
        self.path_can_view.start().return_value = True

        self.patch_state = patch('hbp_nrp_backend.simulation_control.__Simulation.Simulation.state')
        self.mock_state = self.patch_state.start()

        self.patch_sm = patch('hbp_nrp_backend.simulation_control.__Simulation.StateMachineManager')
        self.mock_sm_manager = self.patch_sm.start()

        sm = StateMachineManager()
        self.mock_sm_manager_instance = MagicMock(name='SM_manager', wraps=sm)
        self.mock_sm_manager.return_value = self.mock_sm_manager_instance

        self.sm_instance_name = "Control1"
        self.sm_instance = sm.create_state_machine(self.sm_instance_name, 0, '/tmp/sim-dir')
        self.mock_sm_instance = MagicMock(name='SM_instance', sm_id=self.sm_instance_name, sim_dir='/tmp/sim-dir', wraps=self.sm_instance)
        self.mock_sm_manager_instance.create_state_machine.return_value = self.mock_sm_instance
        self.mock_sm_manager_instance.get_state_machine = Mock(side_effect=lambda name: self.mock_sm_instance if name == self.sm_instance_name else None)

        load_data = {
            "experimentID": "some_experiment_id",
            "gzserverHost": "local"
        }
        self.client.post('/simulation', data=json.dumps(load_data))

        simulation = _get_simulation_or_abort(0)
        simulation.state = "paused"
Beispiel #5
0
    def put(self, sim_id):
        """
        Sets the simulation with the given name into a new state. Allowed values are:
        created, initialized, started, paused, stopped

        :param sim_id: The simulation id

        :< json string state: The state of the simulation to set

        :> json string state: The state of the simulation

        :status 404: {0}
        :status 401: {1}
        :status 400: The state transition is invalid
        :status 200: The state of the simulation with the given ID was successfully set
        """
        simulation = _get_simulation_or_abort(sim_id)

        if not UserAuthentication.can_modify(simulation):
            raise NRPServicesWrongUserException()

        body = request.get_json(force=True)
        try:
            simulation.state = body['state']
        except MachineError:
            raise NRPServicesStateException("Invalid transition (" +
                                            simulation.state + "->" +
                                            body['state'] + ")")
        return {'state': str(simulation.state)}, 200
    def get(self, sim_id):
        """
        Get brain data of the simulation specified with simulation ID.

        :param sim_id: The simulation ID

        :> json string brain_type: Type of the brain file ('h5' or 'py')
        :> json string data_type: type of the data field ('text' or 'base64')
        :> json string data: Contents of the brain file. Encoding given in field data_type
        :> json dict additional_populations: A dictionary indexed by population names and containing
                                             neuron indices.

        :status 500: {0}
        :status 404: {1}
        :status 200: Success. The experiment brain file was retrieved
        """

        simulation = _get_simulation_or_abort(sim_id)

        result = simulation.cle.get_simulation_brain()

        return {
            'data': result.brain_data,
            'brain_type': result.brain_type,
            'data_type': result.data_type,
            'additional_populations': json.loads(result.brain_populations),
        }, 200
Beispiel #7
0
    def post(self, sim_id):
        """
        Extends the simulation timeout

        :param sim_id: The simulation id

        :status 404: {0}
        :status 402: Failed to extend the timeout
        :status 412: Failed due to simulation timeout type being 'simulation'
        :status 401: {1}
        :status 200: Success. The simulation timeout has been extended
        """
        simulation = _get_simulation_or_abort(sim_id)

        if not UserAuthentication.can_modify(simulation):
            raise NRPServicesWrongUserException()

        if simulation.timeout_type == TimeoutType.SIMULATION:
            return {}, 412

        new_timeout = simulation.kill_datetime + \
            datetime.timedelta(minutes=SIMULATION_TIMEOUT_EXTEND)

        if not simulation.cle.extend_simulation_timeout(new_timeout):
            return {}, 402

        simulation.kill_datetime = new_timeout

        return {}, 200
    def put(self, sim_id, transfer_function_name, activate):
        """

        Sets the activation state of the transfer function

        :param sim_id: The simulation ID
        :param transfer_function_name: The name of the transfer function to be modified
        :param activate A boolean denoting the new desired activation status

        :status 404: {0}
        :status 401: {1}
        :status 400: {2}
        :status 200: Success. The activation state of the TF has been successfully changed

        """

        simulation = _get_simulation_or_abort(sim_id)
        if not UserAuthentication.matches_x_user_name_header(
                request, simulation.owner):
            raise NRPServicesWrongUserException()

        activate_bool = activate.lower(
        ) == "true"  # convert unicode to boolean

        error_message = simulation.cle.activate_simulation_transfer_function(
            transfer_function_name, activate_bool)

        if error_message:
            raise NRPServicesTransferFunctionException(
                "Transfer function (de-)activation failed: " + error_message +
                "\n")

        return 200
    def get(self, sim_id):
        """
        Gets the simulation CSV recorders' content

        :param sim_id: The simulation ID whose transfer functions are retrieved will be saved

        :> json string file: CSV file name
        :> json array data: CSV data as a list of strings

        :status 500: Error when retrieving recorder files
        :status 404: {0}
        :status 401: {1}
        :status 200: Returns a list of recorded csv files and data
        """
        simulation = _get_simulation_or_abort(sim_id)
        if not UserAuthentication.matches_x_user_name_header(
                request, simulation.owner):
            raise NRPServicesWrongUserException()

        response = []
        csv_files = simulation.cle.get_simulation_CSV_recorders_files()
        if csv_files:
            for csv_file in csv_files:
                file_data = []
                response.append({"file": csv_file.name, "data": file_data})
                with open(csv_file.temporary_path) as csvfile:
                    spamreader = csv.reader(csvfile,
                                            delimiter=' ',
                                            quotechar='|')
                    for row in spamreader:
                        file_data.append(', '.join(row))

        return response, 200
 def test_simulation_state_machines_put_source_code_error(self):
     simulation = _get_simulation_or_abort(0)
     simulation.set_state_machine_code(self.sm_instance_name, SM)
     self.__put_initialization_side_effect(self.mock_sm_instance, Exception)
     response = self.client.put('/simulation/0/state-machines/Control1', data="ERROR")
     self.assertIsInstance(response, Response)
     self.assertEqual(response.status_code, 500)
    def put(self, sim_id):
        """
        Puts the structured transfer functions

        :param sim_id: The simulation id

        :status 500: Simulation in state [STATE]. Can't update transfer function
        :status 404: {0}
        :status 401: {1}
        :status 400: {2}
        :status 200: Success. The transfer function was successfully patched
        """
        simulation = _get_simulation_or_abort(sim_id)

        if not UserAuthentication.matches_x_user_name_header(
                request, simulation.owner):
            raise NRPServicesWrongUserException()

        transfer_function = json.loads(request.data, object_hook=JSONObject)
        error_message = simulation.cle.set_structured_transfer_function(
            transfer_function)
        if error_message:
            raise NRPServicesTransferFunctionException(
                "Transfer function patch failed: " + error_message + "\n" +
                "Transfer function:\n" + request.data)
        return 200
Beispiel #12
0
    def delete(self, sim_id, robot_id):
        """
        Delete a robot from the simulation.

        :param sim_id: The simulation ID.
        :param robot_id: The robot ID.

        :status 500: {0}
        :status 404: {1}
        :status 401: {2}
        :status 400: Invalid request, the JSON parameters are incorrect
        :status 200: The requested robot was deleted successfully
        """
        # pylint: disable=no-self-use
        sim = _get_simulation_or_abort(sim_id)

        if not UserAuthentication.can_modify(sim):
            raise NRPServicesWrongUserException()
        try:
            res, err = SimulationRobot.__delete_robot(sim, robot_id)

        except ROSCLEClientException as e:
            raise NRPServicesGeneralException(str(e), 'CLE error', 500)
        if not res:
            return {'res': err}, 404
        return {'res': 'success'}, 200
Beispiel #13
0
    def get(self, sim_id):
        """
        Gets the list of robots in the running simulation.
        """
        # pylint: disable=no-self-use
        sim = _get_simulation_or_abort(sim_id)

        if not UserAuthentication.can_view(sim):
            raise NRPServicesWrongUserException()

        try:
            robots = SimulationRobots.__get_simulation_robots(sim)
        except ROSCLEClientException as e:
            raise NRPServicesGeneralException(str(e), 'CLE error', 500)

        result = {
            'robots': [{
                ParamNames.ROBOT_ID:
                robot.robot_id,
                ParamNames.ROBOT_ABS_PATH:
                robot.robot_model,
                ParamNames.IS_CUSTOM:
                robot.is_custom,
                ParamNames.ROBOT_POSE:
                SimulationRobots.__jsonisePose(robot.pose)
            } for robot in robots]
        }
        return result, 200
Beispiel #14
0
    def post(self, sim_id):
        """
        Extends the simulation timeout

        :param sim_id: The simulation id

        :status 404: {0}
        :status 402: Failed to extend the timeout
        :status 401: {1}
        :status 200: Success. The simulation timeout has been extended
        """
        simulation = _get_simulation_or_abort(sim_id)

        if not UserAuthentication.matches_x_user_name_header(
                request, simulation.owner):
            raise NRPServicesWrongUserException()

        new_timeout = simulation.kill_datetime + \
            datetime.timedelta(minutes=SIMULATION_TIMEOUT_EXTEND)

        if not simulation.cle.extend_simulation_timeout(new_timeout):
            return {}, 402

        simulation.kill_datetime = new_timeout

        return {}, 200
    def post(self, sim_id, command):
        """
        Issue user commands to the simulator recorder. See parameter description for
        supported query commands.

        :param sim_id: The simulation ID to command.
        :param command: The command to issue, supported: [start, stop, cancel, reset, save]

        :status 500: {0}
        :status 404: {1}
        :status 401: {2}
        :status 400: The command is invalid/refused by recorder - see message returned.
        :status 200: Success. The command was issued.
        """

        # validate simulation id
        sim = _get_simulation_or_abort(sim_id)

        # only the simulation owner can command the recorder
        if not UserAuthentication.can_modify(sim):
            raise NRPServicesWrongUserException()

        # pure local command to save file to storage
        if command == 'save':
            try:
                file_name = sim.lifecycle.save_record_to_user_storage()
                return {'filename': file_name}, 200

            except Exception as e:
                raise NRPServicesClientErrorException(
                    'Cannot copy record to client storage', error_code=404)

        else:

            # validate the remote command type
            valid_commands = {
                'start': SimulationRecorderRequest.START,
                'stop': SimulationRecorderRequest.STOP,
                'cancel': SimulationRecorderRequest.CANCEL,
                'reset': SimulationRecorderRequest.RESET
            }
            if command not in valid_commands:
                raise NRPServicesClientErrorException(
                    'Invalid recorder command: %s' % command, error_code=404)

            # command the recorder, if unsuccessful return the error message
            try:
                resp = sim.cle.command_simulation_recorder(
                    valid_commands[command])

                # check the command success, on failure return status 400 + error
                if not resp.value:
                    raise NRPServicesClientErrorException(resp.message)

                # successful, return status 200
                return 'success', 200

            # internal CLE ROS error if service call fails, notify frontend
            except ROSCLEClientException as e:
                raise NRPServicesGeneralException(str(e), 'CLE error', 500)
    def test_simulation_state_machines_delete_not_found(self):
        simulation = _get_simulation_or_abort(0)
        simulation.set_state_machine_code(self.sm_instance_name, SM)

        response = self.client.delete('/simulation/0/state-machines/Control2')
        self.assertRaises(NRPServicesStateMachineException)
        self.assertEqual(response.status_code, 404)
    def get(self, sim_id):
        """
        Gets all transfer functions (robot to neuron and neuron to robot) in a dictionary with
        string values.

        :param sim_id: The simulation ID

        :> json dict data: Dictionary containing all transfer functions ('name': 'source')
        :> json dict active: Dictionary containing a mask for active TFs ('name': 'isActive')

        :status 404: {0}
        :status 200: Transfer functions retrieved successfully
        """

        simulation = _get_simulation_or_abort(sim_id)

        transfer_functions = dict()
        active_tfs_mask = dict()

        transfer_functions_list, active_tfs_mask_list = \
            simulation.cle.get_simulation_transfer_functions()

        for tf, tf_active in zip(transfer_functions_list,
                                 active_tfs_mask_list):
            name = get_tf_name(tf)
            transfer_functions[name] = tf
            active_tfs_mask[name] = tf_active

        return dict(data=transfer_functions, active=active_tfs_mask), 200
Beispiel #18
0
    def put(self, sim_id):
        """
        Set the populations of the brain in a simulation with the specified simulation id.

        :param sim_id: The simulation ID

        :< json dict brain_populations: A dictionary indexed by population names and containing
                                             neuron indices

        :< json string brain_type: Type of the brain file ('h5' or 'py')
        :< param brain_populations: Contents of the brain file. Encoding given in field data_type
        :< json string data_type: type of the data field ('text' or 'base64')
        :< json string change_population: indicates if it has to be changes
                                        in the transfer functions
        :> json string message: Error Message if there is a syntax error in the code
        :status 404: {0}
        :status 200: Success. The populations of the brain where successfully set
        """

        simulation = _get_simulation_or_abort(sim_id)
        if not UserAuthentication.can_modify(simulation):
            raise NRPServicesWrongUserException()

        body = request.get_json(force=True)

        result = simulation.cle.set_simulation_populations(
            brain_type=body['brain_type'],
            brain_populations=json.dumps(body['brain_populations']),
            data_type=body['data_type'],
            change_population=body['change_population'])

        if result.message:
            return {'error_message': result.message}, 400

        return {'message': 'Success'}, 200
    def put(self, sim_id, transfer_function_name):
        """
        Applies user changes to transfer function code

        :param sim_id: The simulation ID
        :param transfer_function_name: The name of the transfer function to be modified

        :< string data: The source code of the transfer function

        :status 404: {0}
        :status 403: {1}
        :status 401: {2}
        :status 400: {3}
        :status 200: Success. The transfer function was successfully patched
        """
        simulation = _get_simulation_or_abort(sim_id)
        if not UserAuthentication.matches_x_user_name_header(
                request, simulation.owner):
            raise NRPServicesWrongUserException()

        transfer_function_source = request.data
        error_message = simulation.cle.edit_simulation_transfer_function(
            transfer_function_name, transfer_function_source)

        if error_message and "duplicate" in error_message:
            raise NRPServicesDuplicateNameException(
                "Transfer function patch failed: " + error_message + "\n" +
                "Updated source:\n" + str(transfer_function_source))
        elif error_message:
            raise NRPServicesTransferFunctionException(
                "Transfer function patch failed: " + error_message + "\n" +
                "Updated source:\n" + str(transfer_function_source))
        return 200
Beispiel #20
0
    def delete(self, sim_id, state_machine_name):
        """
        Delete a state machine

        :param sim_id: The simulation ID
        :param state_machine_name: The name of the state machine to be deleted

        :status 500: {0}
        :status 404: {1}
        :status 401: {2}
        :status 200: The delete operation was successfully called. This does not imply that the
                     state machine function was correctly deleted though.
        """
        simulation = _get_simulation_or_abort(sim_id)
        if not UserAuthentication.can_modify(simulation):
            raise NRPServicesWrongUserException()

        failure_message = "State machine destruction failed: "
        try:
            ok, response_message = simulation.delete_state_machine(
                state_machine_name)
            if ok:
                return "Success. The state machine was successfully deleted.", 200
        except Exception as e:
            info = exc_info()
            raise NRPServicesGeneralException(
                failure_message +
                " {0}: {1}".format(e.__class__.__name__, e.message),
                "State machine error",
            ), None, info[2]
        raise NRPServicesStateMachineException(
            failure_message + "\n" + response_message, 404)
Beispiel #21
0
    def post(self, sim_id):
        """
        Adds a new transfer function

        :param sim_id: The simulation ID

        :< string data: The source code of the transfer function

        :status 404: {0}
        :status 403: {1}
        :status 401: {2}
        :status 400: {3}
        :status 200: Success. The transfer function was successfully added
        """
        simulation = _get_simulation_or_abort(sim_id)
        if not UserAuthentication.can_modify(simulation):
            raise NRPServicesWrongUserException()

        transfer_function_source = request.data

        error_message = simulation.cle.add_simulation_transfer_function(
            transfer_function_source)
        if error_message:
            ex_msg = ("Adding a new Transfer Function failed: {error_msg}\n"
                      "Updated source:\n"
                      "{tf_src}").format(error_msg=error_message,
                                         tf_src=str(transfer_function_source))
            raise NRPServicesDuplicateNameException(ex_msg) if "duplicate" in error_message \
                else NRPServicesTransferFunctionException(ex_msg)

        return 200
    def put(self, sim_id, experiment_id):
        """
        Calls the CLE for resetting a given simulation to the last saved state in the storage.

        :param sim_id: The simulation ID.
        :param experiment_id: The experiment ID

        :> json resetType: the reset type the user wants to be performed, details about possible
                          values are given in
                          GazeboRosPackages/src/cle_ros_msgs/srv/ResetSimulation.srv

        :status 500: {0}
        :status 404: {1}
        :status 401: {2}
        :status 400: Invalid request, the JSON parameters are incorrect
        :status 200: The requested reset was performed successfully
        """
        sim = _get_simulation_or_abort(sim_id)

        if not UserAuthentication.can_modify(sim):
            raise NRPServicesWrongUserException()

        req_body = request.get_json(force=True)
        context_id = req_body.get('contextId', None)

        for missing_par in (par for par in self.ResetRequest.required if par not in req_body):
            raise NRPServicesClientErrorException('Missing parameter {}'.format(missing_par))

        for invalid_p in (par for par in req_body if par not in self.ResetRequest.resource_fields):
            raise NRPServicesClientErrorException('Invalid parameter {}'.format(invalid_p))

        reset_type = req_body.get('resetType')

        rsr = srv.ResetSimulationRequest

        try:
            if reset_type == rsr.RESET_ROBOT_POSE:
                sim.cle.reset(reset_type)
            elif reset_type == rsr.RESET_WORLD:
                sim.cle.reset(reset_type,
                              world_sdf=self._get_sdf_world_from_storage(experiment_id, context_id))
            elif reset_type == rsr.RESET_FULL:
                brain_path, populations, _ = \
                    self._get_brain_info_from_storage(experiment_id, context_id)

                if sim.playback_path is None:
                    self.reset_from_storage_all(sim, experiment_id, context_id)

                sim.cle.reset(reset_type,
                              world_sdf=self._get_sdf_world_from_storage(experiment_id, context_id),
                              brain_path=brain_path,
                              populations=populations)
            else:
                return {}, 400  # Other reset modes are unsupported

        except ROSCLEClientException as e:
            raise NRPServicesGeneralException(str(e), 'CLE error', 500)

        return {}, 200
    def get(self, sim_id):
        """
        Gets simulation resource files of the experiment running for the simulation ID

        :param sim_id: The simulation ID

        :> json string resources: Resource files

        :status 500: {0}
        :status 404: {1}. Or, {2}.
        :status 200: Success. The simulation BIBI configuration files were retrieved
        """

        simulation = _get_simulation_or_abort(sim_id)
        experiment_file = simulation.lifecycle.experiment_path

        if not os.path.isfile(experiment_file):
            raise NRPServicesClientErrorException(
                ErrorMessages.EXPERIMENT_CONF_FILE_NOT_FOUND_404,
                error_code=404)
        with open(experiment_file) as exd_file:
            experiment_dom = exp_conf_api_gen.CreateFromDocument(
                exd_file.read())

        bibi_fullpath = os.path.join(
            simulation.lifecycle.simulation_root_folder,
            experiment_dom.bibiConf.src)

        if not os.path.isfile(bibi_fullpath):
            raise NRPServicesClientErrorException(
                ErrorMessages.EXPERIMENT_BIBI_FILE_NOT_FOUND_404,
                error_code=404)

        resources = []
        for conf in experiment_dom.configuration:
            resources.append({'file': conf.src, 'type': conf.type})

        with open(bibi_fullpath) as _file:
            bibi_dom = bibi_api_gen.CreateFromDocument(_file.read())

        for conf in bibi_dom.configuration:
            resources.append({'file': conf.src, 'type': conf.type})

        if simulation.private:
            for conf in resources:
                conf['file'] = os.path.join(
                    '/config-from-cloned-folder',
                    os.path.basename(
                        simulation.lifecycle.simulation_root_folder),
                    os.path.basename(conf['file']))
        else:
            # Get the template experiment folder name, e.g., "template_husky"
            experiment_folder = os.path.basename(
                os.path.dirname(experiment_file))
            for conf in resources:
                conf['file'] = os.path.join('/config-from-template-folder',
                                            experiment_folder, conf['file'])

        return {'resources': resources}, 200
    def put(self, sim_id):
        """
        Set brain file of the simulation specified with simulation ID.
        Depending on the type of brain file, it has to be transmitted as text or as base64
        :param sim_id: The simulation ID

        :< json string brain_type: Type of the brain file ('h5' or 'py')
        :< json string data_type: type of the data field ('text' or 'base64')
        :< json string data: Contents of the brain file. Encoding given in field data_type
        :< json dict brain_populations: A dictionary indexed by population names and containing
                                        neuron indices
        :> json string error_message: Error Message if there is a syntax error in the code
        :> json int error_line: Line of code, where error occurred
        :> json int error_column: Column, where error occurred (if available)
        :> json bool handle_population_change: a flag indicating if user wants to change transfer
                                               functions according to population changes.

        :status 500: {0}
        :status 404: {1}
        :status 401: {2}
        :status 400: {3}
        :status 200: Success. The experiment brain file was replaced
        """

        simulation = _get_simulation_or_abort(sim_id)
        storage_client = StorageClient()
        if not UserAuthentication.can_modify(simulation):
            raise NRPServicesWrongUserException()

        body = request.get_json(force=True)

        file_url = body.get('urls', {}).get('fileUrl')
        if file_url:
            # TODO: fix server certificate and remove verify
            with requests.get(file_url, verify=False) as h5:
                filename = os.path.basename(file_url)
                with open(os.path.join(simulation.lifecycle.sim_dir, filename),
                          'w') as f:
                    f.write(h5.content)
                storage_client.create_or_update(simulation.token,
                                                simulation.experiment_id,
                                                filename, h5.content,
                                                "text/plain")

        result = simulation.cle.set_simulation_brain(
            brain_type=body['brain_type'],
            data=body['data'],
            data_type=body['data_type'],
            brain_populations=json.dumps(body['brain_populations']))

        if result.error_message:
            # Error in given brain
            return {
                'error_message': result.error_message,
                'error_line': result.error_line,
                'error_column': result.error_column
            }, 400
        # Success
        return {'message': "Success"}, 200
    def test_simulation_state_machines_delete_OK(self):
        self.mock_sm_manager_instance.state_machines = [self.mock_sm_instance]
        simulation = _get_simulation_or_abort(0)

        simulation.set_state_machine_code(self.sm_instance_name, SM)

        response = self.client.delete('/simulation/0/state-machines/Control1')
        self.assertEqual(response.status_code, 200)
    def test_simulation_state_machines_get_ok2(self):
        self.mock_sm_manager_instance.state_machines = [self.mock_sm_instance]
        simulation = _get_simulation_or_abort(0)

        simulation.set_state_machine_code(self.sm_instance_name, SM)

        response = self.client.get('/simulation/0/state-machines')

        self.assertIsInstance(response, Response)
        self.assertMultiLineEqual(json.loads(response.data)["data"][self.sm_instance_name], SM)
        self.assertEqual(response.status_code, 200)
    def test_simulation_state_machines_put_OK(self):
        simulation = _get_simulation_or_abort(0)
        simulation.set_state_machine_code(self.sm_instance_name, SM)

        response = self.client.put('/simulation/0/state-machines/Control1', data=SM)
        self.assertIsInstance(response, Response)
        self.assertEqual(response.status_code, 200)

        simulation.state = "paused"
        response = self.client.put('/simulation/0/state-machines/Control1', data=SM)
        self.assertIsInstance(response, Response)
        self.assertEqual(response.status_code, 200)
    def get(self, sim_id):
        """
        Gets the structured transfer functions

        :param sim_id: The simulation id

        :status 404: {0}
        :status 200: Success. The transfer functions were returned
        """
        simulation = _get_simulation_or_abort(sim_id)

        tfs = []
        transfer_functions_list = simulation.cle.get_structured_transfer_functions(
        )
        for tf in transfer_functions_list:
            devices = [{
                'name': dev.name,
                'type': dev.type,
                'neurons': {
                    'name': dev.neurons.name,
                    'type': dev.neurons.type,
                    'ids': [{
                        'id': n_id
                    } for n_id in dev.neurons.ids],
                    'start': dev.neurons.start,
                    'stop': dev.neurons.stop,
                    'step': dev.neurons.step
                }
            } for dev in tf.devices]

            topics = [{
                'name': top.name,
                'topic': top.topic,
                'type': top.type,
                'publishing': top.publishing
            } for top in tf.topics]

            variables = [{
                'name': var.name,
                'type': var.type,
                'initial_value': var.initial_value
            } for var in tf.variables]

            tf_e = {
                'name': tf.name,
                'code': tf.code,
                'type': tf.type,
                'devices': devices,
                'topics': topics,
                'variables': variables
            }
            tfs.append(tf_e)
        return {'transferFunctions': tfs}, 200
Beispiel #29
0
    def put(self, sim_id, state_machine_name):
        """
        Applies user changes to state machine code.
        If the simulation is paused or started, it will be paused.
        A stopped, created or failed simulation will fail the request with error code 403

        :param sim_id: The simulation ID
        :param state_machine_name: The name of the state machine to be modified

        :< json string data: The source code of the state machine

        :status 404: {0}
        :status 401: {1}
        :status 400: {2}
        :status 200: Success. The code was successfully patched
        """
        simulation = _get_simulation_or_abort(sim_id)
        assert simulation, Simulation
        if not UserAuthentication.matches_x_user_name_header(request, simulation.owner):
            raise NRPServicesWrongUserException()

        state_machine_source = request.data
        try:
            simulation.set_state_machine_code(
                state_machine_name,
                state_machine_source
            )
            return "Success. The code was successfully patched.", 200
        except (AttributeError, NameError) as e:
            info = exc_info()
            raise NRPServicesStateMachineException(e.message, 400), None, info[2]

        except SyntaxError as e:
            info = exc_info()
            args_txt = ""
            for text in e.args:
                args_txt += " {0}".format(text)
            raise NRPServicesStateMachineException(
                "The source code is invalid: "
                "SyntaxError in line {0}{1}.".format(e.lineno, args_txt),
                400
            ), None, info[2]

        except Exception as e:
            info = exc_info()
            raise NRPServicesGeneralException(
                "Update of state machine code failed. "
                "{0}: {1}".format(
                    e.__class__.__name__,
                    e.message
                ), "State machine error"
            ), None, info[2]
Beispiel #30
0
    def post(self, sim_id):
        """
        Save the current running experiment SDF back to the storage
        :param sim_id: The sim_id
        :param context_id: The context_id of the experiment
        :status 500: Error saving file
        :status 200: Success. File written.
        """
        # pylint: disable=too-many-locals
        simulation = _get_simulation_or_abort(sim_id)

        try:
            rospy.wait_for_service('/gazebo/export_world_sdf', 3)
        except rospy.ROSException as exc:
            raise NRPServicesUnavailableROSService(str(exc))

        dump_sdf_world = rospy.ServiceProxy('/gazebo/export_world_sdf',
                                            ExportWorldSDF)

        try:
            sdf_string = dump_sdf_world().sdf_dump
            tree = ET.fromstring(sdf_string)
            # Erase all robots from the SDF
            robots = simulation.cle.get_simulation_robots()
            for robot in robots:
                for m in tree.findall(".//model[@name='" + robot.robot_id +
                                      "']"):
                    m.getparent().remove(m)
            sdf_string = ET.tostring(tree, encoding='utf8', method='xml')
        except rospy.ServiceException as exc:
            raise NRPServicesClientErrorException(
                "Service did not process request:" + str(exc))

        client = StorageClient()

        # find the sdf world filename from the .exc
        exp_xml_file_path = client.clone_file(
            'experiment_configuration.exc',
            UserAuthentication.get_header_token(), simulation.experiment_id)

        experiment_file = client.parse_and_check_file_is_valid(
            exp_xml_file_path, exp_conf_api_gen.CreateFromDocument,
            exp_conf_api_gen.ExD_)

        world_file_name = experiment_file.environmentModel.src

        client.create_or_update(UserAuthentication.get_header_token(),
                                simulation.experiment_id, world_file_name,
                                sdf_string, "text/plain")

        return 200