Initial commit
[clearscm.git] / clearadm / updatefs.pl
1 #!/usr/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
58 use lib "$FindBin::Bin/lib", "$FindBin::Bin/../lib";
59
60 use Clearadm;
61 use Clearexec;
62 use DateUtils;
63 use Display;
64 use Utils;
65
66 my $VERSION  = '$Revision: 1.29 $';
67   ($VERSION) = ($VERSION =~ /\$Revision: (.*) /);
68
69 my $clearadm  = Clearadm->new;
70 my $clearexec = Clearexec->new; 
71
72 my ($host, $fs);
73
74 # Given a host and a filesystem, formulate a fs record
75 sub snapshotFS ($$) {
76   my ($systemRef, $filesystem) = @_;
77
78   my %system = %{$systemRef};
79
80   my %filesystem = $clearadm->GetFilesystem ($system{name}, $filesystem);
81   
82   unless (%filesystem) {
83         error "Filesystem $host:$filesystem not in clearadm database - try adding it";
84         
85         return;
86   } # unless
87   
88   my %fs = (
89     system     => $system{name},
90     filesystem => $filesystem,
91     timestamp  => Today2SQLDatetime,
92   );
93
94   # Sun is so braindead!
95   # TODO: Verify this works under Solaris
96   if ($system{type} eq 'Unix') {
97     foreach ('ufs', 'vxfs') {
98       my $cmd = "/usr/bin/df -k -F $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     
108         return;
109       } # if
110
111       # Skip heading
112       shift @unixfs;
113
114       for (my $i = 0; $i < scalar @unixfs; $i++) {
115         my $firstField;
116     
117         # Trim leading and trailing spaces
118         $unixfs[$i] =~ s/^\s+//;
119         $unixfs[$i] =~ s/\s+$//;
120
121         my @fields = split /\s+/, $unixfs[$i];
122
123         if (@fields == 1) {
124           $firstField   = 0;
125           $i++;
126
127           @fields   = split /\s+/, $unixfs[$i];;
128         } else {
129           $firstField   = 1;
130         } #if
131
132         $fs{size}    = $fields[$firstField]     * 1024;
133         $fs{used}    = $fields[$firstField + 1] * 1024;
134         $fs{free}    = $fields[$firstField + 2] * 1024;
135         $fs{reserve} = $fs{size} - $fs{used} - $fs{free};
136       } # for
137     } # foreach
138   } elsif ($system{type} eq 'Linux' or $system{type} eq 'Windows') {
139     my $cmd = "/bin/df --block-size=1 -P $filesystem{mount}";
140
141     my ($status, @linuxfs) = $clearexec->execute ($cmd);
142
143     if ($status != 0) {
144       error ("Unable to determine fsinfo for $system{name}:$filesystem{mount}\n"
145           . join "\n", @linuxfs
146       );
147                
148       return;
149     } # if
150
151     # Skip heading
152     shift @linuxfs;
153     
154     $_ = shift @linuxfs;
155     my @fields = split;
156     
157     $fs{size}    = $fields[1];
158     $fs{used}    = $fields[2];
159     $fs{free}    = $fields[3];
160     $fs{mount}   = $fields[5];
161     $fs{reserve} = $fs{size} - $fs{used} - $fs{free};
162   } # if
163
164   return %fs;  
165 } # snapshotFS
166
167 # Main
168 GetOptions (
169   'usage'   => sub { Usage },
170   'verbose' => sub { set_verbose },
171   'debug'   => sub { set_debug },
172   'host=s'  => \$host,
173   'fs=s'    => \$fs,
174 ) or Usage "Invalid parameter";
175
176 Usage 'Extraneous options: ' . join ' ', @ARGV
177   if @ARGV;
178
179 # Announce ourselves
180 verbose "$FindBin::Script V$VERSION";
181
182 my $exit = 0;
183
184 foreach my $system ($clearadm->FindSystem ($host)) {
185   next if $$system{active} eq 'false';
186   
187   my $status = $clearexec->connectToServer (
188     $$system{name}, 
189     $$system{port}
190   );
191   
192   unless ($status) {
193     verbose "Unable to connect to system $$system{name}:$$system{port}";
194     next;
195   } # unless
196
197   foreach my $filesystem ($clearadm->FindFilesystem ($$system{name}, $fs)) {
198     verbose "Snapshotting $$system{name}:$$filesystem{filesystem}";
199   
200     my %fs = snapshotFS ($system, $$filesystem{filesystem});
201     
202     if (%fs) {
203       my ($err, $msg) = $clearadm->AddFS (%fs);
204   
205       error $msg, $err if $err;
206     } # if
207     
208     # Check if over threshold
209     my %notification = $clearadm->GetNotification ('Filesystem');
210
211     next
212       unless %notification;
213   
214     my $usedPct = sprintf (
215       '%.2f',
216       (($fs{used} + $fs{reserve}) / $fs{size}) * 100
217     );
218     
219     if ($usedPct >= $$filesystem{threshold}) {
220       $exit = 2;
221       display YMDHMS . " System: $$filesystem{system} "
222             . "Filesystem: $$filesystem{filesystem} Used: $usedPct% " 
223             . "Threshold: $$filesystem{threshold}";    
224     } else {
225       $clearadm->ClearNotifications ($$system{name}, $$filesystem{filesystem});    
226     } # if
227   } # foreach
228   
229   $clearexec->disconnectFromServer;
230 } # foreach
231
232 exit $exit;
233
234 =pod
235
236 =head1 CONFIGURATION AND ENVIRONMENT
237
238 DEBUG: If set then $debug is set to this level.
239
240 VERBOSE: If set then $verbose is set to this level.
241
242 TRACE: If set then $trace is set to this level.
243
244 =head1 DEPENDENCIES
245
246 =head2 Perl Modules
247
248 L<FindBin>
249
250 L<Getopt::Long|Getopt::Long>
251
252 L<Net::Domain|Net::Domain>
253
254 =head2 ClearSCM Perl Modules
255
256 =begin man 
257
258  Clearadm
259  Clearexec
260  DateUtils
261  Display
262  Utils
263
264 =end man
265
266 =begin html
267
268 <blockquote>
269 <a href="http://clearscm.com/php/cvs_man.php?file=clearadm/lib/Clearadm.pm">Clearadm</a><br>
270 <a href="http://clearscm.com/php/cvs_man.php?file=clearadm/lib/Clearexec.pm">Clearexec</a><br>
271 <a href="http://clearscm.com/php/cvs_man.php?file=lib/DateUtils.pm">DateUtils</a><br>
272 <a href="http://clearscm.com/php/cvs_man.php?file=lib/Display.pm">Display</a><br>
273 <a href="http://clearscm.com/php/cvs_man.php?file=lib/Utils.pm">Utils</a><br>
274 </blockquote>
275
276 =end html
277
278 =head1 BUGS AND LIMITATIONS
279
280 There are no known bugs in this script
281
282 Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
283
284 =head1 LICENSE AND COPYRIGHT
285
286 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
287
288 =cut