NBU::Host - Implements support for clients, Media Servers and Masters alike


NBU documentation Contained in the NBU distribution.

Index


Code Index:

NAME

Top

NBU::Host - Implements support for clients, Media Servers and Masters alike

SUPPORTED PLATFORMS

Top

*

Solaris

*

Windows/NT

SYNOPSIS

Top

    To come...

DESCRIPTION

Top

This module provides support for ...

SEE ALSO

Top

NBU::Media

AUTHOR

Top

Winkeler, Paul pwinkeler@pbnj-solutions.com

COPYRIGHT

Top


NBU documentation Contained in the NBU distribution.

#
# Copyright (c) 2002 Paul Winkeler.  All Rights Reserved.
# This program is free software; you may redistribute it and/or modify it under
# the same terms as Perl itself.
#
package NBU::Host;

use strict;
use Carp;

my %hostList;

BEGIN {
  use Exporter   ();
  use AutoLoader qw(AUTOLOAD);
  use vars       qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $AUTOLOAD);
  $VERSION =	 do { my @r=(q$Revision: 1.33 $=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
  @ISA =         qw();
  @EXPORT =      qw();
  @EXPORT_OK =   qw();
  %EXPORT_TAGS = qw();
}

my %aliases;
sub loadAlias {
  my $proto = shift;
  my ($alias, $canonical) = @_;

  $aliases{$alias} = $canonical;
}

sub new {
  my $proto = shift;
  my $host;

  if (@_) {
    my $name = shift;
    $name = $aliases{$name} if (exists($aliases{$name}));
#    my $keyName = substr($name, 0, 12);
    my $keyName = $name;

    if (!($host = $hostList{$keyName})) {
      $host = {};
      bless $host, $proto;
      $host->{NAME} = $name;

      $hostList{$keyName} = $host;

      $host->{ENROLLED} = 0;
      $host->{MM} = 0;
      $host->{MMTYPE} = 0;
    }
  }
  return $host;
}

sub populate {
  my $proto = shift;

  my $pipe = NBU->cmd("bpclclients -allunique -noheader |");
  while (<$pipe>) {
    my ($platform, $os, $name) = split;
    my $host = NBU::Host->new($name);

    $host->os($os);
    $host->platform($platform);
  }
  close($pipe);
}

sub byName {
  my $proto = shift;
  my $name = shift;
  my $keyName = substr($name, 0, 12);

  if (my $host = $hostList{$keyName}) {
    return $host;
  }
  return undef;
}

sub list {
  my $proto = shift;

  return (values %hostList);
}

sub enrolled {
  my $self = shift;

  $self->{ENROLLED} = 1;
}

sub mediaManager {
  my $self = shift;

  if (@_) {
    $self->{MM} = shift;
  }
  return $self->{MM};
}

sub roboticMediaManager {
  my $self = shift;

  if (@_) {
    $self->{MMTYPE} = shift;
  }
  return $self->{MMTYPE};
}

sub loadClasses {
  my $self = shift;

  NBU::Pool->populate;

  my $pipe = NBU->cmd("bpcllist -byclient ".$self->name." -l |");
  NBU::Class->loadClasses($pipe, "CLIENT", $self->clientOf);

  close($pipe);
}

sub makeClassMember {
  my $self = shift;
  my $newClass = shift;

  if (!defined($self->{CLASSES})) {
    $self->{CLASSES} = [];
  }

  my $classesR = $self->{CLASSES};
  push @$classesR, $newClass;

  return $newClass;
}

sub classes {
  my $self = shift;

  $self->loadClasses if (!$self->{ENROLLED});

  my $classesR = $self->{CLASSES};
  if (defined($classesR)) {
    return (@$classesR);
  }
  return ();
}

sub name {
  my $self = shift;

  return $self->{NAME};
}

sub loadConfig {
  my $self = shift;

  return 1 if ($self->{CONFIGLOADED});
  $self->{PLATFORM} = undef;
  $self->{OS} = undef;
  $self->{NBUVERSION} = undef;
  $self->{RELEASE} = undef;
  $self->{RELEASEID} = undef;
  $self->{CONFIGLOADED} = 1;

  my $pipe = NBU->cmd("bpgetconfig -g ".$self->name." |");
  unless (defined($_ = <$pipe>)) { close($pipe); return; } chop;  s/[\s]*$//;
  if (/Client of ([\S]+)/) {
    $self->{MASTER} = NBU::Host->new($1);
    NBU->addMaster($self->{MASTER});
  }
  else {
    $self->{MEDIASERVER} = 1;
  }

  # OS on this machine
  unless (defined($_ = <$pipe>)) { close($pipe); return; } chop;  s/[\s]*$//;
  if (/^([\S]+), ([\S]+)$/) {
    $self->{PLATFORM} = $1;
    $self->{OS} = $2;
  }
  else {
    $self->{PLATFORM} = $self->{OS} = $_;
  }

  # Now get the NetBackup version information
  # All the hosts in the cluster better be running the same version
  # but we're not checking for that at this time.
  unless (defined($_ = <$pipe>)) { close($pipe); return; } chop;  s/[\s]*$//;
  $self->{NBUVERSION} = $_;

  # Product identifier
  unless (defined($_ = <$pipe>)) { close($pipe); return; } chop;  s/[\s]*$//;

  if (defined($_ = <$pipe>)) {
    chop;  s/[\s]*$//;
    $self->{RELEASE} = $_;
  }

  if (defined($_ = <$pipe>) && ($_ !~ /^[\s]*$/)) {
    chop;  s/[\s]*$//;
    $self->{RELEASEID} = $_;
  }
  else {
    $self->{RELEASEID} = "000000";
  }

  if ($self->releaseID >= "450000") {
    # Install path
    return unless defined($_ = <$pipe>);  chop;  s/[\s]*$//;
    # Detailed OS
    return unless defined($_ = <$pipe>);  chop;  s/[\s]*$//;
    my ($os, $v) = split;
    $self->{OS} = $os;
  }
 
  close($pipe);

  # The -f option used to tell us, when we were media managers,
  # which host was our master with the "Client of" line.  With 4.5 this
  # feature has been removed.  Now we run bpgetconfig against ourselves
  # and use the "first server in the list must be the master" rule.
  $pipe = NBU->cmd("bpgetconfig -X |");
  while (<$pipe>) {
    if ((/SERVER = ([\S]+)/) && !defined($self->{MASTER})) {
      $self->{MASTER} = NBU::Host->new($1);
    }
    if (/EMMSERVER = ([\S]+)/) {
      $self->{EMMSERVER} = NBU::Host->new($1);
    }
  }
  close($pipe);

  my $detailAvailable;
  $pipe = NBU->cmd("bpclient -All -FI |");
  unless (defined($_ = <$pipe>)) { close($pipe); return; } chop;  s/[\s]*$//;
  while (<$pipe>) {
    if (/$self->name/i) {
      $detailAvailable = 1;
      last;
    }
  }
  close($pipe);

  if ($detailAvailable) {
    $pipe = NBU->cmd("bpclient -client ".$self->name." -l |");
    unless (defined($_ = <$pipe>)) { close($pipe); return; } chop;  s/[\s]*$//;
    close($pipe);
  }
}

sub clientOf {
  my $self = shift;

  $self->loadConfig;
  return $self->{MASTER};
}

sub EMMserver {
  my $self = shift;

  $self->loadConfig;
  return $self->{EMMSERVER};
}

sub platform {
  my $self = shift;

  if (@_) {
    $self->{PLATFORM} = shift;
  }
  else {
    $self->loadConfig;
  }

  return $self->{PLATFORM};
}

sub os {
  my $self = shift;

  if (@_) {
    $self->{OS} = shift;
  }
  else {
    $self->loadConfig;
  }

  return $self->{OS};
}

sub NBUVersion {
  my $self = shift;

  if (@_) {
    $self->{NBUVERSION} = shift;
  }
  else {
    $self->loadConfig;
  }

  return $self->{NBUVERSION};
}

sub NBUmajorVersion {
  my $self = shift;

  $self->NBUVersion =~ /^([\d])\.([\d\.]*$)/;
  return $1;
}

sub IPaddress {
  my $self = shift;

  if (!defined($self->{IPADDRESS})) {
    my $rawAddress = (gethostbyname($self->name))[4];
    my @octets = unpack("C4", $rawAddress);
    $self->{IPADDRESS} = join(".", @octets);
  }

  return $self->{IPADDRESS};
}

sub release {
  my $self = shift;

  if (@_) {
    $self->{RELEASE} = shift;
  }
  else {
    $self->loadConfig;
  }

  return $self->{RELEASE};
}

sub releaseID {
  my $self = shift;

  if (@_) {
    $self->{RELEASEID} = shift;
  }
  else {
    $self->loadConfig;
  }

  return $self->{RELEASEID};
}

sub loadCoverage {
  my $self = shift;
  my $name = $self->name;

  my %coverage;
  my $loadOK;

  my $pipe = NBU->cmd("bpcoverage -c $name -no_cov_header -no_hw_header |");
  while (<$pipe>) {
    if (!$loadOK) {
      if (/^CLIENT: $name/) {
	while (<$pipe>) {
          last if (/Mount Point/ || /Drive Letter/);
	}
        $_ = <$pipe>;
        $loadOK = 1;
      }
    }
    elsif ($loadOK && !(/^[\s]*$/) && !(/   Exit status/)) {
      #
      # Preserve input line in local variable because some methods called below
      # open other streams and thus clobber the global $_!
      my $l = $_;

      if ($self->os =~ /rs6000_42|SunOS|[Ss]olaris|linux|hp10.20/) {
        $_ = $l;
	my ($mountPoint, @remainder) = split;
	my ($deviceFile, $className, $status) = @remainder;

	next if ($deviceFile !~ /^\//);

        if ($className eq "UNCOVERED") {
	  $coverage{$mountPoint} = undef;
        }
        else {
	  $className =~ s/^\*//;
	  my $clR = $coverage{$mountPoint};
	  if (!$clR) {
	    $coverage{$mountPoint} = $clR = [];
	  }
	  my $class = NBU::Class->byName($className, $self->clientOf);
	  $class->providesCoverage(1);
          push @$clR, $class;
        }
      }
      elsif ($self->os =~ /Windows(NET|NT|2000|2003|XP)/) {
        $_ = $l;
        s/^[\s]*([\S].*:.)//;  my $mountPoint = $1;
        my (@remainder) = split;
	my $deviceFile;

	if ((($self->releaseID eq "451000") && defined($self->{MEDIASERVER}))) {
	  $deviceFile = shift @remainder;
	}
        my ($className, $status) = @remainder;
        if ($className eq "UNCOVERED") {
	  $coverage{$mountPoint} = undef;
        }
        else {
	  $className =~ s/^\*//;
	  my $clR = $coverage{$mountPoint};
	  if (!$clR) {
	    $coverage{$mountPoint} = $clR = [];
	  }
	  my $class = NBU::Class->byName($className, $self->clientOf);
          print STDERR "Unknown class referenced: $className\n" if (!defined($class));
	  $class->providesCoverage(1);
          push @$clR, $class;
        }
      }
      else {
        print "coverage from ".$self->os.": $_";
      }
    }
    else {
      last;
    }
  }
  close($pipe);

  $self->{COVERAGE} = \%coverage;
}

sub coverage {
  my $self = shift;

  if (!$self->{COVERAGE}) {
    $self->loadCoverage;
  }

  my $coverageR = $self->{COVERAGE};
  return (%$coverageR);
}

#
# Add an image to a host's list of backup images
sub addImage {
  my $self = shift;
  my $image = shift;
  
  $self->{IMAGES} = {} if (!defined($self->{IMAGES}));

  my $images = $self->{IMAGES};

  $$images{$image->id} =  $image;
}

#
# Load the list of images run against this host
sub loadImages {
  my $self = shift;

  if (!defined($self->{ALLIMAGES})) {
    NBU::Image->loadImages(NBU->cmd("bpimmedia -l -client ".$self->name." |"));
  }
  return ($self->{ALLIMAGES} = $self->{IMAGES});
}

sub images {
  my $self = shift;

  $self->loadImages;

  if (defined(my $images = $self->{IMAGES})) {
    return (values %$images);
  }
  else {
    return ();
  }
}

1;

__END__