diff options
author | chenjiankun <chenjiankun1@huawei.com> | 2017-08-09 03:23:58 +0000 |
---|---|---|
committer | chenjiankun <chenjiankun1@huawei.com> | 2017-08-11 09:29:58 +0000 |
commit | 43bf12d6ab7bcaea16dc75ed4ccbe3895cf51da3 (patch) | |
tree | 234d642e36564dab4e9d48cff09c0b93901c252f | |
parent | 55234666785b0fdc81365da4dac5563e954f8a09 (diff) |
Add real time log view in GUI
JIRA: YARDSTICK-775
We have GUI now, but we can't see real time log in GUI view.
So I add real time log view in GUI.
Change-Id: Ie83f327ef0a94302afa6b3def764fec6ef5818d1
Signed-off-by: chenjiankun <chenjiankun1@huawei.com>
-rw-r--r-- | api/__init__.py | 2 | ||||
-rw-r--r-- | api/resources/v2/tasks.py | 36 | ||||
-rw-r--r-- | api/urls.py | 1 | ||||
-rw-r--r-- | gui/app/index.html | 1 | ||||
-rw-r--r-- | gui/app/scripts/controllers/projectDetail.controller.js | 20 | ||||
-rw-r--r-- | gui/app/scripts/controllers/taskLog.controller.js | 34 | ||||
-rw-r--r-- | gui/app/scripts/factory/main.factory.js | 8 | ||||
-rw-r--r-- | gui/app/scripts/router.config.js | 10 | ||||
-rw-r--r-- | gui/app/views/projectdetail.html | 1 | ||||
-rw-r--r-- | gui/app/views/taskLog.html | 39 | ||||
-rw-r--r-- | tests/unit/benchmark/core/test_task.py | 10 | ||||
-rw-r--r-- | yardstick/benchmark/core/task.py | 17 | ||||
-rw-r--r-- | yardstick/common/constants.py | 1 |
13 files changed, 159 insertions, 21 deletions
diff --git a/api/__init__.py b/api/__init__.py index c5aefffe8..323502232 100644 --- a/api/__init__.py +++ b/api/__init__.py @@ -35,13 +35,11 @@ class ApiResource(Resource): pass args.update({k: v for k, v in request.form.items()}) - LOG.debug('Input args is: action: %s, args: %s', action, args) return action, args def _get_args(self): args = common_utils.translate_to_str(request.args) - LOG.debug('Input args is: args: %s', args) return args diff --git a/api/resources/v2/tasks.py b/api/resources/v2/tasks.py index 885a190c6..25a9cf109 100644 --- a/api/resources/v2/tasks.py +++ b/api/resources/v2/tasks.py @@ -8,6 +8,8 @@ ############################################################################## import uuid import logging +import os +import errno from datetime import datetime from oslo_serialization import jsonutils @@ -252,3 +254,37 @@ class V2Task(ApiResource): 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) diff --git a/api/urls.py b/api/urls.py index 3fef91af8..83cf4daf9 100644 --- a/api/urls.py +++ b/api/urls.py @@ -48,6 +48,7 @@ urlpatterns = [ Url('/api/v2/yardstick/tasks', 'v2_tasks'), Url('/api/v2/yardstick/tasks/action', 'v2_tasks'), Url('/api/v2/yardstick/tasks/<task_id>', 'v2_task'), + Url('/api/v2/yardstick/tasks/<task_id>/log', 'v2_task_log'), Url('/api/v2/yardstick/testcases', 'v2_testcases'), Url('/api/v2/yardstick/testcases/action', 'v2_testcases'), diff --git a/gui/app/index.html b/gui/app/index.html index 5592656cc..d959b14d2 100644 --- a/gui/app/index.html +++ b/gui/app/index.html @@ -100,6 +100,7 @@ <script src="scripts/controllers/suitedetail.controller.js"></script> <script src="scripts/controllers/suitecreate.controller.js"></script> <script src="scripts/controllers/task.controller.js"></script> + <script src="scripts/controllers/taskLog.controller.js"></script> <script src="scripts/controllers/report.controller.js"></script> <script src="scripts/controllers/project.controller.js"></script> <script src="scripts/controllers/projectDetail.controller.js"></script> diff --git a/gui/app/scripts/controllers/projectDetail.controller.js b/gui/app/scripts/controllers/projectDetail.controller.js index 4ab4a055a..a616f3ee7 100644 --- a/gui/app/scripts/controllers/projectDetail.controller.js +++ b/gui/app/scripts/controllers/projectDetail.controller.js @@ -671,20 +671,8 @@ angular.module('yardStickGui2App') }) } - - - - - - - - - - - - - - - + $scope.gotoLog = function gotoLog(task_id) { + $state.go('app2.taskLog', { taskId: task_id }); + } } - ]);
\ No newline at end of file + ]); diff --git a/gui/app/scripts/controllers/taskLog.controller.js b/gui/app/scripts/controllers/taskLog.controller.js new file mode 100644 index 000000000..17722b7da --- /dev/null +++ b/gui/app/scripts/controllers/taskLog.controller.js @@ -0,0 +1,34 @@ +'use strict'; + +angular.module('yardStickGui2App').controller('TaskLogController', ['$scope', '$stateParams', '$http', '$interval', 'mainFactory', function ($scope, $stateParams, $http, $interval, mainFactory) { + $scope.logLines = []; + $scope.getLog = getLog; + $scope.taskId = $stateParams.taskId; + $scope.taskStatus = 0; + $scope.index = 0; + + $scope.goBack = function goBack() { + window.history.back(); + } + + function getLog(){ + + function get_data(){ + mainFactory.getTaskLog().get({'taskId': $scope.taskId, 'index': $scope.index}).$promise.then(function(data){ + angular.forEach(data.result.data, function(ele){ + $scope.logLines.push(ele); + $scope.index = data.result.index; + }); + + if(data.status == 1){ + $interval.cancel($scope.intervalTask); + $scope.taskStatus = 1; + } + }); + } + + $scope.intervalTask = $interval(get_data, 2000); + } + + getLog(); +}]); diff --git a/gui/app/scripts/factory/main.factory.js b/gui/app/scripts/factory/main.factory.js index f8e9df9a1..44fbeb39f 100644 --- a/gui/app/scripts/factory/main.factory.js +++ b/gui/app/scripts/factory/main.factory.js @@ -178,6 +178,14 @@ angular.module('yardStickGui2App') }) }, + getTaskLog: function(){ + return $resource(Base_URL + '/api/v2/yardstick/tasks/:taskId/log?index=:index', { taskId: "@taskId", index: "@index" }, { + 'get': { + method: 'GET' + } + }) + }, + taskAddEnv: function() { return $resource(Base_URL + '/api/v2/yardstick/tasks/:taskId', { taskId: "@taskId" }, { 'put': { diff --git a/gui/app/scripts/router.config.js b/gui/app/scripts/router.config.js index b42954272..9d3c045bd 100644 --- a/gui/app/scripts/router.config.js +++ b/gui/app/scripts/router.config.js @@ -143,6 +143,16 @@ angular.module('yardStickGui2App') } }) + .state('app2.taskLog', { + url: '/task/:taskId/log', + templateUrl: 'views/taskLog.html', + controller: 'TaskLogController', + params: { taskId: null }, + ncyBreadcrumb: { + label: 'TaskLog' + } + + }) .state('app2.report', { url: '/report/:taskId', templateUrl: 'views/report.html', diff --git a/gui/app/views/projectdetail.html b/gui/app/views/projectdetail.html index 357a26add..405ff5af0 100644 --- a/gui/app/views/projectdetail.html +++ b/gui/app/views/projectdetail.html @@ -47,6 +47,7 @@ <li role="menuitem" ng-show="task.status!=0"><a ng-click="runAtaskForTable(task.uuid)">run</a></li> <li role="menuitem" ng-show="task.status!=0"><a ng-click="gotoModify(task.uuid)">modify</a></li> + <li role="menuitem" ng-show="task.status!=-1"><a ng-click="gotoLog(task.uuid)">log</a></li> <li role="menuitem" ng-show="task.status!=-1 && task.status!=0"><a ng-click="gotoReport(task.uuid)" style="color:#2ecc71">reporting</a></li> <li role="menuitem"><a ng-click="openDeleteEnv(task.uuid,'task')">delete</a></li> diff --git a/gui/app/views/taskLog.html b/gui/app/views/taskLog.html new file mode 100644 index 000000000..f90eb22b8 --- /dev/null +++ b/gui/app/views/taskLog.html @@ -0,0 +1,39 @@ +<div class="content"> + <i class="fa fa-arrow-left fa-1x" aria-hidden="true" style="color: #999;cursor:pointer" ng-click="goBack()">Back</i> + <h3>Log</h3> + <hr/> + <div style="display:flex;flex-direction:row"> + <div> + <div style="margin-top:5px;">Task: {{ taskId }}</div> + </div> + <div class="progree-parent" style="margin-top:10px;margin-left:20px"> + <div class="progree-child" ng-show="taskStatus==0" style="width:50%"></div> + <div class="progree-child" ng-show="taskStatus==1" style="width:100%"></div> + </div> + <i class="fa fa-check" aria-hidden="true" style="margin-top:10px;margin-left:5px;color: #2ecc71;" ng-show="taskStatus==1">finish</i> + <i class="fa fa-spinner" aria-hidden="true" style="margin-top:10px;margin-left:5px;color: #2ecc71;" ng-show="taskStatus==0">runing</i> + </div> + <div class="box"> + <div class="line-block" ng-repeat="line in logLines track by $index"> + <span>{{ line }}</span> + </div> + </div> +</div> + +<style> + .box { + width: 90%%; + border-radius: 5px; + border: 1px solid #e8e8e8; + line-height: 180%; + margin-top: 20px; + } + + .line-block { + margin-left: 10px; + } + + .content { + height: 90%; + } +</style> diff --git a/tests/unit/benchmark/core/test_task.py b/tests/unit/benchmark/core/test_task.py index 7f617537e..25688bf48 100644 --- a/tests/unit/benchmark/core/test_task.py +++ b/tests/unit/benchmark/core/test_task.py @@ -118,7 +118,8 @@ class TaskTestCase(unittest.TestCase): }, ]) - expected_get_network_calls = 4 # once for each vld_id in the nodes dict + # once for each vld_id in the nodes dict + expected_get_network_calls = 4 expected = { 'a': {'name': 'a', 'network_type': 'private'}, 'b': {'name': 'b', 'vld_id': 'y', 'subnet_cidr': '10.20.0.0/16'}, @@ -289,6 +290,13 @@ class TaskTestCase(unittest.TestCase): task.change_server_name(scenario, suffix) self.assertTrue(scenario['target']['name'], 'demo-8') + @mock.patch('yardstick.benchmark.core.task.logging') + def test_set_log(self, mock_logging): + task_obj = task.Task() + task_obj.task_id = 'task_id' + task_obj._set_log() + self.assertTrue(mock_logging.root.addHandler.called) + def _get_file_abspath(self, filename): curr_path = os.path.dirname(os.path.abspath(__file__)) file_path = os.path.join(curr_path, filename) diff --git a/yardstick/benchmark/core/task.py b/yardstick/benchmark/core/task.py index 395f3b8e8..dd35bd4f4 100644 --- a/yardstick/benchmark/core/task.py +++ b/yardstick/benchmark/core/task.py @@ -65,6 +65,8 @@ class Task(object): # pragma: no cover task_id = getattr(args, 'task_id') self.task_id = task_id if task_id else str(uuid.uuid4()) + self._set_log() + check_environment() try: @@ -156,6 +158,17 @@ class Task(object): # pragma: no cover print("Done, exiting") return result + def _set_log(self): + log_format = '%(asctime)s %(name)s %(filename)s:%(lineno)d %(levelname)s %(message)s' + log_formatter = logging.Formatter(log_format) + + log_path = os.path.join(constants.TASK_LOG_DIR, '{}.log'.format(self.task_id)) + log_handler = logging.FileHandler(log_path) + log_handler.setFormatter(log_formatter) + log_handler.setLevel(logging.DEBUG) + + logging.root.addHandler(log_handler) + def _init_output_config(self, output_config): output_config.setdefault('DEFAULT', {}) output_config.setdefault('dispatcher_http', {}) @@ -414,7 +427,7 @@ class TaskParser(object): # pragma: no cover try: with open(self.path) as stream: - cfg = yaml.safe_load(stream) + cfg = yaml.load(stream) except IOError as ioerror: sys.exit(ioerror) @@ -478,7 +491,7 @@ class TaskParser(object): # pragma: no cover raise e print("Input task is:\n%s\n" % rendered_task) - cfg = yaml.safe_load(rendered_task) + cfg = yaml.load(rendered_task) except IOError as ioerror: sys.exit(ioerror) diff --git a/yardstick/common/constants.py b/yardstick/common/constants.py index 822d3b4fa..f80e10488 100644 --- a/yardstick/common/constants.py +++ b/yardstick/common/constants.py @@ -64,6 +64,7 @@ RELENG_DIR = get_param('dir.releng', '/home/opnfv/repos/releng') LOG_DIR = get_param('dir.log', '/tmp/yardstick/') YARDSTICK_ROOT_PATH = dirname( dirname(abspath(pkg_resources.resource_filename(__name__, "")))) + sep +TASK_LOG_DIR = get_param('dir.tasklog', '/var/log/yardstick/') CONF_SAMPLE_DIR = join(REPOS_DIR, 'etc/yardstick/') ANSIBLE_DIR = join(REPOS_DIR, 'ansible') SAMPLE_CASE_DIR = join(REPOS_DIR, 'samples') |