mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
feature: Application auto discovery (#6143)
This commit is contained in:
committed by
Neil Lathwood
parent
4e40314a3a
commit
e7057ecea5
56
html/includes/forms/application-update.inc.php
Normal file
56
html/includes/forms/application-update.inc.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* application-update.php
|
||||
*
|
||||
* Handle application enable disable from ajax
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @package LibreNMS
|
||||
* @link http://librenms.org
|
||||
* @copyright 2017 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
if (is_admin() === false) {
|
||||
$status = array('status' => 1, 'message' => 'You need to be admin');
|
||||
} else {
|
||||
$device_id = $_POST['device_id'];
|
||||
$app = $_POST['application'];
|
||||
|
||||
if (!isset($app) && validate_device_id($device_id) === false) {
|
||||
$status = array('status' => 1, 'message' => 'Error with data');
|
||||
} else {
|
||||
$status = array('status' => 1, 'message' => 'Database update failed');
|
||||
if ($_POST['state'] == 'true') {
|
||||
$update = array(
|
||||
'device_id' => $device_id,
|
||||
'app_type' => $app,
|
||||
'app_status' => '',
|
||||
'app_instance' => ''
|
||||
);
|
||||
if (dbInsert($update, 'applications')) {
|
||||
log_event("Application enabled by user: $app", $device_id, 'application', 1);
|
||||
$status = array('status' => 0, 'message' => 'Application enabled');
|
||||
}
|
||||
} else {
|
||||
if (dbDelete('applications', '`device_id`=? AND `app_type`=?', array($device_id, $app))) {
|
||||
log_event("Application disabled by user: $app", $device_id, 'application', 3);
|
||||
$status = array('status' => 0, 'message' => 'Application disabled');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
header('Content-Type: application/json');
|
||||
echo _json_encode($status);
|
@ -2,95 +2,68 @@
|
||||
<?php
|
||||
|
||||
// Load our list of available applications
|
||||
foreach (scandir($config['install_dir'].'/includes/polling/applications/') as $file) {
|
||||
if (substr($file, -8) == '.inc.php') {
|
||||
$applications[] = substr($file, 0, -8);
|
||||
}
|
||||
$applications = array();
|
||||
foreach (glob($config['install_dir'] . '/includes/polling/applications/*.inc.php') as $file) {
|
||||
$name = basename($file, '.inc.php');
|
||||
$applications[$name] = $name;
|
||||
}
|
||||
|
||||
// Check if the form was POSTed
|
||||
if ($_POST['device']) {
|
||||
$updated = 0;
|
||||
$param[] = $device['device_id'];
|
||||
foreach (array_keys($_POST) as $key) {
|
||||
if (substr($key, 0, 4) == 'app_') {
|
||||
$param[] = substr($key, 4);
|
||||
$enabled[] = substr($key, 4);
|
||||
$replace[] = '?';
|
||||
}
|
||||
}
|
||||
// Generate a list of enabled apps with a value of whether they are discovered or not
|
||||
$enabled_apps = array_reduce(dbFetchRows(
|
||||
'SELECT `app_type`,`discovered` FROM `applications` WHERE `device_id`=? ORDER BY `app_type`',
|
||||
array($device['device_id'])
|
||||
), function ($result, $app) {
|
||||
$result[$app['app_type']] = $app['discovered'];
|
||||
return $result;
|
||||
}, array());
|
||||
|
||||
if (count($enabled)) {
|
||||
$updated += dbDelete('applications', '`device_id` = ? AND `app_type` NOT IN ('.implode(',', $replace).')', $param);
|
||||
} else {
|
||||
$updated += dbDelete('applications', '`device_id` = ?', array($param));
|
||||
}
|
||||
|
||||
foreach (dbFetchRows('SELECT `app_type` FROM `applications` WHERE `device_id` = ?', array($device['device_id'])) as $row) {
|
||||
$app_in_db[] = $row['app_type'];
|
||||
}
|
||||
|
||||
foreach ($enabled as $app) {
|
||||
if (!in_array($app, $app_in_db)) {
|
||||
$updated += dbInsert(array('device_id' => $device['device_id'], 'app_type' => $app, 'app_status' => '', 'app_instance' => ''), 'applications');
|
||||
}
|
||||
}
|
||||
|
||||
if ($updated) {
|
||||
print_message('Applications updated!');
|
||||
} else {
|
||||
print_message('No changes.');
|
||||
}
|
||||
}//end if
|
||||
|
||||
// Show list of apps with checkboxes
|
||||
echo '<div style="padding: 10px;">';
|
||||
|
||||
$apps_enabled = dbFetchRows('SELECT * from `applications` WHERE `device_id` = ? ORDER BY app_type', array($device['device_id']));
|
||||
if (count($apps_enabled)) {
|
||||
foreach ($apps_enabled as $application) {
|
||||
$app_enabled[] = $application['app_type'];
|
||||
}
|
||||
}
|
||||
|
||||
echo "<div class='row'>
|
||||
<div class='col-md-4'>
|
||||
<form id='appedit' name='appedit' method='post' action='' role='form' class='form-horizontal'>
|
||||
<input type=hidden name=device value='".$device['device_id']."'>
|
||||
<table class='table table-hover table-responsive'>
|
||||
<tr align=center>
|
||||
<th>Enable</th>
|
||||
<th>Application</th>
|
||||
</tr>
|
||||
";
|
||||
|
||||
$row = 1;
|
||||
|
||||
echo '<ul class="list-group row">';
|
||||
foreach ($applications as $app) {
|
||||
if (is_integer($row / 2)) {
|
||||
$row_colour = $list_colour_a;
|
||||
} else {
|
||||
$row_colour = $list_colour_b;
|
||||
$modifiers = '';
|
||||
$app_text = nicecase($app);
|
||||
// check if the app exists in the enable apps array and check if it was automatically enabled
|
||||
if (isset($enabled_apps[$app])) {
|
||||
$modifiers = ' checked';
|
||||
if ($enabled_apps[$app]) {
|
||||
$app_text .= '<span class="text-success"> (Discovered)</span>';
|
||||
$modifiers .= ' disabled';
|
||||
}
|
||||
}
|
||||
|
||||
echo " <tr bgcolor=$row_colour>";
|
||||
echo ' <td>';
|
||||
echo ' <input type=checkbox'.(in_array($app, $app_enabled) ? ' checked="1"' : '')." name='app_".$app."'>";
|
||||
echo ' </td>';
|
||||
echo ' <td>'.nicecase($app).'</td>';
|
||||
echo ' </tr>
|
||||
';
|
||||
|
||||
$row++;
|
||||
echo '<li class="list-group-item col-xs-12 col-md-6 col-lg-4">';
|
||||
echo "<input style='visibility:hidden;width:100px;' type='checkbox' name='application' data-size='small'";
|
||||
echo " data-application='$app' data-device_id='{$device['device_id']}'$modifiers>";
|
||||
echo '<span style="font-size:medium;padding-left:5px;"> ' . $app_text . '</span>';
|
||||
echo '</li>';
|
||||
}
|
||||
|
||||
echo '</table>';
|
||||
echo '<div class="row">
|
||||
<div class="col-md-1">
|
||||
<button type="submit" name="Submit" class="btn btn-default"><i class="fa fa-check"></i> Save</button>
|
||||
</div>
|
||||
</div>
|
||||
';
|
||||
echo '</form>';
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
echo '</ul>';
|
||||
?>
|
||||
|
||||
<script>
|
||||
$('[name="application"]').bootstrapSwitch('offColor', 'danger');
|
||||
$('input[name="application"]').on('switchChange.bootstrapSwitch', function (event, state) {
|
||||
event.preventDefault();
|
||||
var $this = $(this);
|
||||
var application = $this.data("application");
|
||||
var device_id = $this.data("device_id");
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: 'ajax_form.php',
|
||||
data: {type: "application-update", application: application, device_id: device_id, state: state},
|
||||
success: function(result){
|
||||
if (result.status == 0) {
|
||||
toastr.success(result.message);
|
||||
} else {
|
||||
toastr.error(result.message);
|
||||
$this.bootstrapSwitch('state', !state, true);
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
toastr.error('Problem with backend');
|
||||
$this.bootstrapSwitch('state', !state, true);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
@ -77,7 +77,8 @@ foreach ($poller_modules as $module => $module_status) {
|
||||
<td>
|
||||
');
|
||||
|
||||
echo('<input type="checkbox" name="poller-module" data-poller_module="'.$module.'" data-device_id="'.$device['device_id'].'" '.$module_checked.'>');
|
||||
echo '<input type="checkbox" style="visibility:hidden;width:100px;" name="poller-module" data-poller_module="'
|
||||
.$module.'" data-device_id="'.$device['device_id'].'" '.$module_checked.'>';
|
||||
|
||||
echo('
|
||||
</td>
|
||||
@ -159,7 +160,8 @@ foreach ($discovery_modules as $module => $module_status) {
|
||||
</td>
|
||||
<td>');
|
||||
|
||||
echo('<input type="checkbox" name="discovery-module" data-discovery_module="'.$module.'" data-device_id="'.$device['device_id'].'" '.$module_checked.'>');
|
||||
echo '<input type="checkbox" style="visibility:hidden;width:100px;" name="discovery-module" data-discovery_module="'
|
||||
.$module.'" data-device_id="'.$device['device_id'].'" '.$module_checked.'>';
|
||||
|
||||
echo('
|
||||
</td>
|
||||
|
@ -769,6 +769,7 @@ $config['discovery_modules']['vmware-vminfo'] = 0;
|
||||
$config['discovery_modules']['libvirt-vminfo'] = 0;
|
||||
$config['discovery_modules']['toner'] = 0;
|
||||
$config['discovery_modules']['ucd-diskio'] = 1;
|
||||
$config['discovery_modules']['applications'] = 0;
|
||||
$config['discovery_modules']['services'] = 1;
|
||||
$config['discovery_modules']['stp'] = 1;
|
||||
$config['discovery_modules']['ntp'] = 1;
|
||||
|
@ -6,3 +6,5 @@ processor_stacked: 1
|
||||
over:
|
||||
- { graph: device_processor, text: 'Processor Usage' }
|
||||
- { graph: device_ucd_memory, text: 'Memory Usage' }
|
||||
discovery_modules:
|
||||
applications: 1
|
||||
|
@ -15,6 +15,7 @@ poller_modules:
|
||||
ospf: 0
|
||||
stp: 0
|
||||
discovery_modules:
|
||||
applications: 1
|
||||
bgp-peers: 0
|
||||
stp: 0
|
||||
vmware-vminfo: 1
|
||||
|
120
includes/discovery/applications.inc.php
Normal file
120
includes/discovery/applications.inc.php
Normal file
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
/**
|
||||
* applications.inc.php
|
||||
*
|
||||
* Discover applications
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @package LibreNMS
|
||||
* @link http://librenms.org
|
||||
* @copyright 2016 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
echo "\nApplications: ";
|
||||
|
||||
// fetch applications from the client
|
||||
$results = snmpwalk_cache_oid($device, 'nsExtendStatus', array(), 'NET-SNMP-EXTEND-MIB');
|
||||
|
||||
// Load our list of available applications
|
||||
$applications = array();
|
||||
if ($results) {
|
||||
foreach (glob($config['install_dir'] . '/includes/polling/applications/*.inc.php') as $file) {
|
||||
$name = basename($file, '.inc.php');
|
||||
$applications[$name] = $name;
|
||||
}
|
||||
|
||||
// fix applications that don't match their snmp extend name
|
||||
$applications['dhcpstats'] = 'dhcp-stats';
|
||||
$applications['fbsdnfsclient'] = 'fbsd-nfs-client';
|
||||
$applications['fbsdnfsserver'] = 'fbsd-nfs-server';
|
||||
$applications['mailq'] = 'postfix';
|
||||
$applications['osupdate'] = 'os-updates';
|
||||
$applications['phpfpmsp'] = 'php-fpm';
|
||||
$applications['postfixdetailed'] = 'postfix';
|
||||
}
|
||||
|
||||
d_echo(PHP_EOL . 'Available: ' . implode(', ', array_keys($applications)) . PHP_EOL);
|
||||
d_echo('Checking for: ' . implode(', ', array_keys($results)) . PHP_EOL);
|
||||
|
||||
// Generate a list of enabled apps and a list of all discovered apps from the db
|
||||
list($enabled_apps, $discovered_apps) = array_reduce(dbFetchRows(
|
||||
'SELECT `app_type`,`discovered` FROM `applications` WHERE `device_id`=? ORDER BY `app_type`',
|
||||
array($device['device_id'])
|
||||
), function ($result, $app) {
|
||||
$result[0][] = $app['app_type'];
|
||||
if ($app['discovered']) {
|
||||
$result[1][] = $app['app_type'];
|
||||
}
|
||||
return $result;
|
||||
}, array(array(), array()));
|
||||
|
||||
|
||||
// Enable applications
|
||||
$current_apps = array();
|
||||
foreach ($results as $extend => $result) {
|
||||
if (isset($applications[$extend])) {
|
||||
$app = $applications[$extend];
|
||||
$current_apps[] = $app;
|
||||
|
||||
if (in_array($app, $enabled_apps)) {
|
||||
echo '.';
|
||||
} else {
|
||||
dbInsert(array(
|
||||
'device_id' => $device['device_id'],
|
||||
'app_type' => $app,
|
||||
'discovered' => 1,
|
||||
'app_status' => '',
|
||||
'app_instance' => ''
|
||||
), 'applications');
|
||||
|
||||
echo '+';
|
||||
log_event("Application enabled by discovery: $app", $device, 'application', 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove non-existing apps
|
||||
$apps_to_remove = array_diff($discovered_apps, $current_apps);
|
||||
$num = count($apps_to_remove);
|
||||
if ($num > 0) {
|
||||
echo str_repeat('-', $num);
|
||||
$vars = $apps_to_remove;
|
||||
array_unshift($vars, $device['device_id']);
|
||||
dbDelete(
|
||||
'applications',
|
||||
'`device_id`=? AND `app_type` IN (' . implode(',', array_fill(0, $num, '?')) . ')',
|
||||
$vars
|
||||
);
|
||||
foreach ($apps_to_remove as $app) {
|
||||
log_event("Application disabled by discovery: $app", $device, 'application', 3);
|
||||
}
|
||||
}
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
unset(
|
||||
$applications,
|
||||
$enabled_apps,
|
||||
$discovered_apps,
|
||||
$current_apps,
|
||||
$apps_to_remove,
|
||||
$results,
|
||||
$file,
|
||||
$name,
|
||||
$extend,
|
||||
$app,
|
||||
$num
|
||||
);
|
3
sql-schema/181.sql
Normal file
3
sql-schema/181.sql
Normal file
@ -0,0 +1,3 @@
|
||||
ALTER TABLE `applications` CHANGE `app_state_prev` `app_state_prev` VARCHAR(32) NULL;
|
||||
ALTER TABLE `applications` ADD `discovered` TINYINT NOT NULL DEFAULT '0' AFTER `app_state`;
|
||||
ALTER IGNORE TABLE `applications` ADD UNIQUE `unique_index`(`device_id`, `app_type`);
|
Reference in New Issue
Block a user