Merge branch 'master' of ssh://git.freeside.biz/home/git/freeside
[freeside.git] / FS / FS / part_export / saisei.pm
index 799220e..fc0dee5 100644 (file)
@@ -1,19 +1,15 @@
 package FS::part_export::saisei;
 
 use strict;
-use base qw( FS::part_export );
 use vars qw( @ISA %info );
+use base qw( FS::part_export );
 use Date::Format 'time2str';
 use Cpanel::JSON::XS;
-use Net::HTTPS::Any qw(https_post);
 use MIME::Base64;
 use REST::Client;
 use Data::Dumper;
-
 use FS::Conf;
 
-#@ISA = qw( FS::part_export::http );
-
 =pod
 
 =head1 NAME
@@ -28,24 +24,30 @@ Saisei integration for Freeside
 
 This export offers basic svc_broadband provisioning for Saisei.
 
+This is a customer integration with Saisei.  This will setup a rate plan and tie
+the rate plan to a host via the Saisei API when the broadband service is provisioned.
+It will also untie the rate  plan via the API upon unprovisioning of the broadband service.
+
+This export will use the broadband service descriptive label for the Saisei rate plan name and
+will use the email from the first contact for the Saisei username that will be
+attached to this rate plan.  It will use the Saisei default Access Point.
+
+Hostname or IP - Host name to Saisei API
+Port - <I>Port number to Saisei API
+User Name -  <I>Saisei API user name
+Password - <I>Saisei API password
+
 This module also provides generic methods for working through the L</Saisei API>.
 
 =cut
 
 tie my %options, 'Tie::IxHash',
+  'port'             => { label => 'Port',
+                          default => 5000 },
   'username'         => { label => 'User Name',
                           default => '' },
   'password'         => { label => 'Password',
                           default => '' },
-  'host'             => { label => 'Host',
-                          default => 'STM IP ADDRESS' },
-  'port'             => { label => 'Port',
-                          default => 5000 },
-  'customer_name'    => { label => 'Customer Name',
-                          default => 'FREESIDE CUST $custnum' },
-  'account_id'       => { label => 'Account ID',
-                          default => 'SVC$svcnum' },
-  'product_id'       => { label => 'Account Product ID' },
   'debug'            => { type => 'checkbox',
                           label => 'Enable debug warnings' },
 ;
@@ -55,18 +57,23 @@ tie my %options, 'Tie::IxHash',
   'desc'            => 'Export broadband service/account to Saisei',
   'options'         => \%options,
   'notes'           => <<'END',
-This is customer integration with Saisei.
+This is a customer integration with Saisei.  This will setup a rate plan and tie 
+the rate plan to a host via the Saisei API when the broadband service is provisioned.  
+It will also untie the rate  plan via the API upon unprovisioning of the broadband service.
+<P>This export will use the broadband service descriptive label for the Saisei rate plan name and
+will use the email from the first contact for the Saisei username that will be
+attached to this rate plan.  It will use the Saisei default Access Point.
+<P>
+Required Fields:
+<UL>
+<LI>Hostname or IP - <I>Host name to Saisei API</I></LI>
+<LI>Port - <I>Port number to Saisei API</I></LI>
+<LI>User Name -  <I>Saisei API user name</I></LI>
+<LI>Password - <I>Saisei API password</I></LI>
+</UL>
 END
 );
 
-#"/STM_IP:5000/rest/top/configurations/running/" is for http 5029 for https
-
-#Creating User Names
-#Users are tracked by their name which gives access to the internal slice data which in turn allows the viewing of  Applications and Geo-Locations.
-#Creating a user name requires a command of the following format: -
-#'put', 'users/USER_NAME', {'description':description}
-#When creating a user name it is usual to add a description and since a user attribute set does not normally contain the users plan name it is best to encode it into the description field.
-
 sub _export_insert {
   my ($self, $svc_broadband) = @_;
   my $rateplan_name = $svc_broadband->{Hash}->{description};
@@ -101,22 +108,28 @@ sub _export_insert {
   my $username = $email[0];
   my $description = $cust_main->{Hash}->{first}." ".$cust_main->{Hash}->{last};
 
-  # check for existing user.
-  my $existing_user;
-  $existing_user = $self->api_get_user($username) unless ( $self->{'__saisei_error'} || !$username);
+  if (!$username) {
+    $self->{'__saisei_error'} = 'no username - can not export';
+    warn "No email found $username\n" if $self->option('debug');
+    return;
+  }
+  else {
+    # check for existing user.
+    my $existing_user;
+    $existing_user = $self->api_get_user($username) unless $self->{'__saisei_error'};
  
-  # if no existing user create one.
-  $self->api_create_user($username, $description) unless $existing_user;
+    # if no existing user create one.
+    $self->api_create_user($username, $description) unless $existing_user;
 
-  # set user to existing one or newly created one.
-  my $user = $existing_user ? $existing_user : $self->api_get_user($username);
+    # set user to existing one or newly created one.
+    my $user = $existing_user ? $existing_user : $self->api_get_user($username);
 
-  ## add access point ?
+    ## add access point ?
  
-  ## tie host to user
-  $self->api_add_host_to_user($user->{collection}->[0]->{name}, $rateplan->{collection}->[0]->{name}, $svc_broadband->{Hash}->{ip_addr}) unless $self->{'__saisei_error'};
+    ## tie host to user
+    $self->api_add_host_to_user($user->{collection}->[0]->{name}, $rateplan->{collection}->[0]->{name}, $svc_broadband->{Hash}->{ip_addr}) unless $self->{'__saisei_error'};
+  }
 
-  #die('ending for testing');
   return '';
 
 }
@@ -169,15 +182,10 @@ set in the export options.
 
 =head2 api_call
 
-Accepts I<$service>, I<$method>, I<$params> hashref and optional
-I<$returnfield>.  Places an api call to the specified service
-and method with the specified params.  Returns the decoded json
-object returned by the api call.  If I<$returnfield> is specified,
-returns only that field of the decoded object, and errors out if
-that field does not exist.  Returns empty on failure;  retrieve
-error messages using L</api_error>.
-
-Must run L</api_login> first.
+Accepts I<$method>, I<$path>, I<$params> hashref and optional.
+Places an api call to the specified path and method with the specified params.
+Returns the decoded json object returned by the api call.
+Returns empty on failure;  retrieve error messages using L</api_error>.
 
 =cut
 
@@ -187,14 +195,18 @@ sub api_call {
   my $auth_info = $self->option('username') . ':' . $self->option('password');
   $params ||= {};
 
-  print "Calling /$method\n" if $self->option('debug');
+  warn "Calling $method on http://"
+    .$self->{Hash}->{machine}.':'.$self->option('port')
+    ."/rest/stm/configurations/running/$path\n" if $self->option('debug');
 
   my $data = encode_json($params) if keys %{ $params };
 
   my $client = REST::Client->new();
   $client->addHeader("Authorization", "Basic ".encode_base64($auth_info));
-  $client->setHost('http://'.$self->option('host').':'.$self->option('port'));
-  $client->$method('/rest/stm/configurations/running/'.$path, $data, { "Content-type" => 'application/json'});
+  $client->setHost('http://'.$self->{Hash}->{machine}.':'.$self->option('port'));
+  $client->$method('/rest/stm/configurations/running'.$path, $data, { "Content-type" => 'application/json'});
+
+  warn "Response Code is ".$client->responseCode()."\n" if $self->option('debug');
 
   my $result;
 
@@ -207,7 +219,7 @@ sub api_call {
   }
   else {
     $self->{'__saisei_error'} = "Bad response from server during $method: " . $client->responseContent();
-    print "My response content fo /$method\n". Dumper($client->responseContent) if $self->option('debug');
+    warn "Response Content is\n".$client->responseContent."\n" if $self->option('debug');
     return; 
   }
 
@@ -236,7 +248,7 @@ Gets a list of global policies.
 sub api_get_policies {
   my $self = shift;
 
-  my $get_policies = $self->api_call("GET", 'policies/?token=1&order=name&start=0&limit=20&select=name%2Cpercent_rate%2Cassured%2C');
+  my $get_policies = $self->api_call("GET", '/policies/?token=1&order=name&start=0&limit=20&select=name%2Cpercent_rate%2Cassured%2C');
   return if $self->api_error;
   $self->{'__saisei_error'} = "Did not receive any global policies"
     unless $get_policies;
@@ -254,7 +266,7 @@ sub api_get_rateplan {
   my $self = shift;
   my $rateplan = shift;
 
-  my $get_rateplan = $self->api_call("GET", "rate_plans/$rateplan");
+  my $get_rateplan = $self->api_call("GET", "/rate_plans/$rateplan");
   return if $self->api_error;
   $self->{'__saisei_error'} = "Did not receive any rateplan info"
     unless $get_rateplan;
@@ -272,7 +284,7 @@ sub api_get_user {
   my $self = shift;
   my $user = shift;
 
-  my $get_user = $self->api_call("GET", "users/$user");
+  my $get_user = $self->api_call("GET", "/users/$user");
   return if $self->api_error;
   $self->{'__saisei_error'} = "Did not receive any user info"
     unless $get_user;
@@ -290,7 +302,7 @@ sub api_get_accesspoint {
   my $self = shift;
   my $accesspoint;
 
-  my $get_accesspoint = $self->api_call("GET", "access_points/$accesspoint");
+  my $get_accesspoint = $self->api_call("GET", "/access_points/$accesspoint");
   return if $self->api_error;
   $self->{'__saisei_error'} = "Did not receive any user info"
     unless $get_accesspoint;
@@ -309,7 +321,7 @@ sub api_create_rateplan {
 
   my $new_rateplan = $self->api_call(
       "PUT", 
-      "rate_plans/$rateplan",
+      "/rate_plans/$rateplan",
       {
         'downstream_rate' => $svc->{Hash}->{speed_down},
         'upstream_rate' => $svc->{Hash}->{speed_up},
@@ -337,7 +349,7 @@ sub api_modify_rateplan {
     if ($policy->{background}) { $rate_multiplier = ".01"; }
     my $modified_rateplan = $self->api_call(
       "PUT", 
-      "rate_plans/$rateplan_name/partitions/$policyname",
+      "/rate_plans/$rateplan_name/partitions/$policyname",
       {
         'restricted'      =>  $policy->{assured},         # policy_assured_flag
         'rate_multiplier' => $rate_multiplier,           # policy_background 0.1
@@ -356,7 +368,7 @@ sub api_modify_rateplan {
 
 =head2 api_create_user
 
-Creates a rateplan.
+Creates a user.
 
 =cut
 
@@ -365,7 +377,7 @@ sub api_create_user {
 
   my $new_user = $self->api_call(
       "PUT", 
-      "users/$user",
+      "/users/$user",
       {
         'description' => $description,
       },
@@ -387,23 +399,24 @@ Creates a access point.
 sub api_create_accesspoint {
   my ($self,$accesspoint) = @_;
 
-  my $new_accesspoint = $self->api_call(
-      "PUT", 
-      "access_points/$accesspoint",
-      {
-        'description' => 'my description',
-      },
-  );
-
-  $self->{'__saisei_error'} = "Access point not created"
-    unless $new_accesspoint; # should never happen
+  # this has not been tested, but should work, if needed.
+  #my $new_accesspoint = $self->api_call(
+  #    "PUT", 
+  #    "/access_points/$accesspoint",
+  #    {
+  #      'description' => 'my description',
+  #    },
+  #);
+
+  #$self->{'__saisei_error'} = "Access point not created"
+  #  unless $new_accesspoint; # should never happen
   return;
 
 }
 
 =head2 api_add_host_to_user
 
-ties host to user and rateplan.
+ties host to user, rateplan and default access point.
 
 =cut
 
@@ -412,7 +425,7 @@ sub api_add_host_to_user {
 
   my $new_host = $self->api_call(
       "PUT", 
-      "hosts/$ip",
+      "/hosts/$ip",
       {
         'user'      => $user,
         'rate_plan' => $rateplan,
@@ -426,16 +439,31 @@ sub api_add_host_to_user {
 
 }
 
-=head2 api_add_host_to_user
+=head2 api_delete_host_to_user
 
-ties host to user and rateplan.
+unties host to user and rateplan.
 
 =cut
 
 sub api_delete_host_to_user {
   my ($self,$user, $rateplan, $ip) = @_;
 
-  my $delete_host = $self->api_call("DELETE", "hosts/$ip");
+  my $default_rate_plan = $self->api_call("GET", '?token=1&select=default_rate_plan');
+    return if $self->api_error;
+  $self->{'__saisei_error'} = "Did not receive a default rate plan"
+    unless $default_rate_plan;
+
+  my $default_rateplan_name = $default_rate_plan->{collection}->[0]->{default_rate_plan}->{link}->{name};
+
+  my $delete_host = $self->api_call(
+      "PUT",
+      "/hosts/$ip",
+      {
+        'user'          => '<none>',
+        'access_point'  => '<none>',
+        'rate_plan'     => $default_rateplan_name,
+      },
+  );
 
   $self->{'__saisei_error'} = "Host not created"
     unless $delete_host; # should never happen