LibreNMS/scripts/new-os.php

182 lines
7.0 KiB
PHP
Executable File

#!/usr/bin/env php
<?php
$init_modules = array('');
require __DIR__ . '/../includes/init.php';
$options = getopt('h:o:t:v:d::');
if ($options['h'] && $options['o'] && $options['t'] && $options['v']) {
$type = $options['t'];
$vendor = $options['v'];
set_debug(isset($options['d']));
$device_id = ctype_digit($options['h']) ? $options['h'] : getidbyname($options['h']);
$device = device_by_id_cache($device_id);
$definition_file = $config['install_dir'] . "/includes/definitions/{$options['o']}.yaml";
$discovery_file = $config['install_dir'] . "/includes/definitions/discovery/{$options['o']}.yaml";
$test_file = $config['install_dir'] . "/tests/snmpsim/{$options['o']}.snmprec";
if (file_exists($definition_file)) {
c_echo("The OS {$options['o']} appears to exist already, skipping to sensors support\n");
} else {
$sysDescr = snmp_get($device, 'sysDescr.0', '-OvQ', 'SNMPv2-MIB');
$sysObjectID = explode('.', ltrim(snmp_get($device, 'sysObjectID.0', '-OnvQ', 'SNMPv2-MIB'), '.'));
$end_oid = array_pop($sysObjectID);
$sysObjectID = '.' . implode('.', $sysObjectID);
$full_sysObjectID = "$sysObjectID.$end_oid";
c_echo("
sysDescr: $sysDescr
sysObjectID: $full_sysObjectID
");
$os = getHostOS($device);
$continue = 'n';
if ($os != 'generic') {
$continue = get_user_input("We already detect this device as OS $os type, do you want to continue to add sensors? (Y/n)");
}
if (!str_i_contains($continue, 'y')) {
$descr = get_user_input('Enter the description for this OS, i.e Cisco IOS:');
$icon = get_user_input('Enter the logo to use, this can be the name of an existing one (i.e: cisco) or the url to retrieve one:');
if (filter_var($icon, FILTER_VALIDATE_URL)) {
$icon_data = file_get_contents($icon);
file_put_contents($config['temp_dir'] . "/{$options['o']}", $icon_data);
$file_info = mime_content_type($config['temp_dir'] . "/{$options['o']}");
if ($file_info === 'image/png') {
$ext = '.png';
} elseif ($file_info === 'image/svg+xml') {
$ext = '.svg';
}
rename($config['temp_dir'] . "/{$options['o']}", $config['install_dir'] . "/html/images/os/$vendor$ext");
$icon = $vendor;
}
$disco = "os: {$options['o']}
text: '$descr'
type: $type
icon: $icon
group: $vendor
over:
- { graph: device_bits, text: 'Device Traffic' }
- { graph: device_processor, text: 'CPU Usage' }
- { graph: device_mempool, text: 'Memory Usage' }
discovery:
- sysObjectID:
- $sysObjectID
";
file_put_contents($definition_file, $disco);
$snmprec = "1.3.6.1.2.1.1.1.0|4|$sysDescr
1.3.6.1.2.1.1.2.0|6|$full_sysObjectID
";
file_put_contents($test_file, $snmprec);
}
if ($os === 'generic') {
c_echo("Base discovery file created,");
}
}
$mib_name = get_user_input("ctrl+c to exit now otherwise please enter the MIB name including path (url is also fine) for us to check for sensors:");
if (filter_var($mib_name, FILTER_VALIDATE_URL)) {
$mib_data = file_get_contents($mib_name);
file_put_contents($config['temp_dir'] . "/{$options['o']}.mib", $mib_data);
$file_info = mime_content_type($config['temp_dir'] . "/{$options['o']}.mib");
if ($file_info !== 'text/plain') {
c_echo("That mib file isn't a plain text file and is instead $file_info so we aren't using it");
exit(1);
}
preg_match('/(.* DEFINITIONS ::)/', $mib_data, $matches);
list($mib_name,) = explode(' ', $matches[0], 2);
if (file_exists($config['install_dir'] . "/mibs/$vendor/") == false) {
mkdir($config['install_dir'] . "/mibs/$vendor/");
}
rename($config['temp_dir'] . "/{$options['o']}.mib", $config['install_dir'] . "/mibs/$vendor/$mib_name");
}
$tables = `{$config['snmptranslate']} -M {$config['mib_dir']}:{$config['mib_dir']}/$vendor -m $mib_name -TB '.*Table$' -Os`;
foreach (explode(PHP_EOL, $tables) as $table_name) {
if ($table_name) {
$continue = get_user_input("Do you want to add $table_name? (y/N)");
if ($continue === 'y' || $continue === 'Y') {
$tmp_info = `env MIBDIRS={$config['mib_dir']}:{$config['mib_dir']}/$vendor/ env MIBS="$mib_name" mib2c -q -c misc/mib2c.conf $table_name`;
$table_info = Symfony\Component\Yaml\Yaml::parse($tmp_info);
$type = get_user_input('Enter the sensor type, i.e temperature, voltage, etc:');
echo 'Table info:' . PHP_EOL;
foreach ($table_info['data'] as $data) {
echo $data['name'] . PHP_EOL;
$tmp_table[$data['name']] = $data['oid'];
}
$value = get_user_input('Enter value:');
$descr = get_user_input('Enter descr:');
$divisor = get_user_input('Enter divisor (defaults to 1)');
$multiplier = get_user_input('Enter multiplier (defaults to 1)');
if ($type && $value && $descr) {
$discovery[$type] .= "
-
oid: $table_name
value: $value
num_oid: {$tmp_table[$value]}.
descr: $descr";
if ($multiplier) {
$discovery[$type] .= "\n multiplier: $multiplier";
}
if ($divisor) {
$discovery[$type] .= "\n divisor: $divisor";
}
}
}
}
}
if (is_array($discovery)) {
$discovery_data = "mib: $mib_name
modules:
sensors:";
foreach ($discovery as $sensor => $sensor_data) {
$discovery_data .= "
$sensor:
data:$sensor_data";
}
}
if (file_exists($discovery_file) === false) {
if (file_put_contents($discovery_file, $discovery_data)) {
c_echo("New discovery file $discovery_file has been created");
} else {
c_echo("Failed to create new discovery file $discovery_file");
}
} else {
c_echo("$discovery_file already exists, here's the data we would have added:");
c_echo($discovery_data);
}
} else {
c_echo("
Info:
You can use to build the yaml files for a new OS.
Usage:
-h Is the device ID or hostname of the device in LibreNMS detected as generic
-o This is the OS name, i.e ios, nxos, eos
-t This is the OS type, i.e network, power, etc
-v The vendor name in lower case, i.e cisco, arista
Example:
./scripts/new-os.php -h 44 -o new-eos
");
exit(1);
}
function get_user_input($msg)
{
c_echo($msg . ' ');
$handle = fopen("php://stdin", "r");
$line = fgets($handle);
return trim($line);
}