Python3: resources and libraries
[csit.git] / resources / tools / presentation / generator_alerts.py
index b106d95..3a9b5dd 100644 (file)
@@ -19,7 +19,7 @@ from email.mime.multipart import MIMEMultipart
 from os.path import isdir
 from collections import OrderedDict
 
-from utils import execute_command
+from utils import get_last_completed_build_number
 from errors import PresentationError
 
 
@@ -57,7 +57,7 @@ class AlertingError(PresentationError):
             format(msg=self._msg, dets=self._details, level=self._level))
 
 
-class Alerting(object):
+class Alerting:
     """Class implementing the alerting mechanism.
     """
 
@@ -71,8 +71,10 @@ class Alerting(object):
         # Implemented alerts:
         self._ALERTS = ("failed-tests", )
 
+        self._spec = spec
+
         try:
-            self._spec = spec.alerting
+            self._spec_alert = spec.alerting
         except KeyError as err:
             raise  AlertingError("Alerting is not configured, skipped.",
                                  repr(err),
@@ -81,7 +83,7 @@ class Alerting(object):
         self._path_failed_tests = spec.environment["paths"]["DIR[STATIC,VPP]"]
 
         # Verify and validate input specification:
-        self.configs = self._spec.get("configurations", None)
+        self.configs = self._spec_alert.get("configurations", None)
         if not self.configs:
             raise AlertingError("No alert configuration is specified.")
         for config_type, config_data in self.configs.iteritems():
@@ -104,7 +106,7 @@ class Alerting(object):
                 raise AlertingError("Alert of type '{0}' is not implemented.".
                                     format(config_type))
 
-        self.alerts = self._spec.get("alerts", None)
+        self.alerts = self._spec_alert.get("alerts", None)
         if not self.alerts:
             raise AlertingError("No alert is specified.")
         for alert, alert_data in self.alerts.iteritems():
@@ -235,9 +237,9 @@ class Alerting(object):
         :type alert: dict
         :type test_set: str
         :type sort: bool
-        :returns: CSIT build number, VPP version, Number of failed tests,
-            Compressed failed tests.
-        :rtype: tuple(str, str, int, OrderedDict)
+        :returns: CSIT build number, VPP version, Number of passed tests,
+            Number of failed tests, Compressed failed tests.
+        :rtype: tuple(str, str, int, int, OrderedDict)
         """
 
         directory = self.configs[alert["way"]]["output-dir"]
@@ -253,6 +255,12 @@ class Alerting(object):
                     if idx == 1:
                         version = line[:-1]
                         continue
+                    if idx == 2:
+                        passed = line[:-1]
+                        continue
+                    if idx == 3:
+                        failed = line[:-1]
+                        continue
                     try:
                         test = line[:-1].split('-')
                         nic = test[0]
@@ -274,16 +282,16 @@ class Alerting(object):
         except IOError:
             logging.error("No such file or directory: {file}".
                           format(file=file_path))
-            return None, None, None, None
+            return None, None, None, None, None
         if sort:
             sorted_failed_tests = OrderedDict()
             keys = [k for k in failed_tests.keys()]
             keys.sort()
             for key in keys:
                 sorted_failed_tests[key] = failed_tests[key]
-            return build, version, idx-1, sorted_failed_tests
+            return build, version, passed, failed, sorted_failed_tests
         else:
-            return build, version, idx-1, failed_tests
+            return build, version, passed, failed, failed_tests
 
     def _generate_email_body(self, alert):
         """Create the file which is used in the generated alert.
@@ -300,22 +308,41 @@ class Alerting(object):
 
         text = ""
         for idx, test_set in enumerate(alert.get("include", [])):
-            build, version, nr, failed_tests = \
+            build, version, passed, failed, failed_tests = \
                 self._get_compressed_failed_tests(alert, test_set)
             if build is None:
-                text += "\n\nNo data for the test set '{set}'.\n".\
-                    format(set=test_set)
+                ret_code, build_nr, _ = get_last_completed_build_number(
+                    self._spec.environment["urls"]["URL[JENKINS,CSIT]"],
+                    alert["urls"][idx].split('/')[-1])
+                if ret_code != 0:
+                    build_nr = ''
+                text += "\n\nNo input data available for '{set}'. See CSIT " \
+                        "build {link}/{build} for more information.\n".\
+                    format(set='-'.join(test_set.split('-')[-2:]),
+                           link=alert["urls"][idx],
+                           build=build_nr)
                 continue
             text += ("\n\n{topo}-{arch}, "
-                     "{nr} tests failed, "
+                     "{failed} tests failed, "
+                     "{passed} tests passed, "
                      "CSIT build: {link}/{build}, "
                      "VPP version: {version}\n\n".
                      format(topo=test_set.split('-')[-2],
                             arch=test_set.split('-')[-1],
-                            nr=nr,
+                            failed=failed,
+                            passed=passed,
                             link=alert["urls"][idx],
                             build=build,
                             version=version))
+            regression_hdr = ("\n\n{topo}-{arch}, "
+                              "CSIT build: {link}/{build}, "
+                              "VPP version: {version}\n\n"
+                              .format(topo=test_set.split('-')[-2],
+                                      arch=test_set.split('-')[-1],
+                                      link=alert["urls"][idx],
+                                      build=build,
+                                      version=version
+                                      ))
             max_len_name = 0
             max_len_nics = 0
             max_len_framesizes = 0
@@ -344,10 +371,44 @@ class Alerting(object):
                     cores=params["cores"] +
                         " " * (max_len_cores - len(params["cores"])))
 
+            # Add list of regressions:
+            file_name = "{0}/cpta-regressions-{1}.txt".\
+                format(config["output-dir"], alert["urls"][idx].split('/')[-1])
+            try:
+                with open(file_name, 'r') as txt_file:
+                    file_content = txt_file.read()
+                    reg_file_name = "{dir}/trending-regressions.txt". \
+                        format(dir=config["output-dir"])
+                    with open(reg_file_name, 'a+') as reg_file:
+                        reg_file.write(regression_hdr)
+                        if file_content:
+                            reg_file.write(file_content)
+                        else:
+                            reg_file.write("No regressions")
+            except IOError as err:
+                logging.warning(repr(err))
+
+            # Add list of progressions:
+            file_name = "{0}/cpta-progressions-{1}.txt".\
+                format(config["output-dir"], alert["urls"][idx].split('/')[-1])
+            try:
+                with open(file_name, 'r') as txt_file:
+                    file_content = txt_file.read()
+                    pro_file_name = "{dir}/trending-progressions.txt". \
+                        format(dir=config["output-dir"])
+                    with open(pro_file_name, 'a+') as pro_file:
+                        pro_file.write(regression_hdr)
+                        if file_content:
+                            pro_file.write(file_content)
+                        else:
+                            pro_file.write("No progressions")
+            except IOError as err:
+                logging.warning(repr(err))
+
         text += "\nFor detailed information visit: {url}\n".\
             format(url=alert["url-details"])
         file_name = "{0}/{1}".format(config["output-dir"],
-                                                config["output-file"])
+                                     config["output-file"])
         logging.info("Writing the file '{0}.txt' ...".format(file_name))
 
         try: