summaryrefslogtreecommitdiffstats
path: root/meta/lib
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib')
-rw-r--r--meta/lib/oeqa/runtime/parselogs.py128
1 files changed, 128 insertions, 0 deletions
diff --git a/meta/lib/oeqa/runtime/parselogs.py b/meta/lib/oeqa/runtime/parselogs.py
new file mode 100644
index 0000000000..4d4a21b12f
--- /dev/null
+++ b/meta/lib/oeqa/runtime/parselogs.py
@@ -0,0 +1,128 @@
1import os
2import unittest
3from oeqa.oetest import oeRuntimeTest
4from oeqa.utils.decorators import *
5
6#in the future these lists could be moved outside of module
7errors = ["error", "cannot", "can\'t", "failed"]
8
9ignore_errors = { 'genericx86-64': ['mmci-pl18x', 'error changing net interface name', 'dma timeout'], \
10 'genericx86': ['mmci-pl18x', 'error changing net interface name', 'dma timeout', 'AE_ALREADY_EXISTS'], \
11 'emenlow': ['mmci-pl18x', 'error changing net interface name', 'dma timeout', 'AE_ALREADY_EXISTS', '\[drm:psb_do_init\] \*ERROR\* Debug is'], \
12 'crownbay': ['mmci-pl18x', 'error changing net interface name', 'dma timeout', 'AE_ALREADY_EXISTS', 'Could not enable PowerButton event', 'probe of LNXPWRBN:00 failed with error -22'], \
13 'qemuarm': ['mmci-pl18x', 'error changing net interface name', 'dma timeout', 'mmci-pl18x: probe of fpga:[0-f][0-f] failed with error -38', 'wrong ELF class', 'Fast TSC calibration', 'AE_NOT_FOUND', 'Open ACPI failed', 'Failed to load module "glx"', '\(EE\) error', 'perfctr msr \(MSR c1 is 0\)', 'MMCONFIG information'], \
14 'qemux86-64': ['mmci-pl18x', 'error changing net interface name', 'dma timeout', 'wrong ELF class', 'Fast TSC calibration', 'AE_NOT_FOUND', 'Open ACPI failed', 'Failed to load module "glx"', '\(EE\) error', 'perfctr msr \(MSR c1 is 0\)', 'MMCONFIG information'] }
15
16log_locations = ["/var/log/","/var/log/dmesg", "/tmp/dmesg_output.log"]
17
18class ParseLogsTest(oeRuntimeTest):
19
20 @classmethod
21 def setUpClass(self):
22 self.errors = errors
23 self.ignore_errors = ignore_errors
24 self.log_locations = log_locations
25 self.msg = ""
26
27 def getMachine(self):
28 (status, output) = self.target.run("uname -n")
29 return output
30
31 #get some information on the CPU of the machine to display at the beginning of the output. This info might be useful in some cases.
32 def getHardwareInfo(self):
33 hwi = ""
34 (status, cpu_name) = self.target.run("cat /proc/cpuinfo | grep \"model name\" | head -n1 | awk 'BEGIN{FS=\":\"}{print $2}'")
35 (status, cpu_physical_cores) = self.target.run("cat /proc/cpuinfo | grep \"cpu cores\" | head -n1 | awk {'print $4'}")
36 (status, cpu_logical_cores) = self.target.run("cat /proc/cpuinfo | grep \"processor\" | wc -l")
37 (status, cpu_arch) = self.target.run("uname -m")
38 hwi += "Machine information: \n"
39 hwi += "*******************************\n"
40 hwi += "Machine name: "+self.getMachine()+"\n"
41 hwi += "CPU: "+str(cpu_name)+"\n"
42 hwi += "Arch: "+str(cpu_arch)+"\n"
43 hwi += "Physical cores: "+str(cpu_physical_cores)+"\n"
44 hwi += "Logical cores: "+str(cpu_logical_cores)+"\n"
45 hwi += "*******************************\n"
46 return hwi
47
48 #go through the log locations provided and if it's a folder create a list with all the .log files in it, if it's a file just add
49 #it to that list
50 def getLogList(self, log_locations):
51 logs = []
52 for location in log_locations:
53 (status, output) = self.target.run("test -f "+str(location))
54 if (status == 0):
55 logs.append(str(location))
56 else:
57 (status, output) = self.target.run("test -d "+str(location))
58 if (status == 0):
59 (status, output) = self.target.run("find "+str(location)+"/*.log -maxdepth 1 -type f")
60 output = output.splitlines()
61 for logfile in output:
62 logs.append(os.path.join(location,str(logfile)))
63 return logs
64
65 #build the grep command to be used with filters and exclusions
66 def build_grepcmd(self, errors, ignore_errors, log):
67 grepcmd = "grep "
68 grepcmd +="-Ei \""
69 for error in errors:
70 grepcmd += error+"|"
71 grepcmd = grepcmd[:-1]
72 grepcmd += "\" "+str(log)+" | grep -Eiv \'"
73 try:
74 errorlist = ignore_errors[self.getMachine()]
75 except KeyError:
76 self.msg += "No ignore list found for this machine, using generic\n"
77 errorlist = ignore_errors['genericx86']
78 for ignore_error in errorlist:
79 grepcmd += ignore_error+"|"
80 grepcmd = grepcmd[:-1]
81 grepcmd += "\'"
82 return grepcmd
83
84 #grep only the errors so that their context could be collected. Default context is 10 lines before and after the error itself
85 def parse_logs(self, errors, ignore_errors, logs, lines_before = 10, lines_after = 10):
86 results = {}
87 rez = []
88 for log in logs:
89 thegrep = self.build_grepcmd(errors, ignore_errors, log)
90 try:
91 (status, result) = self.target.run(thegrep)
92 except:
93 pass
94 if result:
95 results[log] = {}
96 rez = result.splitlines()
97 for xrez in rez:
98 command = "grep \"\\"+str(xrez)+"\" -B "+str(lines_before)+" -A "+str(lines_after)+" "+str(log)
99 try:
100 (status, yrez) = self.target.run(command)
101 except:
102 pass
103 results[log][xrez]=yrez
104 return results
105
106 #get the output of dmesg and write it in a file. This file is added to log_locations.
107 def write_dmesg(self):
108 (status, dmesg) = self.target.run("dmesg")
109 (status, dmesg2) = self.target.run("echo \""+str(dmesg)+"\" > /tmp/dmesg_output.log")
110
111 @skipUnlessPassed('test_ssh')
112 def test_parselogs(self):
113 self.write_dmesg()
114 log_list = self.getLogList(self.log_locations)
115 result = self.parse_logs(self.errors, self.ignore_errors, log_list)
116 print self.getHardwareInfo()
117 errcount = 0
118 for log in result:
119 self.msg += "Log: "+log+"\n"
120 self.msg += "-----------------------\n"
121 for error in result[log]:
122 errcount += 1
123 self.msg += "Central error: "+str(error)+"\n"
124 self.msg += "***********************\n"
125 self.msg += result[str(log)][str(error)]+"\n"
126 self.msg += "***********************\n"
127 self.msg += "%s errors found in logs." % errcount
128 self.assertEqual(errcount, 0, msg=self.msg) \ No newline at end of file