diff options
Diffstat (limited to 'reporting')
39 files changed, 860 insertions, 466 deletions
diff --git a/reporting/html/colorado.html b/reporting/3rd_party/html/colorado.html index 58cb009..7a7326e 100644 --- a/reporting/html/colorado.html +++ b/reporting/3rd_party/html/colorado.html @@ -58,7 +58,7 @@ <span class="image">
<img src="img/projectIcon_functest_250x250.png" alt="" />
</span>
- <a href="functest-colorado.html">
+ <a href="colorado/functest/functest.html">
<h2>Functest</h2>
<div class="content">
<p>Functional testing</p>
diff --git a/reporting/html/danube.html b/reporting/3rd_party/html/danube.html index e06d6e5..ae8a3ac 100644 --- a/reporting/html/danube.html +++ b/reporting/3rd_party/html/danube.html @@ -58,7 +58,7 @@ <span class="image"> <img src="img/projectIcon_functest_250x250.png" alt="" /> </span> - <a href="functest-danube.html"> + <a href="danube/functest/functest.html"> <h2>Functest</h2> <div class="content"> <p>Functional testing</p> diff --git a/reporting/html/elements.html b/reporting/3rd_party/html/elements.html index 7b9bb4d..7b9bb4d 100644 --- a/reporting/html/elements.html +++ b/reporting/3rd_party/html/elements.html diff --git a/reporting/html/euphrates.html b/reporting/3rd_party/html/euphrates.html index 1828fc7..e357edc 100644 --- a/reporting/html/euphrates.html +++ b/reporting/3rd_party/html/euphrates.html @@ -42,7 +42,7 @@ <span class="image"> <img src="img/projectIcon_functest_250x250.png" alt="" /> </span> - <a href="functest-euphrates.html"> + <a href="euphrates/functest/functest.html"> <h2>Functest</h2> <div class="content"> <p>Functional testing</p> diff --git a/reporting/html/functest-colorado.html b/reporting/3rd_party/html/fraser.html index 2fc76d1..65b996c 100644 --- a/reporting/html/functest-colorado.html +++ b/reporting/3rd_party/html/fraser.html @@ -1,124 +1,141 @@ -<!DOCTYPE HTML>
-<!--
- Phantom by HTML5 UP
- html5up.net | @ajlkn
- Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
--->
-<html>
- <head>
- <title>Phantom by HTML5 UP</title>
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <!--[if lte IE 8]><script src="3rd_party/js/ie/html5shiv.js"></script><![endif]-->
- <link rel="stylesheet" href="3rd_party/css/main.css" />
- <!--[if lte IE 9]><link rel="stylesheet" href="3rd_party/css/ie9.css" /><![endif]-->
- <!--[if lte IE 8]><link rel="stylesheet" href="3rd_party/css/ie8.css" /><![endif]-->
- </head>
- <body>
- <!-- Wrapper -->
- <div id="wrapper">
-
- <!-- Header -->
- <header id="header">
- <div class="inner">
-
- <!-- Logo -->
- <a href="index.html" class="logo">
- <span class="symbol"><img src="img/logo.svg" alt="" /></span><span class="title">Phantom</span>
- </a>
-
- <!-- Nav -->
- <!-- <nav>
- <ul>
- <li><a href="#menu">Menu</a></li>
- </ul>
- </nav>
- --->
- </div>
- </header>
-
- <!-- Menu -->
- <!--- <nav id="menu">
- <h2>Menu</h2>
- <ul>
- <li><a href="index.html">Home</a></li>
- <li><a href="colorado.html">Colorado</a></li>
- <li><a href="danube.html">Danube</a></li>
- </ul>
- </nav>
- --->
- <!-- Main -->
- <div id="main">
- <div class="inner">
- <header>
- <h1>Functest reporting</h1>
- </header>
- <section class="tiles">
- <article class="style5">
- <span class="image">
- <img src="img/pic05.jpg" alt="" />
- </span>
- <a href="colorado/functest/status-apex.html">
- <h2>Status</h2>
- <div class="content">
- <p>Scenario status</p>
- </div>
- </a>
- </article>
- <article class="style2">
- <span class="image">
- <img src="img/pic02.jpg" alt="" />
- </span>
- <a href="colorado/functest/vims-apex.html">
- <h2>vIMS</h2>
- <div class="content">
- <p>Virtual IMS</p>
- </div>
- </a>
- </article>
- <article class="style3">
- <span class="image">
- <img src="img/pic03.jpg" alt="" />
- </span>
- <a href="colorado/functest/tempest-apex.html">
- <h2>Tempest</h2>
- <div class="content">
- <p>Tempest OpenStack suite</p>
- </div>
- </a>
- </article>
- </section>
- </div>
- </div>
-
- <!-- Footer -->
- <footer id="footer">
- <div class="inner">
- <section>
- <h2>OPNFV Testing Working group</h2>
- </section>
- <section>
- <h2>Follow</h2>
- <ul class="icons">
- <li><a href="https://twitter.com/opnfv" class="icon style2 fa-twitter"><span class="label">Twitter</span></a></li>
- <li><a href="http://git.opnfv.org" class="icon style2 fa-github"><span class="label">GitHub</span></a></li>
- <li><a href="mailto:test-wg@list.opnfv.org" class="icon style2 fa-envelope-o"><span class="label">Email</span></a></li>
- </ul>
- </section>
- <ul class="copyright">
- <li>© Untitled. All rights reserved</li><li>Design: <a href="http://html5up.net">HTML5 UP</a></li>
- </ul>
- </div>
- </footer>
-
- </div>
-
- <!-- Scripts -->
- <script src="3rd_party/js/jquery.min.js"></script>
- <script src="3rd_party/js/skel.min.js"></script>
- <script src="3rd_party/js/util.js"></script>
- <!--[if lte IE 8]><script src="3rd_party/js/ie/respond.min.js"></script><![endif]-->
- <script src="3rd_party/js/main.js"></script>
-
- </body>
-</html>
+<!DOCTYPE HTML> +<!-- + Phantom by HTML5 UP + html5up.net | @ajlkn + Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) +--> +<html> + <head> + <title>Phantom by HTML5 UP</title> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <!--[if lte IE 8]><script src="3rd_party/js/ie/html5shiv.js"></script><![endif]--> + <link rel="stylesheet" href="3rd_party/css/main.css" /> + <!--[if lte IE 9]><link rel="stylesheet" href="3rd_party/css/ie9.css" /><![endif]--> + <!--[if lte IE 8]><link rel="stylesheet" href="3rd_party/css/ie8.css" /><![endif]--> + </head> + <body> + <!-- Wrapper --> + <div id="wrapper"> + + <!-- Header --> + <header id="header"> + <div class="inner"> + + <!-- Logo --> + <a href="index.html" class="logo"> + <span class="symbol"><img src="img/logo.svg" alt="" /></span><span class="title">Phantom</span> + </a> + + </div> + </header> + + <!-- Menu --> + <!-- Main --> + <div id="main"> + <div class="inner"> + <header> + <h1>Fraser reporting</h1> + </header> + <section class="tiles"> + <article class="style3"> + <span class="image"> + <img src="img/projectIcon_functest_250x250.png" alt="" /> + </span> + <a href="fraser/functest/functest.html"> + <h2>Functest</h2> + <div class="content"> + <p>Functional testing</p> + </div> + </a> + </article> + <article class="style2"> + <span class="image"> + <img src="img/projectIcon_yardstick_250x250.png" alt="" /> + </span> + <a href="fraser/yardstick/status-apex.html"> + <h2>Yardstick</h2> + <div class="content"> + <p>Qualification and performance testing</p> + </div> + </a> + </article> + <article class="style4"> + <span class="image"> + <img src="img/projectIcon_storperf_250x250.png" alt="" /> + </span> + <a href="fraser/storperf/status-apex.html"> + <h2>Storperf</h2> + <div class="content"> + <p>Storage testing</p> + </div> + </a> + </article> + <article class="style5"> + <span class="image"> + <img src="img/projectIcon_vsperf_250x250.png" alt="" /> + </span> + <a href="fraser/vsperf/reporting.html"> + <h2>Vsperf</h2> + <div class="content"> + <p>Virtual switch testing</p> + </div> + </a> + </article> + <article class="style1"> + <span class="image"> + <img src="img/projectIcon_qtip_250x250.png" alt="" /> + </span> + <a href="fraser/qtip/status-apex.html"> + <h2>Qtip</h2> + <div class="content"> + <p>Benchmark as a service</p> + </div> + </a> + </article> + <article class="style6"> + <span class="image"> + <img src="img/projectIcon_bottlenecks_250x250.png" alt="" /> + </span> + <a href="fraser/bottlenecks/status-apex.html"> + <h2>Bottlenecks</h2> + <div class="content"> + <p>Bottleneck finder</p> + </div> + </a> + </article> + </section> + </div> + </div> + + <!-- Footer --> + <footer id="footer"> + <div class="inner"> + <section> + <h2>OPNFV Testing Working group</h2> + </section> + <section> + <h2>Follow</h2> + <ul class="icons"> + <li><a href="https://twitter.com/opnfv" class="icon style2 fa-twitter"><span class="label">Twitter</span></a></li> + <li><a href="http://git.opnfv.org" class="icon style2 fa-github"><span class="label">GitHub</span></a></li> + <li><a href="mailto:test-wg@list.opnfv.org" class="icon style2 fa-envelope-o"><span class="label">Email</span></a></li> + </ul> + </section> + <ul class="copyright"> + <li>© Untitled. All rights reserved</li><li>Design: <a href="http://html5up.net">HTML5 UP</a></li> + </ul> + </div> + </footer> + + </div> + + <!-- Scripts --> + <script src="3rd_party/js/jquery.min.js"></script> + <script src="3rd_party/js/skel.min.js"></script> + <script src="3rd_party/js/util.js"></script> + <!--[if lte IE 8]><script src="3rd_party/js/ie/respond.min.js"></script><![endif]--> + <script src="3rd_party/js/main.js"></script> + + </body> +</html> diff --git a/reporting/html/functest-euphrates.html b/reporting/3rd_party/html/functest.html index c203e61..d5f78c5 100644 --- a/reporting/html/functest-euphrates.html +++ b/reporting/3rd_party/html/functest.html @@ -9,10 +9,7 @@ <title>Phantom by HTML5 UP</title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> - <!--[if lte IE 8]><script src="3rd_party/js/ie/html5shiv.js"></script><![endif]--> - <link rel="stylesheet" href="3rd_party/css/main.css" /> - <!--[if lte IE 9]><link rel="stylesheet" href="3rd_party/css/ie9.css" /><![endif]--> - <!--[if lte IE 8]><link rel="stylesheet" href="3rd_party/css/ie8.css" /><![endif]--> + <link rel="stylesheet" href="../../3rd_party/css/main.css" /> </head> <body> <!-- Wrapper --> @@ -24,7 +21,9 @@ <!-- Logo --> <a href="index.html" class="logo"> - <span class="symbol"><img src="img/logo.svg" alt="" /></span><span class="title">Phantom</span> + <span class="symbol"><img src="../../img/logo.svg" alt="" /> + </span> + <span class="title">Functest</span> </a> </div> @@ -41,9 +40,9 @@ <section class="tiles"> <article class="style5"> <span class="image"> - <img src="img/pic05.jpg" alt="" /> + <img src="../../img/pic05.jpg" alt="" /> </span> - <a href="euphrates/functest/status-apex.html"> + <a href="status-apex.html"> <h2>Status</h2> <div class="content"> <p>Scenario status</p> @@ -52,9 +51,9 @@ </article> <article class="style2"> <span class="image"> - <img src="img/pic02.jpg" alt="" /> + <img src="../../img/pic02.jpg" alt="" /> </span> - <a href="euphrates/functest/vims-apex.html"> + <a href="vims-apex.html"> <h2>vIMS</h2> <div class="content"> <p>Virtual IMS</p> @@ -63,9 +62,9 @@ </article> <article class="style3"> <span class="image"> - <img src="img/pic03.jpg" alt="" /> + <img src="../../img/pic03.jpg" alt="" /> </span> - <a href="euphrates/functest/tempest-apex.html"> + <a href="tempest-apex.html"> <h2>Tempest</h2> <div class="content"> <p>Tempest OpenStack suite</p> @@ -99,11 +98,11 @@ </div> <!-- Scripts --> - <script src="3rd_party/js/jquery.min.js"></script> - <script src="3rd_party/js/skel.min.js"></script> - <script src="3rd_party/js/util.js"></script> + <script src="../../3rd_party/js/jquery.min.js"></script> + <script src="../../3rd_party/js/skel.min.js"></script> + <script src="../../3rd_party/js/util.js"></script> <!--[if lte IE 8]><script src="3rd_party/js/ie/respond.min.js"></script><![endif]--> - <script src="3rd_party/js/main.js"></script> + <script src="../../3rd_party/js/main.js"></script> </body> </html> diff --git a/reporting/html/functest-danube.html b/reporting/3rd_party/html/gambia.html index ac99cb0..d5f6fcd 100644 --- a/reporting/html/functest-danube.html +++ b/reporting/3rd_party/html/gambia.html @@ -27,63 +27,80 @@ <span class="symbol"><img src="img/logo.svg" alt="" /></span><span class="title">Phantom</span> </a> - <!-- Nav --> - <!-- <nav> - <ul> - <li><a href="#menu">Menu</a></li> - </ul> - </nav> - ---> </div> </header> <!-- Menu --> - <!--- <nav id="menu"> - <h2>Menu</h2> - <ul> - <li><a href="index.html">Home</a></li> - <li><a href="colorado.html">Colorado</a></li> - <li><a href="danube.html">Danube</a></li> - </ul> - </nav> - ---> <!-- Main --> <div id="main"> <div class="inner"> <header> - <h1>Functest reporting</h1> + <h1>Gambia reporting</h1> </header> <section class="tiles"> - <article class="style5"> + <article class="style3"> <span class="image"> - <img src="img/pic05.jpg" alt="" /> + <img src="img/projectIcon_functest_250x250.png" alt="" /> </span> - <a href="danube/functest/status-apex.html"> - <h2>Status</h2> + <a href="gambia/functest/functest.html"> + <h2>Functest</h2> <div class="content"> - <p>Scenario status</p> + <p>Functional testing</p> </div> </a> </article> <article class="style2"> <span class="image"> - <img src="img/pic02.jpg" alt="" /> + <img src="img/projectIcon_yardstick_250x250.png" alt="" /> </span> - <a href="danube/functest/vims-apex.html"> - <h2>vIMS</h2> + <a href="gambia/yardstick/status-apex.html"> + <h2>Yardstick</h2> <div class="content"> - <p>Virtual IMS</p> + <p>Qualification and performance testing</p> </div> </a> </article> - <article class="style3"> + <article class="style4"> + <span class="image"> + <img src="img/projectIcon_storperf_250x250.png" alt="" /> + </span> + <a href="gambia/storperf/status-apex.html"> + <h2>Storperf</h2> + <div class="content"> + <p>Storage testing</p> + </div> + </a> + </article> + <article class="style5"> + <span class="image"> + <img src="img/projectIcon_vsperf_250x250.png" alt="" /> + </span> + <a href="gambia/vsperf/reporting.html"> + <h2>Vsperf</h2> + <div class="content"> + <p>Virtual switch testing</p> + </div> + </a> + </article> + <article class="style1"> + <span class="image"> + <img src="img/projectIcon_qtip_250x250.png" alt="" /> + </span> + <a href="gambia/qtip/status-apex.html"> + <h2>Qtip</h2> + <div class="content"> + <p>Benchmark as a service</p> + </div> + </a> + </article> + <article class="style6"> <span class="image"> - <img src="img/pic03.jpg" alt="" /> + <img src="img/projectIcon_bottlenecks_250x250.png" alt="" /> </span> - <a href="danube/functest/tempest-apex.html"> - <h2>Tempest</h2> + <a href="gambia/bottlenecks/status-apex.html"> + <h2>Bottlenecks</h2> <div class="content"> - <p>Tempest OpenStack suite</p> + <p>Bottleneck finder</p> </div> </a> </article> diff --git a/reporting/html/generic.html b/reporting/3rd_party/html/generic.html index 39273da..39273da 100644 --- a/reporting/html/generic.html +++ b/reporting/3rd_party/html/generic.html diff --git a/reporting/html/index.html b/reporting/3rd_party/html/index.html index 22d7078..9165250 100644 --- a/reporting/html/index.html +++ b/reporting/3rd_party/html/index.html @@ -43,40 +43,29 @@ <h1>OPNFV Testing group reporting</h1> </header> <section class="tiles"> - <article class="style3"> + <article class="style4"> <span class="image"> - <img src="img/colorado.jpg" alt="" /> + <img src="img/fraser.jpg" alt="" /> </span> - <a href="colorado.html"> - <h2>Colorado</h2> + <a href="fraser.html"> + <h2>Fraser</h2> <div class="content"> - <p>Colorado 1.0 (22/09/2016)</p> + <p>Fraser (ETA 04/2018)</p> </div> </a> </article> - <article class="style2"> - <span class="image"> - <img src="img/danube.jpg" alt="" /> - </span> - <a href="danube.html"> - <h2>Danube</h2> - <div class="content"> - <p>Danube 1.0 (22/03/2017)</p> - </div> - </a> - </article> - <article class="style4"> + <article class="style6"> <span class="image"> - <img src="img/euphrates.jpg" alt="" /> + <img src="img/gambia.jpg" alt="" /> </span> - <a href="euphrates.html"> - <h2>Euphrates</h2> + <a href="gambia.html"> + <h2>Gambia</h2> <div class="content"> - <p>Euphrates (ETA 10/2017)</p> + <p>Gambia (ETA 11/2018)</p> </div> </a> </article> - <article class="style6"> + <article class="style5"> <span class="image"> <img src="img/misc-npc-letterblock-m-800px.png" alt="" /> </span> diff --git a/reporting/html/master.html b/reporting/3rd_party/html/master.html index 312e8e6..5d4f916 100644 --- a/reporting/html/master.html +++ b/reporting/3rd_party/html/master.html @@ -58,7 +58,7 @@ <span class="image"> <img src="img/projectIcon_functest_250x250.png" alt="" /> </span> - <a href="functest-master.html"> + <a href="master/functest/functest.html"> <h2>Functest</h2> <div class="content"> <p>Functional testing</p> diff --git a/reporting/api/conf.py b/reporting/api/conf.py index 5897d4f..d0023e0 100644 --- a/reporting/api/conf.py +++ b/reporting/api/conf.py @@ -1 +1,5 @@ base_url = 'http://testresults.opnfv.org/test/api/v1' + +versions = ['master', 'fraser', 'gambia'] + +period = 10 diff --git a/reporting/api/extension/__init__.py b/reporting/api/extension/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/reporting/api/extension/__init__.py diff --git a/reporting/api/extension/client.py b/reporting/api/extension/client.py new file mode 100644 index 0000000..03371fd --- /dev/null +++ b/reporting/api/extension/client.py @@ -0,0 +1,15 @@ +from tornado.simple_httpclient import SimpleAsyncHTTPClient +from tornado.log import gen_log + + +class NoQueueTimeoutHTTPClient(SimpleAsyncHTTPClient): + def fetch_impl(self, request, callback): + key = object() + + self.queue.append((key, request, callback)) + self.waiting[key] = (request, callback, None) + + self._process_queue() + + if self.queue: + gen_log.debug("max_clients limit reached, request queued.") diff --git a/reporting/api/handlers/scenarios.py b/reporting/api/handlers/scenarios.py new file mode 100644 index 0000000..70447c7 --- /dev/null +++ b/reporting/api/handlers/scenarios.py @@ -0,0 +1,27 @@ +from tornado.web import asynchronous +from tornado.gen import coroutine +from tornado.escape import json_encode + +from api.handlers import BaseHandler +from api.service.scenario import ScenarioTableResult + + +class Result(BaseHandler): + @asynchronous + @coroutine + def get(self): + self._set_header() + + scenario = self.get_argument('scenario', None) + version = self.get_argument('version', 'master') + installer = self.get_argument('installer', None) + iteration = int(self.get_argument('iteration', 10)) + + yield self._get_scenario_data(scenario, version, installer, iteration) + + @coroutine + def _get_scenario_data(self, scenario, version, installer, iteration): + results = ScenarioTableResult(scenario, version, installer, iteration) + result = yield results.get() + self.write(json_encode(result)) + self.finish() diff --git a/reporting/api/server.py b/reporting/api/server.py index e340b01..461e6d5 100644 --- a/reporting/api/server.py +++ b/reporting/api/server.py @@ -12,6 +12,7 @@ from tornado.options import define from tornado.options import options from api.urls import mappings +from api.service.result import ResultCache define("port", default=8000, help="run on the given port", type=int) @@ -20,7 +21,12 @@ def main(): tornado.options.parse_command_line() application = tornado.web.Application(mappings) application.listen(options.port) - tornado.ioloop.IOLoop.current().start() + + tornado.ioloop.PeriodicCallback(ResultCache.update, 1800000).start() + + ioloop = tornado.ioloop.IOLoop.current() + ioloop.call_later(1000, ResultCache.update()) + ioloop.start() if __name__ == "__main__": diff --git a/reporting/api/service/__init__.py b/reporting/api/service/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/reporting/api/service/__init__.py diff --git a/reporting/api/service/result.py b/reporting/api/service/result.py new file mode 100644 index 0000000..fa6553c --- /dev/null +++ b/reporting/api/service/result.py @@ -0,0 +1,90 @@ +import json +import logging +from collections import defaultdict + +from tornado.gen import coroutine +from tornado.gen import Return +from tornado.httpclient import AsyncHTTPClient + +from api import conf as consts +from api.extension.client import NoQueueTimeoutHTTPClient + +LOG = logging.getLogger(__name__) +AsyncHTTPClient.configure(NoQueueTimeoutHTTPClient) + + +class Result(object): + + def __init__(self): + self._url = '{}/results?period={}&version={}&page={}' + self._client = AsyncHTTPClient() + self._result = defaultdict(list) + + @property + @coroutine + def result(self): + if not self._result: + yield self.update_results() + raise Return(self._result) + + @coroutine + def update_results(self): + LOG.info('start update results') + + for version in consts.versions: + yield self._update_version_result(version) + + LOG.info('results update finished') + + @coroutine + def _update_version_result(self, version): + total_page = yield self._get_total_page(version) + + responses = yield self._fetch_results(version, total_page) + + self._update_version_dict(version, responses) + + @coroutine + def _fetch_results(self, version, total_page): + urls = [self._url.format(consts.base_url, consts.period, version, i) + for i in range(1, total_page + 1)] + responses = yield [self._client.fetch(url) for url in urls] + raise Return(responses) + + @coroutine + def _get_total_page(self, version): + url = self._url.format(consts.base_url, consts.period, version, 1) + response = yield self._client.fetch(url) + raise Return(json.loads(response.body)['pagination']['total_pages']) + + def _update_version_dict(self, version, responses): + for response in responses: + results = json.loads(response.body)['results'] + for result in results: + data = {k: v for k, v in result.items() if k != 'details'} + self._result[version].append(data) + + +class ResultCache(Result): + + @classmethod + @coroutine + def update(cls): + cls._check() + + yield cls.cache.update_results() + + @classmethod + @coroutine + def get(cls, version): + cls._check() + + result = yield cls.cache.result + raise Return(result[version]) + + @classmethod + def _check(cls): + try: + cls.cache + except AttributeError: + cls.cache = cls() diff --git a/reporting/api/service/scenario.py b/reporting/api/service/scenario.py new file mode 100644 index 0000000..f9e2a91 --- /dev/null +++ b/reporting/api/service/scenario.py @@ -0,0 +1,133 @@ +import abc +from collections import defaultdict + +import six +from tornado.gen import coroutine +from tornado.gen import Return + +from api.service.result import ResultCache + +PROJECTS = ['fastdatastacks', 'barometer', 'sfc', 'sdnvpn', 'doctor', 'parser'] + + +def _set(key, llist): + return set(x[key] for x in llist) + + +def _filter(key, value, llist): + return filter(lambda x: x[key] == value, llist) + + +class ScenarioTableResult(object): + + def __init__(self, scenario, version, installer, iteration): + self.scenario = scenario + self.version = version + self.installer = installer + self.iteration = iteration + + @coroutine + def get(self): + results = yield ResultCache.get(self.version) + results = self._filter_result(results) + results = self._struct_result(results) + + raise Return(results) + + def _filter_result(self, results): + results = [x for x in results if x['build_tag']] + if self.installer: + results = _filter('installer', self.installer, results) + if self.scenario: + results = _filter('scenario', self.scenario, results) + return results + + def _struct_result(self, results): + + return { + s: self._struct_scenario(_filter('scenario', s, results)) + for s in _set('scenario', results) + } + + def _struct_scenario(self, data): + return sorted([ + HandlerFacade.get_result(b, _filter('build_tag', b, data)) + for b in _set('build_tag', data) + ], key=lambda x: x['date'], reverse=True)[:self.iteration] + + +class HandlerFacade(object): + + @classmethod + def get_result(cls, index, data): + if not data: + return {} + + cls._change_name_to_functest(data) + data = cls._sort_by_start_date(data) + + return { + 'id': index, + 'date': data[0]['start_date'], + 'version': data[0]['version'], + 'installer': data[0]['installer'], + 'projects': cls._get_projects_data(data) + } + + @classmethod + def _sort_by_start_date(cls, data): + return sorted(data, key=lambda x: x['start_date']) + + @classmethod + def _get_projects_data(cls, data): + + return { + p: HANDLER_MAP[p](_filter('project_name', p, data)).struct() + for p in _set('project_name', data) + } + + @classmethod + def _change_name_to_functest(cls, data): + for ele in data: + if ele['project_name'] in PROJECTS: + ele['project_name'] = 'functest' + + +@six.add_metaclass(abc.ABCMeta) +class ProjectHandler(object): + + def __init__(self, data): + self.data = data + + def struct(self): + return self._struct_project_data() + + def _struct_project_data(self): + return { + 'gating': self._gating() + } + + @abc.abstractmethod + def _gating(self): + pass + + +class DefaultHandler(ProjectHandler): + + def _struct_project_data(self): + return {} + + def _gating(self): + pass + + +class FunctestHandler(ProjectHandler): + + def _gating(self): + if all([x['criteria'] == 'PASS' for x in self.data]): + return 'PASS' + else: + return 'FAIL' + + +HANDLER_MAP = defaultdict(lambda: DefaultHandler, functest=FunctestHandler) diff --git a/reporting/api/urls.py b/reporting/api/urls.py index a5228b2..34f61d8 100644 --- a/reporting/api/urls.py +++ b/reporting/api/urls.py @@ -9,6 +9,7 @@ from api.handlers import landing from api.handlers import projects from api.handlers import testcases +from api.handlers import scenarios mappings = [ (r"/landing-page/filters", landing.FiltersHandler), @@ -16,5 +17,7 @@ mappings = [ (r"/projects-page/projects", projects.Projects), (r"/projects/([^/]+)/cases", testcases.TestCases), - (r"/projects/([^/]+)/cases/([^/]+)", testcases.TestCase) + (r"/projects/([^/]+)/cases/([^/]+)", testcases.TestCase), + + (r"/scenarios/results", scenarios.Result) ] diff --git a/reporting/css/default.css b/reporting/css/default.css index e32fa5f..686e886 100644 --- a/reporting/css/default.css +++ b/reporting/css/default.css @@ -26,6 +26,7 @@ width: 100%; background-color: #0095a2 } + .panel-default > .panel-heading h4 { color: white; } @@ -55,7 +56,7 @@ td{ background-color: #0095a2; } -h1 { +h1 { display: block; font-size: 2em; margin-top: 0.67em; @@ -191,4 +192,3 @@ h2 { position:relative; top:1px; } - diff --git a/reporting/docker/reporting.sh b/reporting/docker/reporting.sh index 2cb438d..f3f3d50 100755 --- a/reporting/docker/reporting.sh +++ b/reporting/docker/reporting.sh @@ -3,7 +3,7 @@ export PYTHONPATH="${PYTHONPATH}:./reporting" export CONFIG_REPORTING_YAML=./reporting/reporting.yaml -declare -a versions=(euphrates danube master) +declare -a versions=(gambia fraser master) declare -a projects=(functest storperf yardstick qtip vsperf bottlenecks) project=$1 @@ -21,7 +21,7 @@ done # copy images, js, css, 3rd_party cp -Rf 3rd_party display cp -Rf css display -cp -Rf html/* display +cp -Rf 3rd_party/html/* display cp -Rf img display cp -Rf js display diff --git a/reporting/html/functest-master.html b/reporting/html/functest-master.html deleted file mode 100644 index 4b1f763..0000000 --- a/reporting/html/functest-master.html +++ /dev/null @@ -1,124 +0,0 @@ -<!DOCTYPE HTML> -<!-- - Phantom by HTML5 UP - html5up.net | @ajlkn - Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) ---> -<html> - <head> - <title>Phantom by HTML5 UP</title> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <!--[if lte IE 8]><script src="3rd_party/js/ie/html5shiv.js"></script><![endif]--> - <link rel="stylesheet" href="3rd_party/css/main.css" /> - <!--[if lte IE 9]><link rel="stylesheet" href="3rd_party/css/ie9.css" /><![endif]--> - <!--[if lte IE 8]><link rel="stylesheet" href="3rd_party/css/ie8.css" /><![endif]--> - </head> - <body> - <!-- Wrapper --> - <div id="wrapper"> - - <!-- Header --> - <header id="header"> - <div class="inner"> - - <!-- Logo --> - <a href="index.html" class="logo"> - <span class="symbol"><img src="img/logo.svg" alt="" /></span><span class="title">Phantom</span> - </a> - - <!-- Nav --> - <!-- <nav> - <ul> - <li><a href="#menu">Menu</a></li> - </ul> - </nav> - ---> - </div> - </header> - - <!-- Menu --> - <!--- <nav id="menu"> - <h2>Menu</h2> - <ul> - <li><a href="index.html">Home</a></li> - <li><a href="colorado.html">Colorado</a></li> - <li><a href="danube.html">Danube</a></li> - </ul> - </nav> - ---> - <!-- Main --> - <div id="main"> - <div class="inner"> - <header> - <h1>Functest reporting</h1> - </header> - <section class="tiles"> - <article class="style5"> - <span class="image"> - <img src="img/pic05.jpg" alt="" /> - </span> - <a href="master/functest/status-apex.html"> - <h2>Status</h2> - <div class="content"> - <p>Scenario status</p> - </div> - </a> - </article> - <article class="style2"> - <span class="image"> - <img src="img/pic02.jpg" alt="" /> - </span> - <a href="master/functest/vims-apex.html"> - <h2>vIMS</h2> - <div class="content"> - <p>Virtual IMS</p> - </div> - </a> - </article> - <article class="style3"> - <span class="image"> - <img src="img/pic03.jpg" alt="" /> - </span> - <a href="master/functest/tempest-apex.html"> - <h2>Tempest</h2> - <div class="content"> - <p>Tempest OpenStack suite</p> - </div> - </a> - </article> - </section> - </div> - </div> - - <!-- Footer --> - <footer id="footer"> - <div class="inner"> - <section> - <h2>OPNFV Testing Working group</h2> - </section> - <section> - <h2>Follow</h2> - <ul class="icons"> - <li><a href="https://twitter.com/opnfv" class="icon style2 fa-twitter"><span class="label">Twitter</span></a></li> - <li><a href="http://git.opnfv.org" class="icon style2 fa-github"><span class="label">GitHub</span></a></li> - <li><a href="mailto:test-wg@list.opnfv.org" class="icon style2 fa-envelope-o"><span class="label">Email</span></a></li> - </ul> - </section> - <ul class="copyright"> - <li>© Untitled. All rights reserved</li><li>Design: <a href="http://html5up.net">HTML5 UP</a></li> - </ul> - </div> - </footer> - - </div> - - <!-- Scripts --> - <script src="3rd_party/js/jquery.min.js"></script> - <script src="3rd_party/js/skel.min.js"></script> - <script src="3rd_party/js/util.js"></script> - <!--[if lte IE 8]><script src="3rd_party/js/ie/respond.min.js"></script><![endif]--> - <script src="3rd_party/js/main.js"></script> - - </body> -</html> diff --git a/reporting/img/fraser.jpg b/reporting/img/fraser.jpg Binary files differnew file mode 100644 index 0000000..8bc6b51 --- /dev/null +++ b/reporting/img/fraser.jpg diff --git a/reporting/img/gambia.jpg b/reporting/img/gambia.jpg Binary files differnew file mode 100644 index 0000000..fd91d11 --- /dev/null +++ b/reporting/img/gambia.jpg diff --git a/reporting/js/gauge.js b/reporting/js/gauge.js index 4cad16c..a9842e5 100644 --- a/reporting/js/gauge.js +++ b/reporting/js/gauge.js @@ -28,7 +28,9 @@ var gauge = function(container) { labelFormat : d3.format(',g'), labelInset : 10, - arcColorFn : d3.interpolateHsl(d3.rgb('#ff0000'), d3.rgb('#00ff00')) + arcColorFn : d3.scale.quantile() + .domain([0, , 0.6, 0.8, 1]) + .range([d3.rgb('#ff0000'),d3.rgb('#ffcc00'),d3.rgb('#00ff00')]) }; diff --git a/reporting/pages/app/index.html b/reporting/pages/app/index.html index 843a623..6ef1d02 100644 --- a/reporting/pages/app/index.html +++ b/reporting/pages/app/index.html @@ -87,6 +87,7 @@ <script src="scripts/controllers/auth.controller.js"></script> <script src="scripts/controllers/admin.controller.js"></script> <script src="scripts/controllers/main.controller.js"></script> + <script src="scripts/controllers/gating.controller.js"></script> <script src="scripts/controllers/testvisual.controller.js"></script> <!-- endbuild --> diff --git a/reporting/pages/app/scripts/config.router.js b/reporting/pages/app/scripts/config.router.js index d3724b7..45a6997 100644 --- a/reporting/pages/app/scripts/config.router.js +++ b/reporting/pages/app/scripts/config.router.js @@ -17,11 +17,11 @@ angular.module('opnfvApp') ]).config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) { - $urlRouterProvider.otherwise('/landingpage/table'); + $urlRouterProvider.otherwise('/home/gating'); $stateProvider - .state('landingpage', { - url: "/landingpage", + .state('home', { + url: "/home", controller: 'MainController', templateUrl: "views/main.html", data: { pageTitle: '首页', specialClass: 'landing-page' }, @@ -33,7 +33,7 @@ angular.module('opnfvApp') }] } }) - .state('landingpage.table', { + .state('home.table', { url: "/table", controller: 'TableController', templateUrl: "views/commons/table.html", @@ -47,6 +47,19 @@ angular.module('opnfvApp') }] } }) + .state('home.gating', { + url: "/gating", + controller: 'GatingController', + templateUrl: "views/gating.html", + data: { pageTitle: 'OPNFV Release Gating Page', specialClass: 'landing-page' }, + resolve: { + controller: ['$ocLazyLoad', function($ocLazyLoad) { + return $ocLazyLoad.load([ + + ]) + }] + } + }) .state('select', { url: '/select', templateUrl: "views/testcase.html", diff --git a/reporting/pages/app/scripts/controllers/gating.controller.js b/reporting/pages/app/scripts/controllers/gating.controller.js new file mode 100644 index 0000000..52b381d --- /dev/null +++ b/reporting/pages/app/scripts/controllers/gating.controller.js @@ -0,0 +1,119 @@ +'use strict'; + +angular.module('opnfvApp') + .controller('GatingController', ['$scope', '$state', '$stateParams', 'TableFactory', function($scope, $state, $stateParams, TableFactory) { + + init(); + + function init() { + $scope.goTest = goTest; + $scope.goLogin = goLogin; + + $scope.scenarios = {}; + + $scope.scenarioList = _toSelectList(['all']); + $scope.versionList = _toSelectList(['master', 'fraser', 'gambia']); + $scope.installerList = _toSelectList(['all', 'apex', 'compass', 'daisy', 'fuel', 'joid']); + $scope.iterationList = _toSelectList([10, 20, 30]); + + $scope.selectScenario = 'all'; + $scope.selectVersion = 'master'; + $scope.selectInstaller = 'all'; + $scope.selectIteration = 10; + + $scope.ScenarioConfig = { + create: true, + valueField: 'title', + labelField: 'title', + delimiter: '|', + maxItems: 1, + placeholder: 'Scenario', + onChange: function(value) { + $scope.selectScenario = value; + } + } + + $scope.VersionConfig = { + create: true, + valueField: 'title', + labelField: 'title', + delimiter: '|', + maxItems: 1, + placeholder: 'Version', + onChange: function(value) { + $scope.selectVersion = value; + getScenarioResult(); + } + } + + $scope.InstallerConfig = { + create: true, + valueField: 'title', + labelField: 'title', + delimiter: '|', + maxItems: 1, + placeholder: 'Installer', + onChange: function(value) { + $scope.selectInstaller = value; + getScenarioResult(); + } + } + + $scope.IterationConfig = { + create: true, + valueField: 'title', + labelField: 'title', + delimiter: '|', + maxItems: 1, + placeholder: 'Iteration', + onChange: function(value) { + $scope.selectIteration = value; + getScenarioResult(); + } + } + getScenarioResult(); + } + + function getScenarioResult(){ + _getScenarioResult($scope.selectVersion, $scope.selectInstaller, $scope.selectIteration); + } + + function _getScenarioResult(version, installer, iteration){ + var data = { + 'version': version, + 'iteration': iteration + } + + if(installer != 'all'){ + data['installer'] = installer; + } + + TableFactory.getScenarioResult().get(data).$promise.then(function(resp){ + $scope.scenarios = resp; + _concat($scope.scenarioList, _toSelectList(Object.keys(resp))); + }, function(err){ + }); + } + + function _concat(aList, bList){ + angular.forEach(bList, function(ele){ + aList.push(ele); + }); + } + + function _toSelectList(arr){ + var tempList = []; + angular.forEach(arr, function(ele){ + tempList.push({'title': ele}); + }); + return tempList; + } + + function goTest() { + $state.go("select.selectTestCase"); + } + + function goLogin() { + $state.go("login"); + } + }]); diff --git a/reporting/pages/app/scripts/factory/table.factory.js b/reporting/pages/app/scripts/factory/table.factory.js index e715c5c..a2c5c76 100644 --- a/reporting/pages/app/scripts/factory/table.factory.js +++ b/reporting/pages/app/scripts/factory/table.factory.js @@ -6,7 +6,7 @@ angular.module('opnfvApp') .factory('TableFactory', function($resource, $rootScope, $http) { - var BASE_URL = 'http://testresults.opnfv.org/reporting2'; + var BASE_URL = ' http://testresults.opnfv.org/testing'; $.ajax({ url: 'config.json', async: false, @@ -15,11 +15,19 @@ angular.module('opnfvApp') BASE_URL = response.url; }, error: function (response){ - alert('fail to get api url, using default: http://testresults.opnfv.org/reporting2') + alert('fail to get api url, using default: http://testresults.opnfv.org/testing') } }); return { + getScenarioResult: function() { + return $resource(BASE_URL + '/scenarios/results', {'scenario': '@scenario', 'version': '@version', 'installer': '@installer', 'iteration': '@iteration'}, { + 'get': { + method: 'GET', + + } + }); + }, getFilter: function() { return $resource(BASE_URL + '/landing-page/filters', {}, { 'get': { diff --git a/reporting/pages/app/views/gating.html b/reporting/pages/app/views/gating.html new file mode 100644 index 0000000..0215c87 --- /dev/null +++ b/reporting/pages/app/views/gating.html @@ -0,0 +1,68 @@ +<section class="container-tablesize"> + <div class="row border-bottom white-bg dashboard-header"> + <div class="row"> + + <div class="ibox float-e-margins"> + <div class="ibox-title"> + <h5>OPNFV Release Gating Reporting </h5> + </div> + + <div class="ibox-content row"> + <div class="col-md-2" style="margin-top:5px;margin-right: 5px;"> + <selectize options="scenarioList" ng-model="selectScenario" config="ScenarioConfig"></selectize> + </div> + <div class="col-md-2" style="margin-top:5px;margin-right: 5px;"> + <selectize options="versionList" ng-model="selectVersion" config="VersionConfig"></selectize> + </div> + + <div class="col-md-2" style="margin-top:5px;margin-right: 5px;"> + <selectize options="installerList" ng-model="selectInstaller" config="InstallerConfig"></selectize> + + </div> + + <div class="col-md-2" style="margin-top:5px;margin-right: 5px;"> + <selectize options="iterationList" ng-model="selectIteration" config="IterationConfig"></selectize> + </div> + </div> + + <div class="table-responsive"> + <table class="table table-bordered" id="table"> + <thead class="thead"> + <tr> + <th>Scenario</th> + <th>Date</th> + <th>ID</th> + <th>Version</th> + <th>Installer</th> + <th>Deployment</th> + <th>Functest</th> + <th>Yardstick</th> + </tr> + </thead> + <tbody class="tbody" ng-show="selectScenario == 'all' || scenario == selectScenario" ng-repeat="(scenario,value) in scenarios"> + <tr ng-repeat="record in value"> + <td ng-if="$index == 0">{{ scenario }}</td> + <td ng-if="$index != 0"></td> + <td>{{ record.date }}</td> + <td>{{ record.id }}</td> + <td>{{ record.version }}</td> + <td>{{ record.installer }}</td> + <td>{{ record.projects.deployment.gating }}</td> + <td>{{ record.projects.functest.gating }}</td> + <td>{{ record.projects.yardstick.gating }}</td> + </tr> + </tbody> + </table> + + </div> + + </div> + </div> + </div> + +</section> +<style> +.selectize-input { + width: 200px !important; +} +</style> diff --git a/reporting/reporting/bottlenecks/reporting-status.py b/reporting/reporting/bottlenecks/reporting-status.py index 225227a..8966d06 100644 --- a/reporting/reporting/bottlenecks/reporting-status.py +++ b/reporting/reporting/bottlenecks/reporting-status.py @@ -37,14 +37,10 @@ for version in VERSIONS: # For all the installers for installer in INSTALLERS: # get scenarios results data - if version != 'master': - new_version = "stable/{}".format(version) - else: - new_version = version scenario_results = rp_utils.getScenarios("bottlenecks", "posca_factor_ping", installer, - new_version) + version) LOGGER.info("scenario_results: %s", scenario_results) scenario_stats = rp_utils.getScenarioStats(scenario_results) diff --git a/reporting/reporting/functest/reporting-status.py b/reporting/reporting/functest/reporting-status.py index 592f929..e36aede 100755 --- a/reporting/reporting/functest/reporting-status.py +++ b/reporting/reporting/functest/reporting-status.py @@ -25,8 +25,6 @@ Functest reporting status LOGGER = rp_utils.getLogger("Functest-Status") # Initialization -testValid = [] -otherTestCases = [] reportingDate = datetime.datetime.now().strftime("%Y-%m-%d %H:%M") # init just connection_check to get the list of scenarios @@ -43,8 +41,7 @@ blacklist = rp_utils.get_config('functest.blacklist') log_level = rp_utils.get_config('general.log.log_level') exclude_noha = rp_utils.get_config('functest.exclude_noha') exclude_virtual = rp_utils.get_config('functest.exclude_virtual') - -functest_yaml_config = rp_utils.getFunctestConfig() +tiers_for_scoring = {'healthcheck', 'smoke', 'vnf', 'features'} LOGGER.info("*******************************************") LOGGER.info("* *") @@ -57,38 +54,36 @@ LOGGER.info("* NOHA scenarios excluded: %s *", exclude_noha) LOGGER.info("* *") LOGGER.info("*******************************************") -# Retrieve test cases of Tier 1 (smoke) -config_tiers = functest_yaml_config.get("tiers") +# For all the versions +for version in versions: + testValid = [] + # Retrieve test cases of Tier 1 (smoke) + version_config = "" + if (version != "master" and version != "latest"): + version_config = "?h=stable/" + version + functest_yaml_config = rp_utils.getFunctestConfig(version_config) + config_tiers = functest_yaml_config.get("tiers") + + # we consider Tier 0 (Healthcheck), Tier 1 (smoke),2 (features) + # to validate scenarios + # Tier > 2 are not used to validate scenarios but we display + # the results anyway + # tricky thing for the API as some tests are Functest tests + # other tests are declared directly in the feature projects + for tier in config_tiers: -# we consider Tier 0 (Healthcheck), Tier 1 (smoke),2 (features) -# to validate scenarios -# Tier > 2 are not used to validate scenarios but we display the results anyway -# tricky thing for the API as some tests are Functest tests -# other tests are declared directly in the feature projects -for tier in config_tiers: - if tier['order'] >= 0 and tier['order'] < 2: for case in tier['testcases']: + try: + dependencies = case['dependencies'] + except KeyError: + dependencies = "" if case['case_name'] not in blacklist: testValid.append(tc.TestCase(case['case_name'], "functest", - case['dependencies'])) - elif tier['order'] == 2: - for case in tier['testcases']: - if case['case_name'] not in blacklist: - otherTestCases.append(tc.TestCase(case['case_name'], - case['case_name'], - case['dependencies'])) - elif tier['order'] > 2: - for case in tier['testcases']: - if case['case_name'] not in blacklist: - otherTestCases.append(tc.TestCase(case['case_name'], - "functest", - case['dependencies'])) + dependencies, + tier=tier['name'])) + LOGGER.debug("Functest reporting start") -LOGGER.debug("Functest reporting start") - -# For all the versions -for version in versions: # For all the installers scenario_directory = "./display/" + version + "/functest/" scenario_file_name = scenario_directory + "scenario_history.txt" @@ -155,10 +150,8 @@ for version in versions: # Check if test case is runnable / installer, scenario # for the test case used for Scenario validation try: - # 1) Manage the test cases for the scenario validation - # concretely Tiers 0-3 for test_case in testValid: - test_case.checkRunnable(installer, s, + test_case.checkRunnable(installer, s, architecture, test_case.getConstraints()) LOGGER.debug("testcase %s (%s) is %s", test_case.getDisplayName(), @@ -169,7 +162,8 @@ for version in versions: name = test_case.getName() displayName = test_case.getDisplayName() project = test_case.getProject() - nb_test_runnable_for_this_scenario += 1 + if test_case.getTier() in tiers_for_scoring: + nb_test_runnable_for_this_scenario += 1 LOGGER.info(" Searching results for case %s ", displayName) if "fuel" in installer: @@ -185,53 +179,18 @@ for version in versions: LOGGER.info(" >>>> Test score = " + str(result)) test_case.setCriteria(result) test_case.setIsRunnable(True) - testCases2BeDisplayed.append(tc.TestCase(name, - project, - "", - result, - True, - 1)) - scenario_score = scenario_score + result - - # 2) Manage the test cases for the scenario qualification - # concretely Tiers > 3 - for test_case in otherTestCases: - test_case.checkRunnable(installer, s, - test_case.getConstraints()) - LOGGER.debug("testcase %s (%s) is %s", - test_case.getDisplayName(), - test_case.getName(), - test_case.isRunnable) - time.sleep(1) - if test_case.isRunnable: - name = test_case.getName() - displayName = test_case.getDisplayName() - project = test_case.getProject() - LOGGER.info(" Searching results for case %s ", - displayName) - if "fuel" in installer: - result = rp_utils.getCaseScoreFromBuildTag( - name, - s_result) - else: - result = rp_utils.getCaseScore(name, installer, - s, version) - # at least 1 result for the test - if result > -1: - test_case.setCriteria(result) - test_case.setIsRunnable(True) - testCases2BeDisplayed.append(tc.TestCase( - name, - project, - "", - result, - True, - 4)) - else: - LOGGER.debug("No results found") - - items[s] = testCases2BeDisplayed - except Exception: # pylint: disable=broad-except + testCases2BeDisplayed.append( + tc.TestCase(name, + project, + "", + result, + True, + tier=test_case.getTier())) + if test_case.getTier() in tiers_for_scoring: + scenario_score = scenario_score + result + + items[s] = testCases2BeDisplayed + except KeyError: # pylint: disable=broad-except LOGGER.error("Error installer %s, version %s, scenario %s", installer, version, s) LOGGER.error("No data available: %s", sys.exc_info()[0]) @@ -259,6 +218,12 @@ for version in versions: else: k_score = 2 + # TODO for the scoring we should consider 3 tiers + # - Healthcheck + # - Smoke + # - Vnf + # components + scenario_criteria = nb_test_runnable_for_this_scenario*k_score # score for reporting diff --git a/reporting/reporting/functest/reporting-tempest.py b/reporting/reporting/functest/reporting-tempest.py index d78d9a1..b82f96c 100755 --- a/reporting/reporting/functest/reporting-tempest.py +++ b/reporting/reporting/functest/reporting-tempest.py @@ -83,8 +83,16 @@ for version in rp_utils.get_config('general.versions'): # retrieve results # **************** - nb_tests_run = result['details']['tests'] - nb_tests_failed = result['details']['failures'] + try: + nb_tests_run = result['details']['success_number'] + nb_tests_failed = result['details']['failures_number'] + except KeyError: + try: + nb_tests_run = result['details']['tests'] + nb_tests_failed = result['details']['failures'] + except KeyError: + logger.error("Impossible to retrieve results") + logger.debug("nb_tests_run= %s", nb_tests_run) logger.debug("nb_tests_failed= %s", nb_tests_failed) @@ -140,12 +148,14 @@ for version in rp_utils.get_config('general.versions'): # Error management # **************** try: - errors = result['details']['errors'] - logger.info("errors: %s", errors) - result['errors'] = errors - except Exception: # pylint: disable=broad-except - logger.error("Error field not present (Brahamputra runs?)") - + errors = result['details']['failures'] + except KeyError: + try: + errors = result['details']['errors'] + except KeyError: + logger.error("Error field not present (old runs?)") + logger.info("errors: %s", errors) + result['errors'] = errors templateLoader = jinja2.FileSystemLoader(".") templateEnv = jinja2.Environment(loader=templateLoader, autoescape=True) diff --git a/reporting/reporting/functest/reporting-vims.py b/reporting/reporting/functest/reporting-vims.py index 3b25e91..bc9308c 100755 --- a/reporting/reporting/functest/reporting-vims.py +++ b/reporting/reporting/functest/reporting-vims.py @@ -120,7 +120,7 @@ for version in VERSIONS: LOGGER.debug("vIMS deployment: %ss", res_vnf) LOGGER.debug("VNF testing: %ss", res_test_vnf) LOGGER.debug("VNF testing results: %s", format_result) - except Exception as err: # pylint: disable=broad-except + except KeyError as err: # pylint: disable=broad-except LOGGER.error("Uncomplete data %s", err) LOGGER.debug("----------------------------------------") diff --git a/reporting/reporting/functest/template/index-status-tmpl.html b/reporting/reporting/functest/template/index-status-tmpl.html index 50fc648..48b5a2d 100644 --- a/reporting/reporting/functest/template/index-status-tmpl.html +++ b/reporting/reporting/functest/template/index-status-tmpl.html @@ -144,33 +144,32 @@ $(document).ready(function (){ <span class="panel-header-item"> </span> </div> + {% for tier in ['healthcheck', 'smoke', 'vnf', 'features'] -%} <table class="table"> <tr> + <h2>{{tier}}</h2> {% for test in items[scenario] -%} - <th> - {% if test.getCriteria() > -1 -%} - {{test.getDisplayName() }} + {% if test.getCriteria() > -1 and test.getTier() == tier -%} + <th>{{test.getDisplayName() }}</th> {%- endif %} - {% if test.getTier() > 3 -%} - * - {%- endif %} - </th> - {%- endfor %} + {%- endfor %} </tr> <tr class="tr-weather-weather"> - {% for test in items[scenario] -%} - {% if test.getCriteria() > 2 -%} + {% for test in items[scenario] -%} + {% if test.getCriteria() > 2 and test.getTier() == tier -%} <td><img src="../../img/weather-clear.png"></td> - {%- elif test.getCriteria() > 1 -%} + {%- elif test.getCriteria() > 1 and test.getTier() == tier -%} <td><img src="../../img/weather-few-clouds.png"></td> - {%- elif test.getCriteria() > 0 -%} + {%- elif test.getCriteria() > 0 and test.getTier() == tier -%} <td><img src="../../img/weather-overcast.png"></td> - {%- elif test.getCriteria() > -1 -%} + {%- elif test.getCriteria() > -1 and test.getTier() == tier -%} <td><img src="../../img/weather-storm.png"></td> {%- endif %} {%- endfor %} </tr> </table> + <br><hr> + {%- endfor %} </div> </div> {%- endfor %} diff --git a/reporting/reporting/functest/testCase.py b/reporting/reporting/functest/testCase.py index a182dd4..fba3216 100644 --- a/reporting/reporting/functest/testCase.py +++ b/reporting/reporting/functest/testCase.py @@ -26,7 +26,9 @@ class TestCase(object): 'onos': 'ONOS', 'ocl': 'OCL', 'tempest_smoke_serial': 'Tempest (smoke)', + 'tempest_smoke': 'Tempest (smoke)', 'tempest_full_parallel': 'Tempest (full)', + 'tempest_full': 'Tempest (full)', 'tempest_defcore': 'Tempest (Defcore)', 'refstack_defcore': 'Refstack', 'rally_sanity': 'Rally (smoke)', @@ -43,20 +45,45 @@ class TestCase(object): 'functest-odl-sfc': 'SFC', 'onos_sfc': 'SFC', 'parser-basics': 'Parser', - 'connection_check': 'Health (connection)', - 'api_check': 'Health (api)', + 'connection_check': 'connectivity', + 'api_check': 'api', 'snaps_smoke': 'SNAPS', - 'snaps_health_check': 'Health (dhcp)', + 'snaps_health_check': 'dhcp', 'gluon_vping': 'Netready', 'fds': 'FDS', 'cloudify_ims': 'vIMS (Cloudify)', + 'cloudify': 'Cloudify', 'orchestra_openims': 'OpenIMS (OpenBaton)', 'orchestra_clearwaterims': 'vIMS (OpenBaton)', 'opera_ims': 'vIMS (Open-O)', 'vyos_vrouter': 'vyos (Cloudify)', 'barometercollectd': 'Barometer', 'odl_netvirt': 'Netvirt', - 'security_scan': 'Security'} + 'security_scan': 'Security', + 'patrole': 'Patrole', + 'tenantnetwork1': 'tenant network 1', + 'tenantnetwork2': 'tenant network 2', + 'vmready1': 'vm ready 1', + 'vmready2': 'vm ready 2', + 'singlevm1': 'single vm 1', + 'singlevm2': 'single vm 2', + 'cinder_test': 'cinder tests', + 'barbican': 'barbican', + 'vmtp': 'vmtp', + 'juju_epc': 'vEPC (Juju)', + 'shaker': 'shaker', + 'neutron_trunk': 'Neutron trunk', + 'tempest_scenario': 'tempest_scenario', + 'networking-bgpvpn': 'networking-bgpvpn', + 'networking-sfc': 'networking-sfc', + 'tempest_full': 'Tempest (full)', + 'cloudify': 'cloudify', + 'heat_ims': 'vIMS (Heat)', + 'vmtp': 'vmtp', + 'tempest_smoke': 'Tempest (smoke)', + 'neutron-tempest-plugin-api': 'Neutron API', + 'vgpu': 'vgpu', + 'stor4nfv_os': 'stor4nfv_os'} try: self.displayName = display_name_matrix[self.name] except: @@ -68,22 +95,22 @@ class TestCase(object): def getProject(self): return self.project - def getConstraints(self): - return self.constraints - def getCriteria(self): return self.criteria def getTier(self): return self.tier + def getConstraints(self): + return self.constraints + def setCriteria(self, criteria): self.criteria = criteria def setIsRunnable(self, isRunnable): self.isRunnable = isRunnable - def checkRunnable(self, installer, scenario, config): + def checkRunnable(self, installer, scenario, arch, config): # Re-use Functest declaration # Retrieve Functest configuration file functest_config.yaml is_runnable = True @@ -98,27 +125,36 @@ class TestCase(object): # Retrieve test constraints # Retrieve test execution param - test_execution_context = {"installer": installer, - "scenario": scenario} + test_execution_context = {"INSTALLER_TYPE": installer, + "DEPLOY_SCENARIO": scenario, + "POD_ARCH": arch} + + # 3 types of constraints + # INSTALLER_TYPE + # DEPLOY_SCENARIO + # POD_ARCH # By default we assume that all the tests are always runnable... # if test_env not empty => dependencies to be checked - if config_test is not None and len(config_test) > 0: - # possible criteria = ["installer", "scenario"] - # consider test criteria from config file - # compare towards CI env through CI en variable - for criteria in config_test: - if re.search(config_test[criteria], - test_execution_context[criteria]) is None: - # print "Test "+ test + " cannot be run on the environment" - is_runnable = False + try: + if config_test is not None and len(config_test) > 0: + # possible criteria = ["installer", "scenario"] + # consider test criteria from config file + # compare towards CI env through CI en variable + for criterias in config_test: + for criteria_key, criteria_value in criterias.iteritems(): + if re.search( + criteria_value, + test_execution_context[criteria_key]) is None: + is_runnable = False + except AttributeError: + is_runnable = False # print is_runnable self.isRunnable = is_runnable def toString(self): testcase = ("Name=" + self.name + ";Criteria=" + str(self.criteria) + ";Project=" + self.project + - ";Constraints=" + str(self.constraints) + ";IsRunnable" + str(self.isRunnable)) return testcase diff --git a/reporting/reporting/reporting.yaml b/reporting/reporting/reporting.yaml index 8123d01..6a59a44 100644 --- a/reporting/reporting/reporting.yaml +++ b/reporting/reporting/reporting.yaml @@ -9,7 +9,7 @@ general: versions: - master - - euphrates + - gambia log: log_file: reporting.log @@ -36,9 +36,11 @@ testapi: functest: blacklist: - odl_netvirt - - juju_epc - tempest_full_parallel + - tempest_full - rally_full + - heat_ims + - tempest_scenario max_scenario_criteria: 50 test_conf: https://git.opnfv.org/cgit/functest/plain/functest/ci/testcases.yaml log_level: ERROR diff --git a/reporting/reporting/vsperf/reporting-status.py b/reporting/reporting/vsperf/reporting-status.py index b307ef0..377c315 100644 --- a/reporting/reporting/vsperf/reporting-status.py +++ b/reporting/reporting/vsperf/reporting-status.py @@ -127,7 +127,7 @@ def main(): period=50) version_data = _get_version_data(data['vsperf']) - for version in {'master', 'danube', 'euphrates'}: + for version in {'master', 'fraser', 'gambia'}: _generate_reporting(version, version_data.get(version, [])) LOG.info("End") diff --git a/reporting/reporting/yardstick/reporting-status.py b/reporting/reporting/yardstick/reporting-status.py index 10cacf0..a6e3cdf 100644 --- a/reporting/reporting/yardstick/reporting-status.py +++ b/reporting/reporting/yardstick/reporting-status.py @@ -140,8 +140,7 @@ def generate_reporting_page(version, installer, archi, scenarios, period): percent) LOG.info("--------------------------") - if scenario_data: - generate_page(scenario_data, installer, period, version, archi) + generate_page(scenario_data, installer, period, version, archi) def main(): |