1 | <?php |
||
2 | |||
3 | /* |
||
4 | |-------------------------------------------------------------------------- |
||
5 | | Console Routes |
||
6 | |-------------------------------------------------------------------------- |
||
7 | | |
||
8 | | This file is where you may define all of your Closure based console |
||
9 | | commands. Each Closure is bound to a command instance allowing a |
||
10 | | simple approach to interacting with each command's IO methods. |
||
11 | | |
||
12 | */ |
||
13 | |||
14 | use App\Models\Device; |
||
15 | use LibreNMS\Exceptions\HostUnreachableException; |
||
16 | use LibreNMS\Util\Debug; |
||
17 | use Symfony\Component\Process\Process; |
||
18 | |||
19 | Artisan::command('device:rename |
||
20 | {old hostname : ' . __('The existing hostname, IP, or device id') . '} |
||
21 | {new hostname : ' . __('The new hostname or IP') . '} |
||
22 | ', function () { |
||
23 | /** @var \Illuminate\Console\Command $this */ |
||
24 | (new Process([ |
||
25 | base_path('renamehost.php'), |
||
26 | $this->argument('old hostname'), |
||
27 | $this->argument('new hostname'), |
||
28 | ]))->setTimeout(null)->setIdleTimeout(null)->setTty(true)->run(); |
||
29 | })->purpose(__('Rename a device, this can be used to change the hostname or IP of a device')); |
||
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
30 | |||
31 | Artisan::command('device:add |
||
32 | {device spec : Hostname or IP to add} |
||
33 | {--v1 : ' . __('Use SNMP v1') . '} |
||
34 | {--v2c : ' . __('Use SNMP v2c') . '} |
||
35 | {--v3 : ' . __('Use SNMP v3') . '} |
||
36 | {--f|force : ' . __('Just add the device, do not make any safety checks') . '} |
||
37 | {--g|group= : ' . __('Poller group (for distributed polling)') . '} |
||
38 | {--b|ping-fallback : ' . __('Add the device as ping only if it does not respond to SNMP') . '} |
||
39 | {--p|port-association-mode=ifIndex : ' . __('Sets how ports are mapped :modes, ifName is suggested for Linux/Unix', ['modes' => '[ifIndex, ifName, ifDescr, ifAlias]']) . '} |
||
40 | {--c|community= : ' . __('SNMP v1 or v2 community') . '} |
||
41 | {--t|transport=udp : ' . __('Transport to connect to the device') . ' [udp, udp6, tcp, tcp6]} |
||
42 | {--r|port=161 : ' . __('SNMP transport port') . '} |
||
43 | {--u|security-name=root : ' . __('SNMPv3 security username') . '} |
||
44 | {--A|auth-password= : ' . __('SNMPv3 authentication password') . '} |
||
45 | {--a|auth-protocol=md5 : ' . __('SNMPv3 authentication protocol') . ' [md5, sha, sha-512, sha-384, sha-256, sha-224]} |
||
46 | {--x|privacy-protocol=aes : ' . __('SNMPv3 privacy protocol') . ' [des, aes]} |
||
47 | {--X|privacy-password= : ' . __('SNMPv3 privacy password') . '} |
||
48 | {--P|ping-only : ' . __('Add a ping only device') . '} |
||
49 | {--o|os=ping : ' . __('Ping only: specify OS') . '} |
||
50 | {--w|hardware= : ' . __('Ping only: specify hardware') . '} |
||
51 | {--s|sysName= : ' . __('Ping only: specify sysName') . '} |
||
52 | ', function () { |
||
53 | /** @var \Illuminate\Console\Command $this */ |
||
54 | // Value Checks |
||
55 | if (! in_array($this->option('port-association-mode'), ['ifIndex', 'ifName', 'ifDescr', 'ifAlias'])) { |
||
56 | $this->error(__('Invalid port association mode')); |
||
57 | } |
||
58 | |||
59 | if (! in_array($this->option('transport'), ['udp', 'udp6', 'tcp', 'tcp6'])) { |
||
60 | $this->error(__('Invalid SNMP transport')); |
||
61 | } |
||
62 | |||
63 | if (! in_array($this->option('auth-protocol'), ['md5', 'sha', 'sha-512', 'sha-384', 'sha-256', 'sha-224'])) { |
||
64 | $this->error(__('Invalid authentication protocol')); |
||
65 | } |
||
66 | |||
67 | if (! in_array($this->option('privacy-protocol'), ['des', 'aes'])) { |
||
68 | $this->error(__('Invalid privacy protocol')); |
||
69 | } |
||
70 | |||
71 | $port = (int) $this->option('port'); |
||
72 | if ($port < 1 || $port > 65535) { |
||
73 | $this->error(__('Port should be 1-65535')); |
||
74 | } |
||
75 | |||
76 | // build additional |
||
77 | $additional = [ |
||
78 | 'os' => $this->option('os'), |
||
79 | 'hardware' => $this->option('hardware'), |
||
80 | 'sysName' => $this->option('sysName'), |
||
81 | ]; |
||
82 | if ($this->option('ping-only')) { |
||
83 | $additional['snmp_disable'] = 1; |
||
84 | } elseif ($this->option('ping-fallback')) { |
||
85 | $additional['ping_fallback'] = 1; |
||
86 | } |
||
87 | |||
88 | if ($this->option('community')) { |
||
89 | $community_config = \LibreNMS\Config::get('snmp.community'); |
||
90 | array_unshift($community_config, $this->option('community')); |
||
91 | \LibreNMS\Config::set('snmp.community', $community_config); |
||
92 | } |
||
93 | $auth = $this->option('auth-password'); |
||
94 | $priv = $this->option('privacy-password'); |
||
95 | $v3_config = \LibreNMS\Config::get('snmp.v3'); |
||
96 | array_unshift($v3_config, [ |
||
97 | 'authlevel' => ($auth ? 'auth' : 'noAuth') . (($priv && $auth) ? 'Priv' : 'NoPriv'), |
||
98 | 'authname' => $this->option('security-name'), |
||
99 | 'authpass' => $this->option('auth-password'), |
||
100 | 'authalgo' => $this->option('auth-protocol'), |
||
101 | 'cryptopass' => $this->option('privacy-password'), |
||
102 | 'cryptoalgo' => $this->option('privacy-protocol'), |
||
103 | ]); |
||
104 | \LibreNMS\Config::set('snmp.v3', $v3_config); |
||
105 | |||
106 | try { |
||
107 | $init_modules = []; |
||
108 | include base_path('includes/init.php'); |
||
109 | |||
110 | if (($verbosity = $this->getOutput()->getVerbosity()) >= 128) { |
||
111 | Debug::set(); |
||
112 | if ($verbosity >= 256) { |
||
113 | global $verbose; |
||
114 | $verbose = true; |
||
115 | } |
||
116 | } |
||
117 | |||
118 | $device_id = addHost( |
||
119 | $this->argument('device spec'), |
||
120 | $this->option('v3') ? 'v3' : ($this->option('v2c') ? 'v2c' : ($this->option('v1') ? 'v1' : '')), |
||
121 | $port, |
||
122 | $this->option('transport'), |
||
123 | $this->option('group'), |
||
124 | $this->option('force'), |
||
125 | $this->option('port-association-mode'), |
||
126 | $additional |
||
127 | ); |
||
128 | $hostname = Device::where('device_id', $device_id)->value('hostname'); |
||
129 | $this->info("Added device $hostname ($device_id)"); |
||
130 | |||
131 | return 0; |
||
132 | } catch (HostUnreachableException $e) { |
||
133 | $this->error($e->getMessage() . PHP_EOL . implode(PHP_EOL, $e->getReasons())); |
||
134 | |||
135 | return 1; |
||
136 | } catch (Exception $e) { |
||
137 | $this->error($e->getMessage()); |
||
138 | |||
139 | return 3; |
||
140 | } |
||
141 | })->purpose('Add a new device'); |
||
142 | |||
143 | Artisan::command('device:remove |
||
144 | {device spec : ' . __('Hostname, IP, or device id to remove') . '} |
||
145 | ', function () { |
||
146 | /** @var \Illuminate\Console\Command $this */ |
||
147 | (new Process([ |
||
148 | base_path('delhost.php'), |
||
149 | $this->argument('device spec'), |
||
150 | ]))->setTimeout(null)->setIdleTimeout(null)->setTty(true)->run(); |
||
151 | })->purpose('Remove a device'); |
||
152 | |||
153 | Artisan::command('update', function () { |
||
154 | (new Process([base_path('daily.sh')]))->setTimeout(null)->setIdleTimeout(null)->setTty(true)->run(); |
||
155 | })->purpose(__('Update LibreNMS and run maintenance routines')); |
||
156 | |||
157 | Artisan::command('poller:ping |
||
158 | {groups?* : ' . __('Optional List of distributed poller groups to poll') . '} |
||
159 | ', function () { |
||
160 | // PingCheck::dispatch(new PingCheck($this->argument('groups'))); |
||
161 | $command = [base_path('ping.php')]; |
||
162 | if ($this->argument('groups')) { |
||
163 | $command[] = '-g'; |
||
164 | $command[] = implode(',', $this->argument('groups')); |
||
165 | } |
||
166 | if (($verbosity = $this->getOutput()->getVerbosity()) >= 128) { |
||
167 | $command[] = '-d'; |
||
168 | if ($verbosity >= 256) { |
||
169 | $command[] = '-v'; |
||
170 | } |
||
171 | } |
||
172 | (new Process($command))->setTimeout(null)->setIdleTimeout(null)->setTty(true)->run(); |
||
173 | })->purpose(__('Check if devices are up or down via icmp')); |
||
174 | |||
175 | Artisan::command('poller:discovery |
||
176 | {device spec : ' . __('Device spec to discover: device_id, hostname, wildcard, odd, even, all, new') . '} |
||
177 | {--o|os= : ' . __('Only devices with the specified operating system') . '} |
||
178 | {--t|type= : ' . __('Only devices with the specified type') . '} |
||
179 | {--m|modules= : ' . __('Specify single module to be run. Comma separate modules, submodules may be added with /') . '} |
||
180 | ', function () { |
||
181 | $command = [base_path('discovery.php'), '-h', $this->argument('device spec')]; |
||
182 | if ($this->option('os')) { |
||
183 | $command[] = '-o'; |
||
184 | $command[] = $this->option('os'); |
||
185 | } |
||
186 | if ($this->option('type')) { |
||
187 | $command[] = '-t'; |
||
188 | $command[] = $this->option('type'); |
||
189 | } |
||
190 | if ($this->option('modules')) { |
||
191 | $command[] = '-m'; |
||
192 | $command[] = $this->option('modules'); |
||
193 | } |
||
194 | if (($verbosity = $this->getOutput()->getVerbosity()) >= 128) { |
||
195 | $command[] = '-d'; |
||
196 | if ($verbosity >= 256) { |
||
197 | $command[] = '-v'; |
||
198 | } |
||
199 | } |
||
200 | (new Process($command))->setTimeout(null)->setIdleTimeout(null)->setTty(true)->run(); |
||
201 | })->purpose(__('Discover information about existing devices, defines what will be polled')); |
||
202 | |||
203 | Artisan::command('poller:poll |
||
204 | {device spec : ' . __('Device spec to poll: device_id, hostname, wildcard, odd, even, all') . '} |
||
205 | {--m|modules= : ' . __('Specify single module to be run. Comma separate modules, submodules may be added with /') . '} |
||
206 | {--x|no-data : ' . __('Do not update datastores (RRD, InfluxDB, etc)') . '} |
||
207 | ', function () { |
||
208 | $command = [base_path('poller.php'), '-h', $this->argument('device spec')]; |
||
209 | if ($this->option('no-data')) { |
||
210 | array_push($command, '-r', '-f', '-p'); |
||
211 | } |
||
212 | if ($this->option('modules')) { |
||
213 | $command[] = '-m'; |
||
214 | $command[] = $this->option('modules'); |
||
215 | } |
||
216 | if (($verbosity = $this->getOutput()->getVerbosity()) >= 128) { |
||
217 | $command[] = '-d'; |
||
218 | if ($verbosity >= 256) { |
||
219 | $command[] = '-v'; |
||
220 | } |
||
221 | } |
||
222 | (new Process($command))->setTimeout(null)->setIdleTimeout(null)->setTty(true)->run(); |
||
223 | })->purpose(__('Poll data from devices as defined by discovery')); |
||
224 | |||
225 | Artisan::command('poller:alerts', function () { |
||
226 | $command = [base_path('alerts.php')]; |
||
227 | if (($verbosity = $this->getOutput()->getVerbosity()) >= 128) { |
||
228 | $command[] = '-d'; |
||
229 | if ($verbosity >= 256) { |
||
230 | $command[] = '-v'; |
||
231 | } |
||
232 | } |
||
233 | |||
234 | (new Process($command))->setTimeout(null)->setIdleTimeout(null)->setTty(true)->run(); |
||
235 | })->purpose(__('Check for any pending alerts and deliver them via defined transports')); |
||
236 | |||
237 | Artisan::command('poller:billing |
||
238 | {bill id? : ' . __('The bill id to poll') . '} |
||
239 | ', function () { |
||
240 | /** @var \Illuminate\Console\Command $this */ |
||
241 | $command = [base_path('poll-billing.php')]; |
||
242 | if ($this->argument('bill id')) { |
||
243 | $command[] = '-b'; |
||
244 | $command[] = $this->argument('bill id'); |
||
245 | } |
||
246 | |||
247 | if (($verbosity = $this->getOutput()->getVerbosity()) >= 128) { |
||
248 | $command[] = '-d'; |
||
249 | if ($verbosity >= 256) { |
||
250 | $command[] = '-v'; |
||
251 | } |
||
252 | } |
||
253 | (new Process($command))->setTimeout(null)->setIdleTimeout(null)->setTty(true)->run(); |
||
254 | })->purpose(__('Collect billing data')); |
||
255 | |||
256 | Artisan::command('poller:services |
||
257 | {device spec : ' . __('Device spec to poll: device_id, hostname, wildcard, all') . '} |
||
258 | {--x|no-data : ' . __('Do not update datastores (RRD, InfluxDB, etc)') . '} |
||
259 | ', function () { |
||
260 | /** @var \Illuminate\Console\Command $this */ |
||
261 | $command = [base_path('check-services.php')]; |
||
262 | if ($this->option('no-data')) { |
||
263 | array_push($command, '-r', '-f', '-p'); |
||
264 | } |
||
265 | if ($this->argument('device spec') !== 'all') { |
||
266 | $command[] = '-h'; |
||
267 | $command[] = $this->argument('device spec'); |
||
268 | } |
||
269 | |||
270 | if (($verbosity = $this->getOutput()->getVerbosity()) >= 128) { |
||
271 | $command[] = '-d'; |
||
272 | if ($verbosity >= 256) { |
||
273 | $command[] = '-v'; |
||
274 | } |
||
275 | } |
||
276 | (new Process($command))->setTimeout(null)->setIdleTimeout(null)->setTty(true)->run(); |
||
277 | })->purpose(__('Update LibreNMS and run maintenance routines')); |
||
278 | |||
279 | Artisan::command('poller:billing-calculate |
||
280 | {--c|clear-history : ' . __('Delete all billing history') . '} |
||
281 | ', function () { |
||
282 | /** @var \Illuminate\Console\Command $this */ |
||
283 | $command = [base_path('billing-calculate.php')]; |
||
284 | if ($this->option('clear-history')) { |
||
285 | $command[] = '-r'; |
||
286 | } |
||
287 | |||
288 | (new Process($command))->setTimeout(null)->setIdleTimeout(null)->setTty(true)->run(); |
||
289 | })->purpose(__('Run billing calculations')); |
||
290 | |||
291 | Artisan::command('scan |
||
292 | {network?* : ' . __('CIDR notation network(s) to scan, can be ommited if \'nets\' config is set') . '} |
||
293 | {--P|ping-only : ' . __('Add the device as a ping only device if it replies to ping but not SNMP') . '} |
||
294 | {--t|threads=32 : ' . __('How many IPs to scan at a time, more will increase the scan speed, but could overload your system') . '} |
||
295 | {--l|legend : ' . __('Print the legend') . '} |
||
296 | ', function () { |
||
297 | /** @var \Illuminate\Console\Command $this */ |
||
298 | $command = [base_path('snmp-scan.py')]; |
||
299 | |||
300 | if (empty($this->argument('network')) && ! \LibreNMS\Config::has('nets')) { |
||
301 | $this->error(__('Network is required if \'nets\' is not set in the config')); |
||
302 | |||
303 | return 1; |
||
304 | } |
||
305 | |||
306 | if ($this->option('ping-only')) { |
||
307 | $command[] = '-P'; |
||
308 | } |
||
309 | |||
310 | $command[] = '-t'; |
||
311 | $command[] = $this->option('threads'); |
||
312 | |||
313 | if ($this->option('legend')) { |
||
314 | $command[] = '-l'; |
||
315 | } |
||
316 | |||
317 | $verbosity = $this->getOutput()->getVerbosity(); |
||
318 | if ($verbosity >= 64) { |
||
319 | $command[] = '-v'; |
||
320 | if ($verbosity >= 128) { |
||
321 | $command[] = '-v'; |
||
322 | if ($verbosity >= 256) { |
||
323 | $command[] = '-v'; |
||
324 | } |
||
325 | } |
||
326 | } |
||
327 | |||
328 | $command = array_merge($command, $this->argument('network')); |
||
329 | |||
330 | (new Process($command))->setTimeout(null)->setIdleTimeout(null)->setTty(true)->run(); |
||
331 | })->purpose(__('Scan the network for hosts and try to add them to LibreNMS')); |
||
332 |