File Coverage

blib/lib/App/Validation/Automation.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             package App::Validation::Automation;
2              
3 1     1   25727 use Carp;
  1         3  
  1         91  
4 1     1   758 use Switch;
  0            
  0            
5             use Moose;
6             use Net::SSH::Perl;
7             use namespace::autoclean;
8             use English qw(-no_match_vars);
9              
10             =head1 NAME
11              
12             App::Validation::Automation
13              
14             =head1 VERSION
15              
16             Version 0.01
17              
18             =cut
19              
20             our $VERSION = '0.01';
21              
22             =head1 SYNOPSIS
23              
24             use App::Validation::Automation;
25              
26             my $obj = App::Validation::Automation->new(
27             config => \%config,
28             log_file_handle => $log_handle,
29             user_name => $config{'COMMON.USER'}, #Optional Parameter
30             password => $config{'COMMON.PASSWORD'}, #Optional Parameter
31             site => $config{'COMMON.SITE'}, #Optional Parameter
32             zone => $config{'COMMON.ZONE'}, #Optional Parameter
33             secret_pphrase => $secret_pphrase, #Optional Parameter
34             );
35              
36             $success = $obj->validate_urls();
37             $success = $obj->test_dnsrr_lb();
38             $success = $obj->validate_processes_mountpoints();
39              
40             #Or, If config is small
41              
42             my $obj = App::Validation::Automation->new(
43             config => {
44             'COMMON.SSH_PROTO' => '2,1',
45             'COMMON.ID_RSA' => [
46             /home/user/.ssh/id_rsa1,
47             /home/user/.ssh/id_rsa2
48             ],
49             'COMMON.DEFAULT_HOME' => /home/user/App/Validation,
50             'COMMON.LOG_DIR' => /home/user/App/Validation/log,
51             'COMMON.LINK' => http://ap.xyz.com/loginproxy_servlet,
52             'COMMON.PROCESS_TMPL' => ps -eaf |grep -i %s|grep -v grep|wc -l
53             'COMMON.FILESYS_TMPL' => cd %s
54             'HOSTNAME1.PROCESSES' => [BBL:1, DMADM:],
55             'HOSTNAME1.FILE_SYS' => [/home, /],
56             'HOSTNAME2.PROCESSES' => [BL:1, DADM:],
57             'HOSTNAME2.FILE_SYS' => [/home, /],
58             'HOSTNAME2.LINKS' => [
59             http://hostname2.xyz.com:6666,
60             http://hostname2.xyz.com:6667,
61             ]
62             },
63             log_file_handle => $log_handle,
64             user_name => $config{'COMMON.USER'}, #Optional Parameter
65             password => $config{'COMMON.PASSWORD'}, #Optional Parameter
66             site => $config{'COMMON.SITE'}, #Optional Parameter
67             zone => $config{'COMMON.ZONE'}, #Optional Parameter
68             secret_pphrase => $secret_pphrase, #Optional Parameter
69             );
70            
71             #Verify All links - calls validate_url for all links under each host
72             $ret = $obj->validate_urls();
73             #Verify filesystems and processes on remote hosts- calls connect,validate_process
74             #and validate_mount for all processes and filesystems on all remote hosts
75             $ret = $obj->validate_processes_mountpoints();
76             #DNS Round Robin and Load Balancing functionality Check - Calls dnsrr and lb
77             #for common link
78             $ret = $obj->test_dnsrr_lb();
79              
80             #Or,do most of the stuff yourself and based on success/failure log/mail
81             $ret = $obj->validate_url("http://cpan.org");
82             $ret = $obj->dnsrr("http://abc.com",10,2);
83             $ret = $obj->lb("http://abc.com",10,2);
84              
85             $ret = $obj->connect("abc.xyz.com","user");
86             $ret = $obj->validate_process("BBL:4","ps -eaf|grep %s|wc -l");
87             $ret = $obj->validate_mountpoint("/home","cd %s");
88            
89              
90             =head1 DESCRIPTION
91            
92             A Validation Framework to check if your Application is running fine or not.This module can be used for Applications that are built on Unix and have a Web interface.
93             The suite has the capabilty to check Application web urls for accessiblity,and also login into each of those urls to ascertain database connectivity along with sub
94             url accessbility.One can also verfiy processes and mountpoints on the remote hosts which house the application. The password for logging into the web urls is stored
95             in an encrypted file.The Module also has capability to test if Load Balancing and DNS Round Robin is funtioning.High Availabilty Web applications use Load Balancing
96             and DNS Round Robin to add redundancy,high availability, and effective load distribution among the various servers(Web,Application, and Database servers).Further to
97             frontend validations the module provides methods to validate the backend.To carryout backend verification it connects to remote hosts using SSH.Backend verfication
98             involves checking if correct not of processe are running and file systems are accessible.App::Validation::Automation is driven by a tunable configuration file(sample
99             config bundled with this distribution)which is formated in Windows .ini format.Please take a look at the configuration file under config/.
100              
101             =head1 INHERITANCE,ATTRIBUTES AND ROLES
102              
103             App::Validation::Automation Class leverages App::Validation::Automation::Web and App::Validation::Automation::Unix to perform Web and Unix level validations.It also acts as an application logger,alarmer and log purger.
104              
105             =cut
106              
107             extends 'App::Validation::Automation::Web','App::Validation::Automation::Unix';
108              
109             has 'config' => (
110             is => 'rw',
111             isa => 'HashRef',
112             required => 1,
113             );
114              
115             has 'log_file_handle' => (
116             is => 'rw',
117             isa => 'FileHandle',
118             required => 1,
119             );
120              
121             has 'inaccessible_urls' => (
122             is => 'ro',
123             isa => 'ArrayRef[Str]',
124             );
125              
126             has 'faulty_processes' => (
127             is => 'ro',
128             isa => 'ArrayRef[Str]',
129             );
130              
131             has 'faulty_mountpoints' => (
132             is => 'ro',
133             isa => 'ArrayRef[Str]',
134             );
135              
136             has 'hostname' => (
137             is => 'rw',
138             isa => 'Str',
139             );
140              
141             has 'secret_pphrase' => (
142             is => 'ro',
143             isa => 'Str',
144             );
145              
146             with 'App::Validation::Automation::Logging',
147             'App::Validation::Automation::Alarming',
148             'App::Validation::Automation::Purging';
149              
150             =head1 METHODS
151              
152             =head2 validate_urls
153              
154             Check various web links stored in config file for accessibility.The real work is done by validate_url method of App::Validation::Automation::Web class.Returns true on success and false on failure.Handles password expiration along with authentication failure.On password expiry calls change_web_pwd and change_unix_pwd to change password at both Web and Unix level.Notifies via text page and email and also logs the error message.
155              
156             =cut
157              
158             sub validate_urls {
159             my $self = shift;
160             my ($msg, @inaccessible_urls, $subject, $body, $url);
161              
162             foreach my $key ( keys %{$self->config} ) {
163             if($key =~ /LINKS/i) {
164             local $WARNING = 0;
165             foreach my $url(@{$self->config->{$key}}) {
166             $self->validate_url($url);
167             switch ($self->web_msg) {
168             case /Password.+?Expired/i {
169             &{$self->_error_handler($url)->{PASSWORD_EXPIRED}};
170             }
171             case /Authentication.+?Failure/i {
172             &{$self->_error_handler($url)->{AUTHENTICATION_FAILURE}};
173             }
174             case /Missdirected/i {
175             &{$self->_error_handler($url)->{MISSDIRECTED}};
176             push @inaccessible_urls,$url;
177             }
178             else {
179             &{$self->_error_handler($url)->{SUCCESS}};
180             }
181             }
182             }
183             }
184             }
185              
186             if ( @inaccessible_urls ) {
187             $subject = "App Valildation -> Failed";
188             $body = "Following Links were not accessible ->\n";
189             $body .= join "\n", @inaccessible_urls;
190             $body .= "\nRefer logs under".$self->config->{'COMMON.LOG_DIR'}." for details";
191              
192             #$self->inaccessible_urls( \@inaccessible_urls );
193             $self->mail( $subject, $body );
194             $self->log( $self->mail_msg );
195              
196             $self->page( $subject, $body );
197             $self->log( $self->page_msg );
198              
199             return 0;
200             }
201             return 1;
202             }
203              
204             =head2 test_dnsrr_lb
205              
206             Validates if DNS Round Robin and Load Balancing feature is working fine or not.
207              
208             =cut
209              
210             sub test_dnsrr_lb {
211             my $self = shift;
212             my ($msg, @inaccessible_urls, $return, $subject, $body,
213             $fail_flag, $ret, $url, $max_requests, $min_unique);
214             $url = $self->config->{'COMMON.LINK'};
215             $max_requests = $self->config->{'COMMON.MAX_REQ'};
216             $min_unique = $self->config->{'COMMON.MIN_UNQ'};
217             $subject = "App Valildation -> Failed";
218              
219             if($self->dnsrr($url, $max_requests, $min_unique)) {
220             $self->log( "DNS Round Robin Validated " );
221             }
222             else {
223             $msg = $self->config->{'COMMON.LINK'}.$self->web_msg;
224             $self->log( $msg );
225              
226             $body = "DNS Round Robin Validation Failed\n";
227             $body .= "\nRefer logs under".$self->config->{'COMMON.LOG_DIR'}." for details";
228             $self->mail( $subject, $body );
229             $self->log( $self->mail_msg );
230              
231             $fail_flag = 1;
232             $self->clear_web_msg;
233             }
234              
235             if($self->lb($url, $max_requests, $min_unique)) {
236             $self->log( "Load Balancing Validated " );
237             }
238             else {
239             $msg = $self->config->{'COMMON.LINK'}.$self->web_msg;
240             $self->log( $msg );
241              
242             $body = "Load Balancing Validation Failed\n";
243             $body .= "\nRefer logs under".$self->config->{'COMMON.LOG_DIR'}." for details";
244             $self->mail( $subject, $body );
245             $self->log( $self->mail_msg );
246              
247             $fail_flag = 1;
248             $self->clear_web_msg;
249             }
250             return 0 if( $fail_flag );
251             return 1;
252             }
253              
254             =head2 validate_processes_mountpoints
255              
256             Checks various processes and filesystems on remote servers.The method establishes connection to the remote server.this pre-cooked connection is used by validate_process
257             and validate_mountpoint to do the real work.The connection is establised using Net::SSH::Perl. Please note to generate and store the Private and Public key pairs for password less SSH login.Refer HOWTO section down below to generate Public/Private key pairs.
258              
259             =cut
260              
261             sub validate_processes_mountpoints {
262             my $self = shift;
263             my $user = $self->config->{'COMMON.REMOTE_USER'} || $ENV{USER};
264             my (@faulty_processes, @faulty_mountpoints, $msg, $subject, $body, $ret);
265              
266             foreach my $key ( keys %{$self->config} ) {
267             if( $key =~/PROCESSES/ ) {
268             my ($host) = ($key =~ /(.*)\..*/);
269             $self->log("Connecting to $host...");
270             $self->log("Connection Successful!")
271             if($self->connect($host, $user));
272              
273             $self->log("Validating Processes...");
274             foreach my $proc_tmpl (@{$self->config->{$key}}) {
275             if($self->validate_process($proc_tmpl)) {
276             $self->log("$host: $proc_tmpl : OK");
277             }
278             else {
279             $self->log("$host: $proc_tmpl : NOT OK\n".$self->unix_msg);
280             push @faulty_processes,$proc_tmpl;
281             $self->clear_unix_msg;
282             }
283             }
284              
285             $key = $host.'.FILE_SYS';
286             $self->log("Validating FileSystems...");
287             foreach my $mountpoint (@{$self->config->{$key}}) {
288             if($self->validate_mountpoint($mountpoint)) {
289             $self->log("$host: $mountpoint : OK");
290             }
291             else {
292             $self->log("$host: $mountpoint : NOT OK ".$self->unix_msg);
293             push @faulty_mountpoints,$mountpoint;
294             $self->clear_unix_msg;
295             }
296             }
297             }
298             }
299              
300             if( @faulty_processes || @faulty_mountpoints ) {
301             $subject = "App Valildation -> Failed";
302             $body = "Unix Validation Failed\n";
303             $body .= "\nRefer logs under".$self->config->{'COMMON.LOG_DIR'}." for details";
304              
305             $self->mail( $subject, $body );
306             $self->log( $self->mail_msg );
307             #$self->faulty_processes( \@faulty_processes );
308             return 0;
309             }
310             return 1;
311             }
312              
313             sub _error_handler {
314             my $self = shift;
315             my $url = shift;
316             my ($msg, $actions);
317              
318             $actions = {
319             PASSWORD_EXPIRED => sub {
320             $msg = $self->web_msg." : About to Change at Web Level :";
321             $self->clear_web_msg;
322             if($self->change_web_pwd($url)) {
323             $self->log("$msg : OK");
324             }
325             else {
326             $self->log($msg.$self->web_msg);
327             confess $msg.$self->web_msg;
328             }
329             $msg = "About to Change at Unix Level :";
330             if($self->change_unix_pwd) {
331             $self->log("$msg : OK");
332             }
333             else {
334             $self->log($msg.$self->unix_msg);
335             confess $msg.$self->unix_msg;
336             }
337             },
338             AUTHENTICATION_FAILURE => sub {
339             $self->log(
340             $self->web_msg."Incorrect Credentials... Exiting!"
341             );
342             confess $self->web_msg."Incorrect Credentials... Exiting!";
343             },
344             MISSDIRECTED => sub {
345             $msg = $url." : Inaccessible\nError : ".$self->web_msg;
346             $self->log( $msg );
347             $self->clear_web_msg;
348             },
349             SUCCESS => sub { $self->log("$url : OK"); },
350             };
351              
352             return $actions;
353              
354             }
355              
356              
357             sub _trim_spaces {
358              
359             my $self = shift;
360             my $line = shift;
361              
362             $line =~ s/^\s+//;
363             $line =~ s/\s+$//;
364              
365             return $line;
366              
367             }
368              
369             =head1 HOWTO
370              
371             =head2 Generate Public/Private key pairs for SSH
372              
373             ssh-keygen is used to generate that Public/Private key pair:
374              
375             user@localhost>ssh-keygen -t rsa
376              
377             Generating public/private rsa key pair.
378              
379             Enter file in which to save the key (/home/user/.ssh/id_rsa):
380              
381             Enter passphrase (empty for no passphrase):
382              
383             Enter same passphrase again:
384              
385             Your identification has been saved in /home/user/.ssh/id_rsa.
386              
387             Your public key has been saved in /home/user/.ssh/id_rsa.pub.
388              
389             The key fingerprint is:
390             f6:61:a8:27:35:cf:4c:6d:13:22:70:cf:4c:c8:a0:23 user@localhost
391              
392             The command ssh-keygen -t rsa initiated the creation of the key pair.Adding a passphrase is not required so just press enter.The private key gets saved in .ssh/id_rsa. This file is read-only and only for you. No one else must see the content of that file, as it is used to decrypt all correspondence encrypted with the public key. The public key gets stored in .ssh/id_rsa.pub.The content of the id_rsa.pub needs to be copied in the file .ssh/authorized_keys of the system you wish to SSH to without being prompted for a password. Here are the steps:
393              
394             Create .ssh dir on remote host(The dir may already exist,No issues):
395              
396             user@localhost>ssh user@remotehost mkdir -p .ssh
397             user@remotehost's password:
398              
399             Append user's new public key to user@remotehost : .ssh/authorized_keys and enter user's password:
400              
401             user@localhost>cat .ssh/id_rsa.pub | ssh user@remotehost 'cat >> .ssh/authorized_keys'
402             user@remotehost's password:
403              
404             Test login without password:
405              
406             user@localhost>ssh user@remotehost
407             user@remotehost>hostname
408              
409             remotehost
410              
411             =head2 Use configuration file
412              
413             App::Validation::Automation is driven by a tunable configuration file.The configuration file is in Windows .ini format.The wrapper script using App::Validation::Automation needs to either read the configuration file or build the configuration itself.The configuration file is broadly divided into two parts COMMON and Remote host specific.The COMMON part contains generic info used by App::Validation::Automation not specific to any host.
414              
415             Example:
416              
417             [COMMON]
418              
419             #User to login into Web links
420              
421             USER = web_user
422              
423             #Common User to login into remote host
424              
425             REMOTE_USER = user
426              
427             #Post link MAX_REQ no of times, used while testing Load
428             #Balancing and DNS round robin functionality
429              
430             MAX_REQ = 10
431            
432             #Minimum distinct redirected uris to ascertain Load Balancing
433             #and DNS round robin is working fine
434              
435             MIN_UNQ = 2
436              
437             #Log file extension
438              
439             LOG_EXTN = log
440              
441             #Print SSH debugging info to STDOUT
442              
443             DEBUG_SSH = 1
444              
445             #Try SSH2 protocol first and then SSH1
446              
447             SSH_PROTO = '2,1'
448              
449             #Private keys for each server(AA,KA...) used for SSH
450              
451             ID_RSA = /home/user/.ssh/id_rsa_AA,/home/user/.ssh/id_rsa_KA
452              
453             MAIL_TO = 'xyz@yahoo.com,123@gmail.com'
454              
455             PAGE_TO = '8168168164@vodafone.in'
456              
457             FROM = xy@localhost.com
458              
459             SMTP = localhost.com
460              
461             #Text file containing Encrypted password for USER
462              
463             ENC_PASS_FILE = pass.txt
464              
465             DEFAULT_HOME = /home/App/Validation
466              
467             LOG_DIR = /home/App/Validation/log
468              
469             #Log file retention period, delete log file older than 5 days
470              
471             RET_PERIOD = 5
472              
473             #Main Weblink used for Load Balancing and DNS round robin test
474              
475             LINK = http://cpan.org
476              
477             #Remote command fired to get process count.%s is replaced process name
478              
479             PROCESS_TMPL = ps -eaf | grep -i %s | grep -v grep | wc -l
480              
481             #Remote command fired to check filesystem.%s is replaced by filesystem name
482              
483             FILESYS_TMPL = cd %s
484              
485             #FQDN of remote server
486              
487             [AA.xyz.com]
488              
489             #Processes to verify on remote hosts along with their minimum quantity
490              
491             PROCESSES = BBL:1, EPsrv:1, WEBLEPsrv:1
492              
493             #Filesystems to verify on remote hosts
494              
495             FILE_SYS = /test, /export/home
496              
497             #FQDN of remote server
498              
499             [KA.xyz.com]
500              
501             #Processes to verify on remote hosts along with their minimum quantity
502              
503             PROCESSES = BBL:1, EPsrv:1, WEBLEPsrv:1
504              
505             #Filesystems to verify on remote hosts
506              
507             FILE_SYS = /test, /export/home
508              
509             #Links specific to KA server these links are checked for accessibility
510              
511             LINKS = http://KA.xyz.com:7000,http://KA.xyz.com:7100
512              
513              
514              
515             =head1 AUTHOR
516              
517             Varun Juyal, C<< <varunjuyal123@yahoo.com> >>
518              
519             =head1 BUGS
520              
521             Please report any bugs or feature requests to C<bug-app-validation-automation at rt.cpan.org>, or through
522             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=App-Validation-Automation>. I will be notified, and then you'll
523             automatically be notified of progress on your bug as I make changes.
524              
525             =head1 SUPPORT
526              
527             You can find documentation for this module with the perldoc command.
528              
529             perldoc App::Validation::Automation
530              
531             Also check out the script under script/ for a full blown example on how to use this
532             suite.
533              
534              
535             You can also look for information at:
536              
537             =over 4
538              
539             =item * RT: CPAN's request tracker (report bugs here)
540              
541             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=App-Validation-Automation>
542              
543             =item * AnnoCPAN: Annotated CPAN documentation
544              
545             L<http://annocpan.org/dist/App-Validation-Automation>
546              
547             =item * CPAN Ratings
548              
549             L<http://cpanratings.perl.org/d/App-Validation-Automation>
550              
551             =item * Search CPAN
552              
553             L<http://search.cpan.org/dist/App-Validation-Automation/>
554              
555             =back
556              
557              
558             =head1 ACKNOWLEDGEMENTS
559              
560              
561             =head1 LICENSE AND COPYRIGHT
562              
563             Copyright 2011 Varun Juyal.
564              
565             This program is free software; you can redistribute it and/or modify it
566             under the terms of either: the GNU General Public License as published
567             by the Free Software Foundation; or the Artistic License.
568              
569             See http://dev.perl.org/licenses/ for more information.
570              
571              
572             =cut
573              
574             1;