diff --git a/qinling/api/controllers/v1/execution.py b/qinling/api/controllers/v1/execution.py index 3a535e4f..92423f36 100644 --- a/qinling/api/controllers/v1/execution.py +++ b/qinling/api/controllers/v1/execution.py @@ -67,7 +67,7 @@ class ExecutionsController(rest.RestController): pass if func_url: - r = requests.post(func_url, data=params.get('input')) + r = requests.post(func_url, json=params.get('input')) params.update( {'status': 'success', 'output': {'result': r.json()}} ) diff --git a/qinling/engine/default_engine.py b/qinling/engine/default_engine.py index 36675499..2ca80a1f 100644 --- a/qinling/engine/default_engine.py +++ b/qinling/engine/default_engine.py @@ -79,8 +79,8 @@ class DefaultEngine(object): input=None): LOG.info( 'Creating execution. execution_id=%s, function_id=%s, ' - 'runtime_id=%s', - execution_id, function_id, runtime_id + 'runtime_id=%s, input=%s', + execution_id, function_id, runtime_id, input ) with db_api.transaction(): diff --git a/qinling/orchestrator/kubernetes/manager.py b/qinling/orchestrator/kubernetes/manager.py index 637e210b..0496ca1b 100644 --- a/qinling/orchestrator/kubernetes/manager.py +++ b/qinling/orchestrator/kubernetes/manager.py @@ -298,7 +298,7 @@ class KubernetesManager(base.OrchestratorBase): # new connection' error for some reason. Needs to find a better # solution. time.sleep(1) - r = requests.post(request_url, data=data) + r = requests.post(request_url, json=data) if r.status_code != requests.codes.ok: raise exc.OrchestratorException( @@ -355,7 +355,7 @@ class KubernetesManager(base.OrchestratorBase): func_url = '%s/execute' % service_url LOG.info('Invoke function %s, url: %s', function_id, func_url) - r = requests.post(func_url, data=input) + r = requests.post(func_url, json=input) return {'result': r.json()} else: diff --git a/runtimes/python2/Dockerfile b/runtimes/python2/Dockerfile index f4a8f01a..d4386aee 100644 --- a/runtimes/python2/Dockerfile +++ b/runtimes/python2/Dockerfile @@ -1,9 +1,9 @@ -FROM alpine:3.5 +FROM phusion/baseimage:0.9.22 +MAINTAINER lingxian.kong@gmail.com -RUN apk update -RUN apk add --no-cache linux-headers python2 python2-dev build-base py2-pip py2-pbr -RUN pip install --upgrade pip -RUN rm -r /root/.cache +RUN apt-get update +RUN apt-get -y install python-dev python-setuptools libffi-dev libxslt1-dev libxml2-dev libyaml-dev libssl-dev python-pip +RUN pip install -U pip setuptools COPY . /app WORKDIR /app diff --git a/runtimes/python2/server.py b/runtimes/python2/server.py index fcf1d0c9..fb2cdccc 100644 --- a/runtimes/python2/server.py +++ b/runtimes/python2/server.py @@ -12,12 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +import importlib import json import logging import sys import time +import traceback import zipfile -import zipimport from flask import abort from flask import Flask @@ -36,11 +37,12 @@ openstack_session = None @app.route('/download', methods=['POST']) def download(): - download_url = request.form['download_url'] - function_id = request.form['function_id'] - entry = request.form['entry'] - token = request.form.get('token') - auth_url = request.form.get('auth_url') + params = request.get_json() or {} + download_url = params.get('download_url') + function_id = params.get('function_id') + entry = params.get('entry') + token = params.get('token') + auth_url = params.get('auth_url') headers = {} if token: @@ -60,14 +62,12 @@ def download(): ) r = requests.get(download_url, headers=headers, stream=True) - with open(zip_file, 'wb') as fd: for chunk in r.iter_content(chunk_size=65535): fd.write(chunk) if not zipfile.is_zipfile(zip_file): abort(500) - app.logger.info('Code package downloaded to %s' % zip_file) global function_module @@ -85,33 +85,24 @@ def execute(): global openstack_session context = {'os_session': openstack_session} - - try: - importer = zipimport.zipimporter(zip_file) - module = importer.load_module(function_module) - except Exception as e: - return Response( - response=json.dumps({'output': str(e), 'duration': 0}), - status=200, - mimetype='application/json' - ) - - input = {} - if request.form: - # Refer to: - # http://werkzeug.pocoo.org/docs/0.12/datastructures/#werkzeug.datastructures.MultiDict - input = request.form.to_dict() - + input = request.get_json() or {} app.logger.debug('Invoking function with input: %s' % input) start = time.time() try: + sys.path.insert(0, zip_file) + module = importlib.import_module(function_module) func = getattr(module, function_method) result = func(context=context, **input) except Exception as e: result = str(e) - duration = time.time() - start + # Print stacktrace + exc_type, exc_value, exc_traceback = sys.exc_info() + lines = traceback.format_exception(exc_type, exc_value, exc_traceback) + app.logger.debug(''.join(line for line in lines)) + + duration = time.time() - start return Response( response=json.dumps({'output': result, 'duration': duration}), status=200,