File Coverage

blib/lib/Siebel/Srvrmgr/Daemon/Light.pm
Criterion Covered Total %
statement 40 48 83.3
branch 3 8 37.5
condition 1 3 33.3
subroutine 12 13 92.3
pod n/a
total 56 72 77.7


line stmt bran cond sub pod time code
1             package Siebel::Srvrmgr::Daemon::Light;
2              
3             =pod
4              
5             =head1 NAME
6              
7             Siebel::Srvrmgr::Daemon::Light - subclass for running commmands with srvrmgr in batch mode
8              
9             =head1 SYNOPSIS
10              
11             use Siebel::Srvrmgr::Daemon::Light;
12              
13             my $daemon = Siebel::Srvrmgr::Daemon::Light->new(
14             {
15             time_zone => 'America/Sao_Paulo',
16             connection => $my_connection,
17             commands => [
18             Siebel::Srvrmgr::Daemon::Command->new(
19             command => 'load preferences',
20             action => 'LoadPreferences'
21             ),
22             Siebel::Srvrmgr::Daemon::Command->new(
23             command => 'list comp type',
24             action => 'ListCompTypes',
25             params => [$comp_types_file]
26             ),
27             Siebel::Srvrmgr::Daemon::Command->new(
28             command => 'list comp',
29             action => 'ListComps',
30             params => [$comps_file]
31             ),
32             Siebel::Srvrmgr::Daemon::Command->new(
33             command => 'list comp def',
34             action => 'ListCompDef',
35             params => [$comps_defs_file]
36             )
37             ]
38             }
39             );
40             $daemon->run;
41              
42              
43             =head1 DESCRIPTION
44              
45             This is a subclass of L<Siebel::Srvrmgr::Daemon> used to execute the C<srvrmgr> program in batch mode. For a better understanding of what batch mode means,
46             check out srvrmgr documentation.
47              
48             This class is recomended for cases where it is not necessary to run several commmands through srvrmgr in a short period of time because in batch mode it will
49             connect to the Siebel Gateway, execute the commands configured and exit, avoiding keeping a connection opened for a long time. For UNIX-like OS, this class
50             would be a good choice for using with Inetd and Xinetd daemons.
51              
52             This class is also highly recommended for OS plataforms like Microsoft Windows where IPC is not reliable enough, since this class uses C<system> instead of
53             L<IPC::Open3>.
54              
55             Since version 0.21, this class does not overrides anymore the parent class method C<shift_command>. Some attention is required is this matter, since a instance of
56             Siebel::Srvrmgr::Daemon::Light will not maintain configuration previously loaded with C<load preferences> command. Be sure to maintain this command everytime you invoke
57             C<run> available in the C<commands> attribute.
58              
59             =cut
60              
61 2     2   5137 use Moose 2.0401;
  2         55  
  2         21  
62 2     2   15713 use namespace::autoclean 0.13;
  2         41  
  2         13  
63 2     2   532 use Siebel::Srvrmgr::Daemon::ActionFactory;
  2         9  
  2         85  
64 2     2   15 use Siebel::Srvrmgr::Daemon::Command;
  2         4  
  2         59  
65 2     2   12 use Carp qw(longmess);
  2         5  
  2         143  
66 2     2   586 use File::Temp 0.2304 qw(:POSIX);
  2         10456  
  2         295  
67 2     2   17 use Data::Dumper;
  2         4  
  2         92  
68 2     2   12 use Siebel::Srvrmgr;
  2         5  
  2         55  
69 2     2   698 use File::BOM 0.14 qw(:all);
  2         30878  
  2         346  
70 2     2   342 use Siebel::Srvrmgr::IPC qw(check_system);
  2         5  
  2         105  
71 2     2   11 use Try::Tiny 0.27;
  2         41  
  2         1940  
72             our $VERSION = '0.29'; # VERSION
73              
74             extends 'Siebel::Srvrmgr::Daemon';
75             with 'Siebel::Srvrmgr::Daemon::Cleanup';
76             with 'Siebel::Srvrmgr::Daemon::Connection';
77              
78             =pod
79              
80             =head1 ATTRIBUTES
81              
82             =head2 output_file
83              
84             A string that represents the "/o" command line parameter of srvrmgr. It is defined internally, so it is read-only.
85              
86             =cut
87              
88             has output_file => (
89             isa => 'Str',
90             is => 'ro',
91             reader => 'get_output_file',
92             writer => '_set_output_file'
93             );
94              
95             =pod
96              
97             =head2 input_file
98              
99             A string that represents the "/i" command line parameter of srvrmgr. It is defined internally, so it is read-only.
100              
101             =cut
102              
103             has input_file => (
104             isa => 'Str',
105             is => 'ro',
106             reader => 'get_input_file',
107             writer => '_set_input_file'
108             );
109              
110             =pod
111              
112             =head1 METHODS
113              
114             =head2 get_output_file
115              
116             Returns the content of the C<output_file> attribute.
117              
118             =head2 get_input_file
119              
120             Returns the content of the C<input_file> attribute.
121              
122             =head2 run
123              
124             This method will try to connect to a Siebel Enterprise through C<srvrmgr> connection to submit the commands and respective actions defined during object creation.
125              
126             Those operations will be executed in the sequence define until all were executed once.
127              
128             Beware that Siebel::Srvrmgr::Daemon uses a B<single instance> of a L<Siebel::Srvrmgr::ListParser> class to process the parsing requests, so it is not possible
129             to execute L<Siebel::Srvrmgr::Daemon::Command> instances in parallel.
130              
131             =cut
132              
133             override 'run' => sub {
134             my ( $self ) = @_;
135             super();
136             my $logger = Siebel::Srvrmgr->gimme_logger( blessed($self) );
137             $logger->info('Starting run method');
138             my $parser = $self->create_parser( $self->get_conn->get_field_del );
139             my $params_ref = $self->get_conn->get_params_pass;
140             $self->_define_params($params_ref);
141              
142             if ( $logger->is_debug() ) {
143             $logger->debug( 'Calling system with the following parameters: '
144             . Dumper($params_ref) );
145             $logger->debug(
146             'Commands to be execute are: ' . Dumper( $self->get_commands() ) );
147             }
148              
149             my $ret_code = system( @{$params_ref} );
150             $self->_check_system( ${^CHILD_ERROR_NATIVE}, $ret_code, $? );
151             my $in;
152              
153             try {
154             open_bom( $in, $self->get_output_file(), ':utf8' );
155             }
156             catch {
157             $logger->logdie(
158             'Cannot read ' . $self->get_output_file() . ': ' . $_ );
159             };
160              
161             # :TODO:22-09-2014 01:32:45:: this might be dangerous if the output is too large
162             my @input_buffer = <$in>;
163             close($in);
164              
165             if ( scalar(@input_buffer) >= 1 ) {
166              
167             # since everything is read from a file, there is not way to identify if is a error from the file handler,
168             # so we will "turn off" warning checking
169             $self->_check_error( \@input_buffer, 0 );
170             $self->normalize_eol( \@input_buffer );
171              
172             # since we should have all output, we parse everything first to call each action after
173             $parser->parse( \@input_buffer );
174              
175             if ( $parser->has_tree() ) {
176             my $total = $self->cmds_vs_tree( $parser->count_parsed() );
177              
178             if ( $logger->is_debug() ) {
179             $logger->debug( 'Total number of parsed items = '
180             . $parser->count_parsed() );
181             $logger->debug( 'Total number of submitted commands = '
182             . scalar( @{ $self->get_commands() } ) );
183             }
184              
185             $logger->logdie(
186             'Number of parsed nodes is different from the number of submitted commands'
187             ) unless ( defined($total) );
188              
189             my $parsed_ref = $parser->get_parsed_tree();
190             $parser->clear_parsed_tree();
191              
192             for ( my $i = 0 ; $i < $total ; $i++ ) {
193             my $cmd = ( @{ $self->get_commands() } )[$i];
194             my $action = Siebel::Srvrmgr::Daemon::ActionFactory->create(
195             $cmd->get_action(),
196             {
197             parser => $parser,
198             params => $cmd->get_params()
199             }
200             );
201             $action->do_parsed( $parsed_ref->[$i] );
202             }
203              
204             }
205             else {
206             $logger->logdie('Parser did not have a parsed tree after parsing');
207             }
208              
209             }
210             else {
211             $logger->debug('buffer is empty');
212             }
213              
214             $self->_set_child_runs( $self->get_child_runs() + 1 );
215             $logger->debug( 'child_runs = ' . $self->get_child_runs() )
216             if ( $logger->is_debug() );
217             $logger->info('Exiting run sub');
218             return 1;
219             };
220              
221             override _my_cleanup => sub {
222             my $self = shift;
223             return $self->_del_input_file() && $self->_del_output_file();
224             };
225              
226             override _setup_commands => sub {
227             my $self = shift;
228             super();
229             my ( $fh, $input_file ) = tmpnam();
230              
231             foreach my $cmd ( @{ $self->get_commands() } ) {
232             print $fh $cmd->get_command(), "\n";
233             }
234              
235             close($fh);
236             $self->_set_input_file($input_file);
237             };
238              
239             override _define_params => sub {
240             my ( $self, $params_ref ) = @_;
241             super();
242             $self->_set_output_file( scalar( tmpnam() ) );
243             push(
244             @{$params_ref},
245             '/b', '/i', $self->get_input_file(),
246             '/o', $self->get_output_file()
247             );
248             return $params_ref;
249             };
250              
251             # :TODO:18-10-2013:arfreitas: this should be done by IPC.pm module?
252             sub _manual_check {
253 0     0   0 my ( $self, $ret_code, $error_code ) = @_;
254 0         0 my $logger = Siebel::Srvrmgr->gimme_logger( blessed($self) );
255              
256 0 0       0 if ( $ret_code == 0 ) {
257 0         0 $logger->info(
258             'Child process terminate successfully with return code = 0');
259             }
260             else {
261 0         0 $logger->logdie( 'system failed to execute srvrmgr: ' . $error_code );
262             }
263              
264             }
265              
266             sub _check_system {
267 3     3   79 my ( $self, $child_error, $ret_code, $error_code ) = @_;
268              
269 3         436 my $logger = Siebel::Srvrmgr->gimme_logger( blessed($self) );
270 3         253 my ( $message, $is_error ) = check_system($child_error);
271              
272 3 50 33     43 unless ( ( defined($message) ) and ( defined($is_error) ) ) {
273 0           $self->_manual_check( $ret_code, $error_code );
274             }
275             else {
276              
277 3 50       16 if ( defined($is_error) ) {
278              
279 3 50       13 if ($is_error) {
280 0         0 $logger->logdie($message);
281             }
282             else {
283 3         36 $logger->info($message);
284             }
285              
286             }
287             else {
288 0           $logger->info( $message . "Error code is $error_code" );
289             }
290              
291             }
292              
293             }
294              
295             =pod
296              
297             =head1 SEE ALSO
298              
299             =over
300              
301             =item *
302              
303             L<Moose>
304              
305             =item *
306              
307             L<Siebel::Srvrmgr::Daemon::Command>
308              
309             =item *
310              
311             L<Siebel::Srvrmgr::Daemon::ActionFactory>
312              
313             =item *
314              
315             L<Siebel::Srvrmgr::ListParser>
316              
317             =item *
318              
319             L<Siebel::Srvrmgr::Regexes>
320              
321             =item *
322              
323             L<POSIX>
324              
325             =item *
326              
327             L<Siebel::Srvrmgr::Daemon::Command>
328              
329             =back
330              
331             =head1 AUTHOR
332              
333             Alceu Rodrigues de Freitas Junior, E<lt>arfreitas@cpan.orgE<gt>.
334              
335             =head1 COPYRIGHT AND LICENSE
336              
337             This software is copyright (c) 2012 of Alceu Rodrigues de Freitas Junior, E<lt>arfreitas@cpan.orgE<gt>.
338              
339             This file is part of Siebel Monitoring Tools.
340              
341             Siebel Monitoring Tools is free software: you can redistribute it and/or modify
342             it under the terms of the GNU General Public License as published by
343             the Free Software Foundation, either version 3 of the License, or
344             (at your option) any later version.
345              
346             Siebel Monitoring Tools is distributed in the hope that it will be useful,
347             but WITHOUT ANY WARRANTY; without even the implied warranty of
348             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
349             GNU General Public License for more details.
350              
351             You should have received a copy of the GNU General Public License
352             along with Siebel Monitoring Tools. If not, see L<http://www.gnu.org/licenses/>.
353              
354             =cut
355              
356             __PACKAGE__->meta->make_immutable;
357              
358             1;
359