From b5106f4e17aa2bd4438011149caef3cb9253683b Mon Sep 17 00:00:00 2001 From: Tony Murray Date: Wed, 10 Feb 2016 12:17:37 -0600 Subject: [PATCH 01/10] Generate and display diffs between versions. Clicking show diff generates a diff between the shown version and the selected version. --- html/pages/device.inc.php | 4 +- html/pages/device/showconfig.inc.php | 84 +++++++++++++++++++++------- 2 files changed, 67 insertions(+), 21 deletions(-) diff --git a/html/pages/device.inc.php b/html/pages/device.inc.php index 94a2968227..54fe3f0933 100644 --- a/html/pages/device.inc.php +++ b/html/pages/device.inc.php @@ -304,7 +304,7 @@ if (device_permitted($vars['device']) || $check_device == $vars['device']) { '; } - if ($_SESSION['userlevel'] >= '7') { + if (is_admin()) { if (!is_array($config['rancid_configs'])) { $config['rancid_configs'] = array($config['rancid_configs']); } @@ -392,7 +392,7 @@ if (device_permitted($vars['device']) || $check_device == $vars['device']) {
  • ssh
  • telnet
  • '; - if ($_SESSION['userlevel'] >= '7') { + if (is_admin()) { echo '
  • diff --git a/html/pages/device/showconfig.inc.php b/html/pages/device/showconfig.inc.php index ed9219cf23..2455aee6b1 100644 --- a/html/pages/device/showconfig.inc.php +++ b/html/pages/device/showconfig.inc.php @@ -3,7 +3,7 @@ require 'includes/geshi/geshi.php'; // FIXME svn stuff still using optc etc, won't work, needs updating! -if ($_SESSION['userlevel'] >= '7') { +if (is_admin()) { if (!is_array($config['rancid_configs'])) { $config['rancid_configs'] = array($config['rancid_configs']); } @@ -104,18 +104,50 @@ if ($_SESSION['userlevel'] >= '7') { } else if ($config['oxidized']['enabled'] === true && isset($config['oxidized']['url'])) { $node_info = json_decode(file_get_contents($config['oxidized']['url'].'/node/show/'.$device['hostname'].'?format=json'), true); - if ($config['oxidized']['features']['versioning'] === true && isset($_POST['config'])) { - list($oid,$date,$version) = explode('|',mres($_POST['config'])); - $text = file_get_contents($config['oxidized']['url'].'/node/version/view?node='.$device['hostname'].'&group='.(!empty($node_info['group']) ? $node_info['group'] : '').'&oid='.$oid.'&date='.urlencode($date).'&num='.$version.'&format=text'); - } - else { - $text = file_get_contents($config['oxidized']['url'].'/node/fetch/'.(!empty($node_info['group']) ? $node_info['group'].'/' : '').$device['hostname']); - } - if ($config['oxidized']['features']['versioning'] === true) { + + if ($config['oxidized']['features']['versioning'] === true) { // fetch a list of versions $config_versions = json_decode(file_get_contents($config['oxidized']['url'].'/node/version?node_full='.(!empty($node_info['group']) ? $node_info['group'].'/' : '').$device['hostname'].'&format=json'), true); } + if (is_array($config_versions)) { + $config_total = count($config_versions); + } - if (is_array($node_info) || is_array($config_versions)) { + if ($config_total > 1) { + if (isset($_POST['config'])) { // versioning with selected version + list($oid,$date,$version) = explode('|',mres($_POST['config'])); + $current_version = array('oid'=>$oid, 'date'=>$date, 'version'=>$version); + } + else { // no version selected + $current_version = array('oid'=>$config_versions[0]['oid'], 'date'=>$current_version[0]['date'], 'version'=>$config_total); + } + + // fetch current_version + $text = file_get_contents($config['oxidized']['url'].'/node/version/view?node='.$device['hostname'].'&group='.(!empty($node_info['group']) ? $node_info['group'] : '').'&oid='.$current_version['oid'].'&date='.urlencode($current_version['date']).'&num='.$current_version['version'].'&format=text'); + + if (isset($_POST['diff']) && isset($_POST['prevconfig'])) { // diff requested + list($oid,$date,$version) = explode('|',mres($_POST['prevconfig'])); + if ($current_version['oid'] == $oid) { // the same version is selected, assume the previous revision + $key = array_search($oid, array_column($config_versions, 'oid')) + 1; // >=PHP 5.5.0 + $oid = $config_versions[$key]['oid']; + $date = $config_versions[$key]['date']; + $version = $config_total - $key; + } + + if ($version > 0) { // if we know the version doesn't exist, don't even try to fetch it + $previous_text = file_get_contents($config['oxidized']['url'].'/node/version/view?node='.$device['hostname'].'&group='.(!empty($node_info['group']) ? $node_info['group'] : '').'&oid='.$oid.'&date='.urlencode($date).'&num='.$version.'&format=text'); + if (!empty($previous_text)) { + $text = xdiff_string_diff($text, $previous_text); // requires pecl xdiff + } + } else { + print_error('No previous version, please select a different version.'); + } + } + } + else { // just fetch the only version + $text = file_get_contents($config['oxidized']['url'].'/node/fetch/'.(!empty($node_info['group']) ? $node_info['group'].'/' : '').$device['hostname']); + } + + if (is_array($node_info) || $config_total > 1) { echo '
    '; @@ -136,7 +168,7 @@ if ($_SESSION['userlevel'] >= '7') { '; } - if (is_array($config_versions)) { + if ($config_total > 1) { echo '
    @@ -144,13 +176,19 @@ if ($_SESSION['userlevel'] >= '7') {
    + +
    @@ -177,9 +219,13 @@ if ($_SESSION['userlevel'] >= '7') { }//end if if (!empty($text)) { - $language = 'ios'; - $geshi = new GeSHi($text, $language); - $geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS); +// if (!empty($previous_text)) { + $language = 'diff'; +// } else { +// $language = 'ios'; +// } + $geshi = new GeSHi($text, $language); +// $geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS); $geshi->set_overall_style('color: black;'); // $geshi->set_line_style('color: #999999'); echo $geshi->parse_code(); From 0e8ea8b6b2ad37c72a25dbae0c802f053d182dfe Mon Sep 17 00:00:00 2001 From: Tony Murray Date: Wed, 10 Feb 2016 17:16:59 -0600 Subject: [PATCH 02/10] Mark displayed diffs. --- html/pages/device/showconfig.inc.php | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/html/pages/device/showconfig.inc.php b/html/pages/device/showconfig.inc.php index 2455aee6b1..2f7f3edb4d 100644 --- a/html/pages/device/showconfig.inc.php +++ b/html/pages/device/showconfig.inc.php @@ -136,6 +136,7 @@ if (is_admin()) { if ($version > 0) { // if we know the version doesn't exist, don't even try to fetch it $previous_text = file_get_contents($config['oxidized']['url'].'/node/version/view?node='.$device['hostname'].'&group='.(!empty($node_info['group']) ? $node_info['group'] : '').'&oid='.$oid.'&date='.urlencode($date).'&num='.$version.'&format=text'); if (!empty($previous_text)) { + $previous_version = array('oid'=>$oid, 'date'=>$date, 'version'=>$version); $text = xdiff_string_diff($text, $previous_text); // requires pecl xdiff } } else { @@ -182,10 +183,18 @@ if (is_admin()) { foreach ($config_versions as $version) { echo ''; $i--; @@ -219,11 +228,11 @@ if (is_admin()) { }//end if if (!empty($text)) { -// if (!empty($previous_text)) { + if (is_array($previous_version)) { $language = 'diff'; -// } else { -// $language = 'ios'; -// } + } else { + $language = 'ios'; + } $geshi = new GeSHi($text, $language); // $geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS); $geshi->set_overall_style('color: black;'); From 9a2d22df0af49337a6ff84f99139e6af80d03153 Mon Sep 17 00:00:00 2001 From: Tony Murray Date: Wed, 10 Feb 2016 19:22:36 -0600 Subject: [PATCH 03/10] Remove array_column() use, it requires php 5.5 --- html/pages/device/showconfig.inc.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/html/pages/device/showconfig.inc.php b/html/pages/device/showconfig.inc.php index 2f7f3edb4d..3ee08d6039 100644 --- a/html/pages/device/showconfig.inc.php +++ b/html/pages/device/showconfig.inc.php @@ -127,10 +127,15 @@ if (is_admin()) { if (isset($_POST['diff']) && isset($_POST['prevconfig'])) { // diff requested list($oid,$date,$version) = explode('|',mres($_POST['prevconfig'])); if ($current_version['oid'] == $oid) { // the same version is selected, assume the previous revision - $key = array_search($oid, array_column($config_versions, 'oid')) + 1; // >=PHP 5.5.0 - $oid = $config_versions[$key]['oid']; - $date = $config_versions[$key]['date']; - $version = $config_total - $key; + foreach ($config_versions as $key => $version) { + if ($version['oid'] == $current_version['oid']) { + $prev_key = $key + 1; + $oid = $config_versions[$prev_key]['oid']; + $date = $config_versions[$prev_key]['date']; + $version = $config_total - $prev_key; + break; + } + } } if ($version > 0) { // if we know the version doesn't exist, don't even try to fetch it From 3eddfd46bd9dd14812e03ef12c50eaefd6f52bc5 Mon Sep 17 00:00:00 2001 From: Tony Murray Date: Wed, 10 Feb 2016 19:31:31 -0600 Subject: [PATCH 04/10] Import GeSHi diff type. --- html/includes/geshi/geshi/diff.php | 194 +++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 html/includes/geshi/geshi/diff.php diff --git a/html/includes/geshi/geshi/diff.php b/html/includes/geshi/geshi/diff.php new file mode 100644 index 0000000000..e4bfc6f470 --- /dev/null +++ b/html/includes/geshi/geshi/diff.php @@ -0,0 +1,194 @@ + 'Diff', + 'COMMENT_SINGLE' => array(), + 'COMMENT_MULTI' => array(), + 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE, + 'QUOTEMARKS' => array(), + 'ESCAPE_CHAR' => ' ', + 'KEYWORDS' => array( + 1 => array( + '\ No newline at end of file' + ), +// 2 => array( +// '***************' /* This only seems to works in some cases? */ +// ), + ), + 'SYMBOLS' => array( + ), + 'CASE_SENSITIVE' => array( + 1 => false, +// 2 => false + ), + 'STYLES' => array( + 'KEYWORDS' => array( + 1 => 'color: #aaaaaa; font-style: italic;', +// 2 => 'color: #dd6611;', + ), + 'COMMENTS' => array( + ), + 'ESCAPE_CHAR' => array( + 0 => '' + ), + 'BRACKETS' => array( + 0 => '' + ), + 'STRINGS' => array( + 0 => '' + ), + 'NUMBERS' => array( + 0 => '' + ), + 'METHODS' => array( + 0 => '' + ), + 'SYMBOLS' => array( + 0 => '' + ), + 'SCRIPT' => array( + 0 => '' + ), + 'REGEXPS' => array( + 0 => 'color: #440088;', + 1 => 'color: #991111;', + 2 => 'color: #00b000;', + 3 => 'color: #888822;', + 4 => 'color: #888822;', + 5 => 'color: #0011dd;', + 6 => 'color: #440088;', + 7 => 'color: #991111;', + 8 => 'color: #00b000;', + 9 => 'color: #888822;', + ), + ), + 'URLS' => array( + 1 => '', +// 2 => '' + ), + 'OOLANG' => false, + 'OBJECT_SPLITTERS' => array(), + 'REGEXPS' => array( + 0 => "[0-9,]+[acd][0-9,]+", + //Removed lines + 1 => array( + GESHI_SEARCH => '(^|(?<=\A\s))\\<.*$', + GESHI_REPLACE => '\\0', + GESHI_MODIFIERS => 'm', + GESHI_BEFORE => '', + GESHI_AFTER => '' + ), + //Inserted lines + 2 => array( + GESHI_SEARCH => '(^|(?<=\A\s))\\>.*$', + GESHI_REPLACE => '\\0', + GESHI_MODIFIERS => 'm', + GESHI_BEFORE => '', + GESHI_AFTER => '' + ), + //Location line + 3 => array( + GESHI_SEARCH => '(^|(?<=\A\s))-{3}\\s.*$', + GESHI_REPLACE => '\\0', + GESHI_MODIFIERS => 'm', + GESHI_BEFORE => '', + GESHI_AFTER => '' + ), + //Inserted line + 4 => array( + GESHI_SEARCH => '(^|(?<=\A\s))(\\+){3}\\s.*$', + GESHI_REPLACE => '\\0', + GESHI_MODIFIERS => 'm', + GESHI_BEFORE => '', + GESHI_AFTER => '' + ), + //Modified line + 5 => array( + GESHI_SEARCH => '(^|(?<=\A\s))\\!.*$', + GESHI_REPLACE => '\\0', + GESHI_MODIFIERS => 'm', + GESHI_BEFORE => '', + GESHI_AFTER => '' + ), + //File specification + 6 => array( + GESHI_SEARCH => '(^|(?<=\A\s))[\\@]{2}.*$', + GESHI_REPLACE => '\\0', + GESHI_MODIFIERS => 'm', + GESHI_BEFORE => '', + GESHI_AFTER => '' + ), + //Removed line + 7 => array( + GESHI_SEARCH => '(^|(?<=\A\s))\\-.*$', + GESHI_REPLACE => '\\0', + GESHI_MODIFIERS => 'm', + GESHI_BEFORE => '', + GESHI_AFTER => '' + ), + //Inserted line + 8 => array( + GESHI_SEARCH => '(^|(?<=\A\s))\\+.*$', + GESHI_REPLACE => '\\0', + GESHI_MODIFIERS => 'm', + GESHI_BEFORE => '', + GESHI_AFTER => '' + ), + //File specification + 9 => array( + GESHI_SEARCH => '(^|(?<=\A\s))(\\*){3}\\s.*$', + GESHI_REPLACE => '\\0', + GESHI_MODIFIERS => 'm', + GESHI_BEFORE => '', + GESHI_AFTER => '' + ), + ), + 'STRICT_MODE_APPLIES' => GESHI_NEVER, + 'SCRIPT_DELIMITERS' => array( + ), + 'HIGHLIGHT_STRICT_BLOCK' => array( + ) +); From aa9d4798dca58b48e066c0129eb9db517384e400 Mon Sep 17 00:00:00 2001 From: Tony Murray Date: Fri, 12 Feb 2016 10:23:49 -0600 Subject: [PATCH 05/10] Remove $config['oxidized']['features']['versioning']. I did not update the schema to remove the entry from the config table. Update the documentation a bit. Issue #2812 --- doc/Extensions/Oxidized.md | 14 +++++--------- html/pages/device/showconfig.inc.php | 5 ++--- html/pages/settings/external.inc.php | 4 ---- 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/doc/Extensions/Oxidized.md b/doc/Extensions/Oxidized.md index e74bf5c3cd..3d2bc3ade0 100644 --- a/doc/Extensions/Oxidized.md +++ b/doc/Extensions/Oxidized.md @@ -12,14 +12,10 @@ $config['oxidized']['enabled'] = TRUE; $config['oxidized']['url'] = 'http://127.0.0.1:8888'; ``` -We also support config versioning within Oxidized, this will allow you to see the old configs stored. - -```php -$config['oxidized']['features']['versioning'] = true; -``` +LibreNMS supports config versioning if Oxidized does. This is known to work with the git output module. Oxidized supports various ways to utilise credentials to login to devices, you can specify global username/password within Oxidized, Group level username/password or per device. -We currently support sending groups back to Oxidized so that you can then define group credentials within Oxidized. To enable this support please switch on 'Enable the return of groups to Oxidized': +LibreNMS currently supports sending groups back to Oxidized so that you can then define group credentials within Oxidized. To enable this support please switch on 'Enable the return of groups to Oxidized': ```php $config['oxidized']['group_support'] = true; @@ -35,7 +31,7 @@ $config['oxidized']['default_group'] = 'default'; Oxidized has support for feeding devices into it via an API call, support for Oxidized has been added to the LibreNMS API. A sample config for Oxidized is provided below. -You will need to configure default credentials for your devices, LibreNMS doesn't provide login credentials at this time. +You will need to configure default credentials for your devices in the Oxidized config, LibreNMS doesn't provide login credentials at this time. ```bash source: @@ -61,7 +57,7 @@ $config['oxidized']['reload_nodes'] = TRUE; ``` -### Using Groups +#### Using Groups To return a group to Oxidized you can do this by matching a regex for either hostname or location. The order is hostname is matched first, if nothing is found then location is attempted. The first match found will be used. To match on the device hostnames that contain 'lon-sw' or if the location contains 'London' then you would place the following within config.php: @@ -80,7 +76,7 @@ groups: password: ``` -### Miscellaneous +#### Miscellaneous If you have devices which you do not wish to appear in Oxidized then you can edit those devices in Device -> Edit -> Misc and enable "Exclude from Oxidized?" diff --git a/html/pages/device/showconfig.inc.php b/html/pages/device/showconfig.inc.php index 3ee08d6039..2efa9cfeed 100644 --- a/html/pages/device/showconfig.inc.php +++ b/html/pages/device/showconfig.inc.php @@ -103,11 +103,10 @@ if (is_admin()) { } } else if ($config['oxidized']['enabled'] === true && isset($config['oxidized']['url'])) { + // fetch info about the node and then a list of versions for that node $node_info = json_decode(file_get_contents($config['oxidized']['url'].'/node/show/'.$device['hostname'].'?format=json'), true); + $config_versions = json_decode(file_get_contents($config['oxidized']['url'].'/node/version?node_full='.(!empty($node_info['group']) ? $node_info['group'].'/' : '').$device['hostname'].'&format=json'), true); - if ($config['oxidized']['features']['versioning'] === true) { // fetch a list of versions - $config_versions = json_decode(file_get_contents($config['oxidized']['url'].'/node/version?node_full='.(!empty($node_info['group']) ? $node_info['group'].'/' : '').$device['hostname'].'&format=json'), true); - } if (is_array($config_versions)) { $config_total = count($config_versions); } diff --git a/html/pages/settings/external.inc.php b/html/pages/settings/external.inc.php index fe89d4645e..0705a146e8 100644 --- a/html/pages/settings/external.inc.php +++ b/html/pages/settings/external.inc.php @@ -13,10 +13,6 @@ $oxidized_conf = array( 'descr' => 'URL to your Oxidized API', 'type' => 'text', ), - array('name' => 'oxidized.features.versioning', - 'descr' => 'Enable config versioning access', - 'type' => 'checkbox', - ), array('name' => 'oxidized.group_support', 'descr' => 'Enable the return of groups to Oxidized', 'type' => 'checkbox', From cc344bf3c35c99c52c3d511c0aaa21a1cf4b2bae Mon Sep 17 00:00:00 2001 From: Tony Murray Date: Fri, 12 Feb 2016 14:21:55 -0600 Subject: [PATCH 06/10] Use Oxidized's built in diffing capability. Drops the need for xdiff and one http call. --- html/pages/device/showconfig.inc.php | 63 ++++++++++++++++------------ 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/html/pages/device/showconfig.inc.php b/html/pages/device/showconfig.inc.php index dd8af7cc2e..c79c4aacbe 100644 --- a/html/pages/device/showconfig.inc.php +++ b/html/pages/device/showconfig.inc.php @@ -105,51 +105,60 @@ if (is_admin()) { else if ($config['oxidized']['enabled'] === true && isset($config['oxidized']['url'])) { // fetch info about the node and then a list of versions for that node $node_info = json_decode(file_get_contents($config['oxidized']['url'].'/node/show/'.$device['hostname'].'?format=json'), true); - $config_versions = json_decode(file_get_contents($config['oxidized']['url'].'/node/version?node_full='.(!empty($node_info['group']) ? $node_info['group'].'/' : '').$device['hostname'].'&format=json'), true); + $config_versions = json_decode(file_get_contents($config['oxidized']['url'].'/node/version?node_full='.(isset($node_info['full_name']) ? $node_info['full_name'] : $device['hostname']).'&format=json'), true); if (is_array($config_versions)) { $config_total = count($config_versions); } if ($config_total > 1) { - if (isset($_POST['config'])) { // versioning with selected version + // populate current_version + if (isset($_POST['config'])) { list($oid,$date,$version) = explode('|',mres($_POST['config'])); - $current_version = array('oid'=>$oid, 'date'=>$date, 'version'=>$version); + $current_config = array('oid'=>$oid, 'date'=>$date, 'version'=>$version); } else { // no version selected - $current_version = array('oid'=>$config_versions[0]['oid'], 'date'=>$current_version[0]['date'], 'version'=>$config_total); + $current_config = array('oid'=>$config_versions[0]['oid'], 'date'=>$current_config[0]['date'], 'version'=>$config_total); } - // fetch current_version - $text = file_get_contents($config['oxidized']['url'].'/node/version/view?node='.$device['hostname'].'&group='.(!empty($node_info['group']) ? $node_info['group'] : '').'&oid='.$current_version['oid'].'&date='.urlencode($current_version['date']).'&num='.$current_version['version'].'&format=text'); - - if (isset($_POST['diff']) && isset($_POST['prevconfig'])) { // diff requested + // populate previous_version + if (isset($_POST['diff'])) { // diff requested list($oid,$date,$version) = explode('|',mres($_POST['prevconfig'])); - if ($current_version['oid'] == $oid) { // the same version is selected, assume the previous revision + if (isset($oid) && $oid != $current_config['oid']) { + $previous_config = array('oid'=>$oid, 'date'=>$date, 'version'=>$version); + } + else if ($current_config['version'] != 1) { // assume previous, unless current is first config foreach ($config_versions as $key => $version) { - if ($version['oid'] == $current_version['oid']) { + if ($version['oid'] == $current_config['oid']) { $prev_key = $key + 1; - $oid = $config_versions[$prev_key]['oid']; - $date = $config_versions[$prev_key]['date']; - $version = $config_total - $prev_key; + $previous_config['oid'] = $config_versions[$prev_key]['oid']; + $previous_config['date'] = $config_versions[$prev_key]['date']; + $previous_config['version'] = $config_total - $prev_key; break; } } } - - if ($version > 0) { // if we know the version doesn't exist, don't even try to fetch it - $previous_text = file_get_contents($config['oxidized']['url'].'/node/version/view?node='.$device['hostname'].'&group='.(!empty($node_info['group']) ? $node_info['group'] : '').'&oid='.$oid.'&date='.urlencode($date).'&num='.$version.'&format=text'); - if (!empty($previous_text)) { - $previous_version = array('oid'=>$oid, 'date'=>$date, 'version'=>$version); - $text = xdiff_string_diff($text, $previous_text); // requires pecl xdiff - } - } else { + else { print_error('No previous version, please select a different version.'); } } + + if (isset($previous_config)) { + $url = $config['oxidized']['url'].'/node/version/diffs?node='.$device['hostname'].'&group='; + if (!empty($node_info['group'])) { + $url .= $node_info['group']; + } + $url .= '&oid='.$previous_config['oid'].'&date='.urlencode($previous_config['date']).'&num='.$previous_config['version'].'&oid2='.$current_config['oid'].'&format=text'; + + $text = file_get_contents($url); // fetch diff + } else { + // fetch current_version + $text = file_get_contents($config['oxidized']['url'].'/node/version/view?node='.$device['hostname'].'&group='.(!empty($node_info['group']) ? $node_info['group'] : '').'&oid='.$current_config['oid'].'&date='.urlencode($current_config['date']).'&num='.$current_config['version'].'&format=text'); + } } else { // just fetch the only version $text = file_get_contents($config['oxidized']['url'].'/node/fetch/'.(!empty($node_info['group']) ? $node_info['group'].'/' : '').$device['hostname']); + } if (is_array($node_info) || $config_total > 1) { @@ -186,15 +195,15 @@ if (is_admin()) { $i = $config_total; foreach ($config_versions as $version) { echo '