From: ivan Date: Fri, 22 Aug 2008 03:01:06 +0000 (+0000) Subject: the master control program has chosen YOU to serve your system on the game grid X-Git-Tag: root_of_webpay_support~424 X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=106d0163556c31a3b2cf9c065ec6d9d6ded0ce64 the master control program has chosen YOU to serve your system on the game grid --- diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index 728a2136b..08b299fba 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -2357,6 +2357,13 @@ worry that config_items is freeside-specific and icky. 'type' => 'text', }, + { + 'key' => 'mcp_svcpart', + 'section' => '', + 'description' => 'Master Control Program svcpart. Leave this blank.', + 'type' => 'text', + }, + ); 1; diff --git a/FS/FS/Mason.pm b/FS/FS/Mason.pm index 219f6b738..77ff66822 100644 --- a/FS/FS/Mason.pm +++ b/FS/FS/Mason.pm @@ -93,6 +93,7 @@ Initializes the Mason environment, loads all Freeside and RT libraries, etc. use FS::Misc qw( send_email send_fax states_hash counties state_label ); use FS::Report::Table::Monthly; use FS::TicketSystem; + use FS::Tron qw( tron_lint ); use FS::agent; use FS::agent_type; diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index e461fc153..86cf4a36c 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -1003,6 +1003,18 @@ sub tables_hashref { 'index' => [ ['svcnum'], ['pkgnum'], ['svcpart'] ], }, + 'cust_svc_option' => { + 'columns' => [ + 'optionnum', 'serial', '', '', '', '', + 'svcnum', 'int', '', '', '', '', + 'optionname', 'varchar', '', $char_d, '', '', + 'optionvalue', 'text', 'NULL', '', '', '', + ], + 'primary_key' => 'optionnum', + 'unique' => [], + 'index' => [ [ 'svcnum' ], [ 'optionname' ] ], + }, + 'part_pkg' => { 'columns' => [ 'pkgpart', 'serial', '', '', '', '', diff --git a/FS/FS/Tron.pm b/FS/FS/Tron.pm new file mode 100644 index 000000000..33280955e --- /dev/null +++ b/FS/FS/Tron.pm @@ -0,0 +1,93 @@ +package FS::Tron; +# a program to monitor outside systems + +use strict; +use warnings; +use base 'Exporter'; +use Net::SSH qw( sshopen2 ); #sshopen3 ); +use FS::Record qw( qsearchs ); +use FS::svc_external; +use FS::cust_svc_option; + +our @EXPORT_OK = qw( tron_scan tron_lint); + +our %desired = ( + #lenient for now, so we can fix up important stuff + 'freeside_version' => qr/^1\.(7\.3|9\.0)/, + 'debian_version' => qr/^4/, + 'apache_mpm' => qw/^(Prefork|$)/, + + #stuff to add/replace later + #'pg_version' => qr/^8\.[1-9]/, + #'apache_version' => qr/^2/, + #'apache_mpm' => qw/^Prefork/, +); + +sub tron_scan { + my $cust_svc = shift; + + my $svc_external; + if ( ref($cust_svc) ) { + $svc_external = $cust_svc->svc_x; + } else { + $svc_external = qsearchs('svc_external', { 'svcnum' => $cust_svc } ); + $cust_svc = $svc_external->cust_svc; + } + + #don't scan again if things are okay + my $bad = 0; + foreach my $option ( keys %desired ) { + my $current = $cust_svc->option($option); + $bad++ unless $current =~ $desired{$option}; + } + return '' unless $bad; + + #do the scan + my %hash = (); + my $machine = $svc_external->title; # or better as a cust_svc_option?? + sshopen2($machine, *READER, *WRITER, '/usr/local/bin/freeside-yori all'); + while () { + chomp; + my($option, $value) = split(/: ?/); + next unless defined($option) && exists($desired{$option}); + $hash{$option} = $value; + } + close READER; + + unless ( keys %hash ) { + return "error scanning $machine\n"; + } + + # store the results + foreach my $option ( keys %hash ) { + my %opthash = ( 'optionname' => $option, + 'svcnum' => $cust_svc->svcnum, + ); + my $cust_svc_option = qsearchs('cust_svc_option', \%opthash ) + || new FS::cust_svc_option \%opthash; + next if $cust_svc_option->optionvalue eq $hash{$option}; + $cust_svc_option->optionvalue( $hash{$option} ); + my $error = $cust_svc_option->optionnum + ? $cust_svc_option->replace + : $cust_svc_option->insert; + return $error if $error; + } + + ''; + +} + +sub tron_lint { + my $cust_svc = shift; + + my @lint; + foreach my $option ( keys %desired ) { + my $current = $cust_svc->option($option); + push @lint, "$option is $current" unless $current =~ $desired{$option}; + } + + @lint; + +} + +1; diff --git a/FS/FS/cust_svc.pm b/FS/FS/cust_svc.pm index 381b97f14..2d6224c92 100644 --- a/FS/FS/cust_svc.pm +++ b/FS/FS/cust_svc.pm @@ -3,6 +3,7 @@ package FS::cust_svc; use strict; use vars qw( @ISA $DEBUG $me $ignore_quantity ); use Carp; +#use Scalar::Util qw( blessed ); use FS::Conf; use FS::Record qw( qsearch qsearchs dbh str2time_sql ); use FS::cust_pkg; @@ -16,7 +17,7 @@ use FS::cdr; #most FS::svc_ classes are autoloaded in svc_x emthod use FS::svc_acct; #this one is used in the cache stuff -@ISA = qw( FS::cust_main_Mixin FS::Record ); +@ISA = qw( FS::cust_main_Mixin FS::option_Common ); #FS::Record ); $DEBUG = 0; $me = '[cust_svc]'; @@ -220,7 +221,13 @@ returns the error, otherwise returns false. =cut sub replace { +# my $new = shift; +# +# my $old = ( blessed($_[0]) && $_[0]->isa('FS::Record') ) +# ? shift +# : $new->replace_old; my ( $new, $old ) = ( shift, shift ); + $old = $new->replace_old unless defined($old); local $SIG{HUP} = 'IGNORE'; local $SIG{INT} = 'IGNORE'; @@ -233,8 +240,6 @@ sub replace { local $FS::UID::AutoCommit = 0; my $dbh = dbh; - $old = $new->replace_old unless defined($old); - if ( $new->svcpart != $old->svcpart ) { my $svc_x = $new->svc_x; my $new_svc_x = ref($svc_x)->new({$svc_x->hash, svcpart=>$new->svcpart }); @@ -246,6 +251,7 @@ sub replace { } } + #my $error = $new->SUPER::replace($old, @_); my $error = $new->SUPER::replace($old); if ( $error ) { $dbh->rollback if $oldAutoCommit; diff --git a/FS/FS/cust_svc_option.pm b/FS/FS/cust_svc_option.pm new file mode 100644 index 000000000..0a242d551 --- /dev/null +++ b/FS/FS/cust_svc_option.pm @@ -0,0 +1,136 @@ +package FS::cust_svc_option; + +use strict; +use vars qw( @ISA ); +#use FS::Record qw( qsearch qsearchs ); + +@ISA = qw(FS::Record); + +=head1 NAME + +FS::cust_svc_option - Object methods for cust_svc_option records + +=head1 SYNOPSIS + + use FS::cust_svc_option; + + $record = new FS::cust_svc_option \%hash; + $record = new FS::cust_svc_option { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::cust_svc_option object represents an customer service option. + FS::cust_svc_option inherits from FS::Record. The following fields are + currently supported: + +=over 4 + +=item optionnum + +primary key + +=item svcnum + +svcnum (see L) + +=item optionname + +Option Name + +=item optionvalue + +Option Value + + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new option. To add the option to the database, see L<"insert">. + +Note that this stores the hash reference, not a distinct copy of the hash it +points to. You can ask the object for a copy with the I method. + +=cut + +# the new method can be inherited from FS::Record, if a table method is defined + +sub table { 'cust_svc_option'; } + +=item insert + +Adds this record to the database. If there is an error, returns the error, +otherwise returns false. + +=cut + +# the insert method can be inherited from FS::Record + +=item delete + +Delete this record from the database. + +=cut + +# the delete method can be inherited from FS::Record + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database. If there is an error, +returns the error, otherwise returns false. + +=cut + +# the replace method can be inherited from FS::Record + +=item check + +Checks all fields to make sure this is a valid option. If there is +an error, returns the error, otherwise returns false. Called by the insert +and replace methods. + +=cut + +# the check method should currently be supplied - FS::Record contains some +# data checking routines + +sub check { + my $self = shift; + + my $error = + $self->ut_numbern('optionnum') + || $self->ut_foreign_key('svcnum', 'cust_svc', 'svcnum') + || $self->ut_alpha('optionname') + || $self->ut_anything('optionvalue') + ; + return $error if $error; + + $self->SUPER::check; +} + +=back + +=head1 BUGS + +The author forgot to customize this manpage. + +=head1 SEE ALSO + +L, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/MANIFEST b/FS/MANIFEST index d83bf1daa..5dcd69649 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -418,3 +418,5 @@ t/pkg_category.t FS/phone_avail.pm t/phone_avail.t FS/Yori.pm +FS/cust_svc_option.pm +t/cust_svc_option.t diff --git a/FS/t/cust_svc_option.t b/FS/t/cust_svc_option.t new file mode 100644 index 000000000..eeaa170db --- /dev/null +++ b/FS/t/cust_svc_option.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::cust_svc_option; +$loaded=1; +print "ok 1\n"; diff --git a/bin/tron-scan b/bin/tron-scan new file mode 100755 index 000000000..914d6d407 --- /dev/null +++ b/bin/tron-scan @@ -0,0 +1,24 @@ +#!/usr/bin/perl + +use FS::UID qw(adminsuidsetup); +use FS::Conf; +use FS::Record qw(qsearch); +use FS::Tron qw(tron_scan tron_lint); +use FS::cust_svc; + +adminsuidsetup shift; + +my $conf = new FS::Conf; +my $mcp_svcpart = $conf->config('mcp_svcpart') or die "no mcp_svcpart"; + +#tron_scan($_) foreach qsearch('cust_svc', { 'svcpart' => $mcp_svcpart } ); +foreach my $svc ( qsearch('cust_svc', { 'svcpart' => $mcp_svcpart } ) ) { + my $error = tron_scan($svc); + warn $error if $error; + + my @lint = tron_lint($svc); + print $svc->svc_x->title. "\n". join('', map " $_\n", @lint ) + if @lint; +} + +1; diff --git a/httemplate/elements/dashboard-toplist.html b/httemplate/elements/dashboard-toplist.html index 7ee6f2d43..d8cd7f306 100644 --- a/httemplate/elements/dashboard-toplist.html +++ b/httemplate/elements/dashboard-toplist.html @@ -23,6 +23,9 @@ <% $cust_main->name %> + + <% include('/elements/mcp_lint.html', 'cust_main'=>$cust_main) %> + (new ticket) @@ -55,7 +58,7 @@ % } elsif ( $line =~ /^\-\-+$/ ) { #divider % - + % next; @@ -63,13 +66,14 @@ % } elsif ( $line =~ /^\s*$/ ) { -   +   % } elsif ( $line =~ /^\S/ ) { #label line <% $line %> + Lint % foreach my $priority ( @custom_priorities, '' ) { @@ -81,7 +85,7 @@ % } else { #regular line - <% $line %> + <% $line %> % } diff --git a/httemplate/elements/mcp_lint.html b/httemplate/elements/mcp_lint.html new file mode 100644 index 000000000..826549c65 --- /dev/null +++ b/httemplate/elements/mcp_lint.html @@ -0,0 +1,37 @@ +% foreach my $lint (@lint) { + <% $lint %>
+% } + +<%init> + +my(%opt) = @_; + +my $conf = new FS::Conf; + +my @svc = (); +if ( $opt{svc} ) { + @svc = ref($opt{svc}) ? @{ $opt{svc} } : ( $opt{svc} ); +} elsif ( $opt{cust_main} ) { + my $custnum = $opt{cust_main}->custnum; + @svc = qsearchs({ + 'table' => 'cust_svc', + 'addl_from' => ' LEFT JOIN cust_pkg USING ( pkgnum ) '. + ' LEFT JOIN cust_main USING ( custnum )', + 'hashref' => { 'svcpart' => $conf->config('mcp_svcpart') }, + 'extra_sql' => " AND custnum = $custnum ", + }); +} else { + die 'neither svc nor cust_main options passed to mcp_lint'; +} + +my @lint = (); +foreach my $svc ( @svc ) { + my @svc_lint = tron_lint($svc); + if ( scalar(@svc) > 1 ) { + push @lint, map $svc->title.": $_", @svc_lint; + } else { + push @lint, @svc_lint; + } +} + +