#!/usr/bin/perl
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2005,2007 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
# @(#)55   1.6   src/csm/install/bhosts.perl, setup, csm_rfish, rfishs001b 11/10/05 03:30:13

# Script called by sensor when it detects some new nodestatus request comes in.
# Read in the host record file and process each recorded node. Then update the
# record file to delete the processed nodes.

use Fcntl qw(:DEFAULT :flock);

use strict;
BEGIN { $::csmpm = $ENV{'CSM_PM'} ? $ENV{'CSM_PM'} : '/opt/csm/pm'; }
use lib $::csmpm;
use Getopt::Std;
use CSMDefs;
use InstallKRB5Utils;
use NodesetUtils;
use NodeUtils;
use ServerUtils;

$::MSGCAT     = 'csmInstall.cat';
$::MSGMAPPATH = $ENV{'CSM_MSGMAPS'} ? $ENV{'CSM_MSGMAPS'} : '/opt/csm/msgmaps';
$::MSGSET     = 'csminstall';

$::progname         = "status_response.perl";
$::HOST_RECORD_FILE = "diskboot_hosts";

# Modify HEX file to make node boot to hard disk. Execute in turn each time for the nodes
# with the same InstallDistributionName, InstallDistributionVersion, InstallPkgArchitecture
# and InstallCSMVersion attributes.
sub changeNodeBootOrder
{
	my ($ref_nodelist) = @_;
	my @nodelist       = @$ref_nodelist;
	my %orig_nodehash  = %::NODEHASH;

	my ($InstallDistributionName);
	my ($InstallDistributionVersion);
	my ($InstallPkgArchitecture);
	my ($InstallCSMVersion);

	my ($distro_name, $distro_version, $arch, $csm_version);
	my (@setupBootNodes, @nextNodes, @doneNodes);

  NEXT_ROUND:
	foreach my $node (@nodelist)
	{
		$InstallDistributionName =
		  $orig_nodehash{$node}{'InstallDistributionName'};
		$InstallDistributionVersion =
		  $orig_nodehash{$node}{'InstallDistributionVersion'};
		$InstallPkgArchitecture =
		  $orig_nodehash{$node}{'InstallPkgArchitecture'};
		$InstallCSMVersion = $orig_nodehash{$node}{'InstallCSMVersion'};

		if (!$distro_name)    { $distro_name    = $InstallDistributionName; }
		if (!$distro_version) { $distro_version = $InstallDistributionVersion; }
		if (!$csm_version)    { $csm_version    = $InstallCSMVersion; }
		if (!$arch)           { $arch           = $InstallPkgArchitecture; }

		if (
			("$distro_name" and ($InstallDistributionName ne $distro_name))
			|| ("$distro_version"
				and ($InstallDistributionVersion ne $distro_version))
			|| ("$arch"        and ($InstallPkgArchitecture ne $arch))
			|| ("$csm_version" and ($InstallCSMVersion      ne $csm_version))
		   )
		{

			# Node with different attributes than the first node would be
			# processed in next round.
			push @nextNodes, $node;
			delete $::NODEHASH{$node};
			next;
		}

		push @setupBootNodes, $node;
	}

	NodesetUtils->run_setupBoot("disk", "onlyhex", \@setupBootNodes);
	push @doneNodes, @setupBootNodes;
	if (@nextNodes)
	{
		@nodelist   = @nextNodes;
		%::NODEHASH = %orig_nodehash;
		foreach my $cnode (keys %::NODEHASH)
		{
			if (grep /$cnode/, @doneNodes)
			{
				delete $::NODEHASH{$cnode};
			}
		}
		@setupBootNodes = ();
		@nextNodes      = ();
		$distro_name    = $distro_version = $arch = $csm_version = "";
		goto NEXT_ROUND;
	}
}

#
# MAIN Main main
#
my $lockFile = qq($::CSMTMP/bhosts.sem);
ServerUtils->get_lock($lockFile);

my $hostsFile = $::CSMSTATUSDIR . "/" . $::HOST_RECORD_FILE;

my @hostlist;
my $hostname;

if (!-e $hostsFile)
{
	die
    MessageUtils->messageFromCat('csmInstall.cat', $::MSGMAPPATH, 
                                 'csminstall',     'E1', 
                                 'EMsgFILE_NOT_FOUND', $hostsFile
                                 ); 
}

open(HOSTS_FILE, $hostsFile) or die
MessageUtils->messageFromCat('csmInstall.cat', $::MSGMAPPATH, 
                             'csminstall',     'E1', 
                             'EMsgCANT_OPEN', $hostsFile
                             );
flock(HOSTS_FILE, LOCK_SH);
while ($hostname = <HOSTS_FILE>)
{
	chomp $hostname;
	push @hostlist, $hostname;
}
close(HOSTS_FILE);

if (scalar @hostlist == 0)
{
	exit(0);
}

#Get KRB5 credentials
my $krb5_tgt   = 0;
my $KRB5CCNAME = InstallKRB5Utils->getKRB5tgt;
if ($KRB5CCNAME ne "")
{
	$ENV{'KRB5CCNAME'} = $KRB5CCNAME;
	$krb5_tgt = 1;
}

delete $ENV{'CSM_NO_NAME_RES'};
my ($ref_DestNode, $ref_lsnode_info, $ref_DestNodeHash) =
  NodeUtils->get_target_nodes(\@hostlist, undef, undef, 1);
%::NODEHASH = %$ref_DestNodeHash;
my @destnode = @$ref_DestNode;

&changeNodeBootOrder(\@destnode);

# get rid of KRB5 tgt if gotten
if ($krb5_tgt == 1)
{
	NodeUtils->runcmd("$::CSMCSMBIN/k5destroytgt 2>&1", -1);    # never errors
}

# Now have to remove the processed nodes from the record file
open(HOSTS_FILE, "+< $hostsFile")
  or die
MessageUtils->messageFromCat('csmInstall.cat', $::MSGMAPPATH, 
                             'csminstall',     'E1', 
                             'EMsgCANT_OPEN', $hostsFile
                             ); 
flock(HOSTS_FILE, LOCK_EX) or die
MessageUtils->messageFromCat('csmInstall.cat', $::MSGMAPPATH, 
                             'csminstall', 'E1', 
                             'EMsgCANT_LOCK_FILE', $hostsFile
                             );

my @hostlist2;
my @backlist;
while ($hostname = <HOSTS_FILE>)
{
	chomp $hostname;
	push @hostlist2, $hostname;
}

foreach $hostname (@hostlist2)
{
	if (!grep($hostname, @hostlist))
	{

		# This host has not been processed yet
		push @backlist, $hostname;
	}
}
truncate(HOSTS_FILE, 0) or die
MessageUtils->messageFromCat('csmInstall.cat', $::MSGMAPPATH, 
                             'csminstall',     'E1', 
                             'EMsgCANT_TRUNC_FILE', $hostsFile
                             );
foreach $hostname (@backlist)
{
	print HOSTS_FILE $hostname . "\n";
}
close(HOSTS_FILE);

ServerUtils->release_lock($lockFile);
