X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=FS%2FFS%2Fpart_export%2Fsaisei.pm;h=8661651df80a7bb4e5bfafe5005efb6e93b9012f;hp=2fc112744cdd25f11f3bd2b16f7f82a2acd11d48;hb=c15c4b8b1afa91049915f77503487e663554938b;hpb=8309e857e05c33d65edee6bfe18a60db5300e310 diff --git a/FS/FS/part_export/saisei.pm b/FS/FS/part_export/saisei.pm index 2fc112744..8661651df 100644 --- a/FS/FS/part_export/saisei.pm +++ b/FS/FS/part_export/saisei.pm @@ -9,6 +9,7 @@ use MIME::Base64; use REST::Client; use Data::Dumper; use FS::Conf; +use Carp qw(carp); =pod @@ -61,6 +62,8 @@ tie my %scripts, 'Tie::IxHash', label => 'Export provisioned services', description => 'will export provisioned services of part service with Saisei export attached.', html_label => 'Export provisioned services attached to this export.', + error_url => '/edit/part_export.cgi?', + success_message => 'Saisei export of provisioned services successful', }, ; @@ -93,7 +96,7 @@ To use this export, follow the below instructions:
@@ -109,7 +112,7 @@ Create a package for the above created service, and order this package for a cus
Unprovisioning this service will set the host entry at Saisei to the default rate plan with the user and access point set to none. @@ -121,16 +124,14 @@ Clicking on this link will export all services attached to this export not curre
- +Documentation END ); sub _export_insert { my ($self, $svc_broadband) = @_; - 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; + my $rateplan_name = $self->get_rateplan_name($svc_broadband); # check for existing rate plan my $existing_rateplan; @@ -170,6 +171,7 @@ sub _export_insert { tower.up_rate_limit as tower_upratelimit, tower.down_rate_limit as tower_downratelimit, tower_sector.sectorname, + tower_sector.towernum, tower_sector.up_rate_limit as sector_upratelimit, tower_sector.down_rate_limit as sector_downratelimit ', 'addl_from' => 'LEFT JOIN tower USING ( towernum )', @@ -183,6 +185,7 @@ sub _export_insert { my $tower_opt = { 'tower_name' => $tower_name, + 'tower_num' => $tower_sector->{Hash}->{towernum}, 'tower_uprate_limit' => $tower_sector->{Hash}->{tower_upratelimit}, 'tower_downrate_limit' => $tower_sector->{Hash}->{tower_downratelimit}, }; @@ -195,19 +198,37 @@ sub _export_insert { my $sector_opt = { 'tower_name' => $tower_name, + 'tower_num' => $tower_sector->{Hash}->{towernum}, 'sector_name' => $sector_name, 'sector_uprate_limit' => $tower_sector->{Hash}->{sector_upratelimit}, 'sector_downrate_limit' => $tower_sector->{Hash}->{sector_downratelimit}, + 'rateplan' => $rateplan_name, }; my $accesspoint = process_sector($self, $sector_opt); return $self->api_error if $self->{'__saisei_error'}; +## get custnum and pkgpart from cust_pkg for virtual access point + my $cust_pkg = FS::Record::qsearchs({ + 'table' => 'cust_pkg', + 'hashref' => { 'pkgnum' => $svc_broadband->{Hash}->{pkgnum}, }, + }); + my $virtual_ap_name = $cust_pkg->{Hash}->{custnum}.'_'.$cust_pkg->{Hash}->{pkgpart}.'_'.$svc_broadband->{Hash}->{speed_down}.'_'.$svc_broadband->{Hash}->{speed_up}; + + my $virtual_ap_opt = { + 'virtual_name' => $virtual_ap_name, + 'sector_name' => $sector_name, + 'virtual_uprate_limit' => $svc_broadband->{Hash}->{speed_up}, + 'virtual_downrate_limit' => $svc_broadband->{Hash}->{speed_down}, + }; + my $virtual_ap = process_virtual_ap($self, $virtual_ap_opt); + return $self->api_error if $self->{'__saisei_error'}; + ## 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}, + $virtual_ap->{collection}->[0]->{name}, ) unless $self->{'__saisei_error'}; } @@ -217,15 +238,15 @@ sub _export_insert { sub _export_replace { my ($self, $svc_broadband) = @_; - return ''; + my $error = $self->_export_insert($svc_broadband); + return $error; } sub _export_delete { my ($self, $svc_broadband) = @_; - 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; + my $rateplan_name = $self->get_rateplan_name($svc_broadband); + my $username = $svc_broadband->{Hash}->{svcnum}; ## untie host to user @@ -247,25 +268,55 @@ sub _export_unsuspend { sub export_partsvc { my ($self, $svc_part) = @_; - my $rateplan_name = $svc_part->{Hash}->{svc}; - $rateplan_name =~ s/\s/_/g; - my $speeddown = $svc_part->{Hash}->{svc_broadband__speed_down}; - my $speedup = $svc_part->{Hash}->{svc_broadband__speed_up}; + if ( $FS::svc_Common::noexport_hack ) { + carp 'export_partsvc() suppressed by noexport_hack' + if $self->option('debug'); + return; + } - my $temp_svc = $svc_part->{Hash}; - my $svc_broadband = {}; - map { if ($_ =~ /^svc_broadband__(.*)$/) { $svc_broadband->{Hash}->{$1} = $temp_svc->{$_}; } } keys %$temp_svc; + my $fcc_477_speeds; + if ($svc_part->{Hash}->{svc_broadband__speed_down} eq "down" || $svc_part->{Hash}->{svc_broadband__speed_up} eq "up") { + for my $type (qw( down up )) { + my $speed_type = "broadband_".$type."stream"; + foreach my $pkg_svc (FS::Record::qsearch({ + 'table' => 'pkg_svc', + 'select' => 'pkg_svc.*, part_pkg_fcc_option.fccoptionname, part_pkg_fcc_option.optionvalue', + 'addl_from' => ' LEFT JOIN part_pkg_fcc_option USING (pkgpart) ', + 'extra_sql' => " WHERE pkg_svc.svcpart = ".$svc_part->{Hash}->{svcpart}." AND pkg_svc.quantity > 0 AND part_pkg_fcc_option.fccoptionname = '".$speed_type."'", + })) { $fcc_477_speeds->{ + $pkg_svc->{Hash}->{pkgpart}}->{$speed_type} = $pkg_svc->{Hash}->{optionvalue} * 1000 unless !$pkg_svc->{Hash}->{optionvalue}; } + } + } + else { + $fcc_477_speeds->{1}->{broadband_downstream} = $svc_part->{Hash}->{"svc_broadband__speed_down"}; + $fcc_477_speeds->{1}->{broadband_upstream} = $svc_part->{Hash}->{"svc_broadband__speed_up"}; + } - # check for existing rate plan - my $existing_rateplan; - $existing_rateplan = $self->api_get_rateplan($rateplan_name) unless $self->{'__saisei_error'}; + foreach my $key (keys %$fcc_477_speeds) { - # Modify the existing rate plan with new service data. - $self->api_modify_existing_rateplan($svc_broadband, $rateplan_name) unless ($self->{'__saisei_error'} || !$existing_rateplan); + $svc_part->{Hash}->{speed_down} = $fcc_477_speeds->{$key}->{broadband_downstream}; + $svc_part->{Hash}->{speed_up} = $fcc_477_speeds->{$key}->{broadband_upstream}; + $svc_part->{Hash}->{svc_broadband__speed_down} = $fcc_477_speeds->{$key}->{broadband_downstream}; + $svc_part->{Hash}->{svc_broadband__speed_up} = $fcc_477_speeds->{$key}->{broadband_upstream}; - # if no existing rate plan create one and modify it. - $self->api_create_rateplan($svc_broadband, $rateplan_name) unless $existing_rateplan; - $self->api_modify_rateplan($svc_part, $rateplan_name) unless ($self->{'__saisei_error'} || $existing_rateplan); + my $temp_svc = $svc_part->{Hash}; + my $svc_broadband = {}; + map { if ($_ =~ /^svc_broadband__(.*)$/) { $svc_broadband->{Hash}->{$1} = $temp_svc->{$_}; } } keys %$temp_svc; + + my $rateplan_name = $self->get_rateplan_name($svc_broadband, $svc_part->{Hash}->{svc}); + + # check for existing rate plan + my $existing_rateplan; + $existing_rateplan = $self->api_get_rateplan($rateplan_name) unless $self->{'__saisei_error'}; + + # Modify the existing rate plan with new service data. + $self->api_modify_existing_rateplan($svc_broadband, $rateplan_name) unless ($self->{'__saisei_error'} || !$existing_rateplan); + + # if no existing rate plan create one and modify it. + $self->api_create_rateplan($svc_broadband, $rateplan_name) unless $existing_rateplan; + $self->api_modify_rateplan($svc_part, $rateplan_name) unless ($self->{'__saisei_error'} || $existing_rateplan); + + } return $self->api_error; @@ -274,17 +325,25 @@ sub export_partsvc { sub export_tower_sector { my ($self, $tower) = @_; + if ( $FS::svc_Common::noexport_hack ) { + carp 'export_tower_sector() suppressed by noexport_hack' + if $self->option('debug'); + return; + } + #modify tower or create it. my $tower_name = $tower->{Hash}->{towername}; $tower_name =~ s/\s/_/g; my $tower_opt = { 'tower_name' => $tower_name, + 'tower_num' => $tower->{Hash}->{towernum}, 'tower_uprate_limit' => $tower->{Hash}->{up_rate_limit}, 'tower_downrate_limit' => $tower->{Hash}->{down_rate_limit}, 'modify_existing' => '1', # modify an existing access point with this info }; my $tower_access_point = process_tower($self, $tower_opt); + return $tower_access_point if $tower_access_point->{error}; #get list of all access points my $hash_opt = { @@ -299,15 +358,30 @@ sub export_tower_sector { $sector_name =~ s/\s/_/g; my $sector_opt = { 'tower_name' => $tower_name, + 'tower_num' => $tower_sector->{Hash}->{towernum}, 'sector_name' => $sector_name, 'sector_uprate_limit' => $tower_sector->{Hash}->{up_rate_limit}, 'sector_downrate_limit' => $tower_sector->{Hash}->{down_rate_limit}, 'modify_existing' => '1', # modify an existing access point with this info }; - my $sector_access_point = process_sector($self, $sector_opt); + my $sector_access_point = process_sector($self, $sector_opt) unless ($sector_name eq "_default"); + return $sector_access_point if $sector_access_point->{error}; } - return $self->api_error; + return { error => $self->api_error, }; +} + +## creates the rateplan name +sub get_rateplan_name { + my ($self, $svc_broadband, $svc_name) = @_; + + my $service_part = FS::Record::qsearchs( 'part_svc', { 'svcpart' => $svc_broadband->{Hash}->{svcpart} } ) unless $svc_name; + my $service_name = $svc_name ? $svc_name : $service_part->{Hash}->{svc}; + + my $rateplan_name = $service_name . " " . $svc_broadband->{Hash}->{speed_down} . "-" . $svc_broadband->{Hash}->{speed_up}; + $rateplan_name =~ s/\s/_/g; $rateplan_name =~ s/[^A-Za-z0-9\-_]//g; + + return $rateplan_name; } =head1 Saisei API @@ -335,30 +409,48 @@ sub api_call { warn "Calling $method on http://" .$self->{Hash}->{machine}.':'.$self->option('port') - ."/rest/stm/configurations/running/$path\n" if $self->option('debug'); + ."/rest/top/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->{Hash}->{machine}.':'.$self->option('port')); - $client->$method('/rest/stm/configurations/running'.$path, $data, { "Content-type" => 'application/json'}); + $client->$method('/rest/top/configurations/running'.$path, $data, { "Content-type" => 'application/json'}); - warn "Response Code is ".$client->responseCode()."\n" if $self->option('debug'); + warn "Saisei Response Code is ".$client->responseCode()."\n" if $self->option('debug'); my $result; if ($client->responseCode() eq '200' || $client->responseCode() eq '201') { eval { $result = decode_json($client->responseContent()) }; unless ($result) { - $self->{'__saisei_error'} = "Error decoding json: $@"; + $self->{'__saisei_error'} = "There was an error decoding the JSON data from Saisei. Bad JSON data logged in error log if debug option was set."; + warn "Saisei RC 201 Response Content is not json\n".$client->responseContent()."\n" if $self->option('debug'); + return; + } + } + elsif ($client->responseCode() eq '404') { + eval { $result = decode_json($client->responseContent()) }; + unless ($result) { + $self->{'__saisei_error'} = "There was an error decoding the JSON data from Saisei. Bad JSON data logged in error log if debug option was set."; + warn "Saisei RC 404 Response Content is not json\n".$client->responseContent()."\n" if $self->option('debug'); return; } + ## check if message is for empty hash. + my($does_not_exist) = $result->{message} =~ /'(.*)' does not exist$/; + $self->{'__saisei_error'} = "Saisei Error: ".$result->{message} unless $does_not_exist; + warn "Saisei Response Content is\n".$client->responseContent."\n" if ($self->option('debug') && !$does_not_exist); + return; + } + elsif ($client->responseCode() eq '500') { + $self->{'__saisei_error'} = "Could not connect to the Saisei export host machine (".$self->{Hash}->{machine}.':'.$self->option('port').") during $method , we received the responce code: " . $client->responseCode(); + warn "Saisei Response Content is\n".$client->responseContent."\n" if $self->option('debug'); + return; } else { - $self->{'__saisei_error'} = "Bad response from server during $method: " . $client->responseContent() - unless ($method eq "GET"); - warn "Response Content is\n".$client->responseContent."\n" if $self->option('debug'); + $self->{'__saisei_error'} = "Received Bad response from server during $method , we received responce code: " . $client->responseCode(); + warn "Saisei Response Content is\n".$client->responseContent."\n" if $self->option('debug'); return; } @@ -389,7 +481,7 @@ sub api_get_policies { 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" + $self->{'__saisei_error'} = "Did not receive any global policies from Saisei." unless $get_policies; return $get_policies->{collection}; @@ -455,7 +547,7 @@ sub api_get_host { my $get_host = $self->api_call("GET", "/hosts/$ip"); - return if $self->api_error; + return { message => $self->api_error, } if $self->api_error; return $get_host; } @@ -469,8 +561,8 @@ Creates a rateplan. sub api_create_rateplan { my ($self, $svc, $rateplan) = @_; - $self->{'__saisei_error'} = "No downrate listed for service $rateplan" if !$svc->{Hash}->{speed_down}; - $self->{'__saisei_error'} = "No uprate listed for service $rateplan" if !$svc->{Hash}->{speed_up}; + $self->{'__saisei_error'} = "There is no download speed set for the service !--service,".$svc->svcnum.",".$rateplan."--! with host (".$svc->{Hash}->{ip_addr}."). All services that are to be exported to Saisei need to have a download speed set for them." if !$svc->{Hash}->{speed_down}; + $self->{'__saisei_error'} = "There is no upload speed set for the service !--service,".$svc->svcnum.",".$rateplan."--! with host (".$svc->{Hash}->{ip_addr}."). All services that are to be exported to Saisei need to have a upload speed set for them." if !$svc->{Hash}->{speed_up}; my $new_rateplan = $self->api_call( "PUT", @@ -481,7 +573,7 @@ sub api_create_rateplan { }, ) unless $self->{'__saisei_error'}; - $self->{'__saisei_error'} = "Rate Plan not created" + $self->{'__saisei_error'} = "Saisei could not create the rate plan $rateplan." unless ($new_rateplan || $self->{'__saisei_error'}); return $new_rateplan; @@ -514,7 +606,7 @@ sub api_modify_rateplan { }, ); - $self->{'__saisei_error'} = "Rate Plan not modified after create" + $self->{'__saisei_error'} = "Saisei could not modify the rate plan $rateplan_name after it was created." unless ($modified_rateplan || $self->{'__saisei_error'}); # should never happen } @@ -532,6 +624,9 @@ Modify a existing rateplan. sub api_modify_existing_rateplan { my ($self,$svc,$rateplan_name) = @_; + $self->{'__saisei_error'} = "There is no download speed set for the service !--service,".$svc->svcnum.",".$rateplan_name."--! with host (".$svc->{Hash}->{ip_addr}."). All services that are to be exported to Saisei need to have a download speed set for them." if !$svc->{Hash}->{speed_down}; + $self->{'__saisei_error'} = "There is no upload speed set for the service !--service,".$svc->svcnum.",".$rateplan_name."--! with host (".$svc->{Hash}->{ip_addr}."). All services that are to be exported to Saisei need to have a upload speed set for them." if !$svc->{Hash}->{speed_up}; + my $modified_rateplan = $self->api_call( "PUT", "/rate_plans/$rateplan_name", @@ -541,7 +636,7 @@ sub api_modify_existing_rateplan { }, ); - $self->{'__saisei_error'} = "Rate Plan not modified" + $self->{'__saisei_error'} = "Saisei could not modify the rate plan $rateplan_name." unless ($modified_rateplan || $self->{'__saisei_error'}); # should never happen return; @@ -565,7 +660,7 @@ sub api_create_user { }, ); - $self->{'__saisei_error'} = "User not created" + $self->{'__saisei_error'} = "Saisei could not create the user $user" unless ($new_user || $self->{'__saisei_error'}); # should never happen return $new_user; @@ -581,7 +676,6 @@ Creates a access point. sub api_create_accesspoint { my ($self,$accesspoint, $upratelimit, $downratelimit) = @_; - # this has not been tested, but should work, if needed. my $new_accesspoint = $self->api_call( "PUT", "/access_points/$accesspoint", @@ -591,7 +685,7 @@ sub api_create_accesspoint { }, ); - $self->{'__saisei_error'} = "Access point not created" + $self->{'__saisei_error'} = "Saisei could not create the access point $accesspoint" unless ($new_accesspoint || $self->{'__saisei_error'}); # should never happen return; @@ -614,7 +708,7 @@ sub api_modify_accesspoint { }, ); - $self->{'__saisei_error'} = "Rate Plan not modified" + $self->{'__saisei_error'} = "Saisei could not modify the access point $accesspoint after it was created." unless ($modified_accesspoint || $self->{'__saisei_error'}); # should never happen return; @@ -640,7 +734,7 @@ sub api_modify_existing_accesspoint { }, ); - $self->{'__saisei_error'} = "Access point not modified" + $self->{'__saisei_error'} = "Saisei could not modify the access point $accesspoint." unless ($modified_accesspoint || $self->{'__saisei_error'}); # should never happen return; @@ -666,7 +760,7 @@ sub api_add_host_to_user { }, ); - $self->{'__saisei_error'} = "Host not created" + $self->{'__saisei_error'} = "Saisei could not create the host $ip" unless ($new_host || $self->{'__saisei_error'}); # should never happen return $new_host; @@ -685,7 +779,7 @@ sub api_delete_host_to_user { 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" + $self->{'__saisei_error'} = "Can not delete the host as Saisei did not return a default rate plan. Please make sure Saisei has a default rateplan setup." unless $default_rate_plan; my $default_rateplan_name = $default_rate_plan->{collection}->[0]->{default_rate_plan}->{link}->{name}; @@ -700,7 +794,7 @@ sub api_delete_host_to_user { }, ); - $self->{'__saisei_error'} = "Host not created" + $self->{'__saisei_error'} = "Saisei could not delete the host $ip" unless ($delete_host || $self->{'__saisei_error'}); # should never happen return $delete_host; @@ -710,6 +804,11 @@ sub api_delete_host_to_user { sub process_tower { my ($self, $opt) = @_; + if (!$opt->{tower_uprate_limit} || !$opt->{tower_downrate_limit}) { + $self->{'__saisei_error'} = "Could not export tower !--tower,".$opt->{tower_num}.",".$opt->{tower_name}."--! because there was no up or down rates attached to the tower. Saisei requires a up and down rate be attached to each tower."; + return { error => $self->api_error, }; + } + my $existing_tower_ap; my $tower_name = $opt->{tower_name}; @@ -722,23 +821,34 @@ sub process_tower { '', # tower does not have a uplink on sectors. $opt->{tower_uprate_limit}, $opt->{tower_downrate_limit}, - ) if $existing_tower_ap && $opt->{modify_existing}; + ) if $existing_tower_ap->{collection} && $opt->{modify_existing}; #if tower does not exist as an access point create it. $self->api_create_accesspoint( $tower_name, $opt->{tower_uprate_limit}, - $opt->{tower_downrate_limit} - ) unless $existing_tower_ap; + $opt->{tower_downrate_limit}, + ) unless $existing_tower_ap->{collection}; my $accesspoint = $self->api_get_accesspoint($tower_name); + return { error => $self->api_error, } if $self->api_error; return $accesspoint; } sub process_sector { my ($self, $opt) = @_; + if (!$opt->{sector_name} || $opt->{sector_name} eq '_default') { + $self->{'__saisei_error'} = "No sector attached to Tower (".$opt->{tower_name}.") for service ".$opt->{'rateplan'}.". Saisei requires a tower sector to be attached to each service that is exported to Saisei."; + return { error => $self->api_error, }; + } + + if (!$opt->{sector_uprate_limit} || !$opt->{sector_downrate_limit}) { + $self->{'__saisei_error'} = "Could not export sector !--tower,".$opt->{tower_num}.",".$opt->{sector_name}."--! because there was no up or down rates attached to the sector. Saisei requires a up and down rate be attached to each sector."; + return { error => $self->api_error, }; + } + my $existing_sector_ap; my $sector_name = $opt->{sector_name}; @@ -766,6 +876,60 @@ sub process_sector { # set access point to existing one or newly created one. my $accesspoint = $existing_sector_ap ? $existing_sector_ap : $self->api_get_accesspoint($sector_name); + return { error => $self->api_error, } if $self->api_error; + return $accesspoint; +} + +=head2 require_tower_and_sector + +sets whether the service export requires a sector with it's tower. + +=cut + +sub require_tower_and_sector { + 1; +} + +sub required_fields { + my @fields = ('svc_broadband__ip_addr_required', 'svc_broadband__speed_up_required', 'svc_broadband__speed_down_required', 'svc_broadband__sectornum_required'); + return @fields; +} + +sub process_virtual_ap { + my ($self, $opt) = @_; + + my $existing_virtual_ap; + my $virtual_name = $opt->{virtual_name}; + + #check if virtual_ap has been set up as an access point. + $existing_virtual_ap = $self->api_get_accesspoint($virtual_name); + + # modify the existing virtual accesspoint if changing it. this should never happen + $self->api_modify_existing_accesspoint ( + $virtual_name, + $opt->{sector_name}, + $opt->{virtual_uprate_limit}, + $opt->{virtual_downrate_limit}, + ) if $existing_virtual_ap && $opt->{modify_existing}; + + #if virtual ap does not exist as an access point create it. + $self->api_create_accesspoint( + $virtual_name, + $opt->{virtual_uprate_limit}, + $opt->{virtual_downrate_limit}, + ) unless $existing_virtual_ap; + + my $update_sector; + if ($existing_virtual_ap && (ref $existing_virtual_ap->{collection}->[0]->{uplink} eq "HASH") && ($existing_virtual_ap->{collection}->[0]->{uplink}->{link}->{name} ne $opt->{sector_name})) { + $update_sector = 1; + } + + # Attach newly created virtual ap to tower sector ap or if sector has changed. + $self->api_modify_accesspoint($virtual_name, $opt->{sector_name}) unless ($self->{'__saisei_error'} || ($existing_virtual_ap && !$update_sector)); + + # set access point to existing one or newly created one. + my $accesspoint = $existing_virtual_ap ? $existing_virtual_ap : $self->api_get_accesspoint($virtual_name); + return $accesspoint; } @@ -774,7 +938,7 @@ sub export_provisioned_services { my $param = shift; my $part_export = FS::Record::qsearchs('part_export', { 'exportnum' => $param->{export_provisioned_services_exportnum}, } ) - or die "unknown exportnum $param->{export_provisioned_services_exportnum}"; + or die "You are trying to use an unknown exportnum $param->{export_provisioned_services_exportnum}. This export does not exist.\n"; bless $part_export; my @svcparts = FS::Record::qsearch({ @@ -795,13 +959,20 @@ sub export_provisioned_services { my $svc_count = scalar @svcs; my %status = {}; - for (my $c=10; $c <=100; $c=$c+10) { $status{int($svc_count * ($c/100))} = $c; } + for (my $c=1; $c <=100; $c=$c+1) { $status{int($svc_count * ($c/100))} = $c; } my $process_count=0; foreach my $svc (@svcs) { if ($status{$process_count}) { my $s = $status{$process_count}; $job->update_statustext($s); } ## check if service exists as host if not export it. - _export_insert($part_export,$svc) unless api_get_host($part_export, $svc->{Hash}->{ip_addr}); + my $host = api_get_host($part_export, $svc->{Hash}->{ip_addr}); + die ("Please double check your credentials as ".$host->{message}."\n") if $host->{message}; + warn "Exporting service ".$svc->{Hash}->{ip_addr}."\n" if ($part_export->option('debug')); + my $export_error = _export_insert($part_export,$svc) unless $host->{collection}; + if ($export_error) { + warn "Error exporting service ".$svc->{Hash}->{ip_addr}."\n" if ($part_export->option('debug')); + die ("$export_error\n"); + } $process_count++; }