X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fpart_export%2Fsaisei.pm;h=f76051ea3361dd9487e2fd6ef8d6329305a95ffe;hb=5f9edcbe9fb3b3eb905614927aa6120d50c06ff1;hp=799220ef2c3f316d0124ca4b06510e9f2f2bd631;hpb=29a34baf1ce240da8e012a7147c4a88d48242260;p=freeside.git diff --git a/FS/FS/part_export/saisei.pm b/FS/FS/part_export/saisei.pm index 799220ef2..f76051ea3 100644 --- a/FS/FS/part_export/saisei.pm +++ b/FS/FS/part_export/saisei.pm @@ -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,41 @@ 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 and access point 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. + +Add a new export and fill out required fields: +
+Add a new export and fill out required fields: +
+Create a tower and add a sector to that tower. The sector name will be the name of the access point, +Make sure you have set an up and down rate for the Tower and Sector. +
+When you provision the service, enter the ip address associated to this service. +Select the Tower and Sector for it's access point. +
+When the service is provisioned it will auto setup the rate plan.
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};
- $rateplan_name =~ s/\s/_/g;
+ my $service_part = FS::Record::qsearchs( 'part_svc', { 'svcpart' => $svc_broadband->{Hash}->{svcpart} } );
+ my $rateplan_name = $service_part->{Hash}->{svc};
+ $rateplan_name =~ s/\s/_/g;
# load needed info from our end
my $cust_main = $svc_broadband->cust_main;
@@ -92,32 +120,85 @@ sub _export_insert {
# set rateplan to existing one or newly created one.
my $rateplan = $existing_rateplan ? $existing_rateplan : $self->api_get_rateplan($rateplan_name);
- my @email = map { $_->emailaddress } FS::Record::qsearch({
- 'table' => 'cust_contact',
- 'select' => 'emailaddress',
- 'addl_from' => ' JOIN contact_email USING (contactnum)',
- 'hashref' => { 'custnum' => $cust_main->{Hash}->{custnum}, },
- });
- my $username = $email[0];
- my $description = $cust_main->{Hash}->{first}." ".$cust_main->{Hash}->{last};
+ my $username = $svc_broadband->{Hash}->{svcnum};
+ my $description = $svc_broadband->{Hash}->{description};
- # 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 user $username\n" if $self->option('debug');
+ return $self->api_error;
+ }
+ 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;
-
- # set user to existing one or newly created one.
- my $user = $existing_user ? $existing_user : $self->api_get_user($username);
+ # 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);
+
+ ## add access point ?
+ my $tower_sector = FS::Record::qsearchs({
+ 'table' => 'tower_sector',
+ 'select' => 'tower.towername,
+ tower.up_rate as toweruprate,
+ tower.down_rate as towerdownrate,
+ tower_sector.sectorname,
+ tower_sector.up_rate as sectoruprate,
+ tower_sector.down_rate as sectordownrate ',
+ 'addl_from' => 'LEFT JOIN tower USING ( towernum )',
+ 'hashref' => {
+ 'sectornum' => $svc_broadband->{Hash}->{sectornum},
+ },
+ });
- ## 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'};
+ my $existing_tower_ap;
+ my $tower_name = $tower_sector->{Hash}->{towername};
+ $tower_name =~ s/\s/_/g;
+
+ #check if tower has been set up as an access point.
+ $existing_tower_ap = $self->api_get_accesspoint($tower_name) unless $self->{'__saisei_error'};;
+
+ #if tower does not exist as an access point create it.
+ $self->api_create_accesspoint(
+ $tower_name,
+ $tower_sector->{Hash}->{toweruprate},
+ $tower_sector->{Hash}->{towerdownrate}
+ ) unless $existing_tower_ap;
+
+ my $existing_sector_ap;
+ my $sector_name = $tower_sector->{Hash}->{sectorname};
+ $sector_name =~ s/\s/_/g;
+
+ #check if sector has been set up as an access point.
+ $existing_sector_ap = $self->api_get_accesspoint($sector_name);
+
+ #if sector does not exist as an access point create it.
+ $self->api_create_accesspoint(
+ $sector_name,
+ $tower_sector->{Hash}->{sectoruprate},
+ $tower_sector->{Hash}->{sectordownrate},
+ $tower_name,
+ ) unless $existing_sector_ap;
+
+ # Attach newly created sector to it's tower.
+ $self->api_modify_accesspoint($sector_name, $tower_name) unless ($self->{'__saisei_error'} || $existing_sector_ap);
+
+ # set access point to existing one or newly created one.
+ my $accesspoint = $existing_sector_ap ? $existing_sector_ap : $self->api_get_accesspoint($sector_name);
+
+ ## tie host to user add sector name as access point.
+ $self->api_add_host_to_user(
+ $user->{collection}->[0]->{name},
+ $rateplan->{collection}->[0]->{name},
+ $svc_broadband->{Hash}->{ip_addr},
+ $accesspoint->{collection}->[0]->{name},
+ ) unless $self->{'__saisei_error'};
+ }
- #die('ending for testing');
- return '';
+ return $self->api_error;
}
@@ -169,15 +250,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.
-
-Must run L 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.
=cut
@@ -187,14 +263,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 +287,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;
}
@@ -217,7 +297,7 @@ sub api_call {
=head2 api_error
-Returns the error string set by L methods,
+Returns the error string set by L methods,
or a blank string if most recent call produced no errors.
=cut
@@ -236,7 +316,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 +334,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 +352,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;
@@ -288,14 +368,14 @@ Gets user info for specific access point.
sub api_get_accesspoint {
my $self = shift;
- my $accesspoint;
+ my $accesspoint = shift;
- 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"
+ $self->{'__saisei_error'} = "Did not receive any access point info"
unless $get_accesspoint;
- return;
+ return $get_accesspoint;
}
=head2 api_create_rateplan
@@ -309,7 +389,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 +417,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 +436,7 @@ sub api_modify_rateplan {
=head2 api_create_user
-Creates a rateplan.
+Creates a user.
=cut
@@ -365,7 +445,7 @@ sub api_create_user {
my $new_user = $self->api_call(
"PUT",
- "users/$user",
+ "/users/$user",
{
'description' => $description,
},
@@ -385,13 +465,15 @@ Creates a access point.
=cut
sub api_create_accesspoint {
- my ($self,$accesspoint) = @_;
+ my ($self,$accesspoint, $uprate, $downrate) = @_;
+ # this has not been tested, but should work, if needed.
my $new_accesspoint = $self->api_call(
- "PUT",
- "access_points/$accesspoint",
+ "PUT",
+ "/access_points/$accesspoint",
{
- 'description' => 'my description',
+ 'downstream_rate_limit' => $downrate,
+ 'upstream_rate_limit' => $uprate,
},
);
@@ -401,21 +483,46 @@ sub api_create_accesspoint {
}
+=head2 api_modify_accesspoint
+
+Modify a access point.
+
+=cut
+
+sub api_modify_accesspoint {
+ my ($self, $accesspoint, $uplink) = @_;
+
+ my $modified_rateplan = $self->api_call(
+ "PUT",
+ "/access_points/$accesspoint",
+ {
+ 'uplink' => $uplink, # name of attached access point
+ },
+ );
+
+ $self->{'__saisei_error'} = "Rate Plan not modified"
+ unless $modified_rateplan; # 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
sub api_add_host_to_user {
- my ($self,$user, $rateplan, $ip) = @_;
+ my ($self,$user, $rateplan, $ip, $accesspoint) = @_;
my $new_host = $self->api_call(
"PUT",
- "hosts/$ip",
+ "/hosts/$ip",
{
'user' => $user,
'rate_plan' => $rateplan,
+ 'access_point' => $accesspoint,
},
);
@@ -426,16 +533,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' => '