diff --git a/opv_status_api/__main__.py b/opv_status_api/__main__.py
index 6f52508..c2c9cbb 100644
--- a/opv_status_api/__main__.py
+++ b/opv_status_api/__main__.py
@@ -16,11 +16,10 @@
# Email: team@openpathview.fr
# Description: OPV status api
-from http.server import HTTPServer
-from opv_status_api.httpHandler import HttpHandler
import docopt
import logging
from opv_status_api.logging import setup_logging
+from opv_status_api.service import Service
__doc__ = """
An api for opv-status front
@@ -43,8 +42,9 @@ def main():
server_address = ('', int(args["--port"]))
logger.info("Starting http server at http://localhost:{} open to {}".format(server_address[1], server_address[0]))
- httpd = HTTPServer(server_address, HttpHandler)
- httpd.serve_forever()
+
+ service = Service(host=server_address[0], port=server_address[1])
+ service.start()
if __name__ == "__main__":
diff --git a/opv_status_api/celery/__init__.py b/opv_status_api/celery/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/opv_status_api/celery/celery.py b/opv_status_api/celery/celery.py
new file mode 100644
index 0000000..2365296
--- /dev/null
+++ b/opv_status_api/celery/celery.py
@@ -0,0 +1,37 @@
+# coding: utf-8
+
+# Copyright (C) 2017 Open Path View, Maison Du Libre
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see .
+
+# Contributors: Simon Archieri
+# Email: team@openpathview.fr
+# Description: OPV status api
+import logging
+from opv_celery.__main__ import launch
+
+
+class Celery:
+ logger = logging.getLogger("opv_status_api")
+
+ def LaunchCelery(self, data):
+ output = {
+ "answer": None,
+ "error": None
+ }
+ if "campaign_id" in data and "malette_id" in data:
+ launch(data["campaign_id"], data["malette_id"])
+
+ output["answer"] = "Celery launched you should check the api"
+ else:
+ output["error"] = "Missing parameter"
+
+ return output
diff --git a/opv_status_api/httpHandler.py b/opv_status_api/httpHandler.py
deleted file mode 100644
index 7f08396..0000000
--- a/opv_status_api/httpHandler.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# coding: utf-8
-
-# Copyright (C) 2017 Open Path View, Maison Du Libre
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-# You should have received a copy of the GNU General Public License along
-# with this program. If not, see .
-
-# Contributors: Simon Archieri
-# Email: team@openpathview.fr
-# Description: OPV status api
-
-from http.server import BaseHTTPRequestHandler
-from opv_status_api.importData.importData import ImportData
-from opv_status_api.spark.spark import Spark
-import json
-import logging
-
-
-class HttpHandler(BaseHTTPRequestHandler):
- importData = ImportData()
- spark = Spark()
- logger = logging.getLogger("opv_status_api")
-
- def do_GET(self):
- self.logger.info("New GET request at {}".format(self.path))
- asked = self.path.split("/")
- del asked[0]
-
- if asked[0] == "import" and len(asked) >= 2:
- del asked[0]
- answer = self.importData.newCommand(path=asked, type=self.command)
- elif asked[0] == "spark" and len(asked) >= 2:
- del asked[0]
- answer = self.spark.newCommand(path=asked, type=self.command)
- else:
- answer = {
- "httpCode": 404,
- "answer": {
- "error": "404",
- "answer": "This api work =). But you look lost"
- }
- }
-
- self.logger.debug("Answer of task : {}".format(answer))
- self.send_response(answer["httpCode"])
- self.send_header('Content-Type', 'application/json')
- self.send_header('Access-Control-Allow-Origin', '*')
- self.end_headers()
- self.wfile.write(json.dumps(answer["answer"]).encode())
-
- def do_POST(self):
- self.logger.info("New GET request at {}".format(self.path))
- asked = self.path.split("/")
- del asked[0]
-
- data = json.loads(self.rfile.read(int(self.headers.get("Content-Length"))).decode())
-
- if asked[0] == "import" and len(asked) >= 2:
- del asked[0]
- answer = self.importData.newCommand(path=asked, type=self.command, data=data)
- elif asked[0] == "spark" and len(asked) >= 2:
- del asked[0]
- answer = self.spark.newCommand(path=asked, type=self.command, data=data)
- else:
- answer = {
- "httpCode": 404,
- "answer": {
- "error": "404",
- "answer": "This api work =). But you look lost"
- }
- }
-
- self.logger.debug("Answer of task : {}".format(answer))
- self.send_response(answer["httpCode"])
- self.send_header('Content-Type', 'application/json')
- self.send_header('Access-Control-Allow-Origin', '*')
- self.end_headers()
- self.wfile.write(json.dumps(answer["answer"]).encode())
diff --git a/opv_status_api/importData/importData.py b/opv_status_api/importData/importData.py
index 2323f22..a3ca13b 100644
--- a/opv_status_api/importData/importData.py
+++ b/opv_status_api/importData/importData.py
@@ -23,86 +23,45 @@
class ImportData:
- defaultOutput = {
- "httpCode": 200,
- "answer": {
- "error": None,
- "answer": {}
- }
- }
-
logger = logging.getLogger("opv_status_api")
defaultLogFile = "/tmp/importData.log"
importDataThread = ImportDataThread()
- def getStatus(self, path=[], data={}, type="GET"):
- output = copy.deepcopy(self.defaultOutput).copy()
-
- if type == "GET":
- info = self.importDataThread.getInfo()
-
- output["answer"]["answer"] = info
-
- else:
- output["httpCode"] = 400
- output["answer"]["error"] = "You must use GET"
-
- return output
-
- def launchImport(self, path=[], data={}, type="POST"):
- output = copy.deepcopy(self.defaultOutput).copy()
-
- if type == "POST":
- if "path" in data and "id_malette" in data and "camera_number" in data and "description" in data and "campaign_name" in data and "id_rederbro" in data:
- self.importDataThread = ImportDataThread(data=data)
- self.importDataThread.start()
+ def getStatus(self):
+ return {
+ "answer": self.importDataThread.getInfo(),
+ "error": None
+ }
- output["answer"]["answer"] = "Launched, you should check status to know if it work"
- else:
- output["httpCode"] = 400
- output["answer"]["error"] = "You must set all param"
+ def launchImport(self, data):
+ output = {
+ "answer": None,
+ "error": None
+ }
+ if "path" in data and "id_malette" in data and "camera_number" in data and "description" in data and "campaign_name" in data and "id_rederbro" in data:
+ self.importDataThread = ImportDataThread(data=data)
+ self.importDataThread.start()
+ output["answer"] = "Launched, you should check status to know if it work"
else:
- output["httpCode"] = 400
- output["answer"]["error"] = "You must use POST"
+ output["error"] = "Missing param"
return output
- def getLog(self, path=[], data={}, type="POST"):
- output = copy.deepcopy(self.defaultOutput).copy()
-
- if type == "POST":
- logFile = self.defaultLogFile if "logFile" not in data else data["logFile"]
-
- if os.path.isfile(logFile):
- with open(logFile) as log:
- output["answer"]["answer"] = log.read()
+ def getLog(self, data):
+ output = {
+ "answer": None,
+ "error": None
+ }
+ logFile = self.defaultLogFile if "logFile" not in data else data["logFile"]
- else:
- output["httpCode"] = 400
- output["answer"]["error"] = "Can't find log file"
+ if os.path.isfile(logFile):
+ with open(logFile) as log:
+ output["answer"] = log.read()
else:
- output["httpCode"] = 400
- output["answer"]["error"] = "You must use POST"
+ output["error"] = "Log file not found"
- return output
-
- command = {
- "status": getStatus,
- "log": getLog,
- "launch": launchImport
- }
-
- def newCommand(self, path=[], data={}, type="GET"):
- if path[0] in self.command:
- self.logger.debug("Launch command {} with path={}, data={}, type={}".format(path[0], path, data, type))
- return self.command[path[0]](self, path=path, data=data, type=type)
- else:
- self.logger.debug("Asked ressource ({}) can't be find in importData".format(path[0]))
- output = copy.deepcopy(self.defaultOutput).copy()
- output["httpCode"] = 400
- output["answer"]["error"] = "We can't find {}".format(path[0])
- return output
+ return output
\ No newline at end of file
diff --git a/opv_status_api/service.py b/opv_status_api/service.py
new file mode 100644
index 0000000..d6dc284
--- /dev/null
+++ b/opv_status_api/service.py
@@ -0,0 +1,77 @@
+from flask import Flask, request, abort
+from flask_cors import CORS
+from gevent.pywsgi import WSGIServer
+from opv_status_api.importData.importData import ImportData
+from opv_status_api.spark.spark import Spark
+from opv_status_api.celery.celery import Celery
+import json
+import logging
+
+
+class Service:
+ def __init__(self, host="", port=5001):
+ self.port = port
+ self.host = host
+
+ def start(self):
+ app = Flask("opv-status-api")
+ CORS(app)
+
+ logger = logging.getLogger("opv_status_api")
+
+ importService = ImportData()
+ spark = Spark()
+ celery = Celery()
+
+ mimetype = {'Content-Type': 'application/json'}
+
+ service = {
+ "import": {
+ "log": (importService.getLog, "POST"),
+ "launch": (importService.launchImport, "POST"),
+ "status": (importService.getStatus, "GET")
+ },
+ "spark": {
+ "launch": (spark.launchSpark, "POST"),
+ "port": (spark.getSparkPort, "GET")
+ },
+ "celery": {
+ "launch": (celery.LaunchCelery, "POST")
+ }
+ }
+
+ def check_args(service_name, command_name):
+ logger.debug("---- New request ----")
+ logger.debug("Request type : {}".format(request.method))
+ logger.debug("Body : {}".format(request.data.decode()))
+ logger.debug("Service : {}, Command : {}".format(service_name, command_name))
+ if (service_name in service and
+ command_name in service[service_name]):
+ if request.method == service[service_name][command_name][1]:
+ if request.method == "POST":
+ try:
+ json.loads(request.data.decode())
+ logger.info("-- Valid request for {} {} --".format(service_name, command_name))
+ except ValueError:
+ logger.debug("-- Error ==> POST request + body isn't json --")
+ abort(415)
+ return
+ logger.debug("-- Error ==> unsupported method for this command --")
+ abort(405)
+ logger.debug("-- Error ==> unknow command --")
+ abort(404)
+
+ @app.route("//", methods=["POST", "GET"])
+ def launchCommand(service_name, command_name):
+ check_args(service_name, command_name)
+ if request.method == "POST":
+ answer = service[service_name][command_name][0](json.loads(request.data.decode()))
+ else:
+ answer = service[service_name][command_name][0]()
+
+ answer = json.dumps(answer), 400 if answer["error"] else 200, mimetype
+ logger.debug("Request answer : {}".format(answer))
+ return answer
+
+ http_server = WSGIServer((self.host, self.port), app)
+ http_server.serve_forever()
\ No newline at end of file
diff --git a/opv_status_api/spark/spark.py b/opv_status_api/spark/spark.py
index 0a9c0e8..a52efd6 100644
--- a/opv_status_api/spark/spark.py
+++ b/opv_status_api/spark/spark.py
@@ -23,14 +23,6 @@
class Spark:
- defaultOutput = {
- "httpCode": 200,
- "answer": {
- "error": None,
- "answer": {}
- }
- }
-
logger = logging.getLogger("opv_status_api")
def getPort(self):
@@ -45,51 +37,27 @@ def getPort(self):
return port
- def getSparkPort(self, path=[], data={}, type="GET"):
- output = copy.deepcopy(self.defaultOutput).copy()
- if type == "GET":
- output["answer"]["answer"] = self.getPort()
- else:
- output["httpCode"] = 400
- output["answer"]["error"] = "You must use GET"
-
- return output
-
- def launchSpark(self, path=[], data={}, type="POST"):
- output = copy.deepcopy(self.defaultOutput).copy()
-
- if type == "POST":
- if "campaign_id" in data and "malette_id" in data:
- self.sparkThread = LaunchSparkThread(campaign_id=data["campaign_id"], malette_id=data["malette_id"])
+ def getSparkPort(self):
+ return {
+ "answer": self.getPort(),
+ "error": None
+ }
- if "customLaunchScript" in data:
- self.sparkThread = LaunchSparkThread(launchScript=data["customLaunchScript"], campaign_id=data["campaign_id"], malette_id=data["malette_id"])
+ def launchSpark(self, data):
+ output = {
+ "answer": None,
+ "error": None
+ }
+ if "campaign_id" in data and "malette_id" in data:
+ self.sparkThread = LaunchSparkThread(campaign_id=data["campaign_id"], malette_id=data["malette_id"])
- self.sparkThread.start()
+ if "customLaunchScript" in data:
+ self.sparkThread = LaunchSparkThread(launchScript=data["customLaunchScript"], campaign_id=data["campaign_id"], malette_id=data["malette_id"])
- output["answer"]["answer"] = "Spark launched you should check the api"
- else:
- output["httpCode"] = 400
- output["answer"]["error"] = "You must set the campaign id and malette id"
+ self.sparkThread.start()
+ output["answer"] = "Spark launched you should check the api"
else:
- output["httpCode"] = 400
- output["answer"]["error"] = "You must use POST"
+ output["error"] = "Missing parameter"
return output
-
- command = {
- "launch": launchSpark,
- "port": getSparkPort
- }
-
- def newCommand(self, path=[], data={}, type="GET"):
- if path[0] in self.command:
- self.logger.debug("Launch command {} with path={}, data={}, type={}".format(path[0], path, data, type))
- return self.command[path[0]](self, path=path, data=data, type=type)
- else:
- self.logger.debug("Asked ressource ({}) can't be find in Spark".format(path[0]))
- output = copy.deepcopy(self.defaultOutput).copy()
- output["httpCode"] = 400
- output["answer"]["error"] = "We can't find {}".format(path[0])
- return output
diff --git a/requirements.txt b/requirements.txt
index e1f3bc6..26ec8c5 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,6 +2,10 @@ psutil
path.py
docopt
PyYAML
+Flask
+Flask-Cors
+gevent
-e git+https://github.com/OpenPathView/OPV_importData/@master#egg=opv_import
-e git+https://github.com/OpenPathView/DirectoryManagerClient@stable#egg=opv_directorymanagerclient
-e git+https://github.com/OpenPathView/OPV_DBRest-client@stable#egg=opv_api_client
+-e git+https://github.com/OpenPathView/OPV_Celery@master#egg=opv_celery
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 2acdcfd..0a08967 100755
--- a/setup.py
+++ b/setup.py
@@ -31,7 +31,8 @@
dependency_links=[
"git+https://github.com/OpenPathView/DirectoryManagerClient@stable#egg=opv_directorymanagerclient",
"git+https://github.com/OpenPathView/OPV_DBRest-client@stable#egg=opv_api_client",
- "git+https://github.com/OpenPathView/OPV_importData/@master#egg=opv_import"
+ "git+https://github.com/OpenPathView/OPV_importData/@master#egg=opv_import",
+ "git+https://github.com/OpenPathView/OPV_Celery/@master#egg=opv_celery"
],
install_requires=[
"path.py",
@@ -40,7 +41,10 @@
"opv_directorymanagerclient",
"opv_api_client",
"docopt",
- "PyYAML"
+ "PyYAML",
+ "Flask",
+ "Flask-Cors",
+ "gevent"
],
# Active la prise en compte du fichier MANIFEST.in
include_package_data=True,