Merge branch 'master' of git+ssh://github.com/adefaria/clearscm
[clearscm.git] / clearadm / updatefs.pl
1 #!/usr/local/bin/perl
2
3 =pod
4
5 =head1 NAME $RCSfile: updatefs.pl,v $
6
7 Update Filesystem
8
9 =head1 VERSION
10
11 =over
12
13 =item Author
14
15 Andrew DeFaria <Andrew@ClearSCM.com>
16
17 =item Revision
18
19 $Revision: 1.29 $
20
21 =item Created:
22
23 Mon Dec 13 09:13:27 EST 2010
24
25 =item Modified:
26
27 $Date: 2011/06/16 15:12:50 $
28
29 =back
30
31 =head1 SYNOPSIS
32
33  Usage updatefs.pl: [-u|sage] [-ve|rbose] [-deb|ug]
34                     [-host [<host>|all]] [-fs [<fs>|all]]
35
36  Where:
37    -u|sage:     Displays usage
38  
39    -ve|rbose:   Be verbose
40    -deb|ug:     Output debug messages
41    
42    -host [<host>|all]: Update host or all hosts (Default: all)
43    -fs   [<fs>|all]:   Update filesystem or all (Default: all)   
44
45 =head1 DESCRIPTION
46
47 This script will record the state of a filesystem.
48
49 =cut
50
51 use strict;
52 use warnings;
53
54 use Net::Domain qw(hostname);
55 use FindBin;
56 use Getopt::Long;
57 use Convert::Base64;
58
59 use lib "$FindBin::Bin/lib", "$FindBin::Bin/../lib";
60
61 use Clearadm;
62 use Clearexec;
63 use DateUtils;
64 use Display;
65 use Utils;
66
67 my $VERSION  = '$Revision: 1.29 $';
68   ($VERSION) = ($VERSION =~ /\$Revision: (.*) /);
69
70 my $clearadm  = Clearadm->new;
71 my $clearexec = Clearexec->new; 
72
73 my ($host, $fs);
74
75 # Given a host and a filesystem, formulate a fs record
76 sub snapshotFS ($$) {
77   my ($systemRef, $filesystem) = @_;
78
79   my %system = %{$systemRef};
80
81   my %filesystem = $clearadm->GetFilesystem ($system{name}, $filesystem);
82   
83   unless (%filesystem) {
84         error "Filesystem $host:$filesystem not in clearadm database - try adding it";
85         
86         return;
87   } # unless
88   
89   my %fs = (
90     system     => $system{name},
91     filesystem => $filesystem,
92     timestamp  => Today2SQLDatetime,
93   );
94
95   # Sun is so braindead!
96   # TODO: Verify this works under Solaris
97   if ($system{type} eq 'Unix') {
98     my $cmd = "df -v $filesystem{mount}";
99
100     my ($status, @unixfs) = $clearexec->execute ($cmd);
101
102     if ($status != 0) {
103       error ('Unable to determine fsinfo for '
104            . "$system{name}:$filesystem{mount} ($cmd)\n" .
105              join "\n", @unixfs);
106    
107       return;
108     } # if
109
110     # Skip heading
111     shift @unixfs;
112
113     for (my $i = 0; $i < scalar @unixfs; $i++) {
114       my @fields = split ' ', $unixfs[$i];
115
116       $fs{mount}   = $fields[0];
117       $fs{size}    = $fields[2] * 1024;
118       $fs{used}    = $fields[3] * 1024;
119       $fs{free}    = $fields[4] * 1024;
120       $fs{reserve} = $fs{size} - $fs{used} - $fs{free};
121     } # for
122   } elsif ($system{type} eq 'Linux' or $system{type} eq 'Windows') {
123     my $cmd = "/bin/df --block-size=1 -P $filesystem{mount}";
124
125     my ($status, @linuxfs) = $clearexec->execute ($cmd);
126
127     if ($status != 0) {
128       error ("Unable to determine fsinfo for $system{name}:$filesystem{mount}\n"
129           . join "\n", @linuxfs
130       );
131                
132       return;
133     } # if
134
135     # Skip heading
136     shift @linuxfs;
137     
138     $_ = shift @linuxfs;
139     my @fields = split;
140     
141     $fs{size}    = $fields[1];
142     $fs{used}    = $fields[2];
143     $fs{free}    = $fields[3];
144     $fs{mount}   = $fields[5];
145     $fs{reserve} = $fs{size} - $fs{used} - $fs{free};
146   } # if
147
148   return %fs;  
149 } # snapshotFS
150
151 # Main
152 GetOptions (
153   'usage'   => sub { Usage },
154   'verbose' => sub { set_verbose },
155   'debug'   => sub { set_debug },
156   'host=s'  => \$host,
157   'fs=s'    => \$fs,
158 ) or Usage "Invalid parameter";
159
160 Usage 'Extraneous options: ' . join ' ', @ARGV
161   if @ARGV;
162
163 # Announce ourselves
164 verbose "$FindBin::Script V$VERSION";
165
166 my $exit = 0;
167
168 for my $system ($clearadm->FindSystem ($host)) {
169   next if $system->{active} eq 'false';
170   
171   my $status = $clearexec->connectToServer (
172     $system->{name}, 
173     $system->{port}
174   );
175   
176   unless ($status) {
177     verbose "Unable to connect to system $system->{name}:$system->{port}";
178     next;
179   } # unless
180
181   for my $filesystem ($clearadm->FindFilesystem ($system->{name}, $fs)) {
182     verbose "Snapshotting $system->{name}:$filesystem->{filesystem}";
183   
184     my %fs = snapshotFS ($system, $filesystem->{filesystem});
185     
186     if (%fs) {
187       my ($err, $msg) = $clearadm->AddFS (%fs);
188   
189       error $msg, $err if $err;
190     } # if
191     
192     # Generate graphs
193     my $cmd = "plotfs.cgi generate=1 system=$system->{name} filesystem=$filesystem->{filesystem} scaling=Day points=7";
194
195     verbose "Generating fssmall for $system->{name}:$filesystem->{filesystem}";
196     my ($error, @output) = Execute("$cmd tiny=1 2>&1");
197
198     error 'Unable to generate fssmall' . join("\n", @output), $error if $error;
199
200     $filesystem->{fssmall} = join '', @output;
201
202     verbose "Generating fslarge for $system->{name}:$filesystem->{filesystem}";
203     ($error, @output) = Execute("$cmd 2>&1");
204
205     error 'Unable to generate fslarge' . join("\n", @output), $error if $error;
206
207     $filesystem->{fslarge} = join '', @output;
208
209     my ($err, $msg) = $clearadm->UpdateFilesystem($system->{name}, $filesystem->{filesystem}, %$filesystem);
210
211     error "Unable to update filesystem record $msg", $err if $err;
212
213     # Check if over threshold
214     my %notification = $clearadm->GetNotification ('Filesystem');
215
216     next unless %notification;
217   
218     my $usedPct = '0%';
219
220     $usedPct = sprintf ('%.2f', (($fs{used} + $fs{reserve}) / $fs{size}) * 100) if $fs{size} != 0;
221     
222     if ($usedPct >= $filesystem->{threshold}) {
223       $exit = 2;
224       display YMDHMS
225             . " System: $filesystem->{system} "
226             . "Filesystem: $filesystem->{filesystem} Used: $usedPct% " 
227             . "Threshold: $filesystem->{threshold}";    
228     } else {
229       $clearadm->ClearNotifications ($system->{name}, $filesystem->{filesystem});    
230     } # if
231   } # for
232   
233   $clearexec->disconnectFromServer;
234 } # for
235
236 exit $exit;
237
238 =pod
239
240 =head1 CONFIGURATION AND ENVIRONMENT
241
242 DEBUG: If set then $debug is set to this level.
243
244 VERBOSE: If set then $verbose is set to this level.
245
246 TRACE: If set then $trace is set to this level.
247
248 =head1 DEPENDENCIES
249
250 =head2 Perl Modules
251
252 L<FindBin>
253
254 L<Getopt::Long|Getopt::Long>
255
256 L<Net::Domain|Net::Domain>
257
258 =head2 ClearSCM Perl Modules
259
260 =begin man 
261
262  Clearadm
263  Clearexec
264  DateUtils
265  Display
266  Utils
267
268 =end man
269
270 =begin html
271
272 <blockquote>
273 <a href="http://clearscm.com/php/scm_man.php?file=clearadm/lib/Clearadm.pm">Clearadm</a><br>
274 <a href="http://clearscm.com/php/scm_man.php?file=clearadm/lib/Clearexec.pm">Clearexec</a><br>
275 <a href="http://clearscm.com/php/scm_man.php?file=lib/DateUtils.pm">DateUtils</a><br>
276 <a href="http://clearscm.com/php/scm_man.php?file=lib/Display.pm">Display</a><br>
277 <a href="http://clearscm.com/php/scm_man.php?file=lib/Utils.pm">Utils</a><br>
278 </blockquote>
279
280 =end html
281
282 =head1 BUGS AND LIMITATIONS
283
284 There are no known bugs in this script
285
286 Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
287
288 =head1 LICENSE AND COPYRIGHT
289
290 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
291
292 =cut