summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgrakiss <grakiss.wanglei@huawei.com>2017-10-30 07:26:37 +0000
committerLeo wang <grakiss.wanglei@huawei.com>2017-11-01 08:44:36 +0000
commit55bb29b1d7b977b387a74f754b4baea94274141c (patch)
tree74ef8f67b87213ad1eacd9d681c05490c000003a
parent62562458e6fd007f4240b669f509f772dd883ca5 (diff)
[cvp-web] Show some SUT hardware info in 'My Results'
[cvp-web] Show SUT endpoint in web page JIRA: DOVETAIL-541 JIRA: DOVETAIL-547 Show some SUT hardware info that dovetail concern in 'My Results' web page. Show the info of all endpoints get from Dovetail tool in the web page. Change-Id: Ibc465396e17b7c22678e3948fa2f659cbff6f323 Signed-off-by: grakiss <grakiss.wanglei@huawei.com>
-rw-r--r--cvp/3rd_party/static/testapi-ui/app.js7
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/results/results.html6
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/results/resultsController.js5
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/sut/sut.html40
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/sut/sutController.js48
-rw-r--r--cvp/3rd_party/static/testapi-ui/index.html3
-rw-r--r--cvp/docker/nginx/sites-enabled/default6
-rw-r--r--cvp/opnfv_testapi/resources/sut_handlers.py112
-rw-r--r--cvp/opnfv_testapi/resources/sut_models.py31
-rw-r--r--cvp/opnfv_testapi/router/url_mappings.py2
10 files changed, 256 insertions, 4 deletions
diff --git a/cvp/3rd_party/static/testapi-ui/app.js b/cvp/3rd_party/static/testapi-ui/app.js
index 5a3cc069..eea8e38e 100644
--- a/cvp/3rd_party/static/testapi-ui/app.js
+++ b/cvp/3rd_party/static/testapi-ui/app.js
@@ -115,7 +115,12 @@
templateUrl: '/testapi-ui/components/products/cloud.html',
controller: 'ProductController as ctrl'
}).
- state('application', {
+ state('sut', {
+ url: '/suts/:testID',
+ templateUrl: '/testapi-ui/components/sut/sut.html',
+ controller: 'SutController as ctrl'
+ }).
+ state('application', {
url: '/application',
templateUrl: '/testapi-ui/components/application/application.html',
controller: 'ApplicationController as ctrl'
diff --git a/cvp/3rd_party/static/testapi-ui/components/results/results.html b/cvp/3rd_party/static/testapi-ui/components/results/results.html
index e1d05b2d..cd38ad75 100644
--- a/cvp/3rd_party/static/testapi-ui/components/results/results.html
+++ b/cvp/3rd_party/static/testapi-ui/components/results/results.html
@@ -25,6 +25,7 @@
<th>Label</th>
<th>Status</th>
<th>Log</th>
+ <th>SUT</th>
<th class="col-md-2">Operation</th>
<th class="col-md-2">Share List</th>
</tr>
@@ -32,13 +33,14 @@
<tbody style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
<tr ng-repeat="(index, result) in ctrl.data.tests">
- <td>{{ result.upload_date }}</td>
+ <td>{{ result.upload_date | limitTo:19}}</td>
<td><a ng-click="ctrl.gotoResultDetail(result.id, result._id)">{{ result.id }}</a></td>
<td>{{ result.filename || "None"}}</td>
<td><div class="popover-wrapper"><a editable-theme="bs3" onbeforesave="ctrl.toggleCheck(result, 'label', $data)" editable-text="result.label"> {{ result.label || "None" }}</a></div></td>
<td>{{ result.status }}</td>
<td><a ng-click="ctrl.downloadLogs(result.id)">logs</a></td>
- <td>
+ <td><a ng-click="ctrl.gotoSUT(result.id)">info</a></td>
+ <td>
<div class="btn-group" uib-dropdown>
<a id="single-button" type="button" class="nectar-button medium accent-color regular-button" uib-dropdown-toggle>
Operation<span class="caret"></span>
diff --git a/cvp/3rd_party/static/testapi-ui/components/results/resultsController.js b/cvp/3rd_party/static/testapi-ui/components/results/resultsController.js
index 2ece86fb..86f7c5d6 100644
--- a/cvp/3rd_party/static/testapi-ui/components/results/resultsController.js
+++ b/cvp/3rd_party/static/testapi-ui/components/results/resultsController.js
@@ -59,6 +59,7 @@
ctrl.associateProductVersion = associateProductVersion;
ctrl.getProductVersions = getProductVersions;
ctrl.prepVersionEdit = prepVersionEdit;
+ ctrl.gotoSUT = gotoSUT;
ctrl.gotoResultDetail = gotoResultDetail;
ctrl.toggleCheck = toggleCheck;
ctrl.toReview = toReview;
@@ -496,5 +497,9 @@
$state.go('resultsDetail', {'testID': testId, 'innerID': innerID});
}
+ function gotoSUT(testId) {
+ $state.go('sut', {'testID': testId});
+ }
+
}
})();
diff --git a/cvp/3rd_party/static/testapi-ui/components/sut/sut.html b/cvp/3rd_party/static/testapi-ui/components/sut/sut.html
new file mode 100644
index 00000000..d9692b87
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/sut/sut.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+
+<link rel="stylesheet" href="testapi-ui/assets/css/combine.css" />
+
+<h2>Endpoints</h2>
+<div class="results-table" style="margin-top:30px;overflow:scroll">
+ <table class="table table-striped table-hover">
+ <thead>
+ <tr>
+ <th>Service Name</th>
+ <th>Service Type</th>
+ <th>URL</th>
+ <th>Enabled</th>
+ </tr>
+ </thead>
+ <tbody style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
+ <tr ng-repeat="endpoint in ctrl.sutData.endpoint_info">
+ <td>{{ endpoint['Service Name'] }}</td>
+ <td>{{ endpoint['Service Type'] }}</td>
+ <td>{{ endpoint['URL'] }}</td>
+ <td>{{ endpoint['Enabled'] }}</td>
+ </tr>
+ </tbody>
+ </table>
+</div>
+
+<h2>Hosts</h2>
+<div ng-repeat="(host, info) in ctrl.sutData.hardware_info">
+ <div class="results-table" style="margin-top:30px;overflow:scroll">
+ <table class="table table-striped table-hover">
+ <tbody style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
+ <tr ng-repeat="record in info">
+ <td>{{ record[0] }}</td>
+ <td>{{ record[1] }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div>
diff --git a/cvp/3rd_party/static/testapi-ui/components/sut/sutController.js b/cvp/3rd_party/static/testapi-ui/components/sut/sutController.js
new file mode 100644
index 00000000..3d662ffa
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/sut/sutController.js
@@ -0,0 +1,48 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+ 'use strict';
+
+ angular
+ .module('testapiApp')
+ .controller('SutController', SutController);
+
+ SutController.$inject = [
+ '$http', '$stateParams', 'testapiApiUrl'
+ ];
+
+ /**
+ */
+ function SutController($http, $stateParams, testapiApiUrl) {
+
+ var ctrl = this;
+
+ function init(){
+ ctrl.sutData = {"hardware_info": {}, "endpoint_info": {}};
+ ctrl.testID = $stateParams.testID;
+ ctrl.getSutData();
+ }
+
+ ctrl.getSutData = function(){
+ $http.get(testapiApiUrl + "/suts/hardware/" + ctrl.testID).then(function(resp){
+ ctrl.sutData = resp.data;
+ }, function(error){
+ alert('Error when get SUT data');
+ });
+ }
+
+ init();
+ }
+})();
diff --git a/cvp/3rd_party/static/testapi-ui/index.html b/cvp/3rd_party/static/testapi-ui/index.html
index b6bdb5a1..8ca6e631 100644
--- a/cvp/3rd_party/static/testapi-ui/index.html
+++ b/cvp/3rd_party/static/testapi-ui/index.html
@@ -51,7 +51,8 @@
<script src="testapi-ui/components/guidelines/guidelinesController.js"></script>
<script src="testapi-ui/components/results/resultsController.js"></script>
<script src="testapi-ui/components/results-report/resultsReportController.js"></script>
- <script src="testapi-ui/components/application/applicationController.js"></script>
+ <script src="testapi-ui/components/sut/sutController.js"></script>
+ <script src="testapi-ui/components/application/applicationController.js"></script>
<script src="testapi-ui/components/profile/profileController.js"></script>
<script src="testapi-ui/components/auth-failure/authFailureController.js"></script>
<script src="testapi-ui/components/logout/logoutController.js"></script>
diff --git a/cvp/docker/nginx/sites-enabled/default b/cvp/docker/nginx/sites-enabled/default
index b6b6a7ed..e2e718ce 100644
--- a/cvp/docker/nginx/sites-enabled/default
+++ b/cvp/docker/nginx/sites-enabled/default
@@ -101,6 +101,12 @@ server {
proxy_set_header Host $host;
}
+ location ~* /api/v1/suts/hardware/([a-zA-Z0-9\-]+) {
+ proxy_pass http://cvpapi/api/v1/suts/hardware/$1;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header Host $host;
+ }
+
location /api/v1/ {
proxy_pass http://testapi/api/v1/;
proxy_set_header X-Real-IP $remote_addr;
diff --git a/cvp/opnfv_testapi/resources/sut_handlers.py b/cvp/opnfv_testapi/resources/sut_handlers.py
new file mode 100644
index 00000000..16c50b83
--- /dev/null
+++ b/cvp/opnfv_testapi/resources/sut_handlers.py
@@ -0,0 +1,112 @@
+##############################################################################
+# Copyright (c) 2017
+# 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 json
+import os
+
+from opnfv_testapi.resources import handlers
+from opnfv_testapi.resources import sut_models
+from opnfv_testapi.tornado_swagger import swagger
+
+LOG = logging.getLogger(__name__)
+LOG.setLevel(logging.DEBUG)
+
+RESULT_PATH = '/home/testapi/logs/{}/results'
+
+
+class GenericSutHandler(handlers.GenericApiHandler):
+ def __init__(self, application, request, **kwargs):
+ super(GenericSutHandler, self).__init__(application,
+ request,
+ **kwargs)
+ self.table = "suts"
+ self.table_cls = sut_models.Sut
+
+
+class HardwareHandler(GenericSutHandler):
+ @swagger.operation(nickname="getHardwareById")
+ def get(self, id):
+ endpoint_info = self._read_endpoint_info(id)
+ LOG.debug('Endpoint info: %s', endpoint_info)
+
+ all_info = self._read_sut_info(id)
+ LOG.debug('All SUT info: %s', all_info)
+
+ hardware_info = {k: self._get_single_host_info(v)
+ for k, v in all_info.items()}
+ LOG.debug('SUT info: %s', hardware_info)
+
+ data = {
+ 'endpoint_info': endpoint_info,
+ 'hardware_info': hardware_info
+ }
+
+ self.write(data)
+
+ def _read_endpoint_info(self, id):
+ path = os.path.join(RESULT_PATH.format(id), 'endpoint_info.json')
+ try:
+ with open(path) as f:
+ endpoint_info = json.load(f)
+ except Exception:
+ endpoint_info = []
+
+ return endpoint_info
+
+ def _read_sut_info(self, id):
+ path = os.path.join(RESULT_PATH.format(id), 'all_hosts_info.json')
+ try:
+ with open(path) as f:
+ all_info = json.load(f)
+ except Exception:
+ all_info = {}
+ return all_info
+
+ def _get_single_host_info(self, single_info):
+ info = []
+ facts = single_info.get('ansible_facts', {})
+
+ info.append(['hostname', facts.get('ansible_hostname')])
+
+ info.append(['product_name', facts.get('ansible_product_name')])
+ info.append(['product_version', facts.get('ansible_product_version')])
+
+ processors = facts.get('ansible_processor', [])
+ try:
+ processor_type = '{} {}'.format(processors[0], processors[1])
+ except IndexError:
+ LOG.exception('No Processor in SUT data')
+ processor_type = None
+ info.append(['processor_type', processor_type])
+ info.append(['architecture', facts.get('ansible_architecture')])
+ info.append(['processor_cores', facts.get('ansible_processor_cores')])
+ info.append(['processor_vcpus', facts.get('ansible_processor_vcpus')])
+
+ memory = facts.get('ansible_memtotal_mb')
+ memory = round(memory * 1.0 / 1024, 2) if memory else None
+ info.append(['memory', '{} GB'.format(memory)])
+
+ devices = facts.get('ansible_devices', {})
+ info.extend([self._get_device_info(k, v) for k, v in devices.items()])
+
+ lsb_description = facts.get('ansible_lsb', {}).get('description')
+ info.append(['OS', lsb_description])
+
+ interfaces = facts.get('ansible_interfaces')
+ info.append(['interfaces', interfaces])
+ info.extend([self._get_interface_info(facts, i) for i in interfaces])
+ info = [i for i in info if i]
+
+ return info
+
+ def _get_interface_info(self, facts, name):
+ mac = facts.get('ansible_{}'.format(name), {}).get('macaddress')
+ return [name, mac] if mac else []
+
+ def _get_device_info(self, name, info):
+ return ['disk_{}'.format(name), info.get('size')]
diff --git a/cvp/opnfv_testapi/resources/sut_models.py b/cvp/opnfv_testapi/resources/sut_models.py
new file mode 100644
index 00000000..b4a869b6
--- /dev/null
+++ b/cvp/opnfv_testapi/resources/sut_models.py
@@ -0,0 +1,31 @@
+##############################################################################
+# Copyright (c) 2017
+# 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
+##############################################################################
+from opnfv_testapi.resources import models
+from opnfv_testapi.tornado_swagger import swagger
+
+
+@swagger.model()
+class Sut(models.ModelBase):
+ """
+ """
+ def __init__(self):
+ pass
+
+
+@swagger.model()
+class Suts(models.ModelBase):
+ """
+ @property suts:
+ @ptype tests: C{list} of L{Sut}
+ """
+ def __init__(self):
+ self.suts = list()
+
+ @staticmethod
+ def attr_parser():
+ return {'suts': Sut}
diff --git a/cvp/opnfv_testapi/router/url_mappings.py b/cvp/opnfv_testapi/router/url_mappings.py
index 73c771fe..83190ee4 100644
--- a/cvp/opnfv_testapi/router/url_mappings.py
+++ b/cvp/opnfv_testapi/router/url_mappings.py
@@ -11,6 +11,7 @@ from opnfv_testapi.resources import handlers
from opnfv_testapi.resources import result_handlers
from opnfv_testapi.resources import test_handlers
from opnfv_testapi.resources import application_handlers
+from opnfv_testapi.resources import sut_handlers
from opnfv_testapi.ui.auth import sign
from opnfv_testapi.ui.auth import user
@@ -27,6 +28,7 @@ mappings = [
(r"/api/v1/cvp/applications/([^/]+)",
application_handlers.ApplicationsGURHandler),
+ (r"/api/v1/suts/hardware/([^/]+)", sut_handlers.HardwareHandler),
(r'/api/v1/auth/signin', sign.SigninHandler),