#!/usr/bin/perl #=============================================================================================== # File Name : /usr/local/bin/reportsnapshots.pl # Author : Rynardt Spies, Michael Davis # Description : This perl script will find all snapshot like files on VMFS datastores # and report the list of snapshots found via email. #Date : 24 March 2009 #=============================================================================================== use strict; use Net::SMTP; use Sys::Hostname; use Time::Local; use File::Spec; use Cwd 'abs_path'; #################################################### # Set variables #################################################### # Email Recipients: Specify recipient email addresses seperated by a space. my @MAILTO=qw(email.address@domain.com email.address2@domain.com); # Email From Adddress: Specify the from email address in $MAILFROM. my $MAILFROM='esxsnapshots@domain.com'; # MailServer: Specify the FQDN or ip address of your email server in $MAILSERVER my $MAILSERVER='internalmailserver.domain.com'; # Specify root path to the datastores where virtual machines are stored. Default: /vmfs/volumes my $VOLUMES_DIR="/vmfs/volumes"; # Log file my $LOGFILE="/var/log/checksnapshots.log"; #################################################### # Some arrays for reference #################################################### my @DAYS=qw(Sunday Monday Tuesday Wednesday Thursday Friday Saturday); my @MONTHS=qw(January February March April May June July August September October November December); my ( undef, undef, undef, $DAY, $MONTH, $YEAR, undef, undef, undef )=localtime(time); # The $SUBJECT variable is used to construct the email subject line. my $SUBJECT = sprintf("Snapshots reported by %s in %s as of %s %s %d", hostname, 'Cluster01', $DAY, $MONTHS[$MONTH], $YEAR+1900); # Find all snapshots. We'll call the find_files function to perform this task. my @LIST = (); find_files( $VOLUMES_DIR, \@LIST ); # ====================================== # A QUICK NOTE ON FIREWALL PORT CONTROL: # ====================================== # The ESX host's firewall should allow outbound port 25 to be open # in order to send email via SMTP. Although this script provides functions # to open and close port 25 on the firewall, it should never be the # the responsibility of a reporting script like this to configure a server as # it could interfere with other applications relying on port 25 to be open. # By default the open_firewall(); and close_firewall(); function calls are # commented out. Uncomment them if you would like this script to control port 25 # on this server. # Open the firewall to send email on port 25 #open_firewall(); open LOG, ">>$LOGFILE" or die "Unable to append to log file $LOGFILE"; # Create the email to be sent to recipients my $EMAIL=Net::SMTP->new($MAILSERVER) or die "Unable to make SMTP connection to $MAILSERVER. Confirm that port 25 is open on the ESX firewall"; $EMAIL->mail($MAILFROM); my $SENTTO=$EMAIL->to(@MAILTO, { SkipBad => 1 }); $EMAIL->data; $EMAIL->datasend("To: ".join(',',@MAILTO)."\n"); $EMAIL->datasend("Subject: ".$SUBJECT."\n"); $EMAIL->datasend("\n"); # End of headers $EMAIL->datasend("The snapshots below are candidates for deletion. Please make sure they're not in use before removing them.\n\n"); foreach(@LIST){ chomp; my ( $LINE ) = ( $_ =~ /^\/.*?\/.*?\/.*?\/(.*)$/ ); $EMAIL->datasend($LINE."\n"); printf(LOG "%s: %s\n", scalar localtime, $LINE); } $EMAIL->dataend; $EMAIL->quit; close LOG; # Close port 25 on the firewall #close_firewall(); exit; ############################################################# # Functions are defined below. ***DO NOT EDIT THIS SECTION*** ############################################################# sub open_firewall(){ my $OPEN_FIREWALL_CMD="esxcfg-firewall -o 25,tcp,out,\"OUTBOUND SMTP\""; qx/$OPEN_FIREWALL_CMD/; die "Open firewall failed: $!" if $?; } sub close_firewall(){ my $CLOSE_FIREWALL_CMD="esxcfg-firewall -c 25,tcp,out"; qx/$CLOSE_FIREWALL_CMD/; die "Close firewall failed: $!" if $?; } sub find_files(){ # # Pass in a start directory and a reference to an array to store the file names # my ( $START_DIR, $FILE_LIST ) = @_; my @DIR_ENTRIES=(); opendir( DIR, $START_DIR ) or die "Unable to open directory $START_DIR"; while( my $ITEM = readdir(DIR) ){ next if $ITEM =~ /^((\.)|(\.\.))$/; my $PATH = File::Spec->catfile($START_DIR, $ITEM); push( @DIR_ENTRIES, $PATH ) unless -l $PATH; } closedir DIR; foreach my $PATH (@DIR_ENTRIES){ find_files( $PATH, $FILE_LIST ) if -d $PATH; push( @$FILE_LIST, $PATH ) if ( ( -f $PATH ) && ( $PATH =~ /0000/ ) ); } }