X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fpart_export%2Fprizm.pm;h=99644895165a330d3eac4c85d8ff6d31adec972b;hb=38e34bbc53a4222c7507e95914e1364a5a74623f;hp=ca02b8f3ee4aebc65d16df10b04cdc796ee768d7;hpb=299f1b7b7b5691d70709aaacfd100d2e088ab0ff;p=freeside.git diff --git a/FS/FS/part_export/prizm.pm b/FS/FS/part_export/prizm.pm index ca02b8f3e..996448951 100644 --- a/FS/FS/part_export/prizm.pm +++ b/FS/FS/part_export/prizm.pm @@ -1,31 +1,96 @@ package FS::part_export::prizm; -use vars qw(@ISA %info %options $DEBUG); +use vars qw(@ISA %info %options $DEBUG $me); use Tie::IxHash; -use FS::Record qw(fields); +use FS::Record qw(fields dbh); use FS::part_export; @ISA = qw(FS::part_export); -$DEBUG = 1; +$DEBUG = 0; +$me = '[' . __PACKAGE__ . ']'; tie %options, 'Tie::IxHash', 'url' => { label => 'Northbound url', default=>'https://localhost:8443/prizm/nbi' }, 'user' => { label => 'Northbound username', default=>'nbi' }, 'password' => { label => 'Password', default => '' }, + 'ems' => { label => 'Full EMS', type => 'checkbox' }, + 'always_bam' => { label => 'Always activate/suspend authentication', type => 'checkbox' }, + 'element_name_length' => { label => 'Size of siteName (best left blank)' }, ; +my $notes = <<'EOT'; +Real-time export of svc_broadband, cust_pkg, and cust_main +record data to Motorola +Canopy Prizm +software via the Northbound interface.

+ +Freeside will attempt to create an element in an existing network with the +values provided in svc_broadband. Of particular interest are + + +In addition freeside attempts to set the service plan name in prizm to the +name of the package in which the service resides. + +The service is associated with a customer in prizm as well, and freeside +will create the customer should none already exist with import id matching +the freeside customer number. The following fields are set. + + + + Additionally set on the element are + + +Freeside provisions, suspends, and unsuspends elements BAM only unless the +'Full EMS' checkbox is checked.

+ +When freeside provisions an element the siteName is copied internally by +prizm in such a manner that it is possible for the value to exceed the size +of the column used in the prizm database. Therefore freeside truncates +by default this value to 50 characters. It is thought that this +column is the account_name column of the element_user_account table. It +may be possible to lift this limit by modifying the prizm database and +setting a new appropriate value on this export. This is untested and +possibly harmful. + +EOT + %info = ( - 'svc' => 'svc_broadband', - 'desc' => 'Real-time export to Northbound Interface', - 'options' => \%options, - 'nodomain' => 'Y', - 'notes' => 'These are notes.' + 'svc' => 'svc_broadband', + 'desc' => 'Real-time export to Northbound Interface', + 'options' => \%options, + 'nodomain' => 'Y', + 'no_machine' => 1, + 'notes' => $notes, ); sub prizm_command { my ($self,$namespace,$method) = (shift,shift,shift); - eval "use Net::Prizm qw(CustomerInfo PrizmElement);"; + eval "use Net::Prizm 0.04 qw(CustomerInfo PrizmElement);"; die $@ if $@; my $prizm = new Net::Prizm ( @@ -38,8 +103,33 @@ sub prizm_command { $prizm->$method(@_); } +sub queued_prizm_command { # subroutine + my( $url, $user, $password, $namespace, $method, @args ) = @_; + + eval "use Net::Prizm 0.04 qw(CustomerInfo PrizmElement);"; + die $@ if $@; + + my $prizm = new Net::Prizm ( + namespace => $namespace, + url => $url, + user => $user, + password => $password, + ); + + $err_or_som = $prizm->$method( @args); + + die $err_or_som + unless ref($err_or_som); + + ''; + +} + sub _export_insert { my( $self, $svc ) = ( shift, shift ); + warn "$me: _export_insert called for export ". $self->exportnum. + " on service ". $svc->svcnum. "\n" + if $DEBUG; my $cust_main = $svc->cust_svc->cust_pkg->cust_main; @@ -66,6 +156,7 @@ sub _export_insert { my $pcustomer; if ($err_or_som->result->[0]) { $pcustomer = $err_or_som->result->[0]->customerId; + warn "$me: found customer $pcustomer in prizm\n" if $DEBUG; }else{ my $chashref = $cust_main->hashref; my $customerinfo = { @@ -92,42 +183,74 @@ sub _export_insert { unless ref($err_or_som); $pcustomer = $err_or_som->result; + warn "$me: added customer $pcustomer to prizm\n" if $DEBUG; } warn "multiple prizm customers found for $cust_main->custnum" if scalar(@$pcustomer) > 1; - #kinda big question/expensive - $err_or_som = $self->prizm_command('NetworkIfService', 'getPrizmElements', - ['Network Default Gateway Address'], - [$svc->addr_block->ip_gateway], - ['='], - ); - return $err_or_som - unless ref($err_or_som); - - return "No elements in network" unless exists $err_or_som->result->[0]; +# #kinda big question/expensive +# $err_or_som = $self->prizm_command('NetworkIfService', 'getPrizmElements', +# ['Network Default Gateway Address'], +# [$svc->addr_block->ip_gateway], +# ['='], +# ); +# return $err_or_som +# unless ref($err_or_som); +# +# return "No elements in network" unless exists $err_or_som->result->[0]; my $networkid = 0; - for (my $i = 0; $i < $err_or_som->result->[0]->attributeNames; $i++) { - if ($err_or_som->result->[0]->attributeNames->[$i] eq "Network.ID"){ - $networkid = $err_or_som->result->[0]->attributeValues->[$i]; - last; - } +# for (my $i = 0; $i < $err_or_som->result->[0]->attributeNames; $i++) { +# if ($err_or_som->result->[0]->attributeNames->[$i] eq "Network.ID"){ +# $networkid = $err_or_som->result->[0]->attributeValues->[$i]; +# last; +# } +# } + +# here we cope with a problem of prizm failing to insert for reason +# of duplicate mac addr, but doing so inconsistently... a race in prizm? + + $self->prizm_command( 'CustomerIfService', 'removeElementFromCustomer', + 0, + $cust_main->custnum, + 0, + $svc->mac_addr, + ); + + $err_or_som = $self->prizm_command( 'NetworkIfService', 'getPrizmElements', + [ 'MAC Address' ], + [ $svc->mac_addr ], + [ '=' ], + ); + if ( ref($err_or_som) && $err_or_som->result->[0] ) { # ignore errors + $self->prizm_command( 'NetworkIfService', 'deleteElement', + $err_or_som->result->[0], + 1, + ); } +# end of coping + + my $performance_profile = $svc->performance_profile; + $performance_profile ||= $svc->cust_svc->cust_pkg->part_pkg->pkg; + my $element_name_length = 50; + $element_name_length = $1 + if $self->option('element_name_length') =~ /^\s*(\d+)\s*$/; $err_or_som = $self->prizm_command('NetworkIfService', 'addProvisionedElement', $networkid, $svc->mac_addr, - $name, # we fix this below (bug in prizm?) + substr($name . " " . $svc->description, + 0, $element_name_length), $location, $contact, - sprintf("%032X", $svc->authkey), - $svc->cust_svc->cust_pkg->part_pkg->pkg, + sprintf("%032X", $svc->authkey || 0), + $performance_profile, $svc->vlan_profile, - 1, + ($self->option('ems') ? 1 : 0 ), ); return $err_or_som unless ref($err_or_som); + warn "$me: added provisioned element to prizm\n" if $DEBUG; my (@names) = ('Management IP', 'GPS Latitude', @@ -155,6 +278,7 @@ sub _export_insert { ); return $err_or_som unless ref($err_or_som); + warn "$me: set element configuration\n" if $DEBUG; $err_or_som = $self->prizm_command('NetworkIfService', 'setElementConfigSet', [ $element ], @@ -164,25 +288,28 @@ sub _export_insert { ); return $err_or_som unless ref($err_or_som); + warn "$me: set element vlan profile\n" if $DEBUG; $err_or_som = $self->prizm_command('NetworkIfService', 'setElementConfigSet', [ $element ], - $svc->cust_svc->cust_pkg->part_pkg->pkg, + $performance_profile, 0, 1, ); return $err_or_som unless ref($err_or_som); + warn "$me: set element configset (performance profile)\n" if $DEBUG; $err_or_som = $self->prizm_command('NetworkIfService', 'activateNetworkElements', [ $element ], 1, - 1, + ( $self->option('ems') ? 1 : 0 ), ); return $err_or_som unless ref($err_or_som); + warn "$me: activated element\n" if $DEBUG; $err_or_som = $self->prizm_command('CustomerIfService', 'addElementToCustomer', @@ -194,6 +321,7 @@ sub _export_insert { return $err_or_som unless ref($err_or_som); + warn "$me: added element to customer\n" if $DEBUG; ''; } @@ -201,39 +329,47 @@ sub _export_insert { sub _export_delete { my( $self, $svc ) = ( shift, shift ); - my $custnum = $svc->cust_svc->cust_pkg->cust_main->custnum; + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; - my $err_or_som = $self->prizm_command('NetworkIfService', 'getPrizmElements', - ['MAC Address'], - [$svc->mac_addr], - ['='], - ); - return $err_or_som - unless ref($err_or_som); + my $cust_pkg = $svc->cust_svc->cust_pkg; - return "Can't find prizm element for " . $svc->mac_addr - unless $err_or_som->result->[0]; + my $depend = []; - $err_or_som = $self->prizm_command('NetworkIfService', - 'suspendNetworkElements', - [$err_or_som->result->[0]->elementId], - 1, - 1, - ); + if ($cust_pkg) { + my $queue = new FS::queue { + 'svcnum' => $svc->svcnum, + 'job' => 'FS::part_export::prizm::queued_prizm_command', + }; + my $error = $queue->insert( + ( map { $self->option($_) } + qw( url user password ) ), + 'CustomerIfService', + 'removeElementFromCustomer', + 0, + $cust_pkg->custnum, + 0, + $svc->mac_addr, + ); + + if ($error) { + $dbh->rollback if $oldAutoCommit; + return $error; + } - return $err_or_som - unless ref($err_or_som); + push @$depend, $queue->jobnum; + } - $err_or_som = $self->prizm_command('CustomerIfService', - 'removeElementFromCustomer', - 0, - $custnum, - 0, - $svc->mac_addr, - ); + my $err_or_queue = + $self->queue_statuschange('deleteElement', $depend, $svc, 1); - return $err_or_som - unless ref($err_or_som); + unless (ref($err_or_queue)) { + $dbh->rollback if $oldAutoCommit; + return $err_or_queue; + } + + $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; } @@ -298,64 +434,159 @@ sub _export_replace { return $err_or_som unless ref($err_or_som); + my $performance_profile = $new->performance_profile; + $performance_profile ||= $new->cust_svc->cust_pkg->part_pkg->pkg; + + $err_or_som = $self->prizm_command('NetworkIfService', 'setElementConfigSet', + [ $element ], + $performance_profile, + 0, + 1, + ); + return $err_or_som + unless ref($err_or_som); + ''; } sub _export_suspend { my( $self, $svc ) = ( shift, shift ); + my $depend = []; + my $ems = $self->option('ems') ? 1 : 0; + my $err_or_queue = ''; + + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; + + $err_or_queue = + $self->queue_statuschange('suspendNetworkElements', [], $svc, 1, $ems); + unless (ref($err_or_queue)) { + $dbh->rollback if $oldAutoCommit; + return $err_or_queue; + } + push @$depend, $err_or_queue->jobnum; + + if ($ems && $self->option('always_bam')) { + $err_or_queue = + $self->queue_statuschange('suspendNetworkElements', $depend, $svc, 1, 0); + unless (ref($err_or_queue)) { + $dbh->rollback if $oldAutoCommit; + return $err_or_queue; + } + } - my $err_or_som = $self->prizm_command('NetworkIfService', 'getPrizmElements', - [ 'MAC Address' ], - [ $svc->mac_addr ], - [ '=' ], - ); - return $err_or_som - unless ref($err_or_som); + $dbh->commit or die $dbh->errstr if $oldAutoCommit; - return "Can't find prizm element for " . $svc->mac_addr - unless $err_or_som->result->[0]; + ''; +} - $err_or_som = $self->prizm_command('NetworkIfService', - 'suspendNetworkElements', - [ $err_or_som->result->[0]->elementId ], - 1, - 1, - ); +sub _export_unsuspend { + my( $self, $svc ) = ( shift, shift ); + my $depend = []; + my $ems = $self->option('ems') ? 1 : 0; + my $err_or_queue = ''; + + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; + + if ($ems && $self->option('always_bam')) { + $err_or_queue = + $self->queue_statuschange('activateNetworkElements', [], $svc, 1, 0); + unless (ref($err_or_queue)) { + $dbh->rollback if $oldAutoCommit; + return $err_or_queue; + } + push @$depend, $err_or_queue->jobnum; + } - return $err_or_som - unless ref($err_or_som); + $err_or_queue = + $self->queue_statuschange('activateNetworkElements', $depend, $svc, 1, $ems); + unless (ref($err_or_queue)) { + $dbh->rollback if $oldAutoCommit; + return $err_or_queue; + } + + $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; +} + +sub export_links { + my( $self, $svc, $arrayref ) = ( shift, shift, shift ); + push @$arrayref, + 'SM'; + + ''; } -sub _export_unsuspend { - my( $self, $svc ) = ( shift, shift ); +sub queue_statuschange { + my( $self, $method, $jobs, $svc, @args ) = @_; + + # already in a transaction and can't die here + + my $queue = new FS::queue { + 'svcnum' => $svc->svcnum, + 'job' => 'FS::part_export::prizm::statuschange', + }; + my $error = $queue->insert( + ( map { $self->option($_) } + qw( url user password ) ), + $method, + $svc->mac_addr, + @args, + ); - my $err_or_som = $self->prizm_command('NetworkIfService', 'getPrizmElements', - [ 'MAC Address' ], - [ $svc->mac_addr ], - [ '=' ], - ); - return $err_or_som + unless ($error) { # successful insertion + foreach my $job ( @$jobs ) { + $error ||= $queue->depend_insert($job); + } + } + + $error or $queue; +} + +sub statuschange { # subroutine + my( $url, $user, $password, $method, $mac_addr, @args) = @_; + + eval "use Net::Prizm 0.04 qw(CustomerInfo PrizmElement);"; + die $@ if $@; + + my $prizm = new Net::Prizm ( + namespace => 'NetworkIfService', + url => $url, + user => $user, + password => $password, + ); + + my $err_or_som = $prizm->getPrizmElements( [ 'MAC Address' ], + [ $mac_addr ], + [ '=' ], + ); + die $err_or_som unless ref($err_or_som); - return "Can't find prizm element for " . $svc->mac_addr + die "Can't find prizm element for " . $mac_addr unless $err_or_som->result->[0]; - $err_or_som = $self->prizm_command('NetworkIfService', - 'activateNetworkElements', - [ $err_or_som->result->[0]->elementId ], - 1, - 1, - ); + my $arg1; + # yuck! + if ($method =~ /suspendNetworkElements/ || $method =~ /activateNetworkElements/) { + $arg1 = [ $err_or_som->result->[0]->elementId ]; + }else{ + $arg1 = $err_or_som->result->[0]->elementId; + } + $err_or_som = $prizm->$method( $arg1, @args ); - return $err_or_som + die $err_or_som unless ref($err_or_som); ''; } + 1;