#!/usr/local/bin/perl
#
#Script to add a project type to PDB
use strict;
use warnings;

use lib "/cell_root/software/HPCC/lib/site_perl";
#Temporary for debugging
#use lib "/afs/.glue.umd.edu/software/HPCC/1.1/lib/site_perl";

use Glue::HPCC::Cluster;
use Glue::HPCC::Project::ProjectType;
use Glue::HPCC::Project::Log;

use Getopt::Long;

#Globals

my $GHPPType = 'Glue::HPCC::Project::ProjectType';
my $GHPLog = 'Glue::HPCC::Project::Log';
my $where;
my $reason;
my $pkey;
my $ptname;
my $changed=0;
my $hpc;

sub usage()
{	print STDERR <<EOF;
$0: Add a new project type

Usage:
$0 [ --cluster CLUSTER ] -type NAME \
	-reason REASON \
	 -desc DESC  \
	[ --pkey PKEY ] \
	[ --force ] \
	[ --expiry DAYS ] \
	[ --auto-replenishes AUTO ] \
	[ --normal-priority NORMAL ] \
	[ --high-priority HIGH ] \
	[ --special-partition SPECIAL ] \
	[ --scavenger-queue SCAV ] \
	[ --debug-queue DEBUG ] \
	[ --unix-group UNXGRP ] \
	[ --members MEMBERS ] \
	[ --metered METERED ] \
	[ -qos_tag QOS_TAG ]

Adds a new project type record.  
NAME is the name of the project type.  
CLUSTER determines which Projects Database to connect to, 
and defaults based on the host you are running the command on.
REASON is a reason which will be put in logs.
DESC is the description of the type.
If --force is given, skips the confirmation prompt.

Rest of parameters are optional, and if given give values
for the field in question.  Booleans all default to FALSE unless
otherwise noted.
Values are:
PKEY: primary key to insert to, default is undef (DB will
	automatically generate a new primary key)
DAYS: default expiry in days, default is 0
AUTO: boolean, auto-replenishes flag (true means replenishes)
NORMAL: boolean, has_normal_priority account flag
HIGH: boolean, high_priority account flag
SPECIAL: boolean, has_special_partition flag
SCAV: boolean, can_use_scavenger_q flag
DEBUG: boolean, can_use_debug_q flag
UNXGRP: boolean, requires_unix_group flag
MEMBERS: boolean, can_have_members flag
METERED: boolean, whether project is metered (has a GrpCPUMins limit).
	Default is true.
QOS_TAG: string, qos tag for Glue::HPCC::Cluster->get_qos_list
	E.g., standard, extended, std+ext, condo

EOF
}


#-------------------------------------------------------------------
#		Main
#-------------------------------------------------------------------

my $help;
my $cluster;
my ($desc, $auto, $normal, $high);
my ( $special, $scavq, $debq);
my ($defexp, $unxgrp, $members);
my ($qos_tag,); 
my $metered = 1;
my $FORCE;
my ($verbose, $dryrun);

my $res = GetOptions(
	'h|help!' => \$help,
	'verbose!' => \$verbose,
	'dryrun!' => \$dryrun,

	'force!' => \$FORCE,
	'cluster=s' => \$cluster,
	'type|name=s' => \$ptname,
	'reason=s' => \$reason,

	'pkey=i' => \$pkey,
	'description=s' => \$desc,
	'expiry-days|expiry_days=i' => \$defexp,
	'auto-replenishes|auto_replenishes=s' => \$auto,
	'normal-priority|normal_priority=s' => \$normal,
	'high-priority|high_priority|hi-priority|hi_priority=s' => \$high,
	'special-partition|special_partition=s' => \$special,
	'scavenger-queue|scavenger_queue=s' => \$scavq,
	'debug-queue|debug_queue=s' => \$debq,
	'unix-group|unix_group=s' => \$unxgrp,
	'members=s' => \$members,
	'metered=s' => \$metered,
	'qos_tag=s' => \$qos_tag,
);

unless ( $res ) 
{	usage;
	die "\nError processing options.\n";
}
if ( $help )
{	usage;
	exit 0;
}

unless ($ptname)
{	usage;
	die "\nYou must supply a project type name\n";
}
unless ($reason)
{	usage;
	die "\nYou must supply a reason\n";
}
unless ($desc)
{	usage;
	die "\nYou must supply a description\n";
}

if ( scalar(@ARGV) )
{	usage;
	my $tmp = join ", ", @ARGV;
	die "\nExtraneous arguments [ $tmp ], aborting.\n";
}

#Default cluster if needed
$hpc = Glue::HPCC::Cluster->new_from_clustername($cluster);
die "\nInvalid cluster $cluster at " if $cluster && ! $hpc && ! ref($hpc);
die "\nError instantiating cluster $hpc " unless $hpc && ref($hpc);
$cluster = $hpc->db_clustername;
$hpc->verbose($verbose);
$hpc->dryrun($dryrun);

my $ptype = Glue::HPCC::Project::ProjectType->projecttype_by_name(
	$hpc, $ptname);
die "Error looking up project type '$ptname': $ptype at "
	if $ptype && ! ref($ptype);
die "Project type with name $ptname already exists, aborting.\n"
	if $ptype;

if ( $pkey )
{	$ptype = Glue::HPCC::Project::ProjectType->projecttype_by_pkey(
		$hpc, $pkey);
	die "Error looking up project type pkey=$pkey: $ptype at "
		if $ptype && ! ref($ptype);
	die "Project type with key $pkey already exists, aborting.\n"
		if $ptype;
}

#Canonicalize the boolean inputs
$auto = $auto?'TRUE':'FALSE';
$normal = $normal?'TRUE':'FALSE';
$high = $high?'TRUE':'FALSE';
$special = $special?'TRUE':'FALSE';
$scavq = $scavq?'TRUE':'FALSE';
$debq = $debq?'TRUE':'FALSE';
$unxgrp = $unxgrp?'TRUE':'FALSE';
$members = $members?'TRUE':'FALSE';
$metered = $metered?'TRUE':'FALSE';

#Default expiration
$defexp = 0 unless defined $defexp;

$qos_tag = lc $qos_tag;
$qos_tag = undef if $qos_tag eq 'null';


unless ( $FORCE )
{	my $tmp = $pkey;
	$tmp = '<to be defaulted by db>' unless defined $tmp;
	my $tmp2 = $qos_tag;
	$tmp2 = '<NULL>' unless defined $tmp2;
	print STDERR <<EOF;
You have requested to insert a project_type
with the following definition:

Name: $ptname
Primary key: $tmp
Description: $desc
Auto-replenishes?: $auto
Has normal priority acct?: $normal
Has high priority acct?: $high
Has special partition?: $special
Can use scavenger queue?: $scavq
Can user debug queue?: $debq
Default expiry (days): $defexp
Requires unix group?: $unxgrp
Can have members?: $members
Is metered?: $metered
QoS tag: $tmp2

If you wish to proceed, type 'yes' at prompt.
Otherwise, ctrl-c out now.

Continue?
EOF
	my $ans = <STDIN>;
	chomp $ans;
	die "Aborting at user request.\n" unless
		$ans =~ /^\s*y(es)?\s*$/i;
}

my @fields = (
	name => $ptname,
	description => $desc,
	auto_replenishes => $auto,
	has_normal_priority => $normal,
	has_high_priority => $high,
	has_special_partition => $special,
	can_use_scavenger_q => $scavq,
	can_use_debug_q => $debq,
	default_expiry_days => $defexp,
	requires_unix_group => $unxgrp,
	can_have_members => $members,
	is_metered => $metered,
	qos_tag => $qos_tag,
);
push @fields, pkey => $pkey if defined $pkey;

my $error = Glue::HPCC::Project::ProjectType->pdb_insert(
	$hpc, @fields);
die "Error inserting project type record: $error at "
	if $error;

print "Committing changes to db\n";
$hpc->db_commit;
