1 package FS::part_export::freeswitch;
2 use base qw( FS::part_export );
4 use vars qw( %info ); # $DEBUG );
8 use FS::Record qw( qsearch ); #qsearchs );
10 #use FS::Schema qw( dbdef );
14 tie my %options, 'Tie::IxHash',
15 'user' => { label => 'SSH username', default=>'root', },
16 'directory' => { label => 'Directory to store FreeSWITCH account XML files (one file per domain)',
17 default => '/usr/local/freeswitch/conf/directory/',
19 #'domain' => { label => 'Optional fixed SIP domain to use, overrides svc_phone domain', },
20 'reload' => { label => 'Reload command',
21 default => '/usr/local/freeswitch/bin/fs_cli -x reloadxml',
23 'header_template' => { label => 'Domain XML configuration header',
28 <domain name="<% $domain %>">
30 <group name="default">
34 'user_template' => { label => 'User XML configuration template',
37 <user id="<% $phonenum %>">
39 <param name="password" value="<% $sip_password %>"/>
45 'footer_template' => { label => 'Domain XML configuration footer',
59 'desc' => 'Provision phone services to FreeSWITCH XML configuration files',
60 'options' => \%options,
62 Export XML account configuration files to FreeSWITCH, one per domain.
64 You will need to enable the svc_phone-domain configuration setting and
65 <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:1.9:Documentation:Administration:SSH_Keys">setup SSH for unattended operation</a>.
69 sub rebless { shift; }
72 my( $self, $svc_phone ) = ( shift, shift );
74 $self->_export_rebuild_domain($svc_phone);
79 my( $self, $new, $old ) = ( shift, shift, shift );
81 my $error = $self->_export_rebuild_domain($new);
82 return $error if $error;
84 if ( $new->domsvc ne $old->domsvc && $old->domsvc ) {
85 $error = $self->_export_rebuild_domain($old);
86 return $error if $error;
93 my( $self, $svc_phone ) = ( shift, shift );
95 $self->_export_rebuild_domain($svc_phone);
98 sub _export_rebuild_domain {
99 my($self, $svc_phone) = ( shift, shift );
101 eval "use Net::SCP;";
104 #create and copy over file
106 my $tempdir = '%%%FREESIDE_CONF%%%/cache.'. $FS::UID::datasrc;
108 my $domain = $svc_phone->domain or return "domain required";
110 my $fh = new File::Temp(
111 TEMPLATE => "$tempdir/freeswitch.$domain.XXXXXXXX",
116 print $fh $self->freeswitch_template_fillin( $domain, 'header' )
117 or die "print to freeswitch template failed: $!";
119 my @dom_svc_phone = qsearch( 'svc_phone', { 'domsvc'=>$svc_phone->domsvc } );
121 foreach my $dom_svc_phone (@dom_svc_phone) {
123 print $fh $self->freeswitch_template_fillin( $dom_svc_phone, 'user' )
124 or die "print to freeswitch template failed: $!";
128 print $fh $self->freeswitch_template_fillin( $domain, 'footer' )
129 or die "print to freeswitch template failed: $!";
133 my $scp = new Net::SCP;
134 my $user = $self->option('user')||'root';
135 my $host = $self->machine;
136 my $dir = $self->option('directory');
138 $scp->scp( $fh->filename, "$user\@$host:$dir/$domain.xml" )
139 or return $scp->{errstr};
141 #signal freeswitch to reload config
142 $self->freeswitch_ssh( command => $self->option('reload') );
148 sub freeswitch_template_fillin {
149 my( $self, $svc_phone_or_dom, $template ) = (shift, shift, shift);
151 $template ||= 'user'; #?
154 my $tt = new Text::Template (
156 SOURCE => $self->option($template.'_template'),
157 DELIMITERS => [ '<%', '%>' ],
160 #false lazinessish w/phone_shellcommands::_export_command
161 my %hash = ref($svc_phone_or_dom)
162 ? ( map { $_ => $svc_phone_or_dom->getfield($_) } $svc_phone_or_dom->fields )
163 : ( 'domain' => $svc_phone_or_dom );
165 #might as well do em all, they're all going in an XML file as attribs
166 foreach ( keys %hash ) {
167 $hash{$_} =~ s/'/'/g;
168 $hash{$_} =~ s/"/"/g;
176 ##a good idea to queue anything that could fail or take any time
177 #sub shellcommands_queue {
178 # my( $self, $svcnum ) = (shift, shift);
179 # my $queue = new FS::queue {
180 # 'svcnum' => $svcnum,
181 # 'job' => "FS::part_export::freeswitch::ssh_cmd",
183 # $queue->insert( @_ );
186 sub freeswitch_ssh { #method
188 ssh_cmd( user => $self->option('user')||'root',
189 host => $self->machine,
194 sub ssh_cmd { #subroutine, not method
197 open my $def_in, '<', '/dev/null' or die "unable to open /dev/null";
198 my $ssh = Net::OpenSSH->new( $opt->{'user'}.'@'.$opt->{'host'},
199 default_stdin_fh => $def_in,
201 die "Couldn't establish SSH connection: ". $ssh->error if $ssh->error;
202 my ($output, $errput) = $ssh->capture2( #{stdin_discard => 1},
205 die "Error running SSH command: ". $ssh->error if $ssh->error;
207 #who the fuck knows what freeswitch reload outputs, probably a fucking
208 # ascii advertisement for cluecon
209 #die $errput if $errput;
210 #die $output if $output;