[freeside-commits] branch FREESIDE_3_BRANCH updated. 1feb4dcca56c44429f7b1ea74a0431ca51185082

Jonathan Prykop jonathan at 420.am
Mon May 11 16:47:27 PDT 2015


The branch, FREESIDE_3_BRANCH has been updated
       via  1feb4dcca56c44429f7b1ea74a0431ca51185082 (commit)
       via  0de4c160e679f3fe794a3f90517277ed14f17a2e (commit)
      from  46b2abec94e5f4963b61ed99ffd38f25b12110d5 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 1feb4dcca56c44429f7b1ea74a0431ca51185082
Author: Jonathan Prykop <jonathan at freeside.biz>
Date:   Mon May 11 18:44:25 2015 -0500

    RT#18834: Cacti integration [FS3 only, removed foreign keys]

diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index 794f566..5dcf3c3 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -4820,16 +4820,6 @@ sub tables_hashref {
       'primary_key' => 'cacti_pagenum',
       'unique'  => [ ],
       'index'   => [ ['svcnum'], ['imported'] ],
-      'foreign_keys' => [
-                          { columns    => [ 'svcnum' ],
-                            table      => 'cust_svc',
-                            references => [ 'svcnum' ],
-                          },
-                          { columns    => [ 'exportnum' ],
-                            table      => 'part_export',
-                            references => [ 'exportnum' ],
-                          },
-                        ],
     },
 
     # name type nullability length default local

commit 0de4c160e679f3fe794a3f90517277ed14f17a2e
Author: Jonathan Prykop <jonathan at freeside.biz>
Date:   Thu Apr 30 17:28:36 2015 -0500

    RT#18834: Cacti integration [added graph generation]

diff --git a/FS/FS/part_export/cacti.pm b/FS/FS/part_export/cacti.pm
index 740be25..cbb50af 100644
--- a/FS/FS/part_export/cacti.pm
+++ b/FS/FS/part_export/cacti.pm
@@ -52,16 +52,42 @@ tie my %options, 'Tie::IxHash',
                            default => '5' },
   'max_graph_size'    => { label   => 'Maximum size per graph (MB)',
                            default => '5' },
-#  'delete_graphs'     => { label   => 'Delete associated graphs and data sources when unprovisioning', 
-#                           type    => 'checkbox',
-#                         },
+  'delete_graphs'     => { label   => 'Delete associated graphs and data sources when unprovisioning', 
+                           type    => 'checkbox',
+                         },
+  'cacti_graph_template_id'  => { 
+    'label'    => 'Graph Template',
+    'type'     => 'custom',
+    'multiple' => 1,
+  },
+  'cacti_snmp_query_id'      => { 
+    'label'    => 'SNMP Query ID',
+    'type'     => 'custom',
+    'multiple' => 1,
+  },
+  'cacti_snmp_query_type_id' => { 
+    'label'    => 'SNMP Query Type ID',
+    'type'     => 'custom',
+    'multiple' => 1,
+  },
+  'cacti_snmp_field'         => { 
+    'label'    => 'SNMP Field',
+    'type'     => 'custom',
+    'multiple' => 1,
+  },
+  'cacti_snmp_value'         => { 
+    'label'    => 'SNMP Value',
+    'type'     => 'custom',
+    'multiple' => 1,
+  },
 ;
 
 %info = (
-  'svc'             => 'svc_broadband',
-  'desc'            => 'Export service to cacti server, for svc_broadband services',
-  'options'         => \%options,
-  'notes'           => <<'END',
+  'svc'                  => 'svc_broadband',
+  'desc'                 => 'Export service to cacti server, for svc_broadband services',
+  'post_config_element'  => '/edit/elements/part_export/cacti.html',
+  'options'              => \%options,
+  'notes'                => <<'END',
 Add service to cacti upon provisioning, for broadband services.<BR>
 See <A HREF="http://www.freeside.biz/mediawiki/index.php/Freeside:4:Documentation:Cacti#Connecting_Cacti_To_Freeside">documentation</A> for details.
 END
@@ -77,8 +103,23 @@ sub _export_insert {
 
 sub _export_delete {
   my ($self, $svc_broadband) = @_;
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+  my $dbh = dbh;
+  foreach my $page (qsearch('cacti_page',{ svcnum => $svc_broadband->svcnum })) {
+    my $error = $page->delete;
+    if ($error) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
   my ($q,$error) = _delete_queue($self, $svc_broadband);
-  return $error;
+  if ($error) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error;
+  }
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+  return '';
 }
 
 sub _export_replace {
@@ -135,6 +176,7 @@ sub _insert_queue {
 	'svc_desc'    => $svc_broadband->description,
     'contact'     => $svc_broadband->cust_main->contact,
     'svcnum'      => $svc_broadband->svcnum,
+    'self'        => $self
   );
   return ($queue,$error);
 }
@@ -150,7 +192,7 @@ sub _delete_queue {
     'user'          => $self->option('user'),
     'hostname'      => $svc_broadband->ip_addr,
     'script_path'   => $self->option('script_path'),
-#    'delete_graphs' => $self->option('delete_graphs'),
+    'delete_graphs' => $self->option('delete_graphs'),
   );
   return ($queue,$error);
 }
@@ -159,6 +201,7 @@ sub _delete_queue {
 
 sub ssh_insert {
   my %opt = @_;
+  my $self = $opt{'self'};
 
   # Option validation
   die "Non-numerical Host Template ID, check export configuration\n"
@@ -171,7 +214,10 @@ sub ssh_insert {
   $desc =~ s/\$ip_addr/$opt{'hostname'}/g;
   $desc =~ s/\$description/$opt{'svc_desc'}/g;
   $desc =~ s/\$contact/$opt{'contact'}/g;
-  $desc =~ s/'/'\\''/g;
+#for some reason, device names with apostrophes fail to export graphs in Cacti
+#just removing them for now, someday maybe dig to figure out why
+#  $desc =~ s/'/'\\''/g;
+  $desc =~ s/'//g;
   my $cmd = $php
           . $opt{'script_path'} 
           . q(add_device.php --description=')
@@ -196,51 +242,94 @@ sub ssh_insert {
          . $id;
     $response = ssh_cmd(%opt, 'command' => $cmd);
     unless ( $response =~ /Added Node node-id: \((\d+)\)/ ) {
-      die "Error adding host to tree: $response";
+      die "Host added, but error adding host to tree: $response";
     }
   }
 
-#  # Get list of graph templates for new id
-#  $cmd = $php
-#       . $opt{'script_path'} 
-#       . q(freeside_cacti.php --get-graph-templates --host-template=)
-#       . $opt{'template_id'};
-#  my @gtids = split(/\n/,ssh_cmd(%opt, 'command' => $cmd));
-#  die "No graphs configured for host template"
-#    unless @gtids;
-#
-#  # Create graphs
-#  foreach my $gtid (@gtids) {
-#
-#    # sanity checks, should never happen
-#    next unless $gtid;
-#    die "Bad graph template: $gtid"
-#      unless $gtid =~ /^\d+$/;
-#
-#    # create the graph
-#    $cmd = $php
-#         . $opt{'script_path'}
-#         . q(add_graphs.php --graph-type=cg --graph-template-id=)
-#         . $gtid
-#         . q( --host-id=)
-#         . $id;
-#    $response = ssh_cmd(%opt, 'command' => $cmd);
-#    die "Error creating graph $gtid: $response"
-#      unless $response =~ /Graph Added - graph-id: \((\d+)\)/;
-#    my $gid = $1;
-#
-#    # add the graph to the tree
-#    $cmd = $php
-#         . $opt{'script_path'}
-#         . q(add_tree.php --type=node --node-type=graph --tree-id=)
-#         . $opt{'tree_id'}
-#         . q( --graph-id=)
-#         . $gid;
-#    $response = ssh_cmd(%opt, 'command' => $cmd);
-#    die "Error adding graph $gid to tree: $response"
-#      unless $response =~ /Added Node/;
-#
-#  } #foreach $gtid
+  # Get list of graph templates for new id
+  $cmd = $php
+       . $opt{'script_path'} 
+       . q(freeside_cacti.php --get-graph-templates --host-template=)
+       . $opt{'template_id'};
+  my $ginfo = { map { $_ ? ($_ => undef) : () } split(/\n/,ssh_cmd(%opt, 'command' => $cmd)) };
+
+  # Add extra config info
+  my @xtragid = split("\n", $self->option('cacti_graph_template_id'));
+  my @query_id = split("\n", $self->option('cacti_snmp_query_id'));
+  my @query_type_id = split("\n", $self->option('cacti_snmp_query_type_id'));
+  my @snmp_field = split("\n", $self->option('cacti_snmp_field'));
+  my @snmp_value = split("\n", $self->option('cacti_snmp_value'));
+  for (my $i = 0; $i < @xtragid; $i++) {
+    my $gtid = $xtragid[$i];
+    $ginfo->{$gtid} ||= [];
+    push(@{$ginfo->{$gtid}},{
+      'gtid'          => $gtid,
+      'query_id'      => $query_id[$i],
+      'query_type_id' => $query_type_id[$i],
+      'snmp_field'    => $snmp_field[$i],
+      'snmp_value'    => $snmp_value[$i],
+    });
+  }
+
+  my @gdefs = map {
+    ref($ginfo->{$_}) ? @{$ginfo->{$_}} : {'gtid' => $_}
+  } keys %$ginfo;
+  warn "Host ".$opt{'hostname'}." exported to cacti, but no graphs configured"
+    unless @gdefs;
+
+  # Create graphs
+  my $gerror = '';
+  foreach my $gdef (@gdefs) {
+    # validate graph info
+    my $gtid = $gdef->{'gtid'};
+    next unless $gtid;
+    $gerror .= " Bad graph template: $gtid"
+      unless $gtid =~ /^\d+$/;
+    my $isds = $gdef->{'query_id'} 
+            || $gdef->{'query_type_id'} 
+            || $gdef->{'snmp_field'} 
+            || $gdef->{'snmp_value'};
+    if ($isds) {
+      $gerror .= " Bad SNMP Query Id: " . $gdef->{'query_id'}
+        unless $gdef->{'query_id'} =~ /^\d+$/;
+      $gerror .= " Bad SNMP Query Type Id: " . $gdef->{'query_type_id'}
+        unless $gdef->{'query_type_id'} =~ /^\d+$/;
+      $gerror .= " SNMP Field cannot contain apostrophe"
+        if $gdef->{'snmp_field'} =~ /'/;
+      $gerror .= " SNMP Value cannot contain apostrophe"
+        if $gdef->{'snmp_value'} =~ /'/;
+    }
+    next if $gerror;
+
+    # create the graph
+    $cmd = $php
+         . $opt{'script_path'}
+         . q(add_graphs.php --graph-type=)
+         . ($isds ? 'ds' : 'cg')
+         . q( --graph-template-id=)
+         . $gtid
+         . q( --host-id=)
+         . $id;
+    if ($isds) {
+      $cmd .= q( --snmp-query-id=)
+           .  $gdef->{'query_id'}
+           .  q( --snmp-query-type-id=)
+           .  $gdef->{'query_type_id'}
+           .  q( --snmp-field=')
+           .  $gdef->{'snmp_field'}
+           .  q(' --snmp-value=')
+           .  $gdef->{'snmp_value'}
+           .  q(');
+    }
+    $response = ssh_cmd(%opt, 'command' => $cmd);
+    #might be more than one graph added, just testing success
+    $gerror .= "Error creating graph $gtid: $response"
+      unless $response =~ /Graph Added - graph-id: \((\d+)\)/;
+
+  } #foreach $gtid
+
+  # job fails, but partial export may have occurred
+  die $gerror . " Partial export occurred\n" if $gerror;
 
   return '';
 }
@@ -252,8 +341,8 @@ sub ssh_delete {
           . q(freeside_cacti.php --drop-device --ip=')
           . $opt{'hostname'}
           . q(');
-#  $cmd .= q( --delete-graphs)
-#    if $opt{'delete_graphs'};
+  $cmd .= q( --delete-graphs)
+    if $opt{'delete_graphs'};
   my $response = ssh_cmd(%opt, 'command' => $cmd);
   die "Error removing from cacti: " . $response
     if $response;
@@ -371,42 +460,43 @@ sub process_graphs {
   for (my $i = 0; $i <= $#graphs; $i++) {
     my $graph = $graphs[$i];
     my $thumbfile = $cachedir . 'graphs/thumb_' . $$graph[0] . '.png';
-    if (
-      (-e $thumbfile) && 
-      ( stat($thumbfile)->size() < $maxgraph )
-    ) {
-      $nographs = 0;
-      # add graph to main file
-      my $graphhead = q(<H3>) . $$graph[1] . q(</H3>);
-      $svchtml .= $graphhead;
-      $svchtml .= anchor_tag( $svcnum, $$graph[0], img_tag($thumbfile) );
-      # create graph details file
-      my $graphhtml = $svchead . $graphhead;
-      my $nodetail = 1;
-      my $j = 1;
-      while (-e (my $graphfile = $cachedir.'graphs/graph_'.$$graph[0].'_'.$j.'.png')) {
-        if ( stat($graphfile)->size() < $maxgraph ) {
-          $nodetail = 0;
-          $graphhtml .= img_tag($graphfile);
+    if (-e $thumbfile) {
+      if ( stat($thumbfile)->size() < $maxgraph ) {
+        $nographs = 0;
+        # add graph to main file
+        my $graphhead = q(<H3>) . $$graph[1] . q(</H3>);
+        $svchtml .= $graphhead;
+        $svchtml .= anchor_tag( $svcnum, $$graph[0], img_tag($thumbfile) );
+        # create graph details file
+        my $graphhtml = $svchead . $graphhead;
+        my $nodetail = 1;
+        my $j = 1;
+        while (-e (my $graphfile = $cachedir.'graphs/graph_'.$$graph[0].'_'.$j.'.png')) {
+          if ( stat($graphfile)->size() < $maxgraph ) {
+            $nodetail = 0;
+            $graphhtml .= img_tag($graphfile);
+          }
+          unlink($graphfile);
+          $j++;
+        }
+        $graphhtml .= '<P>No detail graphs to display for this graph</P>'
+          if $nodetail;
+        my $newobj = new FS::cacti_page {
+          'exportnum' => $self->exportnum,
+          'svcnum'    => $svcnum,
+          'graphnum'  => $$graph[0],
+          'imported'  => $now,
+          'content'   => $graphhtml,
+        };
+        $error = $newobj->insert;
+        if ($error) {
+          $dbh->rollback if $oldAutoCommit;
+          die $error;
         }
-        $j++;
-      }
-      $graphhtml .= '<P>No detail graphs to display for this graph</P>'
-        if $nodetail;
-      my $newobj = new FS::cacti_page {
-        'exportnum' => $self->exportnum,
-        'svcnum'    => $svcnum,
-        'graphnum'  => $$graph[0],
-        'imported'  => $now,
-        'content'   => $graphhtml,
-      };
-      $error = $newobj->insert;
-      if ($error) {
-        $dbh->rollback if $oldAutoCommit;
-        die $error;
       }
+      unlink($thumbfile);
     }
-    $job->update_statustext(49 + int($i / $#graphs) * 50);
+    $job->update_statustext(49 + int($i / @graphs) * 50);
   }
   $svchtml .= '<P>No graphs to display for this service</P>'
     if $nographs;
@@ -455,7 +545,7 @@ sub ssh_cmd {
   my $ssh = Net::OpenSSH->new($opt->{'user'}.'@'.$opt->{'host'});
   die "Couldn't establish SSH connection: ". $ssh->error if $ssh->error;
   my ($output, $errput) = $ssh->capture2($opt->{'command'});
-  die "Error running SSH command: ". $ssh->error if $ssh->error;
+  die "Error running SSH command: ". $opt->{'command'}. ' ERROR: ' . $ssh->error if $ssh->error;
   die $errput if $errput;
   return $output;
 }
diff --git a/bin/freeside_cacti.php b/bin/freeside_cacti.php
index 0a9ee9c..9f8e4dd 100755
--- a/bin/freeside_cacti.php
+++ b/bin/freeside_cacti.php
@@ -39,18 +39,15 @@ but keeping commented out code for potential future development.
 include(dirname(__FILE__)."/../site/include/global.php");
 include_once($config["base_path"]."/lib/api_device.php");
 include_once($config["base_path"]."/lib/api_automation_tools.php");
-
-/*
 include_once($config["base_path"]."/lib/api_data_source.php");
 include_once($config["base_path"]."/lib/api_graph.php");
 include_once($config["base_path"]."/lib/functions.php");
-*/
 
 /* process calling arguments */
 $action = '';
 $ip = '';
 $host_template = '';
-// $delete_graphs = FALSE;
+$delete_graphs = FALSE;
 $parms = $_SERVER["argv"];
 array_shift($parms);
 if (sizeof($parms)) {
@@ -67,21 +64,19 @@ if (sizeof($parms)) {
         case "--get-device":
 			$action = 'get-device';
             break;
+*/
         case "--get-graph-templates":
 			$action = 'get-graph-templates';
             break;
-*/
 		case "--ip":
 			$ip = trim($value);
 			break;
 		case "--host-template":
 			$host_template = trim($value);
 			break;
-/*
 		case "--delete-graphs":
 			$delete_graphs = TRUE;
 			break;
-*/
 		case "--version":
 		case "-V":
 		case "-H":
@@ -102,7 +97,6 @@ case "get-graphs":
 	break;
 case "drop-device":
 	$host_id = host_id($ip);
-/*
 	if ($delete_graphs) {
 		// code copied & pasted from version 0.8.8a
         // cacti/site/lib/host.php and cacti/site/graphs.php 
@@ -126,7 +120,6 @@ case "drop-device":
 			}
 		}
 	}
-*/
 	api_device_remove($host_id);
 	if (host_id($ip,1)) {
 		die("Failed to remove hostname $ip");
@@ -136,6 +129,7 @@ case "drop-device":
 case "get-device":
 	echo host_id($ip);
 	exit(0);
+*/
 case "get-graph-templates":
 	if (!$host_template) {
 		die("No host template specified");
@@ -148,7 +142,6 @@ case "get-graph-templates":
 		exit(0);
 	}
 	die("No graph templates associated with this host template");
-*/
 default:
 	die("Specified action not found, contact a developer");
 }
diff --git a/httemplate/browse/part_export.cgi b/httemplate/browse/part_export.cgi
index 1f835d7..af988d3 100755
--- a/httemplate/browse/part_export.cgi
+++ b/httemplate/browse/part_export.cgi
@@ -66,7 +66,7 @@ function part_export_areyousure(href) {
 %           if ( $group ) {
 %             my @values = split("\n", $opt{$optname});
 %             $multiples{$group} ||= [];
-%             push @{ $multiples{$group} }, [ $optname, @values ] if @values;
+%             push @{ $multiples{$group} }, [ $def->{label} || $optname, @values ] if @values;
 %             delete $opt{$optname};
 %           } elsif (length($opt{$optname})) { # the normal case
 %             my $value = $opt{$optname};
diff --git a/httemplate/edit/elements/part_export/cacti.html b/httemplate/edit/elements/part_export/cacti.html
new file mode 100644
index 0000000..9e4a8ec
--- /dev/null
+++ b/httemplate/edit/elements/part_export/cacti.html
@@ -0,0 +1,42 @@
+<table bgcolor="#cccccc" border=0 cellspacing=3>
+<TR>
+  <TH>Graph Template ID</TH>
+  <TH>SNMP Query ID</TH>
+  <TH>SNMP Query Type ID</TH>
+  <TH>SNMP Field</TH>
+  <TH>SNMP Value</TH>
+</TR>
+<TR id="mytemplate">
+  <TD><INPUT TYPE="text" NAME="graph_template_id" ID="graph_template_id"></TD>
+  <TD><INPUT TYPE="text" NAME="snmp_query_id" ID="snmp_query_id"></TD>
+  <TD><INPUT TYPE="text" NAME="snmp_query_type_id" ID="snmp_query_type_id"></TD>
+  <TD><INPUT TYPE="text" NAME="snmp_field" ID="snmp_field"></TD>
+  <TD><INPUT TYPE="text" NAME="snmp_value" ID="snmp_value"></TD>
+</TR>
+<& /elements/auto-table.html,
+  template_row  => 'mytemplate',
+  fieldorder    => ['graph_template_id','snmp_query_id','snmp_query_type_id','snmp_field','snmp_value'],
+  data          => \@data,
+  table         => 'cacti',
+&>
+</table>
+<INPUT TYPE="hidden" name="multi_options" value="<% $multiopts %>">
+<%init>
+my %opt = @_;
+my $part_export = $opt{part_export} || die "No part_export specified";
+
+my @fields = ('cacti_graph_template_id','cacti_snmp_query_id','cacti_snmp_query_type_id','cacti_snmp_field','cacti_snmp_value');
+my $multiopts = join(',', at fields);
+my @byfield = map {
+  [ split("\n", $part_export->option($_)) ]
+} @fields;
+my @data;
+for (my $i = 0; $i < @{$byfield[0]}; $i++) {
+  my @thisrow;
+  for (my $j = 0; $j < @byfield; $j++) {
+    push(@thisrow,$byfield[$j][$i]);
+  }
+  push(@data,\@thisrow);
+}
+
+</%init>
diff --git a/httemplate/edit/part_export.cgi b/httemplate/edit/part_export.cgi
index 0e53e29..3820931 100644
--- a/httemplate/edit/part_export.cgi
+++ b/httemplate/edit/part_export.cgi
@@ -183,6 +183,10 @@ my $widget = new HTML::Widgets::SelectLayers(
                       ? $optinfo->{default}
                       : ''
                     );
+
+      #handle these with post_config_element
+      next if $type eq 'custom';
+
       if ( $type eq 'title' ) {
         $html .= qq!<TR><TH COLSPAN=1 ALIGN="right"><FONT SIZE="+1">! .
                  $label .
@@ -283,6 +287,17 @@ my $widget = new HTML::Widgets::SelectLayers(
 
     $html .= '</TABLE>';
 
+    # false laziness with config_element above
+    # create 'post_config_element' to generate the whole layer with a Mason component
+    if ( my $include = $exports->{$layer}{post_config_element} ) {
+      # might need to adjust the scope of  this at some point
+      $html .= $m->scomp($include, 
+        part_export => $part_export,
+        layer       => $layer,
+        export_info => $exports->{$layer}
+      );
+    }
+
     $html .= '<INPUT TYPE="hidden" NAME="options" VALUE="'.
              join(',', keys %{$exports->{$layer}{options}} ). '">';
 

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/Schema.pm                                 |   10 -
 FS/FS/part_export/cacti.pm                      |  266 +++++++++++++++--------
 bin/freeside_cacti.php                          |   13 +-
 httemplate/browse/part_export.cgi               |    2 +-
 httemplate/edit/elements/part_export/cacti.html |   42 ++++
 httemplate/edit/part_export.cgi                 |   15 ++
 6 files changed, 239 insertions(+), 109 deletions(-)
 create mode 100644 httemplate/edit/elements/part_export/cacti.html




More information about the freeside-commits mailing list