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): """ 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 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 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 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 state of the simulation with the specified simulation id. Possible values are: created, initialized, started, paused, stopped :param sim_id: The simulation id :> json string state: The state of the simulation :status 404: {0} :status 401: {1} :status 200: The state of the simulation with the given ID was successfully retrieved """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.can_view(simulation): raise NRPServicesWrongUserException() return {'state': str(simulation.state)}, 200
def get(self, sim_id): """ Returns the SDF file describing the world in which the simulation is carried out :> json string sdf: the SDF string describing the world excluding the robots involved :status 500: ROS service not available :status 401: {0} :status 400: A ROS error occurred :status 200: SDF file successfully returned """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.can_view(simulation): raise NRPServicesWrongUserException() 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) # remove all references to the robots in 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)) return {"sdf": sdf_string}, 200
def get(self, sim_id): """ Gets the neurons of the brain in a simulation with the specified simulation id. :param sim_id: The simulation ID :> json array Populations: array of population dictionaries. Each dict contains population name, neuron indices, neuron model, parameters and gids :status 404: {0} :status 401: {1} :status 200: The neurons of the simulation with the given ID where successfully retrieved """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.can_view(simulation): raise NRPServicesWrongUserException() # Get Neurons from cle neurons = simulation.cle.get_populations() return neurons, 200
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 401: {2} :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) if not UserAuthentication.can_view(sim): raise NRPServicesWrongUserException() # validate the command type if command not in ['is-recording', 'is-playingback']: raise NRPServicesClientErrorException( 'Invalid recorder query: %s' % command, error_code=404) try: if command == 'is-recording': state = str( sim.cle.command_simulation_recorder( SimulationRecorderRequest.STATE).value) elif command == 'is-playingback': state = 'False' if sim.playback_path is None else 'True' return {'state': state}, 200 # internal CLE ROS error if service call fails, notify frontend except ROSCLEClientException as e: raise NRPServicesGeneralException(str(e), 'CLE error', 500)
def get(self, sim_id, resource_type, resource_path): """ Download the file in the resource_path for the give resource_type :param sim_id: The ID of the simulation whose files shall be handled :param resource_type: "robots", "brains", "environments", "files" :param resource_path: relative path the particular resource to be downloaded """ # pylint: disable=no-self-use sim = _get_simulation_or_abort(sim_id) if not UserAuthentication.can_view(sim): raise NRPServicesWrongUserException() if resource_type not in SimulationFiles.RESOURCE_TYPES: raise NRPServicesGeneralException("Wrong resource_type specified", 'Wrong Parameter', 500) try: ret, err = SimulationFiles.__download_file(sim, resource_type, resource_path) except ROSCLEClientException as e: raise NRPServicesGeneralException(str(e), 'CLE error', 500) return ({'res': 'success'}, 200) if ret else ({'res': err}, 500)
def get(self, sim_id): """ Get code of all state machines. This works in all simulation states except 'created', where it will deliver an empty dictionary. :param sim_id: The simulation ID :> json dict data: Dictionary containing all state machines ('name': 'source') :status 404: {0} :status 401: {1} :status 200: Success. The state machines were returned """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.can_view(simulation): raise NRPServicesWrongUserException() state_machines = dict() for sm in simulation.state_machines: state_machines[sm.sm_id] = simulation.get_state_machine_code( sm.sm_id) return dict(data=state_machines), 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 401: {3} :status 200: Success. The simulation BIBI configuration files were retrieved """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.can_view(simulation): raise NRPServicesWrongUserException() 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.sim_dir, 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: root_dir = os.path.join( '/config-from-cloned-folder', os.path.basename(simulation.lifecycle.sim_dir)) else: # Get the template experiment folder name, e.g., "template_husky" root_dir = os.path.join( '/config-from-template-folder', os.path.basename(os.path.dirname(experiment_file))) for conf in resources: conf['file'] = os.path.join(root_dir, conf['file']) conf['file_offset'] = len(root_dir) + 1 return {'resources': resources}, 200