RT# 83450 - fixed rateplan export
[freeside.git] / FS / FS / part_export / broadband_shellcommands.pm
1 package FS::part_export::broadband_shellcommands;
2
3 use strict;
4 use vars qw(@ISA %info);
5 use Tie::IxHash;
6 use FS::part_export;
7
8 @ISA = qw(FS::part_export);
9
10 tie my %options, 'Tie::IxHash',
11   'user'          => { label   => 'Remote username',
12                        default => 'freeside' },
13   'insert'        => { label   => 'Insert command',
14                        default => 'php provision.php --mac=$mac_addr --plan=$plan_id --account=active',
15                      },
16   'delete'        => { label   => 'Delete command',
17                        default  => '',
18                      },
19   'replace'       => { label   => 'Modification command',
20                        default => '',
21                      },
22   'suspend'       => { label   => 'Suspension command',
23                        default => 'php provision.php --mac=$mac_addr --plan=$plan_id --account=suspend',
24                      },
25   'unsuspend'     => { label   => 'Unsuspension command',
26                        default => '',
27                      },
28   'uppercase_mac' => { label   => 'Force MACs to uppercase', 
29                        type   => 'checkbox',
30                      }
31 ;
32
33 %info = (
34   'svc'     => 'svc_broadband',
35   'desc'    => 'Run remote commands via SSH, for svc_broadband services',
36   'options' => \%options,
37   'notes'   => <<'END'
38 Run remote commands via SSH, for broadband services.
39 <BR><BR>
40 All fields in svc_broadband are available for interpolation, as well as pkgnum, locationnum and custnum (prefixed with <code>new_</code> or <code>old_</code>
41 for replace operations).
42 END
43 );
44
45
46 sub rebless { shift; }
47
48 sub _export_insert {
49   my($self) = shift;
50   $self->_export_command('insert', @_);
51 }
52
53 sub _export_delete {
54   my($self) = shift;
55   $self->_export_command('delete', @_);
56 }
57
58 sub _export_suspend {
59   my($self) = shift;
60   $self->_export_command('suspend', @_);
61 }
62
63 sub _export_unsuspend {
64   my($self) = shift;
65   $self->_export_command('unsuspend', @_);
66 }
67
68 sub _export_command {
69   my ( $self, $action, $svc_broadband) = (shift, shift, shift);
70   my $command = $self->option($action);
71   return '' if $command =~ /^\s*$/;
72
73   my $command_string = $self->_export_subvars( $svc_broadband, $command );
74
75   $self->shellcommands_queue( $svc_broadband->svcnum,
76     user    => $self->option('user')||'root',
77     host    => $self->machine,
78     command => $command_string,
79   );
80 }
81
82 sub _export_subvars {
83   my( $self, $svc_broadband, $command ) = @_;
84
85   no strict 'vars';
86   {
87     no strict 'refs';
88     ${$_} = $svc_broadband->getfield($_) foreach $svc_broadband->fields;
89   }
90
91   $mac_addr = uc $mac_addr
92     if $self->option('uppercase_mac');
93
94   my $cust_pkg = $svc_broadband->cust_svc->cust_pkg;
95   $pkgnum = $cust_pkg ? $cust_pkg->pkgnum : '';
96   $locationnum = $cust_pkg ? $cust_pkg->locationnum : '';
97   $custnum = $cust_pkg ? $cust_pkg->custnum : '';
98
99   eval(qq("$command"));
100 }
101
102 sub _export_replace {
103   my($self, $new, $old ) = (shift, shift, shift);
104   my $command = $self->option('replace');
105
106   my $command_string = $self->_export_subvars_replace( $new, $old, $command );
107
108   $self->shellcommands_queue( $new->svcnum,
109     user    => $self->option('user')||'root',
110     host    => $self->machine,
111     command => $command_string,
112   );
113 }
114
115 sub _export_subvars_replace {
116   my( $self, $new, $old, $command ) = @_;
117
118   no strict 'vars';
119   {
120     no strict 'refs';
121     ${"old_$_"} = $old->getfield($_) foreach $old->fields;
122     ${"new_$_"} = $new->getfield($_) foreach $new->fields;
123   }
124
125   if ( $self->option('uppercase_mac') ) {
126     $old_mac_addr = uc $old_mac_addr;
127     $new_mac_addr = uc $new_mac_addr;
128   }
129
130   my $old_cust_pkg = $old->cust_svc->cust_pkg;
131   my $new_cust_pkg = $new->cust_svc->cust_pkg;
132   $old_pkgnum = $old_cust_pkg ? $old_cust_pkg->pkgnum : '';
133   $old_locationnum = $old_cust_pkg ? $old_cust_pkg->locationnum : '';
134   $old_custnum = $old_cust_pkg ? $old_cust_pkg->custnum : '';
135   $new_pkgnum = $new_cust_pkg ? $new_cust_pkg->pkgnum : '';
136   $new_locationnum = $new_cust_pkg ? $new_cust_pkg->locationnum : '';
137   $new_custnum = $new_cust_pkg ? $new_cust_pkg->custnum : '';
138
139   eval(qq("$command"));
140 }
141
142
143 #a good idea to queue anything that could fail or take any time
144 sub shellcommands_queue {
145   my( $self, $svcnum ) = (shift, shift);
146   my $queue = new FS::queue {
147     'svcnum' => $svcnum,
148     'job'    => "FS::part_export::broadband_shellcommands::ssh_cmd",
149   };
150   $queue->insert( @_ );
151 }
152
153 sub ssh_cmd { #subroutine, not method
154   use Net::OpenSSH;
155   my $opt = { @_ };
156   my $ssh = Net::OpenSSH->new($opt->{'user'}.'@'.$opt->{'host'});
157   die "Couldn't establish SSH connection: ". $ssh->error if $ssh->error;
158   my ($output, $errput) = $ssh->capture2($opt->{'command'});
159   die "Error running SSH command: ". $ssh->error if $ssh->error;
160   die $errput if $errput;
161   die $output if $output;
162   '';
163 }
164
165 1;