blob: 1f36c61081274edd50c61b8f0dcdbdac41045b70 [file] [log] [blame]
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001import os
2
3from subprocess import check_output
4from shutil import rmtree
5from oeqa.runtime.case import OERuntimeTestCase
6from oeqa.core.decorator.depends import OETestDepends
7from oeqa.core.decorator.oeid import OETestID
8from oeqa.core.decorator.data import skipIfDataVar
9from oeqa.runtime.decorator.package import OEHasPackage
10
11#in the future these lists could be moved outside of module
12errors = ["error", "cannot", "can\'t", "failed"]
13
14common_errors = [
15 "(WW) warning, (EE) error, (NI) not implemented, (??) unknown.",
16 "dma timeout",
17 "can\'t add hid device:",
18 "usbhid: probe of ",
19 "_OSC failed (AE_ERROR)",
20 "_OSC failed (AE_SUPPORT)",
21 "AE_ALREADY_EXISTS",
22 "ACPI _OSC request failed (AE_SUPPORT)",
23 "can\'t disable ASPM",
24 "Failed to load module \"vesa\"",
25 "Failed to load module vesa",
26 "Failed to load module \"modesetting\"",
27 "Failed to load module modesetting",
28 "Failed to load module \"glx\"",
29 "Failed to load module \"fbdev\"",
30 "Failed to load module fbdev",
31 "Failed to load module glx",
32 "[drm] Cannot find any crtc or sizes - going 1024x768",
33 "_OSC failed (AE_NOT_FOUND); disabling ASPM",
34 "Open ACPI failed (/var/run/acpid.socket) (No such file or directory)",
35 "NX (Execute Disable) protection cannot be enabled: non-PAE kernel!",
36 "hd.: possibly failed opcode",
37 'NETLINK INITIALIZATION FAILED',
38 'kernel: Cannot find map file',
39 'omap_hwmod: debugss: _wait_target_disable failed',
40 'VGA arbiter: cannot open kernel arbiter, no multi-card support',
41 'Failed to find URL:http://ipv4.connman.net/online/status.html',
42 'Online check failed for',
43 'netlink init failed',
44 'Fast TSC calibration',
45 "BAR 0-9",
46 "Failed to load module \"ati\"",
47 "controller can't do DEVSLP, turning off",
48 "stmmac_dvr_probe: warning: cannot get CSR clock",
49 "error: couldn\'t mount because of unsupported optional features",
50 "GPT: Use GNU Parted to correct GPT errors",
51 "Cannot set xattr user.Librepo.DownloadInProgress",
52 ]
53
54video_related = [
55 "uvesafb",
56]
57
58x86_common = [
59 '[drm:psb_do_init] *ERROR* Debug is',
60 'wrong ELF class',
61 'Could not enable PowerButton event',
62 'probe of LNXPWRBN:00 failed with error -22',
63 'pmd_set_huge: Cannot satisfy',
64 'failed to setup card detect gpio',
65 'amd_nb: Cannot enumerate AMD northbridges',
66 'failed to retrieve link info, disabling eDP',
67 'Direct firmware load for iwlwifi',
68] + common_errors
69
70qemux86_common = [
71 'wrong ELF class',
72 "fail to add MMCONFIG information, can't access extended PCI configuration space under this bridge.",
73 "can't claim BAR ",
74 'amd_nb: Cannot enumerate AMD northbridges',
75 'uvesafb: 5000 ms task timeout, infinitely waiting',
76 'tsc: HPET/PMTIMER calibration failed',
77] + common_errors
78
79ignore_errors = {
80 'default' : common_errors,
81 'qemux86' : [
82 'Failed to access perfctr msr (MSR',
83 'pci 0000:00:00.0: [Firmware Bug]: reg 0x..: invalid BAR (can\'t size)',
84 ] + qemux86_common,
85 'qemux86-64' : qemux86_common,
86 'qemumips' : [
87 'Failed to load module "glx"',
88 'pci 0000:00:00.0: [Firmware Bug]: reg 0x..: invalid BAR (can\'t size)',
Brad Bishopd7bf8c12018-02-25 22:55:05 -050089 'cacheinfo: Failed to find cpu0 device node',
Brad Bishop6e60e8b2018-02-01 10:27:11 -050090 ] + common_errors,
91 'qemumips64' : [
92 'pci 0000:00:00.0: [Firmware Bug]: reg 0x..: invalid BAR (can\'t size)',
Brad Bishopd7bf8c12018-02-25 22:55:05 -050093 'cacheinfo: Failed to find cpu0 device node',
Brad Bishop6e60e8b2018-02-01 10:27:11 -050094 ] + common_errors,
95 'qemuppc' : [
96 'PCI 0000:00 Cannot reserve Legacy IO [io 0x0000-0x0fff]',
97 'host side 80-wire cable detection failed, limiting max speed',
98 'mode "640x480" test failed',
99 'Failed to load module "glx"',
100 'can\'t handle BAR above 4GB',
101 'Cannot reserve Legacy IO',
102 ] + common_errors,
103 'qemuarm' : [
104 'mmci-pl18x: probe of fpga:05 failed with error -22',
105 'mmci-pl18x: probe of fpga:0b failed with error -22',
106 'Failed to load module "glx"',
107 'OF: amba_device_add() failed (-19) for /amba/smc@10100000',
108 'OF: amba_device_add() failed (-19) for /amba/mpmc@10110000',
109 'OF: amba_device_add() failed (-19) for /amba/sctl@101e0000',
110 'OF: amba_device_add() failed (-19) for /amba/watchdog@101e1000',
111 'OF: amba_device_add() failed (-19) for /amba/sci@101f0000',
112 'OF: amba_device_add() failed (-19) for /amba/ssp@101f4000',
113 'OF: amba_device_add() failed (-19) for /amba/fpga/sci@a000',
114 'Failed to initialize \'/amba/timer@101e3000\': -22',
115 'jitterentropy: Initialization failed with host not compliant with requirements: 2',
116 ] + common_errors,
117 'qemuarm64' : [
118 'Fatal server error:',
119 '(EE) Server terminated with error (1). Closing log file.',
120 'dmi: Firmware registration failed.',
121 'irq: type mismatch, failed to map hwirq-27 for /intc',
122 ] + common_errors,
123 'emenlow' : [
124 '[Firmware Bug]: ACPI: No _BQC method, cannot determine initial brightness',
125 '(EE) Failed to load module "psb"',
126 '(EE) Failed to load module psb',
127 '(EE) Failed to load module "psbdrv"',
128 '(EE) Failed to load module psbdrv',
129 '(EE) open /dev/fb0: No such file or directory',
130 '(EE) AIGLX: reverting to software rendering',
131 ] + x86_common,
132 'intel-core2-32' : [
133 'ACPI: No _BQC method, cannot determine initial brightness',
134 '[Firmware Bug]: ACPI: No _BQC method, cannot determine initial brightness',
135 '(EE) Failed to load module "psb"',
136 '(EE) Failed to load module psb',
137 '(EE) Failed to load module "psbdrv"',
138 '(EE) Failed to load module psbdrv',
139 '(EE) open /dev/fb0: No such file or directory',
140 '(EE) AIGLX: reverting to software rendering',
141 'dmi: Firmware registration failed.',
142 'ioremap error for 0x78',
143 ] + x86_common,
144 'intel-corei7-64' : [
145 'can\'t set Max Payload Size to 256',
146 'intel_punit_ipc: can\'t request region for resource',
147 '[drm] parse error at position 4 in video mode \'efifb\'',
148 'ACPI Error: Could not enable RealTimeClock event',
149 'ACPI Warning: Could not enable fixed event - RealTimeClock',
150 'hci_intel INT33E1:00: Unable to retrieve gpio',
151 'hci_intel: probe of INT33E1:00 failed',
152 'can\'t derive routing for PCI INT A',
153 'failed to read out thermal zone',
154 'Bluetooth: hci0: Setting Intel event mask failed',
155 'ttyS2 - failed to request DMA',
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500156 'Bluetooth: hci0: Failed to send firmware data (-38)',
157 'atkbd serio0: Failed to enable keyboard on isa0060/serio0',
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500158 ] + x86_common,
159 'crownbay' : x86_common,
160 'genericx86' : x86_common,
161 'genericx86-64' : [
162 'Direct firmware load for i915',
163 'Failed to load firmware i915',
164 'Failed to fetch GuC',
165 'Failed to initialize GuC',
166 'Failed to load DMC firmware',
167 'The driver is built-in, so to load the firmware you need to',
168 ] + x86_common,
169 'edgerouter' : [
170 'Fatal server error:',
171 ] + common_errors,
172 'jasperforest' : [
173 'Activated service \'org.bluez\' failed:',
174 'Unable to find NFC netlink family',
175 ] + common_errors,
176}
177
178log_locations = ["/var/log/","/var/log/dmesg", "/tmp/dmesg_output.log"]
179
180class ParseLogsTest(OERuntimeTestCase):
181
182 @classmethod
183 def setUpClass(cls):
184 cls.errors = errors
185
186 # When systemd is enabled we need to notice errors on
187 # circular dependencies in units.
188 if 'systemd' in cls.td.get('DISTRO_FEATURES', ''):
189 cls.errors.extend([
190 'Found ordering cycle on',
191 'Breaking ordering cycle by deleting job',
192 'deleted to break ordering cycle',
193 'Ordering cycle found, skipping',
194 ])
195
196 cls.ignore_errors = ignore_errors
197 cls.log_locations = log_locations
198 cls.msg = ''
199 is_lsb, _ = cls.tc.target.run("which LSB_Test.sh")
200 if is_lsb == 0:
201 for machine in cls.ignore_errors:
202 cls.ignore_errors[machine] = cls.ignore_errors[machine] \
203 + video_related
204
205 def getMachine(self):
206 return self.td.get('MACHINE', '')
207
208 def getWorkdir(self):
209 return self.td.get('WORKDIR', '')
210
211 # Get some information on the CPU of the machine to display at the
212 # beginning of the output. This info might be useful in some cases.
213 def getHardwareInfo(self):
214 hwi = ""
215 cmd = ('cat /proc/cpuinfo | grep "model name" | head -n1 | '
216 " awk 'BEGIN{FS=\":\"}{print $2}'")
217 _, cpu_name = self.target.run(cmd)
218
219 cmd = ('cat /proc/cpuinfo | grep "cpu cores" | head -n1 | '
220 "awk {'print $4'}")
221 _, cpu_physical_cores = self.target.run(cmd)
222
223 cmd = 'cat /proc/cpuinfo | grep "processor" | wc -l'
224 _, cpu_logical_cores = self.target.run(cmd)
225
226 _, cpu_arch = self.target.run('uname -m')
227
228 hwi += 'Machine information: \n'
229 hwi += '*******************************\n'
230 hwi += 'Machine name: ' + self.getMachine() + '\n'
231 hwi += 'CPU: ' + str(cpu_name) + '\n'
232 hwi += 'Arch: ' + str(cpu_arch)+ '\n'
233 hwi += 'Physical cores: ' + str(cpu_physical_cores) + '\n'
234 hwi += 'Logical cores: ' + str(cpu_logical_cores) + '\n'
235 hwi += '*******************************\n'
236
237 return hwi
238
239 # Go through the log locations provided and if it's a folder
240 # create a list with all the .log files in it, if it's a file
241 # just add it to that list.
242 def getLogList(self, log_locations):
243 logs = []
244 for location in log_locations:
245 status, _ = self.target.run('test -f ' + str(location))
246 if status == 0:
247 logs.append(str(location))
248 else:
249 status, _ = self.target.run('test -d ' + str(location))
250 if status == 0:
251 cmd = 'find ' + str(location) + '/*.log -maxdepth 1 -type f'
252 status, output = self.target.run(cmd)
253 if status == 0:
254 output = output.splitlines()
255 for logfile in output:
256 logs.append(os.path.join(location, str(logfile)))
257 return logs
258
259 # Copy the log files to be parsed locally
260 def transfer_logs(self, log_list):
261 workdir = self.getWorkdir()
262 self.target_logs = workdir + '/' + 'target_logs'
263 target_logs = self.target_logs
264 if os.path.exists(target_logs):
265 rmtree(self.target_logs)
266 os.makedirs(target_logs)
267 for f in log_list:
268 self.target.copyFrom(str(f), target_logs)
269
270 # Get the local list of logs
271 def get_local_log_list(self, log_locations):
272 self.transfer_logs(self.getLogList(log_locations))
273 list_dir = os.listdir(self.target_logs)
274 dir_files = [os.path.join(self.target_logs, f) for f in list_dir]
275 logs = [f for f in dir_files if os.path.isfile(f)]
276 return logs
277
278 # Build the grep command to be used with filters and exclusions
279 def build_grepcmd(self, errors, ignore_errors, log):
280 grepcmd = 'grep '
281 grepcmd += '-Ei "'
282 for error in errors:
283 grepcmd += error + '|'
284 grepcmd = grepcmd[:-1]
285 grepcmd += '" ' + str(log) + " | grep -Eiv \'"
286
287 try:
288 errorlist = ignore_errors[self.getMachine()]
289 except KeyError:
290 self.msg += 'No ignore list found for this machine, using default\n'
291 errorlist = ignore_errors['default']
292
293 for ignore_error in errorlist:
294 ignore_error = ignore_error.replace('(', '\(')
295 ignore_error = ignore_error.replace(')', '\)')
296 ignore_error = ignore_error.replace("'", '.')
297 ignore_error = ignore_error.replace('?', '\?')
298 ignore_error = ignore_error.replace('[', '\[')
299 ignore_error = ignore_error.replace(']', '\]')
300 ignore_error = ignore_error.replace('*', '\*')
301 ignore_error = ignore_error.replace('0-9', '[0-9]')
302 grepcmd += ignore_error + '|'
303 grepcmd = grepcmd[:-1]
304 grepcmd += "\'"
305
306 return grepcmd
307
308 # Grep only the errors so that their context could be collected.
309 # Default context is 10 lines before and after the error itself
310 def parse_logs(self, errors, ignore_errors, logs,
311 lines_before = 10, lines_after = 10):
312 results = {}
313 rez = []
314 grep_output = ''
315
316 for log in logs:
317 result = None
318 thegrep = self.build_grepcmd(errors, ignore_errors, log)
319
320 try:
321 result = check_output(thegrep, shell=True).decode('utf-8')
322 except:
323 pass
324
325 if result is not None:
326 results[log.replace('target_logs/','')] = {}
327 rez = result.splitlines()
328
329 for xrez in rez:
330 try:
331 cmd = ['grep', '-F', xrez, '-B', str(lines_before)]
332 cmd += ['-A', str(lines_after), log]
333 grep_output = check_output(cmd).decode('utf-8')
334 except:
335 pass
336 results[log.replace('target_logs/','')][xrez]=grep_output
337
338 return results
339
340 # Get the output of dmesg and write it in a file.
341 # This file is added to log_locations.
342 def write_dmesg(self):
343 (status, dmesg) = self.target.run('dmesg > /tmp/dmesg_output.log')
344
345 @OETestID(1059)
346 @OETestDepends(['ssh.SSHTest.test_ssh'])
347 def test_parselogs(self):
348 self.write_dmesg()
349 log_list = self.get_local_log_list(self.log_locations)
350 result = self.parse_logs(self.errors, self.ignore_errors, log_list)
351 print(self.getHardwareInfo())
352 errcount = 0
353 for log in result:
354 self.msg += 'Log: ' + log + '\n'
355 self.msg += '-----------------------\n'
356 for error in result[log]:
357 errcount += 1
358 self.msg += 'Central error: ' + str(error) + '\n'
359 self.msg += '***********************\n'
360 self.msg += result[str(log)][str(error)] + '\n'
361 self.msg += '***********************\n'
362 self.msg += '%s errors found in logs.' % errcount
363 self.assertEqual(errcount, 0, msg=self.msg)