Removed /usr/local from CDPATH
[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 if @ARGV;
161
162 # Announce ourselves
163 verbose "$FindBin::Script V$VERSION";
164
165 my $exit = 0;
166
167 for my $system ($clearadm->FindSystem ($host)) {
168   next if $system->{active} eq 'false';
169   
170   my $status = $clearexec->connectToServer(
171     $system->{name}, 
172     $system->{port}
173   );
174   
175   unless ($status) {
176     verbose "Unable to connect to system $system->{name}:$system->{port}";
177     next;
178   } # unless
179
180   for my $filesystem ($clearadm->FindFilesystem ($system->{name}, $fs)) {
181     verbose "Snapshotting $system->{name}:$filesystem->{filesystem}";
182   
183     my %fs = snapshotFS($system, $filesystem->{filesystem});
184     
185     if (%fs) {
186       my ($err, $msg) = $clearadm->AddFS(%fs);
187   
188       error $msg, $err if $err;
189     } # if
190     
191     # Generate graphs
192     my $cmd = "plotfs.cgi generate=1 system=$system->{name} filesystem=$filesystem->{filesystem} scaling=Day points=7";
193
194     verbose "Generating fssmall for $system->{name}:$filesystem->{filesystem}";
195     my ($error, @output) = Execute("$cmd tiny=1 2>&1");
196
197     error 'Unable to generate fssmall' . join("\n", @output), $error if $error;
198
199     $filesystem->{fssmall} = join '', @output;
200
201     verbose "Generating fslarge for $system->{name}:$filesystem->{filesystem}";
202     ($error, @output) = Execute("$cmd 2>&1");
203
204     error 'Unable to generate fslarge' . join("\n", @output), $error if $error;
205
206     $filesystem->{fslarge} = join '', @output;
207
208     my ($err, $msg) = $clearadm->UpdateFilesystem($system->{name}, $filesystem->{filesystem}, %$filesystem);
209
210     error "Unable to update filesystem record $msg", $err if $err;
211
212     # Check if over threshold
213     my %notification = $clearadm->GetNotification('Filesystem');
214
215     next unless %notification;
216   
217     my $usedPct = '0%';
218
219     $usedPct = sprintf ('%.2f', (($fs{used} + $fs{reserve}) / $fs{size}) * 100) if $fs{size} != 0;
220     
221     if ($usedPct >= $filesystem->{threshold}) {
222       $exit = 2;
223       display YMDHMS
224             . " System: $filesystem->{system} "
225             . "Filesystem: $filesystem->{filesystem} Used: $usedPct% " 
226             . "Threshold: $filesystem->{threshold}";    
227     } else {
228       $clearadm->ClearNotifications ($system->{name}, $filesystem->{filesystem});    
229     } # if
230   } # for
231   
232   $clearexec->disconnectFromServer;
233 } # for
234
235 exit $exit;
236
237 =pod
238
239 =head1 CONFIGURATION AND ENVIRONMENT
240
241 DEBUG: If set then $debug is set to this level.
242
243 VERBOSE: If set then $verbose is set to this level.
244
245 TRACE: If set then $trace is set to this level.
246
247 =head1 DEPENDENCIES
248
249 =head2 Perl Modules
250
251 L<FindBin>
252
253 L<Getopt::Long|Getopt::Long>
254
255 L<Net::Domain|Net::Domain>
256
257 =head2 ClearSCM Perl Modules
258
259 =begin man 
260
261  Clearadm
262  Clearexec
263  DateUtils
264  Display
265  Utils
266
267 =end man
268
269 =begin html
270
271 <blockquote>
272 <a href="http://clearscm.com/php/scm_man.php?file=clearadm/lib/Clearadm.pm">Clearadm</a><br>
273 <a href="http://clearscm.com/php/scm_man.php?file=clearadm/lib/Clearexec.pm">Clearexec</a><br>
274 <a href="http://clearscm.com/php/scm_man.php?file=lib/DateUtils.pm">DateUtils</a><br>
275 <a href="http://clearscm.com/php/scm_man.php?file=lib/Display.pm">Display</a><br>
276 <a href="http://clearscm.com/php/scm_man.php?file=lib/Utils.pm">Utils</a><br>
277 </blockquote>
278
279 =end html
280
281 =head1 BUGS AND LIMITATIONS
282
283 There are no known bugs in this script
284
285 Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
286
287 =head1 LICENSE AND COPYRIGHT
288
289 Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
290
291 =cut