blob: bb067f4846241d998e7d269a79ac3e2e8246ce01 [file] [log] [blame]
Brad Bishopc342db32019-05-15 21:57:59 -04001#
2# SPDX-License-Identifier: MIT
3#
4
Patrick Williamsc124f4f2015-09-15 14:41:29 -05005import os
6import sys
Andrew Geisslerc926e172021-05-07 16:11:35 -05007import json
Patrick Williamsc124f4f2015-09-15 14:41:29 -05008import errno
9import datetime
10import itertools
Patrick Williamsc0f7c042017-02-23 20:41:17 -060011from .commands import runCmd
Patrick Williamsc124f4f2015-09-15 14:41:29 -050012
Patrick Williamsc124f4f2015-09-15 14:41:29 -050013class BaseDumper(object):
14 """ Base class to dump commands from host/target """
15
16 def __init__(self, cmds, parent_dir):
17 self.cmds = []
Patrick Williamsf1e5d692016-03-30 15:21:19 -050018 # Some testing doesn't inherit testimage, so it is needed
19 # to set some defaults.
Brad Bishop977dc1a2019-02-06 16:01:43 -050020 self.parent_dir = parent_dir
Andrew Geissler5f350902021-07-23 13:09:54 -040021 self.dump_dir = parent_dir
Patrick Williamsf1e5d692016-03-30 15:21:19 -050022 dft_cmds = """ top -bn1
23 iostat -x -z -N -d -p ALL 20 2
24 ps -ef
25 free
26 df
27 memstat
28 dmesg
29 ip -s link
30 netstat -an"""
Patrick Williamsc124f4f2015-09-15 14:41:29 -050031 if not cmds:
Patrick Williamsf1e5d692016-03-30 15:21:19 -050032 cmds = dft_cmds
Patrick Williamsc124f4f2015-09-15 14:41:29 -050033 for cmd in cmds.split('\n'):
34 cmd = cmd.lstrip()
35 if not cmd or cmd[0] == '#':
36 continue
37 self.cmds.append(cmd)
38
39 def create_dir(self, dir_suffix):
40 dump_subdir = ("%s_%s" % (
41 datetime.datetime.now().strftime('%Y%m%d%H%M'),
42 dir_suffix))
43 dump_dir = os.path.join(self.parent_dir, dump_subdir)
44 try:
45 os.makedirs(dump_dir)
46 except OSError as err:
47 if err.errno != errno.EEXIST:
48 raise err
49 self.dump_dir = dump_dir
50
Andrew Geissler5f350902021-07-23 13:09:54 -040051 def _construct_filename(self, command):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050052 if isinstance(self, HostDumper):
53 prefix = "host"
54 elif isinstance(self, TargetDumper):
55 prefix = "target"
Andrew Geisslerc926e172021-05-07 16:11:35 -050056 elif isinstance(self, MonitorDumper):
57 prefix = "qmp"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050058 else:
59 prefix = "unknown"
60 for i in itertools.count():
61 filename = "%s_%02d_%s" % (prefix, i, command)
62 fullname = os.path.join(self.dump_dir, filename)
63 if not os.path.exists(fullname):
64 break
Andrew Geissler5f350902021-07-23 13:09:54 -040065 return fullname
66
67 def _write_dump(self, command, output):
68 fullname = self._construct_filename(command)
Andrew Geisslerc926e172021-05-07 16:11:35 -050069 if isinstance(self, MonitorDumper):
70 with open(fullname, 'w') as json_file:
71 json.dump(output, json_file, indent=4)
72 else:
73 with open(fullname, 'w') as dump_file:
74 dump_file.write(output)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050075
76class HostDumper(BaseDumper):
77 """ Class to get dumps from the host running the tests """
78
79 def __init__(self, cmds, parent_dir):
80 super(HostDumper, self).__init__(cmds, parent_dir)
81
82 def dump_host(self, dump_dir=""):
83 if dump_dir:
84 self.dump_dir = dump_dir
Andrew Geissler82c905d2020-04-13 13:39:40 -050085 env = os.environ.copy()
86 env['PATH'] = '/usr/sbin:/sbin:/usr/bin:/bin'
87 env['COLUMNS'] = '9999'
Patrick Williamsc124f4f2015-09-15 14:41:29 -050088 for cmd in self.cmds:
Andrew Geissler82c905d2020-04-13 13:39:40 -050089 result = runCmd(cmd, ignore_status=True, env=env)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050090 self._write_dump(cmd.split()[0], result.output)
91
Patrick Williamsc124f4f2015-09-15 14:41:29 -050092class TargetDumper(BaseDumper):
93 """ Class to get dumps from target, it only works with QemuRunner """
94
Brad Bishop6e60e8b2018-02-01 10:27:11 -050095 def __init__(self, cmds, parent_dir, runner):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050096 super(TargetDumper, self).__init__(cmds, parent_dir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -050097 self.runner = runner
Patrick Williamsc124f4f2015-09-15 14:41:29 -050098
99 def dump_target(self, dump_dir=""):
100 if dump_dir:
101 self.dump_dir = dump_dir
102 for cmd in self.cmds:
103 # We can continue with the testing if serial commands fail
104 try:
105 (status, output) = self.runner.run_serial(cmd)
106 self._write_dump(cmd.split()[0], output)
107 except:
108 print("Tried to dump info from target but "
109 "serial console failed")
Andrew Geisslerc926e172021-05-07 16:11:35 -0500110 print("Failed CMD: %s" % (cmd))
111
112class MonitorDumper(BaseDumper):
113 """ Class to get dumps via the Qemu Monitor, it only works with QemuRunner """
114
115 def __init__(self, cmds, parent_dir, runner):
116 super(MonitorDumper, self).__init__(cmds, parent_dir)
117 self.runner = runner
118
119 def dump_monitor(self, dump_dir=""):
120 if self.runner is None:
121 return
122 if dump_dir:
123 self.dump_dir = dump_dir
124 for cmd in self.cmds:
Andrew Geissler5f350902021-07-23 13:09:54 -0400125 cmd_name = cmd.split()[0]
Andrew Geisslerc926e172021-05-07 16:11:35 -0500126 try:
Andrew Geissler5f350902021-07-23 13:09:54 -0400127 if len(cmd.split()) > 1:
128 cmd_args = cmd.split()[1]
129 if "%s" in cmd_args:
130 filename = self._construct_filename(cmd_name)
131 cmd_data = json.loads(cmd_args % (filename))
132 output = self.runner.run_monitor(cmd_name, cmd_data)
133 else:
134 output = self.runner.run_monitor(cmd_name)
135 self._write_dump(cmd_name, output)
136 except Exception as e:
137 print("Failed to dump QMP CMD: %s with\nExecption: %s" % (cmd_name, e))