#!/usr/bin/perl

use strict ;

my %servers       = () ;

#my $command         = 'vos part -no' ;
my $command         = 'vos part -server' ;
my %server_free  = () ;
my %server_avail = () ;
my $tot_free        = 0 ;
my %multi          = (
		      'K' => 1024,
		      'k' => 1024,
		      'M' => 1048576,
		      'm' => 1048576
		     ) ;

#my $debug = 'yes' ; # Turn on helpful debugging messages
my $debug = 'no' ; # Turn off debug output. Default for normal running.

# Populate %servers from an input file
#my $config_file = '/home/zzalsdrh/AFS-adm/volconfig' ;
my $config_file = '/afs/mcc/service/install/volconfig' ;
open (CONF, $config_file) ;

while (my $line = <CONF>)
  {
    if ($line =~ /([\w\.]+)\s+(\S+)\s+(\d+)/)
      {
        if ($2 eq '*') # Need to handle this sort of thing differently
          {
            $servers{ $1 }{ $2 } = $3 ;
          }
        else
          {
            $servers{ $1 }{ '/' . $2 } = $3 ;
          }
      }
  }

close (CONF) ;

if ($debug eq 'yes')
  {
    foreach my $one (sort keys %servers)
      {
	foreach my $two (sort keys %{ $servers{ $one } } )
	  {
	    print "$one\t$two\t$servers{ $one }{ $two }\n" ;
	  }
      }
  }

my $mode = 'standard' ; # Standard mode is to print only the best server and partition.

if ($ARGV[0] =~/-v/i)
  {
    $mode = 'verbose' ;
  }
elsif (($ARGV[0] =~/\-\?/i) or ($ARGV[0] =~/\-h/i) or ($ARGV[0] =~/[\-]+help/i))
  {
    $mode = 'help' ;
  }

if ($mode eq 'help')
  {
    print "This is the AFS Create User partition selector.\n\n" ;
    print "If you run this script without any options, it will print the server\n" ;
    print "and partition that the script thinks is the best one to create the new\n" ;
    print "account in, based on free space, space used and the Fiddle Factor.\n\n" ;
    print "If you type the script name and the -v flag, it will list all servers \n" ;
    print "and partitions,ordered with least-favoured to most favoured partition.\n\n" ;
    print "Any of '-?', '-h', '--help' or '-help' will get this message.\n" ;
    print "Anything else will be ignored.\n\n" ;
    exit 0 ;
  }

foreach my $server (sort keys %servers)
  {
    if ($debug eq 'yes')
      {
	print "\n$server\n" ;
      }

    my @output = `$command $server &2>/dev/null` ;
    my %party = () ;
    foreach my $part (keys %{ $servers{ $server } } ) # Make a list of partitions specified
      {
        $party{ $part } = 1 ;
      }

    foreach my $line (@output)
      {
	chomp $line ;
	# Free space on partition /vicepa: 17797752 K blocks out of total 32503296
	#                            1        2     3                        4

	if ($line =~ /(\/\w+):\s+(\d+)\s+(\w)[\s\w]+\s+(\d+)/)
	  {
	    if ($debug eq 'yes')
	      {
		print "$line\n" ;
	      }

	    my $partition = $1 ;

            #Fiddle to make hash matching work
            if ( ( $servers{ $server }{ '*' } ) and ( !($party{ $partition }) ) )
              {
                $servers{ $server }{ $partition } = $servers{ $server }{ '*' } ;
                # If we have a wildcard for the server and NO specific entry for this partition
                # we want to add a specific one that is the same as the partition name.
              }

            my $free      = ( $2 * $multi{ $3 } ) ;
            my $total     = ( $4 * $multi{ $3 } ) ;
            my $used      = ( $total - $free ) ;
	    my $pct_free  = ( ($free / $total) * 100) ;

            $tot_free    += $free ; # increment total free space counter

            $server_free{ $server . "  " . $partition }[0] = $free ; # Amount of free space for this partition + server
            $server_free{ $server . "  " . $partition }[1] = ($servers{ $server }{ $partition } * $pct_free) ; # Fiddle factor for admin control

	  }
      }
  }

if ($debug eq 'yes')
  {

    foreach my $volume (sort keys %server_free)
      {

	print "$volume\n" ;
	print "Free space = " . $server_free{ $volume }[0] . "\n" ;
	print "Fiddle factor = " . $server_free{ $volume }[1] . "\n\n" ;

	# The more free space in each volume, the bigger this fiddle factor is.

      }

print "\n-------------\n\n\n" ;

  }


# Before we can calculate server availabilities, we need to know how much is free in total.

foreach my $partition (keys %server_free)
  {

    # This line looks like complete bollocks and is likely the problem.
    #$server_avail{ $partition } = ((( $server_free{ $partition }[0] * $server_free{ $partition }[1] ) / $tot_free ) * 1) ;
    $server_avail{ $partition } = $server_free{ $partition }[1] ;

    if ($debug eq 'yes')
      {
	print "$partition\n" ;
	print "Free space    = " . $server_free{ $partition }[0] . "\n" ;
	print "Fiddle factor = " . $server_free{ $partition }[1] . "\n" ;
	print "Availability  = " . $server_avail{ $partition } . "\n\n" ;
      }

  }

if ($debug eq 'yes')
  {
    print "\n\n\n" ;
  }

if ($mode eq 'verbose')
  {

    print "The numbers specified here are the percentage free of the partition multiplied by the Admin fiddle factor.\n" ;
    print "The bigger the number, the better place for volumes a partition is; the actual figures don't mean anything.\n\n" ;
    foreach my $server (sort { $server_avail{ $a } <=> $server_avail{ $b } } keys %server_avail)
      {
	print "$server  " . int( $server_avail{ $server } ) . "\n" ;
      }

  }

if ($mode eq 'standard')
  {

    foreach my $server (sort { $server_avail{ $b } <=> $server_avail{ $a } } keys %server_avail)
      {
	print "$server  " . int( $server_avail{ $server } ) . "\n" ;
	exit 0 ;
      }

  }
