]>
Commit | Line | Data |
---|---|---|
2f7faeed EK |
1 | package PVE::Report; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
180a86d3 | 5 | |
2f7faeed EK |
6 | use PVE::Tools; |
7 | ||
3a0b2c40 TL |
8 | # output the content of all the files of a directory |
9 | my sub dir2text { | |
10 | my ($target_dir, $regexp) = @_; | |
11 | ||
6b72e9dd | 12 | print STDERR "dir2text '${target_dir}${regexp}'..."; |
6e167f9a | 13 | my $text = "# output '${target_dir}${regexp}' file(s)\n"; |
3a0b2c40 TL |
14 | PVE::Tools::dir_glob_foreach($target_dir, $regexp, sub { |
15 | my ($file) = @_; | |
798bd39a | 16 | return if $file eq '.' || $file eq '..'; |
3a0b2c40 TL |
17 | $text .= "\n# cat $target_dir$file\n"; |
18 | $text .= PVE::Tools::file_get_contents($target_dir.$file)."\n"; | |
19 | }); | |
20 | return $text; | |
21 | } | |
22 | ||
23 | # command -v is the posix equivalent of 'which' | |
24 | my sub cmd_exists { system("command -v '$_[0]' > /dev/null 2>&1") == 0 } | |
ee3a8989 | 25 | |
01c8f6fe | 26 | my $init_report_cmds = sub { |
01c8f6fe TL |
27 | my $report_def = { |
28 | general => { | |
29 | title => 'general system info', | |
f784b925 | 30 | order => 10, |
01c8f6fe TL |
31 | cmds => [ |
32 | 'hostname', | |
3e441c50 | 33 | 'date -R', |
5148f21a | 34 | 'cat /proc/cmdline', |
01c8f6fe TL |
35 | 'pveversion --verbose', |
36 | 'cat /etc/hosts', | |
01c8f6fe | 37 | 'pvesubscription get', |
ea717e8f | 38 | 'cat /etc/apt/sources.list', |
f4c1565a AZ |
39 | sub { dir2text('/etc/apt/sources.list.d/', '.+\.list') }, |
40 | sub { dir2text('/etc/apt/sources.list.d/', '.+\.sources') }, | |
b7e677d5 | 41 | 'apt-cache policy | grep -vP "^ +origin "', |
9296b343 | 42 | 'apt-mark showhold', |
01c8f6fe TL |
43 | 'lscpu', |
44 | 'pvesh get /cluster/resources --type node --output-format=yaml', | |
45 | ], | |
46 | }, | |
8b94e6bb TL |
47 | 'system-load' => { |
48 | title => 'overall system load info', | |
49 | order => 20, | |
50 | cmds => [ | |
cdb63825 | 51 | 'top -b -c -w512 -n 1 -o TIME | head -n 30', |
8b94e6bb TL |
52 | 'head /proc/pressure/*', |
53 | ], | |
54 | }, | |
f784b925 TL |
55 | storage => { |
56 | order => 30, | |
57 | cmds => [ | |
58 | 'cat /etc/pve/storage.cfg', | |
59 | 'pvesm status', | |
60 | 'cat /etc/fstab', | |
61 | 'findmnt --ascii', | |
80e456f6 | 62 | 'df --human -T', |
ef09450c | 63 | 'proxmox-boot-tool status', |
f784b925 TL |
64 | ], |
65 | }, | |
66 | 'virtual guests' => { | |
67 | order => 40, | |
68 | cmds => [ | |
69 | 'qm list', | |
f4c1565a | 70 | sub { dir2text('/etc/pve/qemu-server/', '\d+\.conf') }, |
f784b925 | 71 | 'pct list', |
f4c1565a | 72 | sub { dir2text('/etc/pve/lxc/', '\d+\.conf') }, |
f784b925 TL |
73 | ], |
74 | }, | |
75 | network => { | |
c5b25c00 | 76 | order => 45, |
f784b925 TL |
77 | cmds => [ |
78 | 'ip -details -statistics address', | |
79 | 'ip -details -4 route show', | |
80 | 'ip -details -6 route show', | |
81 | 'cat /etc/network/interfaces', | |
b2b516f3 | 82 | sub { dir2text('/etc/network/interfaces.d/', '.*') }, |
e5ecadec | 83 | sub { dir2text('/etc/pve/sdn/', '.*') }, |
f784b925 TL |
84 | ], |
85 | }, | |
86 | firewall => { | |
87 | order => 50, | |
88 | cmds => [ | |
f4c1565a | 89 | sub { dir2text('/etc/pve/firewall/', '.+\.fw') }, |
f784b925 | 90 | 'cat /etc/pve/local/host.fw', |
dd9ee03b | 91 | 'iptables-save -c | column -t -l4 -o" "', |
f784b925 TL |
92 | ], |
93 | }, | |
94 | cluster => { | |
95 | order => 60, | |
96 | cmds => [ | |
97 | 'pvecm nodes', | |
98 | 'pvecm status', | |
99 | 'cat /etc/pve/corosync.conf 2>/dev/null', | |
100 | 'ha-manager status', | |
0fb89b4a | 101 | 'cat /etc/pve/datacenter.cfg', |
f784b925 TL |
102 | ], |
103 | }, | |
a26e547e AZ |
104 | jobs => { |
105 | order => 65, | |
106 | cmds => [ | |
107 | 'cat /etc/pve/jobs.cfg', | |
108 | ], | |
109 | }, | |
8b94e6bb | 110 | hardware => { |
f784b925 TL |
111 | order => 70, |
112 | cmds => [ | |
113 | 'dmidecode -t bios', | |
f784b925 TL |
114 | 'lspci -nnk', |
115 | ], | |
116 | }, | |
8b94e6bb | 117 | 'block devices' => { |
f784b925 TL |
118 | order => 80, |
119 | cmds => [ | |
c4c3ed73 | 120 | 'lsblk --ascii -M -o +HOTPLUG,ROTA,PHY-SEC,FSTYPE,MODEL,TRAN', |
f784b925 TL |
121 | 'ls -l /dev/disk/by-*/', |
122 | 'iscsiadm -m node', | |
123 | 'iscsiadm -m session', | |
124 | ], | |
125 | }, | |
126 | volumes => { | |
127 | order => 90, | |
128 | cmds => [ | |
129 | 'pvs', | |
130 | 'lvs', | |
131 | 'vgs', | |
132 | ], | |
133 | }, | |
01c8f6fe | 134 | }; |
1cf7db21 | 135 | |
fb925d65 | 136 | if (cmd_exists('zfs')) { |
f784b925 | 137 | push @{$report_def->{volumes}->{cmds}}, |
fb925d65 TL |
138 | 'zpool status', |
139 | 'zpool list -v', | |
140 | 'zfs list', | |
c46eb47e | 141 | 'arcstat', |
fb925d65 TL |
142 | ; |
143 | } | |
1cf7db21 | 144 | |
01c8f6fe | 145 | if (-e '/etc/ceph/ceph.conf') { |
f784b925 | 146 | push @{$report_def->{volumes}->{cmds}}, |
c83c3d45 TL |
147 | 'pveceph status', |
148 | 'ceph osd status', | |
149 | 'ceph df', | |
150 | 'ceph osd df tree', | |
ea4d55c9 | 151 | 'ceph device ls', |
c83c3d45 TL |
152 | 'cat /etc/ceph/ceph.conf', |
153 | 'ceph config dump', | |
154 | 'pveceph pool ls', | |
155 | 'ceph versions', | |
c1eef1f4 | 156 | 'ceph health detail', |
c83c3d45 | 157 | ; |
01c8f6fe | 158 | } |
2f7faeed | 159 | |
1226cd97 | 160 | if (cmd_exists('multipath')) { |
f784b925 | 161 | push @{$report_def->{disks}->{cmds}}, |
1226cd97 ML |
162 | 'cat /etc/multipath.conf', |
163 | 'cat /etc/multipath/wwids', | |
fb925d65 TL |
164 | 'multipath -ll', |
165 | ; | |
1226cd97 | 166 | } |
2f7faeed | 167 | |
01c8f6fe TL |
168 | return $report_def; |
169 | }; | |
2f7faeed | 170 | |
2f7faeed | 171 | sub generate { |
f784b925 | 172 | my $def = $init_report_cmds->(); |
01c8f6fe | 173 | |
3a0b2c40 | 174 | my $report = ''; |
ee3a8989 TL |
175 | my $record_output = sub { |
176 | $report .= shift . "\n"; | |
177 | }; | |
178 | ||
73cdcc98 TL |
179 | local $ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin'; |
180 | my $cmd_timeout = 10; # generous timeout | |
181 | ||
ee3a8989 TL |
182 | my $run_cmd_params = { |
183 | outfunc => $record_output, | |
184 | errfunc => $record_output, | |
185 | timeout => $cmd_timeout, | |
186 | noerr => 1, # avoid checking programs exit code | |
187 | }; | |
188 | ||
f784b925 | 189 | my $sorter = sub { ($def->{$_[0]}->{order} // 1<<30) <=> ($def->{$_[1]}->{order} // 1<<30) }; |
2c4ef55e | 190 | |
f784b925 TL |
191 | for my $section ( sort { $sorter->($a, $b) } keys %$def) { |
192 | my $s = $def->{$section}; | |
193 | my $title = $s->{title} // "info about $section"; | |
2f7faeed EK |
194 | |
195 | $report .= "\n==== $title ====\n"; | |
f784b925 | 196 | for my $command (@{$s->{cmds}}) { |
ee3a8989 TL |
197 | eval { |
198 | if (ref $command eq 'CODE') { | |
3a0b2c40 | 199 | $report .= PVE::Tools::run_with_timeout($cmd_timeout, $command); |
ee3a8989 | 200 | } else { |
01c8f6fe | 201 | print STDERR "Process ".$command."..."; |
ee3a8989 TL |
202 | $report .= "\n# $command\n"; |
203 | PVE::Tools::run_command($command, %$run_cmd_params); | |
204 | } | |
2bdf85f8 | 205 | print STDERR "OK"; |
ee3a8989 | 206 | }; |
2bdf85f8 | 207 | print STDERR "\n"; |
ee3a8989 | 208 | $report .= "\nERROR: $@\n" if $@; |
2f7faeed EK |
209 | } |
210 | } | |
ee3a8989 TL |
211 | |
212 | return $report; | |
2f7faeed | 213 | } |
2c4ef55e TL |
214 | |
215 | 1; |