attach SM's to default network, improved unsuspend & delete, option for BAM only...
[freeside.git] / FS / FS / part_export / prizm.pm
1 package FS::part_export::prizm;
2
3 use vars qw(@ISA %info %options $DEBUG);
4 use Tie::IxHash;
5 use FS::Record qw(fields);
6 use FS::part_export;
7
8 @ISA = qw(FS::part_export);
9 $DEBUG = 1;
10
11 tie %options, 'Tie::IxHash',
12   'url'      => { label => 'Northbound url', default=>'https://localhost:8443/prizm/nbi' },
13   'user'     => { label => 'Northbound username', default=>'nbi' },
14   'password' => { label => 'Password', default => '' },
15   'ems'      => { label => 'Full EMS', type => 'checkbox' },
16 ;
17
18 %info = (
19   'svc'      => 'svc_broadband',
20   'desc'     => 'Real-time export to Northbound Interface',
21   'options'  => \%options,
22   'nodomain' => 'Y',
23   'notes'    => 'These are notes.'
24 );
25
26 sub prizm_command {
27   my ($self,$namespace,$method) = (shift,shift,shift);
28
29   eval "use Net::Prizm qw(CustomerInfo PrizmElement);";
30   die $@ if $@;
31
32   my $prizm = new Net::Prizm (
33     namespace => $namespace,
34     url => $self->option('url'),
35     user => $self->option('user'),
36     password => $self->option('password'),
37   );
38   
39   $prizm->$method(@_);
40 }
41
42 sub queued_prizm_command {  # subroutine
43   my( $url, $user, $password, $namespace, $method, @args ) = @_;
44
45   eval "use Net::Prizm qw(CustomerInfo PrizmElement);";
46   die $@ if $@;
47
48   my $prizm = new Net::Prizm (
49     namespace => $namespace,
50     url => $url,
51     user => $user,
52     password => $password,
53   );
54   
55   $err_or_som = $prizm->$method( @args);
56
57   die $err_or_som
58     unless ref($err_or_som);
59
60   '';
61
62 }
63
64 sub _export_insert {
65   my( $self, $svc ) = ( shift, shift );
66
67   my $cust_main = $svc->cust_svc->cust_pkg->cust_main;
68
69   my $err_or_som = $self->prizm_command('CustomerIfService', 'getCustomers',
70                                         ['import_id'],
71                                         [$cust_main->custnum],
72                                         ['='],
73                                        );
74   return $err_or_som
75     unless ref($err_or_som);
76
77   my $pre = '';
78   if ( defined $cust_main->dbdef_table->column('ship_last') ) {
79     $pre = $cust_main->ship_last ? 'ship_' : '';
80   }
81   my $name = $pre ? $cust_main->ship_name : $cust_main->name;
82   my $location = join(" ", map { my $method = "$pre$_"; $cust_main->$method }
83                            qw (address1 address2 city state zip)
84                      );
85   my $contact = join(" ", map { my $method = "$pre$_"; $cust_main->$method }
86                           qw (daytime night)
87                      );
88
89   my $pcustomer;
90   if ($err_or_som->result->[0]) {
91     $pcustomer = $err_or_som->result->[0]->customerId;
92   }else{
93     my $chashref = $cust_main->hashref;
94     my $customerinfo = {
95       importId         => $cust_main->custnum,
96       customerName     => $name,
97       customerType     => 'freeside',
98       address1         => $chashref->{"${pre}address1"},
99       address2         => $chashref->{"${pre}address2"},
100       city             => $chashref->{"${pre}city"},
101       state            => $chashref->{"${pre}state"},
102       zipCode          => $chashref->{"${pre}zip"},
103       workPhone        => $chashref->{"${pre}daytime"},
104       homePhone        => $chashref->{"${pre}night"},
105       email            => @{[$cust_main->invoicing_list_emailonly]}[0],
106       extraFieldNames  => [ 'country', 'freesideId',
107                           ],
108       extraFieldValues => [ $chashref->{"${pre}country"}, $cust_main->custnum,
109                           ],
110     };
111
112     $err_or_som = $self->prizm_command('CustomerIfService', 'addCustomer',
113                                        $customerinfo);
114     return $err_or_som
115       unless ref($err_or_som);
116
117     $pcustomer = $err_or_som->result;
118   }
119   warn "multiple prizm customers found for $cust_main->custnum"
120     if scalar(@$pcustomer) > 1;
121
122 #  #kinda big question/expensive
123 #  $err_or_som = $self->prizm_command('NetworkIfService', 'getPrizmElements',
124 #                                     ['Network Default Gateway Address'],
125 #                                     [$svc->addr_block->ip_gateway],
126 #                                     ['='],
127 #                   );
128 #  return $err_or_som
129 #    unless ref($err_or_som);
130 #
131 #  return "No elements in network" unless exists $err_or_som->result->[0];
132
133   my $networkid = 0;
134 #  for (my $i = 0; $i < $err_or_som->result->[0]->attributeNames; $i++) {
135 #    if ($err_or_som->result->[0]->attributeNames->[$i] eq "Network.ID"){
136 #      $networkid = $err_or_som->result->[0]->attributeValues->[$i];
137 #      last;
138 #    }
139 #  }
140
141   $err_or_som = $self->prizm_command('NetworkIfService', 'addProvisionedElement',
142                                       $networkid,
143                                       $svc->mac_addr,
144                                       $name, # we fix this below (bug in prizm?)
145                                       $location,
146                                       $contact,
147                                       sprintf("%032X", $svc->authkey),
148                                       $svc->cust_svc->cust_pkg->part_pkg->pkg,
149                                       $svc->vlan_profile,
150                                       $self->option('ems') == 1,
151                                      );
152   return $err_or_som
153     unless ref($err_or_som);
154
155   my (@names) = ('Management IP',
156                  'GPS Latitude',
157                  'GPS Longitude',
158                  'GPS Altitude',
159                  'Site Name',
160                  'Site Location',
161                  'Site Contact',
162                  );
163   my (@values) = ($svc->ip_addr,
164                   $svc->latitude,
165                   $svc->longitude,
166                   $svc->altitude,
167                   $name . " " . $svc->description,
168                   $location,
169                   $contact,
170                   );
171   $element = $err_or_som->result->elementId;
172   $err_or_som = $self->prizm_command('NetworkIfService', 'setElementConfig',
173                                      [ $element ],
174                                      \@names,
175                                      \@values,
176                                      0,
177                                      1,
178                                     );
179   return $err_or_som
180     unless ref($err_or_som);
181
182   $err_or_som = $self->prizm_command('NetworkIfService', 'setElementConfigSet',
183                                      [ $element ],
184                                      $svc->vlan_profile,
185                                      0,
186                                      1,
187                                     );
188   return $err_or_som
189     unless ref($err_or_som);
190
191   $err_or_som = $self->prizm_command('NetworkIfService', 'setElementConfigSet',
192                                      [ $element ],
193                                      $svc->cust_svc->cust_pkg->part_pkg->pkg,
194                                      0,
195                                      1,
196                                     );
197   return $err_or_som
198     unless ref($err_or_som);
199
200   $err_or_som = $self->prizm_command('NetworkIfService',
201                                      'activateNetworkElements',
202                                      [ $element ],
203                                      1,
204                                      $self->option('ems') == 1,
205                                     );
206
207   return $err_or_som
208     unless ref($err_or_som);
209
210   $err_or_som = $self->prizm_command('CustomerIfService',
211                                      'addElementToCustomer',
212                                      0,
213                                      $cust_main->custnum,
214                                      0,
215                                      $svc->mac_addr,
216                                     );
217
218   return $err_or_som
219     unless ref($err_or_som);
220
221   '';
222 }
223
224 sub _export_delete {
225   my( $self, $svc ) = ( shift, shift );
226
227   my $cust_pkg = $svc->cust_svc->cust_pkg;
228
229   my $depend = [];
230
231   if ($cust_pkg) {
232     my $queue = new FS::queue {
233       'svcnum' => $svc->svcnum,
234       'job'    => 'FS::part_export::prizm::queued_prizm_command',
235     };
236     $queue->insert(
237       ( map { $self->option($_) }
238             qw( url user password ) ),
239       'CustomerIfService',
240       'removeElementFromCustomer',
241       0,
242       $cust_pkg->custnum,
243       0,
244       $svc->mac_addr,
245     ) && push @$depend, $queue->jobnum;
246   }
247
248   $self->queue_statuschange('deleteElement', $depend, $svc, 1);
249 }
250
251 sub _export_replace {
252   my( $self, $new, $old ) = ( shift, shift, shift );
253
254   my $err_or_som = $self->prizm_command('NetworkIfService', 'getPrizmElements',
255                                         [ 'MAC Address' ],
256                                         [ $old->mac_addr ],
257                                         [ '=' ],
258                                        );
259   return $err_or_som
260     unless ref($err_or_som);
261
262   return "Can't find prizm element for " . $old->mac_addr
263     unless $err_or_som->result->[0];
264
265   my %freeside2prizm = (  mac_addr     => 'MAC Address',
266                           ip_addr      => 'Management IP',
267                           latitude     => 'GPS Latitude',
268                           longitude    => 'GPS Longitude',
269                           altitude     => 'GPS Altitude',
270                           authkey      => 'Authentication Key',
271                        );
272   
273   my (@values);
274   my (@names) = map { push @values, $new->$_; $freeside2prizm{$_} }
275     grep { $old->$_ ne $new->$_ }
276       grep { exists($freeside2prizm{$_}) }
277         fields( 'svc_broadband' );
278
279   if ($old->description ne $new->description) {
280     my $cust_main = $old->cust_svc->cust_pkg->cust_main;
281     my $name = defined($cust_main->dbdef_table->column('ship_last'))
282              ? $cust_main->ship_name
283              : $cust_main->name;
284     push @values, $name . " " . $new->description;
285     push @names, "Site Name";
286   }
287
288   my $element = $err_or_som->result->[0]->elementId;
289
290   $err_or_som = $self->prizm_command('NetworkIfService', 'setElementConfig',
291                                         [ $element ],
292                                         \@names,
293                                         \@values,
294                                         0,
295                                         1,
296                                        );
297   return $err_or_som
298     unless ref($err_or_som);
299
300   $err_or_som = $self->prizm_command('NetworkIfService', 'setElementConfigSet',
301                                      [ $element ],
302                                      $new->vlan_profile,
303                                      0,
304                                      1,
305                                     )
306     if $old->vlan_profile ne $new->vlan_profile;
307
308   return $err_or_som
309     unless ref($err_or_som);
310
311   '';
312
313 }
314
315 sub _export_suspend {
316   my( $self, $svc ) = ( shift, shift );
317   my $ems = $self->option('ems') == 1;
318   $self->queue_statuschange('suspendNetworkElements', [], $svc, 1, $ems);
319 }
320
321 sub _export_unsuspend {
322   my( $self, $svc ) = ( shift, shift );
323   my $ems = $self->option('ems') == 1;
324   $self->queue_statuschange('activateNetworkElements', [], $svc, 1, $ems);
325 }
326
327 sub queue_statuschange {
328   my( $self, $method, $jobs, $svc, @args ) = @_;
329
330   # already in a transaction and can't die here
331
332   my $queue = new FS::queue {
333     'svcnum' => $svc->svcnum,
334     'job'    => 'FS::part_export::prizm::statuschange',
335   };
336   $queue->insert(
337     ( map { $self->option($_) }
338           qw( url user password ) ),
339     $method,
340     $svc->mac_addr,
341     @args,
342   );
343
344   if ($queue->jobnum) {                   # successful insertion
345     foreach my $job ( @$jobs ) {
346       $queue->depend_insert($job);
347     }
348   }
349
350 }
351
352 sub statuschange {  # subroutine
353   my( $url, $user, $password, $method, $mac_addr, @args) = @_;
354
355   eval "use Net::Prizm qw(CustomerInfo PrizmElement);";
356   die $@ if $@;
357
358   my $prizm = new Net::Prizm (
359     namespace => 'NetworkIfService',
360     url => $url,
361     user => $user,
362     password => $password,
363   );
364   
365   my $err_or_som = $prizm->getPrizmElements( [ 'MAC Address' ],
366                                              [ $mac_addr ],
367                                              [ '=' ],
368                                            );
369   die $err_or_som
370     unless ref($err_or_som);
371
372   die "Can't find prizm element for " . $mac_addr
373     unless $err_or_som->result->[0];
374
375   my $arg1;
376   # yuck!
377   if ($method =~ /suspendNetworkElements/ || $method =~ /activateNetworkElements/) {
378     $arg1 = [ $err_or_som->result->[0]->elementId ];
379   }else{
380     $arg1 = $err_or_som->result->[0]->elementId;
381   }
382   $err_or_som = $prizm->$method( $arg1, @args );
383
384   die $err_or_som
385     unless ref($err_or_som);
386
387   '';
388
389 }
390
391
392 1;