############################################################################## # Copyright (c) 2017 Huawei Technologies Co.,Ltd. # # 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 uuid import logging import os import errno from datetime import datetime from oslo_serialization import jsonutils from api import ApiResource from api.database.v2.handlers import V2TaskHandler from api.database.v2.handlers import V2ProjectHandler from api.database.v2.handlers import V2EnvironmentHandler from api.utils.thread import TaskThread from yardstick.common.utils import result_handler from yardstick.common.utils import change_obj_to_dict from yardstick.common import constants as consts from yardstick.benchmark.core.task import Task from yardstick.benchmark.core import Param LOG = logging.getLogger(__name__) LOG.setLevel(logging.DEBUG) class V2Tasks(ApiResource): def get(self): task_handler = V2TaskHandler() tasks = [change_obj_to_dict(t) for t in task_handler.list_all()] for t in tasks: result = t['result'] t['result'] = jsonutils.loads(result) if result else None return result_handler(consts.API_SUCCESS, {'tasks': tasks}) def post(self): return self._dispatch_post() def create_task(self, args): try: name = args['name'] except KeyError: return result_handler(consts.API_ERROR, 'name must be provided') try: project_id = args['project_id'] except KeyError: return result_handler(consts.API_ERROR, 'project_id must be provided') task_id = str(uuid.uuid4()) create_time = datetime.now() task_handler = V2TaskHandler() LOG.info('create task in database') task_init_data = { 'uuid': task_id, 'project_id': project_id, 'name': name, 'time': create_time, 'status': -1 } task_handler.insert(task_init_data) LOG.info('create task in project') project_handler = V2ProjectHandler() project_handler.append_attr(project_id, {'tasks': task_id}) return result_handler(consts.API_SUCCESS, {'uuid': task_id}) class V2Task(ApiResource): def get(self, task_id): try: uuid.UUID(task_id) except ValueError: return result_handler(consts.API_ERROR, 'invalid task id') task_handler = V2TaskHandler() try: task = task_handler.get_by_uuid(task_id) except ValueError: return result_handler(consts.API_ERROR, 'no such task id') task_info = change_obj_to_dict(task) result = task_info['result'] task_info['result'] = jsonutils.loads(result) if result else None return result_handler(consts.API_SUCCESS, {'task': task_info}) def delete(self, task_id): try: uuid.UUID(task_id) except ValueError: return result_handler(consts.API_ERROR, 'invalid task id') task_handler = V2TaskHandler() try: project_id = task_handler.get_by_uuid(task_id).project_id except ValueError: return result_handler(consts.API_ERROR, 'no such task id') LOG.info('delete task in database') task_handler.delete_by_uuid(task_id) project_handler = V2ProjectHandler() project = project_handler.get_by_uuid(project_id) if project.tasks: LOG.info('update tasks in project') new_task_list = project.tasks.split(',') new_task_list.remove(task_id) if new_task_list: new_tasks = ','.join(new_task_list) else: new_tasks = None project_handler.update_attr(project_id, {'tasks': new_tasks}) return result_handler(consts.API_SUCCESS, {'task': task_id}) def put(self, task_id): try: uuid.UUID(task_id) except ValueError: return result_handler(consts.API_ERROR, 'invalid task id') task_handler = V2TaskHandler() try: task_handler.get_by_uuid(task_id) except ValueError: return result_handler(consts.API_ERROR, 'no such task id') return self._dispatch_post(task_id=task_id) def add_environment(self, args): task_id = args['task_id'] try: environment_id = args['environment_id'] except KeyError: return result_handler(consts.API_ERROR, 'environment_id must be provided') try: uuid.UUID(environment_id) except ValueError: return result_handler(consts.API_ERROR, 'invalid environment id') environment_handler = V2EnvironmentHandler() try: environment_handler.get_by_uuid(environment_id) except ValueError: return result_handler(consts.API_ERROR, 'no such environment id') LOG.info('update environment_id in task') task_handler = V2TaskHandler() task_handler.update_attr(task_id, {'environment_id': environment_id}) return result_handler(consts.API_SUCCESS, {'uuid': task_id}) def add_case(self, args): task_id = args['task_id'] try: name = args['case_name'] except KeyError: return result_handler(consts.API_ERROR, 'case_name must be provided') try: content = args['case_content'] except KeyError: return result_handler(consts.API_ERROR, 'case_content must be provided') LOG.info('update case info in task') task_handler = V2TaskHandler() task_update_data = { 'case_name': name, 'content': content, 'suite': False } task_handler.update_attr(task_id, task_update_data) return result_handler(consts.API_SUCCESS, {'uuid': task_id}) def add_suite(self, args): task_id = args['task_id'] try: name = args['suite_name'] except KeyError: return result_handler(consts.API_ERROR, 'suite_name must be provided') try: content = args['suite_content'] except KeyError: return result_handler(consts.API_ERROR, 'suite_content must be provided') LOG.info('update suite info in task') task_handler = V2TaskHandler() task_update_data = { 'case_name': name, 'content': content, 'suite': True } task_handler.update_attr(task_id, task_update_data) return result_handler(consts.API_SUCCESS, {'uuid': task_id}) def run(self, args): try: task_id = args['task_id'] except KeyError: return result_handler(consts.API_ERROR, 'task_id must be provided') try: uuid.UUID(task_id) except ValueError: return result_handler(consts.API_ERROR, 'invalid task id') task_handler = V2TaskHandler() try: task = task_handler.get_by_uuid(task_id) except ValueError: return result_handler(consts.API_ERROR, 'no such task id') if not task.environment_id: return result_handler(consts.API_ERROR, 'environment not set') if not task.case_name or not task.content: return result_handler(consts.API_ERROR, 'case not set') if task.status == 0: return result_handler(consts.API_ERROR, 'task is already running') with open('/tmp/{}.yaml'.format(task.case_name), 'w') as f: f.write(task.content) data = { 'inputfile': ['/tmp/{}.yaml'.format(task.case_name)], 'task_id': task_id } if task.suite: data.update({'suite': True}) LOG.info('start task thread') param = Param(data) task_thread = TaskThread(Task().start, param, task_handler) task_thread.start() return result_handler(consts.API_SUCCESS, {'uuid': task_id}) class V2TaskLog(ApiResource): def get(self, task_id): try: uuid.UUID(task_id) except ValueError: return result_handler(consts.API_ERROR, 'invalid task id') task_handler = V2TaskHandler() try: task = task_handler.get_by_uuid(task_id) except ValueError: return result_handler(consts.API_ERROR, 'no such task id') index = int(self._get_args().get('index', 0)) try: with open(os.path.join(consts.TASK_LOG_DIR, '{}.log'.format(task_id))) as f: f.seek(index) data = f.readlines() index = f.tell() except OSError as e: if e.errno == errno.ENOENT: return result_handler(consts.API_ERROR, 'log file does not exist') return result_handler(consts.API_ERROR, 'error with log file') return_data = { 'index': index, 'data': data } return result_handler(task.status, return_data)