grandstream device configuration support #4220
[freeside.git] / FS / FS / part_export / grandstream.pm
1 package FS::part_export::grandstream;
2
3 use vars qw(@ISA $me %info $GAPSLITE_HOME $JAVA_HOME);
4 use URI;
5 use MIME::Base64;
6 use Tie::IxHash;
7 use FS::part_export;
8 use FS::CGI qw(rooturl);
9
10 @ISA = qw(FS::part_export);
11 $me = '[' . __PACKAGE__ . ']';
12 $GAPSLITE_HOME = '/usr/local/src/GS/GS_CFG_GEN/';
13 $JAVA_HOME = '/usr/lib/jvm/java-6-sun/';
14 $JAVA_HOME = '/usr/lib/jvm/java-1.4.2-gcj-4.1-1.4.2.0/';
15
16 tie my %options, 'Tie::IxHash',
17   'upload'          => { label=>'Enable upload to tftpserver',
18                          type=>'checkbox',
19                        },
20   'user'            => { label=>'User name for ssh to tftp server' },
21   'tftproot'        => { label=>'Directory in which to upload configuration' },
22   'java_home'       => { label=>'Path to java to be used',
23                          default=>$JAVA_HOME,
24                        },
25   'gapslite_home'   => { label=>'Path to grandstream configuration tool',
26                          default=>$GAPSLITE_HOME,
27                        },
28   'template'        => { label=>'Configuration template',
29                          type=>'textarea',
30                          notes=>'Type or paste the configuration template here',
31                        },
32 ;
33
34 %info = (
35   'svc'      => [ qw( part_device ) ], # svc_phone
36   'desc'     => 'Provision phone numbers to Grandstream Networks phones',
37   'options'  => \%options,
38   'notes'    => '',
39 );
40
41 sub rebless { shift; }
42
43 sub gs_create_config {
44   my($self, $mac, %opt) = (@_);
45
46   eval "use Net::SCP;";
47   die $@ if $@;
48
49   warn "gs_create_config called with mac of $mac\n";
50   $mac = sprintf('%012s', lc($mac));
51   my $dir = '%%%FREESIDE_CONF%%%/cache.'. $FS::UID::datasrc;
52
53   my $fh = new File::Temp(
54     TEMPLATE => "grandstream.$mac.XXXXXXXX",
55     DIR      => $dir,
56     UNLINK   => 0,
57   );
58
59   my $filename = $fh->filename;
60
61   #my $template = new Text::Template (
62   #  TYPE       => 'ARRAY',
63   #  SOURCE     => $self->option('template'),
64   #  DELIMITERS => $delimiters,
65   #  OUTPUT     => $fh,
66   #);
67
68   #$template->compile or die "Can't compile template: $Text::Template::ERROR\n";
69
70   #my $config = $template->fill_in( HASH => { mac_addr => $mac } );
71
72   print $fh $self->option('template') or die "print failed: $!";
73   close $fh;
74   
75   system( "export GAPSLITE_HOME=$GAPSLITE_HOME; export JAVA_HOME=$JAVA_HOME; ".
76           "cd $dir; $GAPSLITE_HOME/bin/encode.sh $mac $filename $dir/cfg$mac"
77         ) == 0
78     or die "grandstream encode failed: $!";
79
80   unlink $filename;
81
82   open my $encoded, "$dir/cfg$mac"  or die "open cfg$mac failed: $!";
83   
84   my $content;
85
86   if ($opt{upload}) {
87     if ($self->option('upload')) {
88       my $scp = new Net::SCP ( {
89         'host' => $self->machine,
90         'user' => $self->option('user'),
91         'cwd'  => $self->option('tftproot'),
92       } );
93
94       $scp->put( "$dir/cfg$mac" ) or die "upload failed: ". $scp->errstr;
95     }
96   } else {
97     local $/;
98     $content = <$encoded>;
99   }
100
101   close $encoded;
102   unlink "$dir/cfg$mac";
103
104   $content;
105 }
106
107 sub gs_create {
108   my($self, $mac) = (shift, shift);
109
110   return unless $mac;  # be more alarmed?  Or check upstream?
111
112   $self->gs_create_config($mac, 'upload' => 1);
113   '';
114 }
115
116 sub gs_delete {
117   my($self, $mac) = (shift, shift);
118
119   $mac = sprintf('%012s', lc($mac));
120
121   ssh_cmd( user => $self->option('user'),
122            host => $self->machine,
123            command => 'rm',
124            args    => [ '-f', $self->option(tftproot). "/cfg$mac" ],
125          );
126   '';
127
128 }
129
130 sub ssh_cmd { #subroutine, not method
131   use Net::SSH '0.08';
132   &Net::SSH::ssh_cmd( { @_ } );
133 }
134
135 sub _export_insert {
136 #  my( $self, $svc_phone ) = (shift, shift);
137 #  $self->gs_create($svc_phone->mac_addr);
138   '';
139 }
140
141 sub _export_replace {
142 #  my( $self, $new_svc, $old_svc ) = (shift, shift, shift);
143 #  $self->gs_delete($old_svc->mac_addr);
144 #  $self->gs_create($new_svc->mac_addr);
145   '';
146 }
147
148 sub _export_delete {
149 #  my( $self, $svc_phone ) = (shift, shift);
150 #  $self->gs_delete($svc_phone->mac_addr);
151   '';
152 }
153
154 sub _export_suspend {
155   '';
156 }
157
158 sub _export_unsuspend {
159   '';
160 }
161
162 sub export_device_insert {
163   my( $self, $svc_phone, $phone_device ) = (shift, shift, shift);
164   $self->gs_create($phone_device->mac_addr);
165   '';
166 }
167
168 sub export_device_delete {
169   my( $self, $svc_phone, $phone_device ) = (shift, shift, shift);
170   $self->gs_delete($phone_device->mac_addr);
171   '';
172 }
173
174 sub export_device_config {
175   my( $self, $svc_phone, $phone_device ) = (shift, shift, shift);
176
177   my $mac;
178 #  if ($phone_device) {
179     $mac = $phone_device->mac_addr;
180 #  } else {
181 #    $mac = $svc_phone->mac_addr;
182 #  }
183
184   return '' unless $mac;  # be more alarmed?  Or check upstream?
185
186   $self->gs_create_config($mac);
187 }
188
189
190 sub export_device_replace {
191   my( $self, $svc_phone, $new_svc_or_device, $old_svc_or_device ) =
192     (shift, shift, shift, shift);
193
194   $self->gs_delete($old_svc_or_device->mac_addr);
195   $self->gs_create($new_svc_or_device->mac_addr);
196   '';
197 }
198
199 # bad overloading?
200 sub export_links {
201   my($self, $svc_phone, $arrayref) = (shift, shift, shift);
202
203   return;  # remove if we actually support being an export for svc_phone;
204
205   my @deviceparts = map { $_->devicepart } $self->export_device;
206   my @devices = grep { my $part = $_->devicepart;
207                        scalar( grep { $_ == $part } @deviceparts );
208                      } $svc_phone->phone_device;
209
210   my $export = $self->exportnum;
211   my $fsurl = rooturl();
212   if (@devices) {
213     foreach my $device ( @devices ) {
214       next unless $device->mac_addr;
215       my $num = $device->devicenum;
216       push @$arrayref,
217         qq!<A HREF="$fsurl/misc/phone_device_config.html?exportnum=$export;devicenum=$num">!.
218         qq! Phone config </A>!;
219       }
220   } elsif ($svc_phone->mac_addr) {
221     my $num = $svc_phone->svcnum;
222     push @$arrayref,
223       qq!<A HREF="$fsurl/misc/phone_device_config.html?exportnum=$export;svcnum=$num">!.
224       qq! Phone config </A>!;
225   } #else
226   '';
227 }
228
229 sub export_device_links {
230   my($self, $svc_phone, $device, $arrayref) = (shift, shift, shift, shift);
231
232   return unless $device && $device->mac_addr;
233   my $export = $self->exportnum;
234   my $fsurl = rooturl();
235   my $num = $device->devicenum;
236   push @$arrayref,
237     qq!<A HREF="$fsurl/misc/phone_device_config.html?exportnum=$export;devicenum=$num">!.
238     qq! Phone config </A>!;
239   '';
240 }
241
242 1;