blob: e20947b8bcbd9736edf6e93301b2b8b7e5120e0c [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001import os
2import unittest
3import subprocess
4from oeqa.oetest import oeRuntimeTest
5from oeqa.utils.decorators import *
6
7#in the future these lists could be moved outside of module
8errors = ["error", "cannot", "can\'t", "failed"]
9
10common_errors = [
11 "(WW) warning, (EE) error, (NI) not implemented, (??) unknown.",
12 "dma timeout",
13 "can\'t add hid device:",
14 "usbhid: probe of ",
15 "_OSC failed (AE_ERROR)",
16 "_OSC failed (AE_SUPPORT)",
17 "AE_ALREADY_EXISTS",
18 "ACPI _OSC request failed (AE_SUPPORT)",
19 "can\'t disable ASPM",
20 "Failed to load module \"vesa\"",
21 "Failed to load module vesa",
22 "Failed to load module \"modesetting\"",
23 "Failed to load module modesetting",
24 "Failed to load module \"glx\"",
25 "Failed to load module \"fbdev\"",
26 "Failed to load module fbdev",
27 "Failed to load module glx",
28 "[drm] Cannot find any crtc or sizes - going 1024x768",
29 "_OSC failed (AE_NOT_FOUND); disabling ASPM",
30 "Open ACPI failed (/var/run/acpid.socket) (No such file or directory)",
31 "NX (Execute Disable) protection cannot be enabled: non-PAE kernel!",
32 "hd.: possibly failed opcode",
33 'NETLINK INITIALIZATION FAILED',
34 'kernel: Cannot find map file',
35 'omap_hwmod: debugss: _wait_target_disable failed',
36 'VGA arbiter: cannot open kernel arbiter, no multi-card support',
37 'Failed to find URL:http://ipv4.connman.net/online/status.html',
38 'Online check failed for',
39 ]
40
41x86_common = [
42 '[drm:psb_do_init] *ERROR* Debug is',
43 'wrong ELF class',
44 'Could not enable PowerButton event',
45 'probe of LNXPWRBN:00 failed with error -22',
46] + common_errors
47
48qemux86_common = [
49 'Fast TSC calibration',
50 'wrong ELF class',
51 "fail to add MMCONFIG information, can't access extended PCI configuration space under this bridge.",
52 "can't claim BAR ",
53] + common_errors
54
55ignore_errors = {
56 'default' : common_errors,
57 'qemux86' : [
58 'Failed to access perfctr msr (MSR',
59 ] + qemux86_common,
60 'qemux86-64' : qemux86_common,
61 'qemumips' : [
62 'Failed to load module "glx"',
63 'pci 0000:00:00.0: [Firmware Bug]: reg 0x..: invalid BAR (can\'t size)',
64 ] + common_errors,
65 'qemumips64' : [
66 'pci 0000:00:00.0: [Firmware Bug]: reg 0x..: invalid BAR (can\'t size)',
67 ] + common_errors,
68 'qemuppc' : [
69 'PCI 0000:00 Cannot reserve Legacy IO [io 0x0000-0x0fff]',
70 'host side 80-wire cable detection failed, limiting max speed',
71 'mode "640x480" test failed',
72 'Failed to load module "glx"',
73 ] + common_errors,
74 'qemuarm' : [
75 'mmci-pl18x: probe of fpga:05 failed with error -22',
76 'mmci-pl18x: probe of fpga:0b failed with error -22',
77 'Failed to load module "glx"'
78 ] + common_errors,
79 'qemuarm64' : [
80 'Fatal server error:',
81 '(EE) Server terminated with error (1). Closing log file.',
82 ] + common_errors,
83 'emenlow' : [
84 '[Firmware Bug]: ACPI: No _BQC method, cannot determine initial brightness',
85 '(EE) Failed to load module "psb"',
86 '(EE) Failed to load module psb',
87 '(EE) Failed to load module "psbdrv"',
88 '(EE) Failed to load module psbdrv',
89 '(EE) open /dev/fb0: No such file or directory',
90 '(EE) AIGLX: reverting to software rendering',
91 ] + x86_common,
92 'core2_32' : [
93 'ACPI: No _BQC method, cannot determine initial brightness',
94 '[Firmware Bug]: ACPI: No _BQC method, cannot determine initial brightness',
95 '(EE) Failed to load module "psb"',
96 '(EE) Failed to load module psb',
97 '(EE) Failed to load module "psbdrv"',
98 '(EE) Failed to load module psbdrv',
99 '(EE) open /dev/fb0: No such file or directory',
100 '(EE) AIGLX: reverting to software rendering',
101 ] + x86_common,
102 'intel-corei7-64' : [
103 "controller can't do DEVSLP, turning off",
104 ] + common_errors,
105 'crownbay' : x86_common,
106 'genericx86' : x86_common,
107 'genericx86-64' : x86_common,
108 'edgerouter' : [
109 'Fatal server error:',
110 ] + common_errors,
111 'minnow' : [
112 'netlink init failed',
113 ] + common_errors,
114 'jasperforest' : [
115 'Activated service \'org.bluez\' failed:',
116 'Unable to find NFC netlink family',
117 'netlink init failed',
118 ] + common_errors,
119}
120
121log_locations = ["/var/log/","/var/log/dmesg", "/tmp/dmesg_output.log"]
122
123class ParseLogsTest(oeRuntimeTest):
124
125 @classmethod
126 def setUpClass(self):
127 self.errors = errors
128 self.ignore_errors = ignore_errors
129 self.log_locations = log_locations
130 self.msg = ""
131
132 def getMachine(self):
133 return oeRuntimeTest.tc.d.getVar("MACHINE", True)
134
135 #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.
136 def getHardwareInfo(self):
137 hwi = ""
138 (status, cpu_name) = self.target.run("cat /proc/cpuinfo | grep \"model name\" | head -n1 | awk 'BEGIN{FS=\":\"}{print $2}'")
139 (status, cpu_physical_cores) = self.target.run("cat /proc/cpuinfo | grep \"cpu cores\" | head -n1 | awk {'print $4'}")
140 (status, cpu_logical_cores) = self.target.run("cat /proc/cpuinfo | grep \"processor\" | wc -l")
141 (status, cpu_arch) = self.target.run("uname -m")
142 hwi += "Machine information: \n"
143 hwi += "*******************************\n"
144 hwi += "Machine name: "+self.getMachine()+"\n"
145 hwi += "CPU: "+str(cpu_name)+"\n"
146 hwi += "Arch: "+str(cpu_arch)+"\n"
147 hwi += "Physical cores: "+str(cpu_physical_cores)+"\n"
148 hwi += "Logical cores: "+str(cpu_logical_cores)+"\n"
149 hwi += "*******************************\n"
150 return hwi
151
152 #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
153 #it to that list
154 def getLogList(self, log_locations):
155 logs = []
156 for location in log_locations:
157 (status, output) = self.target.run("test -f "+str(location))
158 if (status == 0):
159 logs.append(str(location))
160 else:
161 (status, output) = self.target.run("test -d "+str(location))
162 if (status == 0):
163 (status, output) = self.target.run("find "+str(location)+"/*.log -maxdepth 1 -type f")
164 if (status == 0):
165 output = output.splitlines()
166 for logfile in output:
167 logs.append(os.path.join(location,str(logfile)))
168 return logs
169
170 #copy the log files to be parsed locally
171 def transfer_logs(self, log_list):
172 target_logs = 'target_logs'
173 if not os.path.exists(target_logs):
174 os.makedirs(target_logs)
175 for f in log_list:
176 self.target.copy_from(f, target_logs)
177
178 #get the local list of logs
179 def get_local_log_list(self, log_locations):
180 self.transfer_logs(self.getLogList(log_locations))
181 logs = [ os.path.join('target_logs',f) for f in os.listdir('target_logs') if os.path.isfile(os.path.join('target_logs',f)) ]
182 return logs
183
184 #build the grep command to be used with filters and exclusions
185 def build_grepcmd(self, errors, ignore_errors, log):
186 grepcmd = "grep "
187 grepcmd +="-Ei \""
188 for error in errors:
189 grepcmd += error+"|"
190 grepcmd = grepcmd[:-1]
191 grepcmd += "\" "+str(log)+" | grep -Eiv \'"
192 try:
193 errorlist = ignore_errors[self.getMachine()]
194 except KeyError:
195 self.msg += "No ignore list found for this machine, using default\n"
196 errorlist = ignore_errors['default']
197 for ignore_error in errorlist:
198 ignore_error = ignore_error.replace("(", "\(")
199 ignore_error = ignore_error.replace(")", "\)")
200 ignore_error = ignore_error.replace("'", ".")
201 ignore_error = ignore_error.replace("?", "\?")
202 ignore_error = ignore_error.replace("[", "\[")
203 ignore_error = ignore_error.replace("]", "\]")
204 ignore_error = ignore_error.replace("*", "\*")
205 grepcmd += ignore_error+"|"
206 grepcmd = grepcmd[:-1]
207 grepcmd += "\'"
208 return grepcmd
209
210 #grep only the errors so that their context could be collected. Default context is 10 lines before and after the error itself
211 def parse_logs(self, errors, ignore_errors, logs, lines_before = 10, lines_after = 10):
212 results = {}
213 rez = []
214 grep_output = ''
215 for log in logs:
216 result = None
217 thegrep = self.build_grepcmd(errors, ignore_errors, log)
218 try:
219 result = subprocess.check_output(thegrep, shell=True)
220 except:
221 pass
222 if (result is not None):
223 results[log.replace('target_logs/','')] = {}
224 rez = result.splitlines()
225 for xrez in rez:
226 command = "grep \"\\"+str(xrez)+"\" -B "+str(lines_before)+" -A "+str(lines_after)+" "+str(log)
227 try:
228 grep_output = subprocess.check_output(command, shell=True)
229 except:
230 pass
231 results[log.replace('target_logs/','')][xrez]=grep_output
232 return results
233
234 #get the output of dmesg and write it in a file. This file is added to log_locations.
235 def write_dmesg(self):
236 (status, dmesg) = self.target.run("dmesg")
237 (status, dmesg2) = self.target.run("echo \""+str(dmesg)+"\" > /tmp/dmesg_output.log")
238
239 @testcase(1059)
240 @skipUnlessPassed('test_ssh')
241 def test_parselogs(self):
242 self.write_dmesg()
243 log_list = self.get_local_log_list(self.log_locations)
244 result = self.parse_logs(self.errors, self.ignore_errors, log_list)
245 print self.getHardwareInfo()
246 errcount = 0
247 for log in result:
248 self.msg += "Log: "+log+"\n"
249 self.msg += "-----------------------\n"
250 for error in result[log]:
251 errcount += 1
252 self.msg += "Central error: "+str(error)+"\n"
253 self.msg += "***********************\n"
254 self.msg += result[str(log)][str(error)]+"\n"
255 self.msg += "***********************\n"
256 self.msg += "%s errors found in logs." % errcount
257 self.assertEqual(errcount, 0, msg=self.msg)