aboutsummaryrefslogtreecommitdiffstats
path: root/opnfv_testapi/resources/test_handlers.py
diff options
context:
space:
mode:
authorxudan <xudan16@huawei.com>2018-07-06 05:16:40 -0400
committerxudan <xudan16@huawei.com>2018-07-06 05:21:42 -0400
commitb3e40f026d655501bfa581452c447784604ecb05 (patch)
tree406f8bfc1abc1b33f98153d03abd34ef7b0e2fe9 /opnfv_testapi/resources/test_handlers.py
parentb1b0ea32d1a296c7d055c5391261dcad6be48c63 (diff)
Move all web portal code to the new repo dovetail-webportal
This is only the first step to simply copy the file here. There still need some more work to make sure all work well. All the changes will be submitted with other patches to make it easily to review. JIRA: DOVETAIL-671 Change-Id: I64d32a9df562184166b6199e2719f298687d1a0a Signed-off-by: xudan <xudan16@huawei.com>
Diffstat (limited to 'opnfv_testapi/resources/test_handlers.py')
-rw-r--r--opnfv_testapi/resources/test_handlers.py307
1 files changed, 307 insertions, 0 deletions
diff --git a/opnfv_testapi/resources/test_handlers.py b/opnfv_testapi/resources/test_handlers.py
new file mode 100644
index 0000000..82cf9ae
--- /dev/null
+++ b/opnfv_testapi/resources/test_handlers.py
@@ -0,0 +1,307 @@
+##############################################################################
+# Copyright (c) 2015 Orange
+# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+import logging
+import os
+import json
+
+from tornado import web
+from tornado import gen
+from bson import objectid
+
+from opnfv_testapi.common.config import CONF
+from opnfv_testapi.common import message
+from opnfv_testapi.common import raises
+from opnfv_testapi.resources import handlers
+from opnfv_testapi.resources import test_models
+from opnfv_testapi.tornado_swagger import swagger
+from opnfv_testapi.ui.auth import constants as auth_const
+from opnfv_testapi.db import api as dbapi
+
+DOVETAIL_LOG_PATH = '/home/testapi/logs/{}/results/dovetail.log'
+
+
+class GenericTestHandler(handlers.GenericApiHandler):
+ def __init__(self, application, request, **kwargs):
+ super(GenericTestHandler, self).__init__(application,
+ request,
+ **kwargs)
+ self.table = "tests"
+ self.table_cls = test_models.Test
+
+
+class TestsCLHandler(GenericTestHandler):
+ @swagger.operation(nickname="queryTests")
+ @web.asynchronous
+ @gen.coroutine
+ def get(self):
+ """
+ @description: Retrieve result(s) for a test project
+ on a specific pod.
+ @notes: Retrieve result(s) for a test project on a specific pod.
+ Available filters for this request are :
+ - id : Test id
+ - period : x last days, incompatible with from/to
+ - from : starting time in 2016-01-01 or 2016-01-01 00:01:23
+ - to : ending time in 2016-01-01 or 2016-01-01 00:01:23
+ - signed : get logined user result
+
+ GET /results/project=functest&case=vPing&version=Arno-R1 \
+ &pod=pod_name&period=15&signed
+ @return 200: all test results consist with query,
+ empty list if no result is found
+ @rtype: L{Tests}
+ """
+ def descend_limit():
+ descend = self.get_query_argument('descend', 'true')
+ return -1 if descend.lower() == 'true' else 1
+
+ def last_limit():
+ return self.get_int('last', self.get_query_argument('last', 0))
+
+ def page_limit():
+ return self.get_int('page', self.get_query_argument('page', 0))
+
+ limitations = {
+ 'sort': {'_id': descend_limit()},
+ 'last': last_limit(),
+ 'page': page_limit(),
+ 'per_page': CONF.api_results_per_page
+ }
+
+ query = yield self.set_query()
+ yield self._list(query=query, **limitations)
+ logging.debug('list end')
+
+ @swagger.operation(nickname="createTest")
+ @web.asynchronous
+ def post(self):
+ """
+ @description: create a test
+ @param body: test to be created
+ @type body: L{TestCreateRequest}
+ @in body: body
+ @rtype: L{CreateResponse}
+ @return 200: test is created.
+ @raise 404: pod/project/testcase not exist
+ @raise 400: body/pod_name/project_name/case_name not provided
+ """
+ openid = self.get_secure_cookie(auth_const.OPENID)
+ if openid:
+ self.json_args['owner'] = openid
+
+ self._post()
+
+ @gen.coroutine
+ def _post(self):
+ miss_fields = []
+ carriers = []
+ query = {'owner': self.json_args['owner'], 'id': self.json_args['id']}
+ ret, msg = yield self._check_if_exists(table="tests", query=query)
+ if ret:
+ self.finish_request({'code': '403', 'msg': msg})
+ return
+
+ self._create(miss_fields=miss_fields, carriers=carriers)
+
+
+class TestsGURHandler(GenericTestHandler):
+
+ @swagger.operation(nickname="getTestById")
+ @web.asynchronous
+ @gen.coroutine
+ def get(self, test_id):
+ query = dict()
+ query["_id"] = objectid.ObjectId(test_id)
+
+ data = yield dbapi.db_find_one(self.table, query)
+ if not data:
+ raises.NotFound(message.not_found(self.table, query))
+
+ validation = yield self._check_api_response_validation(data['id'])
+
+ data.update({'validation': validation})
+
+ self.finish_request(self.format_data(data))
+
+ @gen.coroutine
+ def _check_api_response_validation(self, test_id):
+ log_path = DOVETAIL_LOG_PATH.format(test_id)
+ if not os.path.exists(log_path):
+ raises.Forbidden('dovetail.log not found, please check')
+
+ with open(log_path) as f:
+ log_content = f.read()
+
+ warning_keyword = 'Strict API response validation DISABLED'
+ if warning_keyword in log_content:
+ raise gen.Return('API response validation disabled')
+ else:
+ raise gen.Return('API response validation enabled')
+
+ @swagger.operation(nickname="deleteTestById")
+ def delete(self, test_id):
+ query = {'_id': objectid.ObjectId(test_id)}
+ self._delete(query=query)
+
+ @swagger.operation(nickname="updateTestById")
+ @web.asynchronous
+ def put(self, _id):
+ """
+ @description: update a single test by id
+ @param body: fields to be updated
+ @type body: L{TestUpdateRequest}
+ @in body: body
+ @rtype: L{Test}
+ @return 200: update success
+ @raise 404: Test not exist
+ @raise 403: nothing to update
+ """
+ logging.debug('put')
+ data = json.loads(self.request.body)
+ item = data.get('item')
+ value = data.get(item)
+ logging.debug('%s:%s', item, value)
+ try:
+ self.update(_id, item, value)
+ except Exception as e:
+ logging.error('except:%s', e)
+ return
+
+ @gen.coroutine
+ def _convert_to_id(self, email):
+ query = {"email": email}
+ table = "users"
+ if query and table:
+ data = yield dbapi.db_find_one(table, query)
+ if data:
+ raise gen.Return((True, 'Data alreay exists. %s' % (query),
+ data.get("openid")))
+ raise gen.Return((False, 'Data does not exist. %s' % (query), None))
+
+ @gen.coroutine
+ def update(self, _id, item, value):
+ logging.debug("update")
+ if item == "shared":
+ new_list = []
+ for user in value:
+ ret, msg, user_id = yield self._convert_to_id(user)
+ if ret:
+ user = user_id
+ new_list.append(user)
+ query = {"$or": [{"openid": user}, {"email": user}]}
+ table = "users"
+ ret, msg = yield self._check_if_exists(table=table,
+ query=query)
+ logging.debug('ret:%s', ret)
+ if not ret:
+ self.finish_request({'code': '403', 'msg': msg})
+ return
+
+ if len(new_list) != len(set(new_list)):
+ msg = "Already shared with this user"
+ self.finish_request({'code': '403', 'msg': msg})
+ return
+
+ logging.debug("before _update")
+ self.json_args = {}
+ self.json_args[item] = value
+ ret, msg = yield self.check_auth(item, value)
+ if not ret:
+ self.finish_request({'code': '404', 'msg': msg})
+ return
+
+ query = {'_id': objectid.ObjectId(_id)}
+ db_keys = ['_id', ]
+
+ test = yield dbapi.db_find_one("tests", query)
+ if not test:
+ msg = 'Record does not exist'
+ self.finish_request({'code': 404, 'msg': msg})
+ return
+
+ curr_user = self.get_secure_cookie(auth_const.OPENID)
+ if item in {"shared", "label", "sut_label"}:
+ query['owner'] = curr_user
+ db_keys.append('owner')
+
+ if item == 'sut_label':
+ if test['status'] != 'private' and not value:
+ msg = 'SUT version cannot be changed to None after submitting.'
+ self.finish_request({'code': 403, 'msg': msg})
+ return
+
+ if item == "status":
+ if value in {'approved', 'not approved'}:
+ if test['status'] == 'private':
+ msg = 'Not allowed to approve/not approve'
+ self.finish_request({'code': 403, 'msg': msg})
+ return
+
+ user = yield dbapi.db_find_one("users", {'openid': curr_user})
+ if 'administrator' not in user['role']:
+ msg = 'No permission to operate'
+ self.finish_request({'code': 403, 'msg': msg})
+ return
+ elif value == 'review':
+ if test['status'] != 'private':
+ msg = 'Not allowed to submit to review'
+ self.finish_request({'code': 403, 'msg': msg})
+ return
+
+ if not test['sut_label']:
+ msg = 'Please fill out SUT version before submission'
+ self.finish_request({'code': 403, 'msg': msg})
+ return
+
+ query['owner'] = curr_user
+ db_keys.append('owner')
+
+ test_query = {
+ 'id': test['id'],
+ '$or': [
+ {'status': 'review'},
+ {'status': 'approved'},
+ {'status': 'not approved'}
+ ]
+ }
+ record = yield dbapi.db_find_one("tests", test_query)
+ if record:
+ msg = ('{} has already submitted one record with the same '
+ 'Test ID: {}'.format(record['owner'], test['id']))
+ self.finish_request({'code': 403, 'msg': msg})
+ return
+ else:
+ query['owner'] = curr_user
+ db_keys.append('owner')
+
+ logging.debug("before _update 2")
+ self._update(query=query, db_keys=db_keys)
+
+ @gen.coroutine
+ def check_auth(self, item, value):
+ logging.debug('check_auth')
+ user = self.get_secure_cookie(auth_const.OPENID)
+ query = {}
+ if item == "status":
+ if value == "private" or value == "review":
+ logging.debug('check review')
+ query['user_id'] = user
+ data = yield dbapi.db_find_one('applications', query)
+ if not data:
+ logging.debug('not found')
+ raise gen.Return((False, message.no_auth()))
+ if value == "approve" or value == "not approved":
+ logging.debug('check approve')
+ query['role'] = {"$regex": ".*reviewer.*"}
+ query['openid'] = user
+ data = yield dbapi.db_find_one('users', query)
+ if not data:
+ logging.debug('not found')
+ raise gen.Return((False, message.no_auth()))
+ raise gen.Return((True, {}))