]> git.proxmox.com Git - pve-manager.git/blob - PVE/Report.pm
report: avoid extra oder array, define it inline
[pve-manager.git] / PVE / Report.pm
1 package PVE::Report;
2
3 use strict;
4 use warnings;
5
6 use PVE::Tools;
7
8 # output the content of all the files of a directory
9 my sub dir2text {
10 my ($target_dir, $regexp) = @_;
11
12 my $text = '';
13 PVE::Tools::dir_glob_foreach($target_dir, $regexp, sub {
14 my ($file) = @_;
15 $text .= "\n# cat $target_dir$file\n";
16 $text .= PVE::Tools::file_get_contents($target_dir.$file)."\n";
17 });
18 return $text;
19 }
20
21 # command -v is the posix equivalent of 'which'
22 my sub cmd_exists { system("command -v '$_[0]' > /dev/null 2>&1") == 0 }
23
24 my $init_report_cmds = sub {
25 my $report_def = {
26 general => {
27 title => 'general system info',
28 order => 10,
29 cmds => [
30 'hostname',
31 'pveversion --verbose',
32 'cat /etc/hosts',
33 'top -b -n 1 | head -n 15',
34 'pvesubscription get',
35 'cat /etc/apt/sources.list',
36 sub { dir2text('/etc/apt/sources.list.d/', '.*list') },
37 sub { dir2text('/etc/apt/sources.list.d/', '.*sources') },
38 'lscpu',
39 'head /proc/pressure/*',
40 'pvesh get /cluster/resources --type node --output-format=yaml',
41 ],
42 },
43 storage => {
44 order => 30,
45 cmds => [
46 'cat /etc/pve/storage.cfg',
47 'pvesm status',
48 'cat /etc/fstab',
49 'findmnt --ascii',
50 'df --human',
51 ],
52 },
53 'virtual guests' => {
54 order => 40,
55 cmds => [
56 'qm list',
57 sub { dir2text('/etc/pve/qemu-server/', '\d.*conf') },
58 'pct list',
59 sub { dir2text('/etc/pve/lxc/', '\d.*conf') },
60 ],
61 },
62 network => {
63 order => 40,
64 cmds => [
65 'ip -details -statistics address',
66 'ip -details -4 route show',
67 'ip -details -6 route show',
68 'cat /etc/network/interfaces',
69 ],
70 },
71 firewall => {
72 order => 50,
73 cmds => [
74 sub { dir2text('/etc/pve/firewall/', '.*fw') },
75 'cat /etc/pve/local/host.fw',
76 'iptables-save',
77 ],
78 },
79 cluster => {
80 order => 60,
81 cmds => [
82 'pvecm nodes',
83 'pvecm status',
84 'cat /etc/pve/corosync.conf 2>/dev/null',
85 'ha-manager status',
86 ],
87 },
88 bios => {
89 order => 70,
90 cmds => [
91 'dmidecode -t bios',
92 ],
93 },
94 pci => {
95 order => 75,
96 cmds => [
97 'lspci -nnk',
98 ],
99 },
100 disks => {
101 order => 80,
102 cmds => [
103 'lsblk --ascii',
104 'ls -l /dev/disk/by-*/',
105 'iscsiadm -m node',
106 'iscsiadm -m session',
107 ],
108 },
109 volumes => {
110 order => 90,
111 cmds => [
112 'pvs',
113 'lvs',
114 'vgs',
115 ],
116 },
117 };
118
119 if (cmd_exists('zfs')) {
120 push @{$report_def->{volumes}->{cmds}},
121 'zpool status',
122 'zpool list -v',
123 'zfs list',
124 ;
125 }
126
127 if (-e '/etc/ceph/ceph.conf') {
128 push @{$report_def->{volumes}->{cmds}},
129 'pveceph status',
130 'ceph osd status',
131 'ceph df',
132 'ceph osd df tree',
133 'cat /etc/ceph/ceph.conf',
134 'ceph config dump',
135 'pveceph pool ls',
136 'ceph versions',
137 ;
138 }
139
140 if (cmd_exists('multipath')) {
141 push @{$report_def->{disks}->{cmds}},
142 'cat /etc/multipath.conf',
143 'cat /etc/multipath/wwids',
144 'multipath -ll',
145 ;
146 }
147
148 return $report_def;
149 };
150
151 sub generate {
152 my $def = $init_report_cmds->();
153
154 my $report = '';
155 my $record_output = sub {
156 $report .= shift . "\n";
157 };
158
159 local $ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin';
160 my $cmd_timeout = 10; # generous timeout
161
162 my $run_cmd_params = {
163 outfunc => $record_output,
164 errfunc => $record_output,
165 timeout => $cmd_timeout,
166 noerr => 1, # avoid checking programs exit code
167 };
168
169 my $sorter = sub { ($def->{$_[0]}->{order} // 1<<30) <=> ($def->{$_[1]}->{order} // 1<<30) };
170
171 for my $section ( sort { $sorter->($a, $b) } keys %$def) {
172 my $s = $def->{$section};
173 my $title = $s->{title} // "info about $section";
174
175 $report .= "\n==== $title ====\n";
176 for my $command (@{$s->{cmds}}) {
177 eval {
178 if (ref $command eq 'CODE') {
179 $report .= PVE::Tools::run_with_timeout($cmd_timeout, $command);
180 } else {
181 print STDERR "Process ".$command."...";
182 $report .= "\n# $command\n";
183 PVE::Tools::run_command($command, %$run_cmd_params);
184 }
185 print STDERR "OK";
186 };
187 print STDERR "\n";
188 $report .= "\nERROR: $@\n" if $@;
189 }
190 }
191
192 return $report;
193 }
194
195 1;