def test_load_config(self): PipelineManager.pipeline_types = { "GStreamer": "DummyType" } expected_result = { 'gstreamer': { 'object_detection': {} }, 'object_detection': { '1': { "name": "object_detection", "version": 1, "type": "GStreamer", "description": "Object Detection Pipeline" } } } expected_max_running_pipelines = 3 PipelineManager.load_config(os.path.join(os.path.dirname(__file__),"pipelines"), expected_max_running_pipelines) result = PipelineManager.pipelines result_max_running_pipelines = PipelineManager.MAX_RUNNING_PIPELINES self.assertEqual(result, expected_result) self.assertEqual(result_max_running_pipelines, expected_max_running_pipelines)
def _spawn(self, args): self.start_time = time.time() logger.debug(args) self._process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=1, universal_newlines=True) self.state = "RUNNING" self._process.poll() while self._process.returncode is None and self.state != "ABORTED": next_line = self._process.stderr.readline() fps_idx = next_line.rfind('fps=') q_idx = next_line.rfind('q=') if fps_idx != -1 and q_idx != -1: self.fps = int(float(next_line[fps_idx + 4:q_idx].strip())) self._process.poll() self.stop_time = time.time() if self.state == "ABORTED": self._process.kill() else: if self._process.returncode == 0: self.state = "COMPLETED" else: self.state = "ERROR" PipelineManager.pipeline_finished() self._process = None
def loop(self, reqs, pipeline, version="1"): print(reqs, flush=True) pid, msg = PipelineManager.create_instance(pipeline, version, reqs) if pid is None: print("Exception: " + str(msg), flush=True) return -1 fps = 0 while True: self._maincontext.iteration() pinfo = PipelineManager.get_instance_status(pipeline, version, pid) print(pinfo, flush=True) if pinfo is not None: state = pinfo["state"] if state == "COMPLETED": fps = pinfo["avg_fps"] print("Status analysis: Timing {0} {1} {2} {3} {4}".format( reqs["start_time"], pinfo["start_time"], pinfo["elapsed_time"], reqs["user"], reqs["source"]["uri"]), flush=True) break if state == "ABORTED" or state == "ERROR": return -1 PipelineManager.stop_instance(pipeline, version, pid) return fps
def stop_running_pipeline(self): self.pipeline.set_state(Gst.State.NULL) if self.state is "RUNNING": self.state = "ABORTED" logger.debug( "Setting Pipeline {id} State to ABORTED".format(id=self.id)) self.stop_time = time.time() PipelineManager.pipeline_finished()
def __init__(self, pipeline, version="2"): super(RunVA, self).__init__() self._pipeline = pipeline self._version = version self._db = DBIngest(host=dbhost, index="algorithms", office=office) self._maincontext = GLib.MainLoop().get_context() self._stop = None ModelManager.load_config("/home/models", {}) PipelineManager.load_config("/home/pipelines", 1)
def stop(self): if self._process: self.state = "ABORTED" self._process.kill() logger.debug("Setting Pipeline {id} State to ABORTED".format(id=self.id)) PipelineManager.pipeline_finished() if self.state is "QUEUED": PipelineManager.remove_from_queue(self.id) self.state = "ABORTED" logger.debug("Setting Pipeline {id} State to ABORTED and removing from the queue".format(id=self.id))
def main(options): PipelineManager.load_config( os.path.join(CONFIG_PATH, options.pipeline_dir), MAX_RUNNING_PIPELINES) ModelManager.load_config(os.path.join(CONFIG_PATH, options.model_dir)) asyncio.set_event_loop(asyncio.new_event_loop()) app = connexion.App(__name__, specification_dir='./openapi/') app.app.json_encoder = encoder.JSONEncoder app.add_api('openapi.yaml', arguments={'title': 'Video Analytics API'}) logger.info("Starting Tornado Server on port: {p}".format(p=options.port)) app.run(server='tornado', port=options.port)
def stop(self): if self.pipeline is not None: self.stop_running_pipeline() if self.state is "QUEUED": PipelineManager.remove_from_queue(self.id) self.state = "ABORTED" logger.info( "Setting Pipeline {id} State to ABORTED and removing from the queue" .format(id=self.id)) del self.pipeline self.pipeline = None return self.status()
def main(options): PipelineManager.load_config( os.path.join(options.config_path, options.pipeline_dir), options.max_running_pipelines) ModelManager.load_config( os.path.join(options.config_path, options.model_dir), parse_network_preference(options)) app = connexion.App(__name__, specification_dir='./openapi/') app.app.json_encoder = encoder.JSONEncoder app.add_api('openapi.yaml', arguments={'title': 'Video Analytics Serving API'}) logger.info("Starting Tornado Server on port: {p}".format(p=options.port)) app.run(server='tornado', port=options.port)
def pipelines_name_version_instance_id_get(name, version, instance_id): # noqa: E501 """pipelines_name_version_instance_id_get Return instance summary # noqa: E501 :param name: :type name: str :param version: :type version: int :param instance_id: :type instance_id: int :rtype: object """ try: logger.debug("GET on /pipelines/{name}/{version}/{id}".format( name=name, version=version, id=instance_id)) result = PipelineManager.get_instance_parameters( name, version, instance_id) if result: return result return (bad_request_response, HTTPStatus.BAD_REQUEST) except Exception as e: logger.error('pipelines_name_version_instance_id_get ' + e) return ('Unexpected error', HTTPStatus.INTERNAL_SERVER_ERROR)
def pipelines_name_version_instance_id_delete(name, version, instance_id): # noqa: E501 """pipelines_name_version_instance_id_delete Stop and remove an instance of the customized pipeline # noqa: E501 :param name: :type name: str :param version: :type version: int :param instance_id: :type instance_id: int :rtype: None """ try: logger.debug("DELETE on /pipelines/{name}/{version}/{id}".format( name=name, version=version, id=instance_id)) result = PipelineManager.stop_instance(name, version, instance_id) if result: return result return (bad_request_response, HTTPStatus.BAD_REQUEST) except Exception as e: logger.error('pipelines_name_version_instance_id_delete ' + e) return ('Unexpected error', HTTPStatus.INTERNAL_SERVER_ERROR)
def test_stop_instance(self): PipelineManager.pipeline_instances = { 1: type( 'GstreamerPipeline', (object, ), { "stop": lambda self: { "id": 1, "state": "RUNNING", "avg_fps": 100000, "start_time": 1234, "elapsed_time": 1234 } })() } expected_result = { "id": 1, "state": "RUNNING", "avg_fps": 100000, "start_time": 1234, "elapsed_time": 1234 } result = PipelineManager.stop_instance(1) self.assertEqual(result, expected_result)
def shutdown_and_delete_pipeline(self, new_state): if not self.pipeline_is_in_terminal_state(): self.stop_time = time.time() logger.debug("Setting Pipeline {id} State to {next_state}".format( id=self.id, next_state=new_state)) self.state = new_state self.pipeline.set_state(Gst.State.NULL) del self.pipeline self.pipeline = None PipelineManager.pipeline_finished() elif self.state == "QUEUED": logger.debug( "Setting Pipeline {id} State to {next_state} and removing from queue" .format(id=self.id, next_state=new_state)) self.stop_time = time.time() self.state = new_state
def test_create_instance(self): PipelineManager.pipeline_types = { "GStreamer": lambda id, config, models: "Instance" } PipelineManager.pipelines = { "object_detection": { "1": { "name": "object_detection", "version": 1, "type": "GStreamer", "template": "", "description": "Object Detection Pipeline", "parameters": { "send-empty": { "element": "jsonmetaconvert" }, "every-nth-frame": { "element": "detection" } } } } } expected_result = "Instance" result = PipelineManager.create_instance("object_detection", 1) self.assertEqual(result, expected_result)
def pipelines_name_version_post(name, version): # noqa: E501 """pipelines_name_version_post Start new instance of pipeline. Specify the source and destination parameters as URIs # noqa: E501 :param name: :type name: str :param version: :type version: int :param pipeline_request: :type pipeline_request: dict | bytes :rtype: None """ logger.debug("POST on /pipelines/{name}/{version}".format(name=name, version=version)) if connexion.request.is_json: try: pipeline_id, err = PipelineManager.create_instance(name, version, connexion.request.get_json()) if pipeline_id is not None: return pipeline_id return (err, HTTPStatus.BAD_REQUEST) except Exception as e: logger.error('pipelines_name_version_post ' +str(e)) return ('Unexpected error', HTTPStatus.INTERNAL_SERVER_ERROR)
def test_get_loaded_pipelines_empty(self): PipelineManager.pipelines = None expected_result = [] result = PipelineManager.get_loaded_pipelines() self.assertEqual(result, expected_result)
def bus_call(bus, message, self): t = message.type if t == Gst.MessageType.EOS: logger.info("Pipeline {id} Ended".format(id=self.id)) self.pipeline.set_state(Gst.State.NULL) if self.state is "RUNNING": logger.debug("Setting Pipeline {id} State to COMPLETED".format( id=self.id)) self.state = "COMPLETED" self.stop_time = time.time() bus.remove_signal_watch() if (self.destination): del self.destination self.destination = None del self.pipeline self.pipeline = None PipelineManager.pipeline_finished() elif t == Gst.MessageType.ERROR: err, debug = message.parse_error() logger.error("Error on Pipeline {id}: {err}".format(id=id, err=err)) if (self.state is None) or (self.state is "RUNNING") or (self.state is "QUEUED"): logger.debug( "Setting Pipeline {id} State to ERROR".format(id=self.id)) self.stop_time = time.time() self.state = "ERROR" self.pipeline.set_state(Gst.State.NULL) self.stop_time = time.time() bus.remove_signal_watch() del self.pipeline self.pipeline = None PipelineManager.pipeline_finished() elif t == Gst.MessageType.STATE_CHANGED: old_state, new_state, pending_state = message.parse_state_changed() if message.src == self.pipeline: if old_state == Gst.State.PAUSED and new_state == Gst.State.PLAYING: if self.state is "QUEUED": logger.debug( "Setting Pipeline {id} State to RUNNING".format( id=self.id)) self.state = "RUNNING" else: pass return True
def stop(self): if self.pipeline is not None: self.pipeline.set_state(Gst.State.NULL) if self.state is "RUNNING": self.state = "ABORTED" logger.debug("Setting Pipeline {id} State to ABORTED".format(id=self.id)) self.stop_time = time.time() PipelineManager.pipeline_finished() if self.state is "QUEUED": self.state = "ABORTED" PipelineManager.remove_from_queue(self.id) logger.debug("Setting Pipeline {id} State to ABORTED and removing from the queue".format(id=self.id)) del self.pipeline self.pipeline = None return self.status()
def loop(self, reqs, pipeline, version="1"): print(reqs, flush=True) pid, msg = PipelineManager.create_instance(pipeline, version, reqs) if pid is None: print("Exception: " + str(msg), flush=True) return -1 fps = 0 while True: self._maincontext.iteration() pinfo = PipelineManager.get_instance_status(pipeline, version, pid) print(pinfo, flush=True) if pinfo is not None: state = pinfo["state"] if state == "COMPLETED": break if state == "ABORTED" or state == "ERROR": return -1 fps = pinfo["avg_fps"] PipelineManager.stop_instance(pipeline, version, pid) return fps
def pipelines_get(): # noqa: E501 """pipelines_get Return supported pipelines # noqa: E501 :rtype: List[Pipeline] """ logger.debug("GET on /pipelines") return PipelineManager.get_loaded_pipelines()
def test_load_config(self): PipelineManager.pipeline_types = {"GStreamer": "DummyType"} expected_result = { 'gstreamer': { 'object_detection': {} }, 'object_detection': { '1': { "name": "object_detection", "version": 1, "type": "GStreamer", "description": "Object Detection Pipeline" } } } PipelineManager.load_config("modules/test/pipelines") result = PipelineManager.pipelines self.assertEqual(result, expected_result)
def pipelines_get(): # noqa: E501 """pipelines_get Return supported pipelines # noqa: E501 :rtype: List[Pipeline] """ try: logger.debug("GET on /pipelines") return PipelineManager.get_loaded_pipelines() except Exception as e: logger.error('pipelines_name_version_get '+e) return ('Unexpected error', HTTPStatus.INTERNAL_SERVER_ERROR)
def pipelines_name_version_get(name, version): # noqa: E501 """pipelines_name_version_get Return pipeline description and parameters # noqa: E501 :param name: :type name: str :param version: :type version: str :rtype: None """ logger.debug("GET on /pipelines/{name}/{version}".format(name=name, version=version)) return PipelineManager.get_pipeline_parameters(name, version)
def pipelines_name_version_instance_id_delete(name, version, instance_id): # noqa: E501 """pipelines_name_version_instance_id_delete Stop and remove an instance of the customized pipeline # noqa: E501 :param name: :type name: str :param version: :type version: int :param instance_id: :type instance_id: int :rtype: None """ logger.debug("DELETE on /pipelines/{name}/{version}/{id}".format( name=name, version=version, id=instance_id)) return PipelineManager.stop_instance(instance_id)
def pipelines_name_version_instance_id_status_get(name, version, instance_id): # noqa: E501 """pipelines_name_version_instance_id_status_get Return instance status summary # noqa: E501 :param name: :type name: str :param version: :type version: int :param instance_id: :type instance_id: int :rtype: object """ logger.debug("GET on /pipelines/{name}/{version}/{id}/status".format( name=name, version=version, id=instance_id)) return PipelineManager.get_instance_status(instance_id)
def _set_section_properties(self, request_section=[], config_section=[]): request, config = PipelineManager.get_section_and_config( self.request, self.config, request_section, config_section) for key in config: if isinstance(config[key], dict) and "element" in config[key]: if key in request: if (isinstance(config[key]["element"], list)): element_properties = [ self._get_element_property(x, key) for x in config[key]["element"] ] else: element_properties = [ self._get_element_property(config[key]["element"], key) ] for name, property, format in element_properties: element = self.pipeline.get_by_name(name) if (element): if (property in [ x.name for x in element.list_properties() ]): if (format == "json"): element.set_property( property, json.dumps(request[key])) else: element.set_property( property, request[key]) logger.debug( "Setting element: {}, property: {}, value: {}" .format(name, property, element.get_property(property))) else: logger.debug( "Parameter {} given for element {} but no property found" .format(property, name)) else: logger.debug( "Parameter {} given for element {} but no element found" .format(property, name))
def pipelines_name_version_get(name, version): # noqa: E501 """pipelines_name_version_get Return pipeline description and parameters # noqa: E501 :param name: :type name: str :param version: :type version: str :rtype: None """ try: logger.debug("GET on /pipelines/{name}/{version}".format(name=name, version=version)) result = PipelineManager.get_pipeline_parameters(name, version) if result: return result return ('Invalid Pipeline or Version', HTTPStatus.BAD_REQUEST) except Exception as e: logger.error('pipelines_name_version_get '+e) return ('Unexpected error', HTTPStatus.INTERNAL_SERVER_ERROR)
def test_create_instance(self): mock_pipeline = type("MockPipeline", (object,), dict(start=lambda : "started")) PipelineManager.pipeline_types = { "GStreamer": lambda id, config, models, request: mock_pipeline } PipelineManager.pipelines = { "object_detection": { "1": { "name": "object_detection", "version": 1, "type": "GStreamer", "template": "", "description": "Object Detection Pipeline", "parameters": { "send-empty": { "element":"jsonmetaconvert" }, "every-nth-frame": { "element":"detection" } } } } } request_to_send = { 'source': { 'uri': 'path_to_source', 'type': 'uri' }, 'destination': { 'uri': 'path_to_destination', 'type': 'file' } } expected_result = 1 result = PipelineManager.create_instance("object_detection", 1, request_to_send) self.assertEqual(result, expected_result)
def test_get_loaded_pipelines_populated(self): PipelineManager.pipelines = { "object_detection": { 1: { "name": "object_detection", "version": 1, "type": "GStreamer", "template": "", "description": "Object Detection Pipeline", "parameters": { "send-empty": { "element":"jsonmetaconvert" }, "every-nth-frame": { "element":"detection" } } } } } expected_result = [{ "name": "object_detection", "version": 1, "type": "GStreamer", "description": "Object Detection Pipeline", "parameters": { "send-empty": { "element":"jsonmetaconvert" }, "every-nth-frame": { "element":"detection" } } }] result = PipelineManager.get_loaded_pipelines() self.assertEqual(result, expected_result)
def test_get_instance_parameters(self): PipelineManager.pipeline_instances = { 1: type('GstreamerPipeline', (object,), { "params": lambda self: { "id": 1, "request": None, "type": "gstreamer", "launch_command": None } })() } expected_result = { "id": 1, "request": None, "type": "gstreamer", "launch_command": None } result = PipelineManager.get_instance_parameters(1) self.assertEqual(result, expected_result)