1 package FS::part_export::router;
3 =head1 FS::part_export::router
5 This export connects to a router and transmits commands via telnet or SSH.
6 It requires the following custom router fields:
10 =item admin_address - IP address (or hostname) to connect
12 =item admin_user - username for admin access
14 =item admin_password - password for admin access
18 The export itself needs the following options:
22 =item insert, replace, delete - command strings (to be interpolated)
24 =item Prompt - prompt string to expect from router after successful login
26 =item Timeout - time to wait for prompt string
30 (Prompt and Timeout are required only for telnet connections.)
34 use vars qw(@ISA %info @saltset);
36 use String::ShellQuote;
39 @ISA = qw(FS::part_export);
41 tie my %options, 'Tie::IxHash',
45 options => [qw(telnet ssh)],
47 'insert' => {label=>'Insert command', default=>'' },
48 'delete' => {label=>'Delete command', default=>'' },
49 'replace' => {label=>'Replace command', default=>'' },
50 'Timeout' => {label=>'Time to wait for prompt', default=>'20' },
51 'Prompt' => {label=>'Prompt string', default=>'#' }
55 'svc' => 'svc_broadband',
56 'desc' => 'Send a command to a router.',
57 'options' => \%options,
58 'notes' => 'Installation of Net::Telnet from CPAN is required for telnet connections. ( more detailed description from Kristian / fire2wire? )',
61 @saltset = ( 'a'..'z' , 'A'..'Z' , '0'..'9' , '.' , '/' );
63 sub rebless { shift; }
67 $self->_export_command('insert', @_);
72 $self->_export_command('delete', @_);
77 $self->_export_command('suspend', @_);
80 sub _export_unsuspend {
82 $self->_export_command('unsuspend', @_);
86 my ( $self, $action, $svc_broadband) = (shift, shift, shift);
87 my $command = $self->option($action);
88 return '' if $command =~ /^\s*$/;
93 ${$_} = $svc_broadband->getfield($_) foreach $svc_broadband->fields;
96 my $router = $svc_broadband->addr_block->router;
98 $r{$_} = $router->getfield($_) foreach $router->virtual_fields;
100 #warn eval(qq("$command"));
102 warn "admin_address: '$r{admin_address}'";
104 if ($r{admin_address} ne '') {
105 $self->router_queue( $svc_broadband->svcnum, $self->option('protocol'),
106 user => $r{admin_user},
107 password => $r{admin_password},
108 host => $r{admin_address},
109 Timeout => $self->option('Timeout'),
110 Prompt => $self->option('Prompt'),
111 command => eval(qq("$command")),
118 sub _export_replace {
120 # We don't handle the case of a svc_broadband moving between routers.
121 # If you want to do that, reprovision the service.
123 my($self, $new, $old ) = (shift, shift, shift);
124 my $command = $self->option('replace');
128 ${"old_$_"} = $old->getfield($_) foreach $old->fields;
129 ${"new_$_"} = $new->getfield($_) foreach $new->fields;
132 my $router = $new->addr_block->router;
134 $r{$_} = $router->getfield($_) foreach $router->virtual_fields;
136 if ($r{admin_address} ne '') {
137 $self->router_queue( $new->svcnum, $self->option('protocol'),
138 user => $r{admin_user},
139 password => $r{admin_password},
140 host => $r{admin_address},
141 Timeout => $self->option('Timeout'),
142 Prompt => $self->option('Prompt'),
143 command => eval(qq("$command")),
150 #a good idea to queue anything that could fail or take any time
153 my( $self, $svcnum, $protocol ) = (shift, shift, shift);
154 my $queue = new FS::queue {
157 $queue->job ("FS::part_export::router::".$protocol."_cmd");
158 $queue->insert( @_ );
161 sub ssh_cmd { #subroutine, not method
163 &Net::SSH::ssh_cmd( { @_ } );
167 eval 'use Net::Telnet;';
174 my $t = new Net::Telnet (Timeout => $arg{Timeout},
175 Prompt => $arg{Prompt});
176 $t->open($arg{host});
177 $t->login($arg{user}, $arg{password});
178 my @error = $t->cmd($arg{command});
179 die @error if (grep /^ERROR/, @error);
182 #sub router_insert { #subroutine, not method
184 #sub router_replace { #subroutine, not method
186 #sub router_delete { #subroutine, not method