# -*-perl-*-
# vim: syntax=perl

# $Id$

# Return backup information

# $Log$
# Revision 1.1  2007/02/07 17:17:45  thomas
# Module to read sushi data from what.
#
# Revision 1.1  2007/02/07 17:16:57  thomas
# Stuff to read and print what backup data
#

# The logic is largely a duplicate of what's in lib/Sushi/Group/What(Host|Psql)

package Sushi::BackupInfo;

use strict;

# Add the CSL site_modules to the environment.
BEGIN { push(@INC, '/afs/cs.wisc.edu/s/perl-5.24.0/common/lib/site_perl/5.24.0') }

use CSL::WhatDevel;
use What::Data;
use Net::hostent;

our $atom_types = {
                   LinuxTar    => \&add_host_atom,
                   LinuxRmtTar => \&add_host_atom,
                   Sol         => \&add_host_atom,
		   Psql        => \&add_Psql_cluster,
                  };

###############################################################################

sub getBackups {
  my $self = shift;
  my $host = shift;

  return undef unless defined $host;

  my ($Data, $data, $atom_type, $h);
  my ($backups) = [];

  return undef unless defined ($Data = new What::Data);
  if (!defined ($data = $Data->find ($host))) {
    # Try using the gethostbyname
    return unless defined ($h = gethost ($host));
    return unless defined ($data = $Data->find ($h->name));
  }
  return undef unless defined ($data->{status});
  return undef unless $data->{status}=~ /Production|Setup|Repair/;
  return undef unless defined ($data = $data->{Data}->{Sushi});

  # Grok, Igor, Grok!
  foreach $atom_type (sort keys %$data) {
    next unless defined ($atom_types->{$atom_type});
    next unless ref ($data->{$atom_type});

    # Recurse through the tree
    $self->find_atoms_r ($host, $atom_type, $data->{$atom_type}, '/', $backups);
  }

  $backups;
}


###############################################################################
# Recurse down through the tree, creating atoms as needed

sub find_atoms_r {
  my $self = shift;
  my $host = shift;
  my $atom_type = shift;
  my $data = shift;
  my $path = shift;
  my $backups = shift;

  return 0 unless ref ($data);

  my ($key);

  foreach $key (sort keys %$data) {
    if ($key eq '_backup') {
      # Do we back up this node?
      if (!ref $data->{$key}) {
        &{$atom_types->{$atom_type}} ($self, $host, $atom_type, $path, $data->{$key}, $data, $backups);
      }
    } else {
      # Do we recurse this node?
      next unless ref ($data->{$key});
      $self->find_atoms_r (
			   $host,
			   $atom_type,
			   $data->{$key},
			   ($path eq '/')?"/$key":"$path/$key",
			   $backups,
			  );
    }
  }
}


###############################################################################

sub add_Psql_cluster {
  my $self = shift;
  my $host = shift;
  my $atom_type = shift;
  my $port = shift;
  my $backup = shift;
  my $node = shift;
  my $backups = shift;

  return 0 unless $backup =~ /^backup$/i;

  # Stupid port is a path, and has a leading '/'
  $port =~ s/^\///g;

  if ((!defined $host) || (!defined $port)) {
    print STDERR "Incomplete Psql atom spec!\n";
    return 0;
  }

  push @$backups, {
		   type => 'Psql',
		   element => "Port $port",
		   description => 'Database cluster',
		  };

  # Check for specific database names
  foreach (keys %{$node->{skip}}) {
    my $action = ($node->{skip}->{$_}->{skip} =~ /^(1|yes|true)$/i)
      ? "Skip" : "Backup";
    push @$backups, {
		     type => 'Psql',
		     element => "Port $port",
		     description => "$action database $_",
		    };
  }
}


###############################################################################

sub add_host_atom {
  my $self = shift;
  my $host = shift;
  my $atom_type = shift;
  my $path = shift;
  my $backup = shift;
  my $node = shift;
  my $backups = shift;

  my $action;

  if ($backup =~ /^(fstab|fanout)$/i) {
    $action = "(type $1)";
  } elsif ($backup =~ /^backup$/i) {
    $action = '';
  } else {
    return;
  }

  push @$backups, {
		   type => $atom_type,
		   element => $path,
		   description => $action,
		  };
}

