def test_get_header_token(self): # ensure 'Authorization' header is used if available with self.__app.test_request_context( '/test', headers={'Authorization': 'Bearer aaa-bbb'}): token = UserAuthentication.get_header_token() self.assertEqual(token, 'aaa-bbb') # ensure 'no_token' is used if 'Authorization' header is not available with self.__app.test_request_context('/test'): token = UserAuthentication.get_header_token() self.assertEqual(token, 'no_token')
def test_get_x_user_name_header(self): # ensure 'X-User-Name' header is used if available with self.__app.test_request_context('/test', headers={'X-User-Name': 'Test'}): owner = UserAuthentication.get_x_user_name_header() self.assertEqual(owner, 'Test') # ensure 'default-owner' is used if 'X-User-Name' header is not available with self.__app.test_request_context('/test'): owner = UserAuthentication.get_x_user_name_header() self.assertEqual(owner, 'default-owner')
def test_can_modify(self): with self.__app.test_request_context('/test', headers={'X-User-Name': 'Test'}): self.assertTrue( UserAuthentication.can_modify(FakeSimulation('Test'))) self.assertFalse( UserAuthentication.can_modify(FakeSimulation('default-owner'))) with self.__app.test_request_context('/test'): self.assertFalse( UserAuthentication.can_modify(FakeSimulation('Test'))) self.assertTrue( UserAuthentication.can_modify(FakeSimulation('default-owner')))
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
def _check_and_extract_environment_zip(self, experiment): """ Checks for validity and extracts a zipped environment. First we make sure that the zip referenced in the experiment exists in the list of user environments, then we unzip it on the fly in the temporary simulation directory. After the extraction we also make sure to copy the sdf from the experiment folder cause the user may have modified it :param experiment: The experiment object. """ from hbp_nrp_backend.storage_client_api.StorageClient import StorageClient client = StorageClient() environments_list = client.get_custom_models( UserAuthentication.get_header_token(request), self.simulation.ctx_id, 'environments') # we use the paths of the uploaded zips to make sure the selected # zip is there paths_list = [environment['path'] for environment in environments_list] # check if the zip is in the user storage zipped_model_path = [ path for path in paths_list if experiment.environmentModel.customModelPath in path ] if len(zipped_model_path): environment_path = os.path.join( client.get_temp_directory(), os.path.basename(experiment.environmentModel.src)) storage_env_zip_data = client.get_custom_model( UserAuthentication.get_header_token(request), self.simulation.ctx_id, zipped_model_path[0]) env_sdf_name = os.path.basename(experiment.environmentModel.src) env_path = os.path.join( client.get_temp_directory(), experiment.environmentModel.customModelPath) with open(env_path, 'w') as environment_zip: environment_zip.write(storage_env_zip_data) with zipfile.ZipFile(env_path) as env_zip_to_extract: env_zip_to_extract.extractall(path=client.get_temp_directory()) # copy back the .sdf from the experiment folder, cause we don't want the one # in the zip, cause the user might have made manual changes client.clone_file(env_sdf_name, UserAuthentication.get_header_token(request), self.simulation.experiment_id) # if the zip is not there, prompt the user to check his uploaded # models else: raise NRPServicesGeneralException( "Could not find selected zip %s in the list of uploaded models. Please make\ sure that it has been uploaded correctly" % (os.path.dirname(experiment.environmentModel.src)), "Zipped model retrieval failed") return environment_path
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 _get_brain_info_from_storage(cls, experiment_id, context_id): """ Gathers from the storage the brain script and the populations by getting the BIBI configuration file. :param experiment_id: the id of the experiment in which to look for the brain information :param context_id: the context ID for collab based simulations :return: A tuple with the path to the brain file and a list of populations """ del context_id # Unused request_token = UserAuthentication.get_header_token() experiment_file = cls.storage_client.get_file( request_token, experiment_id, 'experiment_configuration.exc', by_name=True) bibi_filename = exp_conf_api_gen.CreateFromDocument(experiment_file).bibiConf.src # find the brain filename from the bibi bibi_file = cls.storage_client.get_file( request_token, experiment_id, bibi_filename, by_name=True) bibi_file_obj = bibi_api_gen.CreateFromDocument(bibi_file) brain_filename = os.path.basename(bibi_file_obj.brainModel.file) brain_filepath = cls.storage_client.clone_file(brain_filename, request_token, experiment_id) neurons_config = get_all_neurons_as_dict(bibi_file_obj.brainModel.populations) neurons_config_clean = \ [SimulationResetStorage._get_experiment_population(name, v) for (name, v) in neurons_config.iteritems()] return brain_filepath, neurons_config_clean, neurons_config
def reset_from_storage_all(cls, simulation, experiment_id, context_id): """ Reset states machines and transfer functions :param: the simulation id :param: the experiment id :param: the context_id for collab based simulations """ SimUtil.clear_dir(simulation.lifecycle.sim_dir) token = UserAuthentication.get_header_token() cls.storage_client.clone_all_experiment_files( token, experiment_id, destination_dir=simulation.lifecycle.sim_dir) with open(simulation.lifecycle.experiment_path) as exc_file: exc = exp_conf_api_gen.CreateFromDocument(exc_file.read()) bibi_path = os.path.join(os.path.dirname(simulation.lifecycle.experiment_path), exc.bibiConf.src) with open(bibi_path) as bibi_file: bibi = bibi_api_gen.CreateFromDocument(bibi_file.read()) cls.reset_brain(simulation, experiment_id, context_id) cls.reset_transfer_functions(simulation, bibi, simulation.lifecycle.sim_dir) cls.reset_state_machines(simulation, exc, simulation.lifecycle.sim_dir)
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): """ 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
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
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
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 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 test_can_view(self): sim = FakeSimulation('Test') with self.__app.test_request_context('/test'): # UserAuthentication.NO_TOKEN should return False self.assertFalse(UserAuthentication.can_view(sim)) with self.__app.test_request_context( '/test', headers={'Authorization': 'bearer my_token'}): with patch( "hbp_nrp_backend.simulation_control.__BackendSimulationLifecycle.UserAuthentication.client" ) as client: client.can_acess_experiment = MagicMock(return_value=True) # If failed to 'can_acess_experiment', it should default to false client.can_acess_experiment.side_effect = Exception('Test') self.assertFalse(UserAuthentication.can_view(sim))
def put(self, sim_id): """ Change the material of a given visual. Currently, only the change of screen materials is implemented :param sim_id: The simulation ID :< json string visual_path: The path to the visual for which a change in material is requested :< json string material_name: The name of the material that will be applied :status 404: {0} :status 401: {1} :status 400: The parameters are invalid :status 200: Material applied successfully """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.matches_x_user_name_header( request, simulation.owner): raise NRPServicesWrongUserException() body = request.get_json(force=True) if 'visual_path' not in body: return "No visual_path given", 400 if 'material' not in body: return "No material given", 400 return self.__set_material(body['visual_path'], body['material'])
def get(self, sim_id): """ Gets the simulation with the specified simulation id :param sim_id: The simulation id :> json string state: The current state of the simulation :> json integer simulationID: The id of the simulation (needed for further REST calls) :> json string environmentConfiguration: Path and name of the environment configuration file :> json string owner: The simulation owner (Unified Portal user id or 'hbp-default') :> json string creationDate: Date of creation of this simulation :> json string gzserverHost: Denotes where the simulation will run once started. Set to 'local' for localhost and 'lugano' for a dedicate machine on the Lugano viz cluster :> json string reservation: the name of the cluster reservation subsequently used to allocate a job :> json string experimentID: The experiment ID if the experiment is using the storage :> json integer brainProcesses: Number of brain processes to use (overrides ExD conf.) :> json string creationUniqueID: unique creation ID (used by Frontend to identify this sim.) :status 404: {0} :status 401: {1} :status 200: The simulation with the given ID is successfully retrieved """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.can_view(simulation): raise NRPServicesWrongUserException() return simulation, 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 brain_populations: A dictionary indexed by population names and containing neuron indices. :status 500: {0} :status 404: {1} :status 401: {2} :status 200: Success. The experiment brain file was retrieved """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.can_view(simulation): raise NRPServicesWrongUserException() result = simulation.cle.get_simulation_brain() return { 'data': result.brain_data, 'brain_type': result.brain_type, 'data_type': result.data_type, 'brain_populations': json.loads(result.brain_populations) }, 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 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 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)
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 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
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 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 401: {1} :status 200: Transfer functions retrieved successfully """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.can_view(simulation): raise NRPServicesWrongUserException() 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
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 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_matches_x_user_name_header(self): with self.__app.test_request_context('/test', headers={'X-User-Name': 'Test'}): self.assertTrue( UserAuthentication.matches_x_user_name_header( flask.request, 'Test')) self.assertFalse( UserAuthentication.matches_x_user_name_header( flask.request, 'default-owner')) with self.__app.test_request_context('/test'): self.assertFalse( UserAuthentication.matches_x_user_name_header( flask.request, 'Test')) self.assertTrue( UserAuthentication.matches_x_user_name_header( flask.request, 'default-owner'))
def test_get_user(self): with self.__app.test_request_context('/test', headers={'X-User-Name': 'Test'}): self.assertEqual(UserAuthentication.get_user(), 'Test') with self.__app.test_request_context('/test', headers={}): self.assertEqual(UserAuthentication.get_user(), 'default-owner') with self.__app.test_request_context('/test', headers={ 'Authorization': 'bearer my_incorrect_token' }): self.assertEqual(UserAuthentication.get_user(), 'default-owner') with patch( "hbp_nrp_backend.simulation_control.__BackendSimulationLifecycle.UserAuthentication.client" ) as client: client.get_user = MagicMock(return_value={'id': 'myid'}) with self.__app.test_request_context( '/test', headers={'Authorization': 'bearer my_token'}): self.assertEqual(UserAuthentication.get_user(), 'myid')