Erik,

> I would appreciate receiving a copy of your script since I have the same
> problem and haven't done anything yet to solve it :-)

No problem.

bacula_next_volumes is the same as next_volumes.sh from my
previous mail.

prompt% bacula_next_volumes -h
Usage: bacula_next_volumes [options]
Outputs the volumes that are required for the next jobs.
Where the valid options are
  -c, --client      Bacula client, ie hostname.
  -d, --debug       Output debug information.
  -h, --help        Output this usage information.
  -m, --mail        Send email.
  -n, --mount       Mount all volumes.
  -q, --quiet       No output if no volumes required.
  -r, --recipient   Who gets mail (set to [EMAIL PROTECTED]).
  -u, --unmount     Unmount volumes that need changing.

Sorry about the state of the script, I got it working and lost
interest in optimising it. I'm sure the queries can be done
in SQL but I don't know how yet, maybe I'll do it on a quiet
day ;)

Do what you like with the script, but if you find something
better please let me know.

Cheers,
Bill
-- 
Bill Hill                w: http://www.hgu.mrc.ac.uk/Users/Bill.Hill
MRC Human Genetics Unit  e: [EMAIL PROTECTED]
Crewe Road               t: +44-131-3322471x2130
Edinburgh EH4 2XU, UK.   f: +44-131-4678456
#!/usr/bin/perl
# \file         bacula_next_volumes
# \author       Bill Hill
# \date         January 2007
# \version      $Id$
# \par
# Address:
#               MRC Human Genetics Unit,
#               Western General Hospital,
#               Edinburgh, EH4 2XU, UK.
# \par
# Copyright (C) 2006 Medical research Council, UK.
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be
# useful but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA  02110-1301, USA.
# \brief        Mails notice of the required volumes for the bacula dump.
# \todo         Quite inefficient code, should cache status.
# \bug          None known.

use strict;
use warnings;
use File::Spec::Unix;
use Getopt::Long;

my $debug = 0;
my $help = 0;
my $bcCmd = "/opt/bacula/sbin/bconsole";
my $bcOpts = "-c /opt/bacula/etc/bconsole.conf";
my $hostName = "server";
my $nJobVols = 0;
my $quiet = 0;
my @jobVols = ();
my @jobVolDevs = ();
my $nJobDevs = 0;
my @jobDevs = ();
my $nDevMounted = 0;
my @devMounted = ();
my $nDevToMount = 0;
my @devToMount = ();
my $outBuf = "";
my $nNewVol = 0;
my $progname = "bacula_next_volumes";
my $mailCmd = "/opt/bacula/sbin/bsmtp";
my $mailHost = 'smtp.some.where';
my $mailFrom = '[EMAIL PROTECTED]';
my $mailRecipient = '[EMAIL PROTECTED]';
my $sendMail = 0;
my $mount = 0;
my $unmount = 0;

my $state = 0;

sub showUsage
{
  print STDERR "Usage: $progname [options]\n";
  print STDERR "Outputs the volumes that are required for the next jobs.\n";
  print STDERR "Where the valid options are\n";
  print STDERR "  -c, --client      Bacula client, ie hostname.\n";
  print STDERR "  -d, --debug       Output debug information.\n";
  print STDERR "  -h, --help        Output this usage information.\n";
  print STDERR "  -m, --mail        Send email.\n";
  print STDERR "  -n, --mount       Mount all volumes.\n";
  print STDERR "  -q, --quiet       No output if no volumes required.\n";
  print STDERR "  -r, --recipient   Who gets mail (set to $mailRecipient).\n";
  print STDERR "  -u, --unmount     Unmount volumes that need changing.\n";
}

sub showGlobals
{
  print STDERR "bcCmd         = $bcCmd\n";
  print STDERR "bcOpts        = $bcOpts\n";
  print STDERR "hostName      = $hostName\n";
  print STDERR "debug         = $debug\n";
  print STDERR "help          = $help\n";
  print STDERR "progname      = $progname\n";
  print STDERR "quiet         = $quiet\n";
  print STDERR "state         = $state\n";
  print STDERR "nNewVol       = $nNewVol\n";
  print STDERR "outBuf        = $outBuf\n";
  print STDERR "mailCmd       = $mailCmd\n";
  print STDERR "mailHost      = $mailHost\n";
  print STDERR "mailFrom      = $mailFrom\n";
  print STDERR "mailRecipient = $mailRecipient\n";
  print STDERR "sendMail      = $sendMail\n";
  print STDERR "mount         = $mount\n";
  print STDERR "unmount       = $unmount\n";
  print STDERR "nJobVols      = $nJobVols\n";
  for(my $jIdx = 0; $jIdx < $nJobVols; ++$jIdx)
  {
    print STDERR "$jobVols[$jIdx][0] " .
                 "$jobVols[$jIdx][1] " .
                 "$jobVols[$jIdx][2] " .
                 "$jobVols[$jIdx][3] " .
                 "$jobVols[$jIdx][4] " .
                 "$jobVols[$jIdx][5] " .
                 "$jobVols[$jIdx][6]\n";
  }
  print STDERR "nJobDevs      = $nJobDevs\n";
  for(my $jIdx = 0; $jIdx < $nJobDevs; ++$jIdx)
  {
    print STDERR "$jobDevs[$jIdx][0] " .
                 "$jobDevs[$jIdx][1]\n";
  }
  print STDERR "nDevMounted   = $nDevMounted\n";
  for(my $jIdx = 0; $jIdx < $nDevMounted; ++$jIdx)
  {
    print STDERR "$devMounted[$jIdx][0] " .
                 "$devMounted[$jIdx][1]\n";
  }
  print STDERR "nDevToMount   = $nDevToMount\n";
  for(my $jIdx = 0; $jIdx < $nDevToMount; ++$jIdx)
  {
    print STDERR "$devToMount[$jIdx][0] " .
                 "$devToMount[$jIdx][1]\n";
  }
}

sub makeExit
{
  my $code = $_[0];
  my $mesg = $_[1];
  if(length($mesg) > 0)
  {
    print STDERR "$progname: $mesg\n";
  }
  exit($code);
}

sub associateJobsVolumesDevices
{
  for(my $jIdx = 0; $jIdx < $nJobVols; ++$jIdx)
  {
    $jobVolDevs[$jIdx][0] = $jobVols[$jIdx][5];
    $jobVolDevs[$jIdx][1] = $jobVols[$jIdx][6];
    $jobVolDevs[$jIdx][2] = "unknown";
    for(my $dIdx = 0; $dIdx < $nJobDevs; ++$dIdx)
    {
      if($jobVols[$jIdx][5] eq $jobDevs[$dIdx][0])
      {
        $jobVolDevs[$jIdx][2] = $jobDevs[$dIdx][1];
        last;
      }
    }
  }
}

sub addVolumesForJobs
{
  for(my $jIdx = 0; $jIdx < $nJobVols; ++$jIdx)
  {
    $outBuf = $outBuf .
              "  Job \"$jobVolDevs[$jIdx][0]\" " .
              "will use \"$jobVolDevs[$jIdx][1]\" " .
              "mounted in \"$jobVolDevs[$jIdx][2]\"\n";
  }
}

sub calcVolumesToBeMounted
{
  my $cnt = 0;

  for(my $jIdx = 0; $jIdx < $nJobVols; ++$jIdx)
  {
    for(my $dIdx = 0; $dIdx < $nDevMounted; ++$dIdx)
    {
      if(($jobVolDevs[$jIdx][2] eq $devMounted[$dIdx][0]) &&
         ($jobVolDevs[$jIdx][1] eq $devMounted[$dIdx][1]))
      {
        ++$cnt;
      }
    }
  }
  return $nJobVols - $cnt;
}

sub addVolumesToBeMounted
{
  $nDevToMount = 0;
  for(my $jIdx = 0; $jIdx < $nJobVols; ++$jIdx)
  {
    my $fnd = 0;
    for(my $dIdx = 0; $dIdx < $nDevMounted; ++$dIdx)
    {
      if(($jobVolDevs[$jIdx][2] eq $devMounted[$dIdx][0]) &&
         ($jobVolDevs[$jIdx][1] eq $devMounted[$dIdx][1]))
      {
        $fnd = 1;
      }
    }
    if($fnd == 0)
    {
      $devToMount[$nDevToMount++][0] = $jobVolDevs[$jIdx][2];
      $outBuf = $outBuf .
                "  \"$jobVolDevs[$jIdx][1]\" in \"$jobVolDevs[$jIdx][2]\"\n";
    }
  }
}

sub mountVolumes
{
  for(my $jIdx = 0; $jIdx < $nDevToMount; ++$jIdx)
  {
    system("echo \"mount storage=$devToMount[$jIdx][0]\" | $bcCmd $bcOpts");
  }
}

sub unmountVolumes
{
  for(my $jIdx = 0; $jIdx < $nDevToMount; ++$jIdx)
  {
    system("echo \"unmount storage=$devToMount[$jIdx][0]\" | $bcCmd $bcOpts");
  }
}

## Main ##

# Parse command line options
Getopt::Long::config('no_ignore_case');
GetOptions (
        "c|client=s"    => \$hostName,
        "d|debug"       => \$debug,
        "h|help"        => \$help,
        "m|mail"        => \$sendMail,
        "n|mount"       => \$mount,
        "q|quiet"       => \$quiet,
        "r|recipient=s" => \$mailRecipient,
        "u|unmount"     => \$unmount
);

if($debug != 0)
{
  &showGlobals();
}

# Show usage and exit if appropriate
if($help)
{
  &showUsage();
  makeExit(0, "");
}

# Collect job - volume association data
if(!(-e $bcCmd))
{
  makeExit(1, "$bcCmd not found.");
}
open(CMD, "echo \"status all\" | $bcCmd $bcOpts |") or
     &makeExit("cant execute $bcCmd.");
$state = 0;
while (<CMD>)
{
  if($state == 0)
  {
    if(/^Scheduled Jobs:/)
    {
      $state = 1;
    }
  }
  elsif($state == 1)
  {
    if(/^==========*/)
    {
      $state = 2;
    }
  }
  elsif($state == 2)
  {
    if(/^====[\t ]*$/)
    {
      $state = 4;
    }
    else
    {
      my $field;
      my $fieldIdx = 0;
      for $field ( split )
      {
        $jobVols[$nJobVols][$fieldIdx] = $field;
        ++$fieldIdx;
      }
      if($jobVols[$nJobVols][1] eq "Backup")
      {
        ++$nJobVols;
      }
    }
  }
}
close(CMD);

# Collect job - storage device association data
if(!(-e $bcCmd))
{
  makeExit(1, "$bcCmd not found.");
}
open(CMD, "echo \"show jobs\" | $bcCmd $bcOpts |") or
     &makeExit("cant execute $bcCmd.");
$state = 0;
while (<CMD>)
{
  if($state == 0)
  {
    if(/^Job:\s+name=(\S+)\s+/)
    {
      $jobDevs[$nJobDevs][0] = $1;
      $state = 1;
    }
  }
  elsif($state == 1)
  {
    if(/^\s*DeviceName=(\S+)\s+/)
    {
      $jobDevs[$nJobDevs][1] = $1;
      ++$nJobDevs;
      $state = 0;
    }
  }
}
close(CMD);

# Collect storage device mount status.
if(!(-e $bcCmd))
{
  makeExit(1, "$bcCmd not found.");
}
open(CMD, "echo \"status all\" | $bcCmd $bcOpts |") or
     &makeExit("cant execute $bcCmd.");
$state = 0;
while (<CMD>)
{
  if($state == 0)
  {
    if(/^Device status:\s*$/)
    {
      $state = 1;
    }
  }
  elsif($state == 1)
  {
    if(/^Device "(\S+)" \S+ is mounted with Volume="(\S+)" Pool="\S+"/)
    {
      $devMounted[$nDevMounted][0] = $1;
      $devMounted[$nDevMounted][1] = $2;
      ++$nDevMounted;
    }
    elsif(/^====/)
    {
      $state = 0;
    }
  }
}
close(CMD);

# Form statements which associate jobs, volumes and devices
&associateJobsVolumesDevices();
$nNewVol = &calcVolumesToBeMounted();

if($nNewVol > 1)
{
  $outBuf = $outBuf . "$nNewVol new volumes need to be mounted:\n";
  &addVolumesToBeMounted();
}
elsif($nNewVol == 1)
{
  $outBuf = $outBuf . "1 new volume needs to be mounted:\n";
  &addVolumesToBeMounted();
}
else
{
  $outBuf = $outBuf . "No new volumes need to be mounted.\n";
}
$outBuf = $outBuf . "\n";

$outBuf = $outBuf . "The following volumes will be used:\n";
&addVolumesForJobs();

# Send mail giving notice of the required volumes
if(($quiet == 0) || ($nNewVol > 0))
{
  if($sendMail == 0)
  {
    print $outBuf;
  }
  else
  {
    open(CMD, "| $mailCmd " .
              "-h $mailHost " .
              "-f \"" . $mailFrom . "\" " .
              "-s \"Bacula: Dump setup for $hostName\" " .
              $mailRecipient) or
         &makeExit("cant execute bsmtp.");
    print CMD $outBuf;
    close(CMD);
  }
}

# Mount and unmount volumes as required
if($mount != 0)
{
  &mountVolumes();
}
if($unmount != 0)
{
  &unmountVolumes();
}

if($debug > 0)
{
  &showGlobals();
}

&makeExit(0, "");
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Bacula-users mailing list
Bacula-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bacula-users

Reply via email to