From 3a02a1bce4190ce0d94883709e0a6c362bcb0af3 Mon Sep 17 00:00:00 2001 From: Jonathan Prykop Date: Wed, 9 Dec 2015 23:39:52 -0600 Subject: [PATCH] RT#39115: View SNMP info on svc_broadband service --- FS/FS/part_export/broadband_snmp_get.pm | 113 +++++++++++++++++++++ .../edit/elements/part_export/broadband_snmp.html | 8 +- .../elements/part_export/broadband_snmp_get.html | 77 ++++++++++++++ httemplate/elements/broadband_snmp_get-dialog.html | 68 +++++++++++++ .../{elements => misc}/select-mib-popup.html | 0 httemplate/misc/xmlhttp-broadband_snmp_get.cgi | 35 +++++++ httemplate/view/svc_broadband.cgi | 1 + 7 files changed, 299 insertions(+), 3 deletions(-) create mode 100644 FS/FS/part_export/broadband_snmp_get.pm create mode 100644 httemplate/edit/elements/part_export/broadband_snmp_get.html create mode 100644 httemplate/elements/broadband_snmp_get-dialog.html rename httemplate/{elements => misc}/select-mib-popup.html (100%) create mode 100644 httemplate/misc/xmlhttp-broadband_snmp_get.cgi diff --git a/FS/FS/part_export/broadband_snmp_get.pm b/FS/FS/part_export/broadband_snmp_get.pm new file mode 100644 index 000000000..faa51ed06 --- /dev/null +++ b/FS/FS/part_export/broadband_snmp_get.pm @@ -0,0 +1,113 @@ +package FS::part_export::broadband_snmp_get; + +use strict; +use vars qw(%info $DEBUG); +use base 'FS::part_export'; +use SNMP; +use Tie::IxHash; + +tie my %snmp_version, 'Tie::IxHash', + v1 => '1', + v2c => '2c' + # v3 unimplemented +; + +tie my %options, 'Tie::IxHash', + 'snmp_version' => { + label=>'SNMP version', + type => 'select', + options => [ keys %snmp_version ], + }, + 'snmp_community' => { 'label'=>'Community', 'default'=>'public' }, + 'snmp_timeout' => { label=>'Timeout (seconds)', 'default'=>1 }, + 'snmp_oid' => { label=>'Object ID', multiple=>1 }, +; + +%info = ( + 'svc' => 'svc_broadband', + 'desc' => 'Enable interface display of realtime SNMP get requests to service IP address', + 'config_element' => '/edit/elements/part_export/broadband_snmp_get.html', + 'options' => \%options, + 'no_machine' => 1, + 'notes' => <<'END', +Use this export to configure the community and object ids for displaying realtime +SNMP data from the service IP address when viewing a provisioned service. Timeout is +per object, and should be small enough for realtime use. This export takes no action +during provisioning itself; it is expected that snmp will be separately +configured on the service machine. +END +); + +sub export_insert { ''; } +sub export_replace { ''; } +sub export_delete { ''; } +sub export_suspend { ''; } +sub export_unsuspend { ''; } + +=pod + +=head1 NAME + +FS::part_export::broadband_snmp_get + +=head1 SYNOPSIS + +Configuration for realtime snmp requests to svc_broadband IP address + +=head1 METHODS + +=cut + +=over 4 + +=item snmp_results SVC + +Request statistics from SVC ip address. Returns an array of hashes with keys + +objectID + +label + +value + +error - error when attempting to load this object + +=cut + +sub snmp_results { + my ($self, $svc) = @_; + my $host = $svc->ip_addr; + my $comm = $self->option('snmp_community'); + my $vers = $self->option('snmp_version'); + my $time = ($self->option('snmp_timeout') || 1) * 1000; + my @oids = split("\n", $self->option('snmp_oid')); + my %connect = ( + 'DestHost' => $host, + 'Community' => $comm, + 'Version' => $vers, + 'Timeout' => $time, + ); + my $snmp = new SNMP::Session(%connect); + return { 'error' => 'Error creating SNMP session' } unless $snmp; + return { 'error' => $snmp->{'ErrorStr'} } if $snmp->{'ErrorStr'}; + my @out; + foreach my $oid (@oids) { + $oid = $SNMP::MIB{$oid}->{'objectID'} if $SNMP::MIB{$oid}; + my $value = $snmp->get($oid.'.0'); + if ($snmp->{'ErrorStr'}) { + push @out, { 'error' => $snmp->{'ErrorStr'} }; + next; + } + my %result = map { $_ => $SNMP::MIB{$oid}{$_} } qw( objectID label value ); + $result{'value'} = $value; + push @out, \%result; + } + return @out; +} + +=back + +=cut + +1; + diff --git a/httemplate/edit/elements/part_export/broadband_snmp.html b/httemplate/edit/elements/part_export/broadband_snmp.html index ebb765dee..b4d57edd5 100644 --- a/httemplate/edit/elements/part_export/broadband_snmp.html +++ b/httemplate/edit/elements/part_export/broadband_snmp.html @@ -11,7 +11,7 @@ <& /elements/tr-input-text.html, label => 'Community', field => 'community', - curr_value => $part_export->option('community'), + curr_value => $part_export->option('community') || $opt{'export_info'}->{'options'}->{'community'}->{'default'}, &> <& /elements/tr-checkbox.html, label => 'Send IP address changes to new address', @@ -30,7 +30,7 @@ function open_select_mib(obj) { nd(1); // if there's already one open, close it var rownum = obj.rownum; var curr_oid = obj.form.elements['oid' + rownum].value || ''; - var url = '<%$fsurl%>/elements/select-mib-popup.html?' + + var url = '<%$fsurl%>misc/select-mib-popup.html?' + 'callback=receive_mib;' + 'arg=' + rownum + ';curr_value=' + curr_oid; @@ -45,8 +45,10 @@ function open_select_mib(obj) { function receive_mib(obj, rownum) { //console.log(JSON.stringify(obj)); // we don't really need the numeric OID or any of the other properties - document.getElementById('oid'+rownum).value = obj.fullname; + var oidfield = document.getElementById('oid'+rownum); + oidfield.value = obj.fullname; document.getElementById('datatype'+rownum).value = obj.type; + oidfield.onchange(); //should be same as datatype, only need to run one } diff --git a/httemplate/edit/elements/part_export/broadband_snmp_get.html b/httemplate/edit/elements/part_export/broadband_snmp_get.html new file mode 100644 index 000000000..8b8717c29 --- /dev/null +++ b/httemplate/edit/elements/part_export/broadband_snmp_get.html @@ -0,0 +1,77 @@ +<%doc> +Quite a bit of false laziness with edit/elements/part_export/broadband_snmp.html + +<& head.html, %opt &> + +<& /elements/tr-select.html, + label => 'SNMP version', + field => 'snmp_version', + options => [ '1', '2c' ], + curr_value => $part_export->option('version') +&> +<& /elements/tr-input-text.html, + label => 'Community', + field => 'snmp_community', + curr_value => $part_export->option('community') || $opt{'export_info'}->{'options'}->{'snmp_community'}->{'default'}, +&> +<& /elements/tr-input-text.html, + label => 'Timeout (seconds)', + field => 'snmp_timeout', + curr_value => $part_export->option('timeout') || $opt{'export_info'}->{'options'}->{'snmp_timeout'}->{'default'}, +&> + + + + + + + + +<& /elements/auto-table.html, + template_row => 'broadband_snmp_get_template', + fieldorder => ['oid'], + data => \@data, + table => 'snmp', +&> + +<& foot.html, %opt &> +<%init> +my %opt = @_; + +my $part_export = $opt{part_export} || FS::part_export->new; + +my @oids = split("\n", $part_export->option('snmp_oid')); + +my @data; +while (@oids) { + my @thisrow = (shift(@oids)); + push @data, \@thisrow if grep length($_), @thisrow; +} + +my $popup_name = 'popup-'.time."-$$-".rand() * 2**32; + diff --git a/httemplate/elements/broadband_snmp_get-dialog.html b/httemplate/elements/broadband_snmp_get-dialog.html new file mode 100644 index 000000000..61bb9c763 --- /dev/null +++ b/httemplate/elements/broadband_snmp_get-dialog.html @@ -0,0 +1,68 @@ +<%doc> +Adds a link to display snmp statistics based on broadband_snmp_get export config. +Performs necessary checks such that, if no such exports are configured for the passed +service, returns blank space (ie may be safely invoked even if no exports are configured.) + + <& '/elements/broadband_snmp_get-dialog.html', svc => $svc &> + + +% if (@snmp) { +<& '/elements/xmlhttp.html', + 'url' => $fsurl.'misc/xmlhttp-broadband_snmp_get.cgi', + 'subs' => [ 'broadband_snmp_get_request' ] + &> + + + +(snmp) + + +% } #if @snmp +<%init> +my(%opt) = @_; +my @snmp = $opt{'svc'}->cust_svc->part_svc->part_export('broadband_snmp_get'); +my $svcnum = $opt{'svc'}->svcnum; + diff --git a/httemplate/elements/select-mib-popup.html b/httemplate/misc/select-mib-popup.html similarity index 100% rename from httemplate/elements/select-mib-popup.html rename to httemplate/misc/select-mib-popup.html diff --git a/httemplate/misc/xmlhttp-broadband_snmp_get.cgi b/httemplate/misc/xmlhttp-broadband_snmp_get.cgi new file mode 100644 index 000000000..a6f926722 --- /dev/null +++ b/httemplate/misc/xmlhttp-broadband_snmp_get.cgi @@ -0,0 +1,35 @@ +<%doc> +Requires arg $svcnum. Returns JSON-encoded realtime snmp results +for configured broadband_snmp_get exports. + +<% encode_json(\@result) %>\ +<%init> + +# access/agent permissions lifted from /view/elements/svc_Common.html + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('View customer services'); + +my %arg = $cgi->param('arg'); +my $svc = qsearchs({ + 'select' => 'svc_broadband.*', + 'table' => 'svc_broadband', + 'addl_from' => ' LEFT JOIN cust_svc USING ( svcnum ) '. + ' LEFT JOIN cust_pkg USING ( pkgnum ) '. + ' LEFT JOIN cust_main USING ( custnum ) ', + 'hashref' => { 'svcnum' => $arg{'svcnum'} }, + 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql( + 'null_right' => 'View/link unlinked services' + ), +}) or die "Unknown svcnum ".$arg{'svcnum'}." in svc_broadband table\n"; + +my @part_export = $svc->cust_svc->part_svc->part_export('broadband_snmp_get'); + +my @result; +foreach my $part_export (@part_export) { + push @result, $part_export->snmp_results($svc); +} + + + + diff --git a/httemplate/view/svc_broadband.cgi b/httemplate/view/svc_broadband.cgi index 4935a1096..bc272e844 100644 --- a/httemplate/view/svc_broadband.cgi +++ b/httemplate/view/svc_broadband.cgi @@ -72,6 +72,7 @@ sub ip_addr { my $out = $ip_addr; $out .= ' (' . include('/elements/popup_link-ping.html', ip => $ip_addr) . ')' if $ip_addr; + $out .= include('/elements/broadband_snmp_get-dialog.html', svc => $svc); if ($svc->cust_svc->part_svc->part_export('cacti')) { $out .= ' (
Object ID
+ + +