[freeside-commits] branch master updated. 2a04f28fa2427e9d61f54fe631d0e455cf9945ac

Ivan ivan at 420.am
Tue May 13 01:45:13 PDT 2014


The branch, master has been updated
       via  2a04f28fa2427e9d61f54fe631d0e455cf9945ac (commit)
      from  25566c0201ea7b86b8c791d5f701b055c0853ece (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 2a04f28fa2427e9d61f54fe631d0e455cf9945ac
Author: Ivan Kohler <ivan at freeside.biz>
Date:   Tue May 13 01:45:11 2014 -0700

    first pass at aradial usage import, RT#29053

diff --git a/bin/aradial-sftp_and_import b/bin/aradial-sftp_and_import
new file mode 100644
index 0000000..95546e4
--- /dev/null
+++ b/bin/aradial-sftp_and_import
@@ -0,0 +1,270 @@
+#!/usr/bin/perl
+
+#i'm kinda like freeside-cdr-sftp_and_import... some parts should be libraried
+
+use strict;
+use Getopt::Std;
+use Text::CSV_XS;
+use DBI;
+use FS::UID qw( adminsuidsetup datasrc );
+
+our %aradial2db = (
+  #'Date' => '',
+  'NASIP' => 'NASIPAddress',
+  'AcctSessionId' => 'AcctSessionId',
+  'Port' => 'NasPortId',
+  #'Status-Type' => 'Acct-Status-Type',
+  'UserID' => 'UserName',
+  'Authentic' => 'AccdtAuthentic',
+  'Service-Type' => 'ServiceType',
+  'FramedProtocol' => 'FramedProtocol',
+  #'FramedCompression' => '', #not handled, needed?  unlikely
+  'FramedAddress' => 'FramedIPAddress',
+  'Acct-Delay-Time' => 'AcctStartDelay', #?
+  'Session-Time' => 'AcctSessionTime',
+  #'Input-Gigawords' => '',
+  'Input-Octets' => 'AcctInputOctets',
+  #'Output-Gigawords' => '',
+  'Output-Octets' => 'AcctOutputOctets',
+  'NAS-Port-Type' => 'NASPortType',
+  'Acct-Terminate-Cause' => 'AcctTerminateCause',
+);
+
+###
+# parse command line
+###
+
+use vars qw( $opt_m $opt_a $opt_b $opt_r $opt_d $opt_v $opt_P );
+getopts('m:abr:dP:v:');
+
+my %options = ();
+
+my $user = shift or die &usage;
+adminsuidsetup $user;
+
+# %%%FREESIDE_CACHE%%%
+my $cachedir = '%%%FREESIDE_CACHE%%%/cache.'. datasrc. '/cdrs';
+mkdir $cachedir unless -d $cachedir;
+
+my $servername = shift or die &usage;
+
+my( $datasrc, $db_user, $db_pass ) = ( shift, shift, shift );
+my $dbh = DBI->connect( $datasrc, $db_user, $db_pass)
+  or die "can't connect: $DBI::errstr\n";
+
+my $csv = Text::CSV_XS->new;
+
+###
+# get the file list
+###
+
+warn "Retrieving directory listing\n" if $opt_v;
+
+$opt_m = 'sftp' if !defined($opt_m);
+$opt_m = lc($opt_m);
+
+my $ls;
+
+if($opt_m eq 'ftp') {
+  $options{'Port'}    = $opt_P if $opt_P;
+  $options{'Debug'}   = $opt_v if $opt_v;
+  $options{'Passive'} = $opt_a if $opt_a;
+
+  my $ls_ftp = ftp();
+
+  $ls = [ grep { /^.*$/i } $ls_ftp->ls ];
+}
+elsif($opt_m eq 'sftp') {
+  $options{'port'}    = $opt_P if $opt_P;
+  $options{'debug'}   = $opt_v if $opt_v;
+
+  my $ls_sftp = sftp();
+
+  $ls_sftp->setcwd($opt_r) or die "can't chdir to $opt_r\n"
+    if $opt_r;
+
+  $ls = $ls_sftp->ls('.', wanted => qr/^$.*\.$/i,
+                          names_only => 1 );
+}
+else {
+  die "Method '$opt_m' not supported; must be ftp or sftp\n";
+}
+
+###
+# import each file
+###
+
+foreach my $filename ( @$ls ) {
+
+  warn "Downloading $filename\n" if $opt_v;
+
+  #get the file
+  if($opt_m eq 'ftp') {
+    my $ftp = ftp();
+    $ftp->get($filename, "$cachedir/$filename")
+      or die "Can't get $filename: ". $ftp->message . "\n";
+  }
+  else {
+    my $sftp = sftp();
+    $sftp->get($filename, "$cachedir/$filename")
+      or die "Can't get $filename: ". $sftp->error . "\n";
+  }
+
+  warn "Processing $filename\n" if $opt_v;
+ 
+  my $file_timestamp = $filename.'-'.time2str('%Y-%m-%d', time);
+
+  open my $fh, "$cachedir/$filename" or die "$cachedir/$filename: $!";
+  my $header = $csv->getline($fh);
+
+  while ( my $row = $csv->getline($fh) ) {
+
+    my $i = 0;
+    my %hash = map { $_ => $row->[$i++] } @$header;
+
+    my %dbhash = map { $aradial2db{$_} => $hash{$_} }
+                   grep $aradial2db{$_},
+                     keys %hash;
+
+    my @keys = keys %dbhash;
+    my @values = map $dbhash{$_}, @keys;
+
+    if ( $hash{'Acct-Status-Type'} eq 'Start' ) {
+
+      $dbhash{'AcctStartTime'} = $hash{'Date'};
+
+      my $sql = 'INSERT INTO radacct ( ', join(',', @keys).
+                ' ) VALUES ( '. map( ' ? ', @values ). ' )';
+      my $sth = $dbh->prepare($sql) or die $dbh->errstr;
+      $sth->execute(@values) or die $sth->errstr;
+
+    } elsif ( $hash{'Acct-Status-Type'} eq 'Stop' ) {
+
+      my $AcctSessionId = delete($dbhash{AcctSessionId});
+      $dbhash{'AcctStopTime'} = $hash{'Date'};
+
+      my $sql = 'UPDATE radacct '. join(' , ', map "SET $_ = ?", @keys ).
+                ' WHERE AcctSessionId = ? ';
+      my $sth = $dbh->prepare($sql) or die $dbh->errstr;
+      $sth->execute(@values, $AcctSessionId) or die $sth->errstr;
+
+    } elsif ( $hash{'Acct-Status-Type'} eq 'Interim' ) {
+      #not handled, but stop should capture the usage.  unless session are
+      # normally super-long, extending across month boundaries, or we need
+      # real-time-ish data usage detail, it isn't a big deal
+    } else {
+      die 'Unknown Acct-Status-Type '. $hash{'Acct-Status-Type'}. "\n";
+    }
+
+  }
+  
+  if ( $opt_d ) {
+    if ( $opt_m eq 'ftp') {
+      my $ftp = ftp();
+      $ftp->rename($filename, "$opt_d/$file_timestamp")
+        or do {
+          unlink "$cachedir/$filename";
+          die "Can't move $filename to $opt_d: ".$ftp->message . "\n";
+        };
+    } else {
+      my $sftp = sftp();
+      $sftp->rename($filename, "$opt_d/$file_timestamp")
+        or do {
+          unlink "$cachedir/$filename";
+          die "can't move $filename to $opt_d: ". $sftp->error . "\n";
+        };
+    }
+  }
+
+  unlink "$cachedir/$filename";
+
+}
+
+###
+# subs
+###
+
+sub usage {
+  "Usage:
+  aradial-sftp_and_import [ -m method ] [ -a ] [ -b ]
+    [ -r remotefolder ] [ -d donefolder ] [ -v level ] [ -P port ]
+    user format [sftpuser@]servername
+  ";
+}
+
+use vars qw( $sftp $ftp );
+
+sub ftp {
+  return $ftp if $ftp && $ftp->pwd;
+  
+  my ($hostname, $userpass) = reverse split('@', $servername);
+  my ($ftp_user, $ftp_pass) = split(':', $userpass);
+
+  my $ftp = Net::FTP->new($hostname, %options) 
+    or die "FTP connection to '$hostname' failed.";
+  $ftp->login($ftp_user, $ftp_pass) or die "FTP login failed: ".$ftp->message;
+  $ftp->cwd($opt_r) or die "can't chdir to $opt_r\n" if $opt_r;
+  $ftp->binary or die "can't set BINARY mode: ". $ftp->message if $opt_b;
+  return $ftp;
+}
+
+sub sftp {
+
+  #reuse connections
+  return $sftp if $sftp && $sftp->cwd;
+
+  my %sftp = ( host => $servername );
+
+  $sftp = Net::SFTP::Foreign->new(%sftp);
+  $sftp->error and die "SFTP connection failed: ". $sftp->error;
+
+  $sftp;
+}
+
+=head1 NAME
+
+freeside-aradial-sftp_and_import - Download Aradial "CDR" (really RADIUS detail) files from a remote server via SFTP
+
+=head1 SYNOPSIS
+
+  aradial-sftp_and_import [ -m method ] [ -a ] [ -b ]
+    [ -r remotefolder ] [ -d donefolder ] [ -v level ] [ -P port ]
+    user format [sftpuser@]servername dbi_datasrc dbi_username dbi_pass
+
+=head1 DESCRIPTION
+
+Command line tool to download CDR files from a remote server via SFTP 
+or FTP and then import them into the database.
+
+-m: transfer method (sftp or ftp), defaults to sftp
+
+-a: use ftp passive mode
+
+-b: use ftp binary mode
+
+-r: if specified, changes into this remote folder before starting
+
+-d: if specified, moves files to the specified folder when done
+
+-P: if specified, sets the port to use
+
+-v: set verbosity level; this script only has one level, but it will 
+    be passed as the 'debug' argument to the transport method
+
+user: freeside username
+
+format: CDR format name
+
+[sftpuser@]servername: remote server
+(or ftpuser:ftppass at servername)
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::cdr>
+
+=cut
+
+1;
+

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

Summary of changes:
 bin/aradial-sftp_and_import |  270 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 270 insertions(+), 0 deletions(-)
 create mode 100644 bin/aradial-sftp_and_import




More information about the freeside-commits mailing list